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