fixup fsid correctly in union_getattr
[unix-history] / usr / src / sys / net / if.c
CommitLineData
cb1c44c2 1/*
815be91a
KB
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
cb1c44c2 4 *
dbf0c423 5 * %sccs.include.redist.c%
5b519e94 6 *
67e8af50 7 * @(#)if.c 8.3 (Berkeley) %G%
cb1c44c2 8 */
1bfd8df7 9
5548a02f
KB
10#include <sys/param.h>
11#include <sys/mbuf.h>
12#include <sys/systm.h>
13#include <sys/proc.h>
14#include <sys/socket.h>
15#include <sys/socketvar.h>
16#include <sys/protosw.h>
17#include <sys/kernel.h>
18#include <sys/ioctl.h>
a0369dcf 19
5548a02f 20#include <net/if.h>
5548a02f
KB
21#include <net/if_dl.h>
22#include <net/if_types.h>
1bfd8df7 23
1e977657 24int ifqmaxlen = IFQ_MAXLEN;
88a0c57a 25void if_slowtimo __P((void *arg));
1e977657 26
ee787340
SL
27/*
28 * Network interface utility routines.
29 *
f211a0b7
MK
30 * Routines with ifa_ifwith* names take sockaddr *'s as
31 * parameters.
ee787340 32 */
c4420f77 33void
85ce71f2
BJ
34ifinit()
35{
36 register struct ifnet *ifp;
37
38 for (ifp = ifnet; ifp; ifp = ifp->if_next)
aad26eac
MK
39 if (ifp->if_snd.ifq_maxlen == 0)
40 ifp->if_snd.ifq_maxlen = ifqmaxlen;
88a0c57a 41 if_slowtimo(0);
85ce71f2
BJ
42}
43
a62dd253 44#ifdef vax
ee787340
SL
45/*
46 * Call each interface on a Unibus reset.
47 */
c4420f77 48void
85ce71f2
BJ
49ifubareset(uban)
50 int uban;
51{
52 register struct ifnet *ifp;
53
54 for (ifp = ifnet; ifp; ifp = ifp->if_next)
8af3ca7c 55 if (ifp->if_reset)
9d6a72e7 56 (*ifp->if_reset)(ifp->if_unit, uban);
85ce71f2 57}
14fa60f2 58#endif
85ce71f2 59
02e54a34 60int if_index = 0;
d6bc9b28 61struct ifaddr **ifnet_addrs;
c4420f77 62static char *sprint_d __P((u_int, char *, int));
45081d0b 63
ee787340
SL
64/*
65 * Attach an interface to the
66 * list of "active" interfaces.
67 */
2c57a64d 68void
405c9168
BJ
69if_attach(ifp)
70 struct ifnet *ifp;
71{
02e54a34 72 unsigned socksize, ifasize;
78cafbd4 73 int namelen, unitlen, masklen, ether_output();
45081d0b 74 char workbuf[12], *unitname;
d6bc9b28 75 register struct ifnet **p = &ifnet;
02e54a34
KS
76 register struct sockaddr_dl *sdl;
77 register struct ifaddr *ifa;
d6bc9b28 78 static int if_indexlim = 8;
78cafbd4 79 extern void link_rtrequest();
405c9168 80
c4af8b24
BJ
81 while (*p)
82 p = &((*p)->if_next);
83 *p = ifp;
02e54a34 84 ifp->if_index = ++if_index;
d6bc9b28
KS
85 if (ifnet_addrs == 0 || if_index >= if_indexlim) {
86 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
87 struct ifaddr **q = (struct ifaddr **)
88 malloc(n, M_IFADDR, M_WAITOK);
89 if (ifnet_addrs) {
90 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
91 free((caddr_t)ifnet_addrs, M_IFADDR);
92 }
93 ifnet_addrs = q;
94 }
f2eb28c8
KS
95 /*
96 * create a Link Level name for this device
97 */
45081d0b 98 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
02e54a34 99 namelen = strlen(ifp->if_name);
45081d0b 100 unitlen = strlen(unitname);
02e54a34 101#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
41290c9a
KS
102 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
103 unitlen + namelen;
104 socksize = masklen + ifp->if_addrlen;
02e54a34
KS
105#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
106 socksize = ROUNDUP(socksize);
d6bc9b28
KS
107 if (socksize < sizeof(*sdl))
108 socksize = sizeof(*sdl);
02e54a34 109 ifasize = sizeof(*ifa) + 2 * socksize;
41290c9a
KS
110 if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) {
111 bzero((caddr_t)ifa, ifasize);
112 sdl = (struct sockaddr_dl *)(ifa + 1);
113 sdl->sdl_len = socksize;
114 sdl->sdl_family = AF_LINK;
115 bcopy(ifp->if_name, sdl->sdl_data, namelen);
116 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
117 sdl->sdl_nlen = (namelen += unitlen);
118 sdl->sdl_index = ifp->if_index;
119 sdl->sdl_type = ifp->if_type;
120 ifnet_addrs[if_index - 1] = ifa;
121 ifa->ifa_ifp = ifp;
122 ifa->ifa_next = ifp->if_addrlist;
123 ifa->ifa_rtrequest = link_rtrequest;
124 ifp->if_addrlist = ifa;
125 ifa->ifa_addr = (struct sockaddr *)sdl;
126 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
127 ifa->ifa_netmask = (struct sockaddr *)sdl;
128 sdl->sdl_len = masklen;
129 while (namelen != 0)
130 sdl->sdl_data[--namelen] = 0xff;
131 }
132 /* XXX -- Temporary fix before changing 10 ethernet drivers */
133 if (ifp->if_output == ether_output)
134 ether_ifattach(ifp);
405c9168 135}
ee787340
SL
136/*
137 * Locate an interface based on a complete address.
138 */
4ad99bae 139/*ARGSUSED*/
f211a0b7
MK
140struct ifaddr *
141ifa_ifwithaddr(addr)
202403f4 142 register struct sockaddr *addr;
1bfd8df7
BJ
143{
144 register struct ifnet *ifp;
f211a0b7 145 register struct ifaddr *ifa;
1bfd8df7 146
ee787340 147#define equal(a1, a2) \
202403f4 148 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
f211a0b7
MK
149 for (ifp = ifnet; ifp; ifp = ifp->if_next)
150 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
202403f4 151 if (ifa->ifa_addr->sa_family != addr->sa_family)
ee787340 152 continue;
202403f4 153 if (equal(addr, ifa->ifa_addr))
f211a0b7 154 return (ifa);
d6bc9b28
KS
155 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
156 equal(ifa->ifa_broadaddr, addr))
f211a0b7 157 return (ifa);
ee787340 158 }
f211a0b7 159 return ((struct ifaddr *)0);
1bfd8df7 160}
ae674e00
KS
161/*
162 * Locate the point to point interface with a given destination address.
163 */
164/*ARGSUSED*/
165struct ifaddr *
166ifa_ifwithdstaddr(addr)
202403f4 167 register struct sockaddr *addr;
ae674e00
KS
168{
169 register struct ifnet *ifp;
170 register struct ifaddr *ifa;
171
172 for (ifp = ifnet; ifp; ifp = ifp->if_next)
173 if (ifp->if_flags & IFF_POINTOPOINT)
174 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
202403f4 175 if (ifa->ifa_addr->sa_family != addr->sa_family)
ae674e00 176 continue;
202403f4 177 if (equal(addr, ifa->ifa_dstaddr))
ae674e00
KS
178 return (ifa);
179 }
180 return ((struct ifaddr *)0);
181}
1bfd8df7 182
ee787340
SL
183/*
184 * Find an interface on a specific network. If many, choice
c1b74e05 185 * is most specific found.
ee787340 186 */
f211a0b7
MK
187struct ifaddr *
188ifa_ifwithnet(addr)
202403f4 189 struct sockaddr *addr;
ee787340
SL
190{
191 register struct ifnet *ifp;
f211a0b7 192 register struct ifaddr *ifa;
c1b74e05 193 struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
202403f4 194 u_int af = addr->sa_family;
c1b74e05 195 char *addr_data = addr->sa_data, *cplim;
ee787340 196
d6bc9b28
KS
197 if (af == AF_LINK) {
198 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
199 if (sdl->sdl_index && sdl->sdl_index <= if_index)
200 return (ifnet_addrs[sdl->sdl_index - 1]);
201 }
f211a0b7
MK
202 for (ifp = ifnet; ifp; ifp = ifp->if_next)
203 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
d6bc9b28 204 register char *cp, *cp2, *cp3;
c1b74e05 205
202403f4 206 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
c1b74e05
KS
207 next: continue;
208 cp = addr_data;
202403f4
KS
209 cp2 = ifa->ifa_addr->sa_data;
210 cp3 = ifa->ifa_netmask->sa_data;
211 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
c1b74e05
KS
212 while (cp3 < cplim)
213 if ((*cp++ ^ *cp2++) & *cp3++)
214 goto next;
215 if (ifa_maybe == 0 ||
c4420f77
KB
216 rn_refines((caddr_t)ifa->ifa_netmask,
217 (caddr_t)ifa_maybe->ifa_netmask))
c1b74e05 218 ifa_maybe = ifa;
202403f4 219 }
c1b74e05 220 return (ifa_maybe);
1bfd8df7
BJ
221}
222
ee787340
SL
223/*
224 * Find an interface using a specific address family
225 */
f211a0b7
MK
226struct ifaddr *
227ifa_ifwithaf(af)
ee787340 228 register int af;
8a13b737 229{
ee787340 230 register struct ifnet *ifp;
f211a0b7 231 register struct ifaddr *ifa;
8a13b737 232
ee787340 233 for (ifp = ifnet; ifp; ifp = ifp->if_next)
f211a0b7 234 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
202403f4 235 if (ifa->ifa_addr->sa_family == af)
f211a0b7
MK
236 return (ifa);
237 return ((struct ifaddr *)0);
8a13b737 238}
f2eb28c8 239
d6bc9b28
KS
240/*
241 * Find an interface address specific to an interface best matching
242 * a given address.
243 */
244struct ifaddr *
245ifaof_ifpforaddr(addr, ifp)
246 struct sockaddr *addr;
247 register struct ifnet *ifp;
248{
249 register struct ifaddr *ifa;
250 register char *cp, *cp2, *cp3;
251 register char *cplim;
252 struct ifaddr *ifa_maybe = 0;
253 u_int af = addr->sa_family;
254
255 if (af >= AF_MAX)
256 return (0);
257 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
258 if (ifa->ifa_addr->sa_family != af)
259 continue;
260 ifa_maybe = ifa;
261 if (ifa->ifa_netmask == 0) {
262 if (equal(addr, ifa->ifa_addr) ||
263 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
264 return (ifa);
265 continue;
266 }
267 cp = addr->sa_data;
268 cp2 = ifa->ifa_addr->sa_data;
269 cp3 = ifa->ifa_netmask->sa_data;
270 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
271 for (; cp3 < cplim; cp3++)
272 if ((*cp++ ^ *cp2++) & *cp3)
273 break;
274 if (cp3 == cplim)
275 return (ifa);
276 }
277 return (ifa_maybe);
278}
5548a02f
KB
279
280#include <net/route.h>
281
f2eb28c8
KS
282/*
283 * Default action when installing a route with a Link Level gateway.
284 * Lookup an appropriate real ifa to point to.
285 * This should be moved to /sys/net/link.c eventually.
286 */
78cafbd4 287void
f2eb28c8 288link_rtrequest(cmd, rt, sa)
2c57a64d
CT
289 int cmd;
290 register struct rtentry *rt;
291 struct sockaddr *sa;
f2eb28c8
KS
292{
293 register struct ifaddr *ifa;
294 struct sockaddr *dst;
67e8af50 295 struct ifnet *ifp;
f2eb28c8
KS
296
297 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
298 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
299 return;
d6bc9b28 300 if (ifa = ifaof_ifpforaddr(dst, ifp)) {
60876470 301 IFAFREE(rt->rt_ifa);
f2eb28c8 302 rt->rt_ifa = ifa;
60876470 303 ifa->ifa_refcnt++;
f2eb28c8
KS
304 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
305 ifa->ifa_rtrequest(cmd, rt, sa);
d6bc9b28 306 }
f2eb28c8 307}
f1b2fa5b 308
72e4f44e
SL
309/*
310 * Mark an interface down and notify protocols of
311 * the transition.
af0b24db 312 * NOTE: must be called at splnet or eqivalent.
72e4f44e 313 */
c4420f77 314void
72e4f44e
SL
315if_down(ifp)
316 register struct ifnet *ifp;
317{
f211a0b7 318 register struct ifaddr *ifa;
5248a70b 319
72e4f44e 320 ifp->if_flags &= ~IFF_UP;
f211a0b7 321 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
202403f4 322 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
ce355163 323 if_qflush(&ifp->if_snd);
41290c9a
KS
324 rt_ifmsg(ifp);
325}
326
327/*
328 * Mark an interface up and notify protocols of
329 * the transition.
330 * NOTE: must be called at splnet or eqivalent.
331 */
c4420f77 332void
41290c9a
KS
333if_up(ifp)
334 register struct ifnet *ifp;
335{
336 register struct ifaddr *ifa;
337
338 ifp->if_flags |= IFF_UP;
339#ifdef notyet
340 /* this has no effect on IP, and will kill all iso connections XXX */
341 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
342 pfctlinput(PRC_IFUP, ifa->ifa_addr);
1524bcb8 343#endif
41290c9a 344 rt_ifmsg(ifp);
ce355163
MK
345}
346
347/*
348 * Flush an interface queue.
349 */
c4420f77 350void
ce355163
MK
351if_qflush(ifq)
352 register struct ifqueue *ifq;
353{
354 register struct mbuf *m, *n;
355
356 n = ifq->ifq_head;
357 while (m = n) {
358 n = m->m_act;
359 m_freem(m);
360 }
361 ifq->ifq_head = 0;
362 ifq->ifq_tail = 0;
363 ifq->ifq_len = 0;
72e4f44e 364}
de602274
SL
365
366/*
367 * Handle interface watchdog timer routines. Called
368 * from softclock, we decrement timers (if set) and
369 * call the appropriate interface routine on expiration.
370 */
88a0c57a
CT
371void
372if_slowtimo(arg)
373 void *arg;
de602274
SL
374{
375 register struct ifnet *ifp;
202403f4 376 int s = splimp();
de602274 377
af0b24db
SL
378 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
379 if (ifp->if_timer == 0 || --ifp->if_timer)
380 continue;
381 if (ifp->if_watchdog)
de602274 382 (*ifp->if_watchdog)(ifp->if_unit);
af0b24db 383 }
202403f4 384 splx(s);
88a0c57a 385 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
de602274 386}
0c33c832
SL
387
388/*
a62dd253
SL
389 * Map interface name to
390 * interface structure pointer.
0c33c832 391 */
a62dd253
SL
392struct ifnet *
393ifunit(name)
394 register char *name;
0c33c832 395{
0c33c832 396 register char *cp;
a62dd253
SL
397 register struct ifnet *ifp;
398 int unit;
725d9baf
MK
399 unsigned len;
400 char *ep, c;
0c33c832 401
a62dd253 402 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
0c33c832
SL
403 if (*cp >= '0' && *cp <= '9')
404 break;
a62dd253
SL
405 if (*cp == '\0' || cp == name + IFNAMSIZ)
406 return ((struct ifnet *)0);
725d9baf
MK
407 /*
408 * Save first char of unit, and pointer to it,
409 * so we can put a null there to avoid matching
410 * initial substrings of interface names.
411 */
412 len = cp - name + 1;
413 c = *cp;
414 ep = cp;
415 for (unit = 0; *cp >= '0' && *cp <= '9'; )
416 unit = unit * 10 + *cp++ - '0';
417 *ep = 0;
0c33c832 418 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
725d9baf 419 if (bcmp(ifp->if_name, name, len))
0c33c832
SL
420 continue;
421 if (unit == ifp->if_unit)
a62dd253 422 break;
0c33c832 423 }
725d9baf 424 *ep = c;
a62dd253
SL
425 return (ifp);
426}
427
428/*
429 * Interface ioctls.
430 */
c4420f77 431int
45081d0b 432ifioctl(so, cmd, data, p)
f211a0b7 433 struct socket *so;
a62dd253
SL
434 int cmd;
435 caddr_t data;
45081d0b 436 struct proc *p;
a62dd253
SL
437{
438 register struct ifnet *ifp;
439 register struct ifreq *ifr;
06c16dfa 440 int error;
0c33c832 441
0c33c832
SL
442 switch (cmd) {
443
a62dd253 444 case SIOCGIFCONF:
202403f4 445 case OSIOCGIFCONF:
a62dd253 446 return (ifconf(cmd, data));
a62dd253
SL
447 }
448 ifr = (struct ifreq *)data;
449 ifp = ifunit(ifr->ifr_name);
450 if (ifp == 0)
451 return (ENXIO);
452 switch (cmd) {
0c33c832 453
0c33c832
SL
454 case SIOCGIFFLAGS:
455 ifr->ifr_flags = ifp->if_flags;
456 break;
457
484ee22e
MK
458 case SIOCGIFMETRIC:
459 ifr->ifr_metric = ifp->if_metric;
460 break;
461
81889e84 462 case SIOCSIFFLAGS:
45081d0b 463 if (error = suser(p->p_ucred, &p->p_acflag))
06c16dfa 464 return (error);
81889e84
SL
465 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
466 int s = splimp();
467 if_down(ifp);
468 splx(s);
469 }
41290c9a
KS
470 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
471 int s = splimp();
472 if_up(ifp);
473 splx(s);
474 }
f211a0b7
MK
475 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
476 (ifr->ifr_flags &~ IFF_CANTCHANGE);
aad26eac
MK
477 if (ifp->if_ioctl)
478 (void) (*ifp->if_ioctl)(ifp, cmd, data);
81889e84
SL
479 break;
480
484ee22e 481 case SIOCSIFMETRIC:
45081d0b 482 if (error = suser(p->p_ucred, &p->p_acflag))
06c16dfa 483 return (error);
484ee22e
MK
484 ifp->if_metric = ifr->ifr_metric;
485 break;
486
78cafbd4
KS
487 case SIOCADDMULTI:
488 case SIOCDELMULTI:
489 if (error = suser(p->p_ucred, &p->p_acflag))
490 return (error);
93aa870c 491 if (ifp->if_ioctl == NULL)
78cafbd4
KS
492 return (EOPNOTSUPP);
493 return ((*ifp->if_ioctl)(ifp, cmd, data));
78cafbd4 494
0c33c832 495 default:
f211a0b7 496 if (so->so_proto == 0)
a62dd253 497 return (EOPNOTSUPP);
202403f4 498#ifndef COMPAT_43
f211a0b7
MK
499 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
500 cmd, data, ifp));
202403f4
KS
501#else
502 {
35c34494 503 int ocmd = cmd;
202403f4
KS
504
505 switch (cmd) {
506
507 case SIOCSIFDSTADDR:
508 case SIOCSIFADDR:
509 case SIOCSIFBRDADDR:
510 case SIOCSIFNETMASK:
511#if BYTE_ORDER != BIG_ENDIAN
512 if (ifr->ifr_addr.sa_family == 0 &&
513 ifr->ifr_addr.sa_len < 16) {
514 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
515 ifr->ifr_addr.sa_len = 16;
516 }
517#else
518 if (ifr->ifr_addr.sa_len == 0)
519 ifr->ifr_addr.sa_len = 16;
520#endif
521 break;
522
523 case OSIOCGIFADDR:
524 cmd = SIOCGIFADDR;
525 break;
526
527 case OSIOCGIFDSTADDR:
528 cmd = SIOCGIFDSTADDR;
529 break;
530
531 case OSIOCGIFBRDADDR:
532 cmd = SIOCGIFBRDADDR;
533 break;
534
535 case OSIOCGIFNETMASK:
536 cmd = SIOCGIFNETMASK;
537 }
538 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
539 cmd, data, ifp));
540 switch (ocmd) {
541
542 case OSIOCGIFADDR:
543 case OSIOCGIFDSTADDR:
544 case OSIOCGIFBRDADDR:
545 case OSIOCGIFNETMASK:
546 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
547 }
548 return (error);
549
550 }
551#endif
0c33c832
SL
552 }
553 return (0);
554}
555
556/*
557 * Return interface configuration
558 * of system. List may be used
559 * in later ioctl's (above) to get
560 * other information.
561 */
9e9695c7 562/*ARGSUSED*/
c4420f77 563int
0c33c832
SL
564ifconf(cmd, data)
565 int cmd;
566 caddr_t data;
567{
568 register struct ifconf *ifc = (struct ifconf *)data;
569 register struct ifnet *ifp = ifnet;
f211a0b7 570 register struct ifaddr *ifa;
9b956fa5
SL
571 register char *cp, *ep;
572 struct ifreq ifr, *ifrp;
0c33c832
SL
573 int space = ifc->ifc_len, error = 0;
574
9b956fa5
SL
575 ifrp = ifc->ifc_req;
576 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
0c33c832 577 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
40105126 578 strncpy(ifr.ifr_name, ifp->if_name, sizeof (ifr.ifr_name) - 2);
9b956fa5 579 for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
a6e3920d 580 continue;
9b956fa5 581 *cp++ = '0' + ifp->if_unit; *cp = '\0';
f211a0b7
MK
582 if ((ifa = ifp->if_addrlist) == 0) {
583 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
40105126
KM
584 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
585 sizeof (ifr));
f211a0b7
MK
586 if (error)
587 break;
588 space -= sizeof (ifr), ifrp++;
589 } else
590 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
202403f4
KS
591 register struct sockaddr *sa = ifa->ifa_addr;
592#ifdef COMPAT_43
593 if (cmd == OSIOCGIFCONF) {
594 struct osockaddr *osa =
595 (struct osockaddr *)&ifr.ifr_addr;
596 ifr.ifr_addr = *sa;
597 osa->sa_family = sa->sa_family;
598 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
599 sizeof (ifr));
600 ifrp++;
601 } else
602#endif
603 if (sa->sa_len <= sizeof(*sa)) {
604 ifr.ifr_addr = *sa;
605 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
606 sizeof (ifr));
607 ifrp++;
608 } else {
609 space -= sa->sa_len - sizeof(*sa);
610 if (space < sizeof (ifr))
611 break;
612 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
613 sizeof (ifr.ifr_name));
614 if (error == 0)
615 error = copyout((caddr_t)sa,
616 (caddr_t)&ifrp->ifr_addr, sa->sa_len);
617 ifrp = (struct ifreq *)
618 (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
619 }
f211a0b7
MK
620 if (error)
621 break;
202403f4 622 space -= sizeof (ifr);
f211a0b7 623 }
0c33c832
SL
624 }
625 ifc->ifc_len -= space;
626 return (error);
627}
02e54a34 628
45081d0b
MK
629static char *
630sprint_d(n, buf, buflen)
631 u_int n;
632 char *buf;
633 int buflen;
02e54a34 634{
45081d0b
MK
635 register char *cp = buf + buflen - 1;
636
637 *cp = 0;
02e54a34 638 do {
45081d0b
MK
639 cp--;
640 *cp = "0123456789"[n % 10];
641 n /= 10;
642 } while (n != 0);
643 return (cp);
02e54a34 644}