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