Annotation of src/sys/net/if.c, Revision 1.39.4.3
1.39.4.3! thorpej 1: /* $NetBSD: if.c,v 1.39.4.2 1997/08/29 00:59:31 thorpej Exp $ */
1.16 cgd 2:
1.1 cgd 3: /*
1.15 mycroft 4: * Copyright (c) 1980, 1986, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
1.16 cgd 35: * @(#)if.c 8.3 (Berkeley) 1/4/94
1.1 cgd 36: */
37:
1.8 mycroft 38: #include <sys/param.h>
39: #include <sys/mbuf.h>
40: #include <sys/systm.h>
1.15 mycroft 41: #include <sys/proc.h>
1.8 mycroft 42: #include <sys/socket.h>
43: #include <sys/socketvar.h>
44: #include <sys/protosw.h>
45: #include <sys/kernel.h>
46: #include <sys/ioctl.h>
1.1 cgd 47:
1.8 mycroft 48: #include <net/if.h>
49: #include <net/if_dl.h>
50: #include <net/if_types.h>
1.24 christos 51: #include <net/radix.h>
1.1 cgd 52:
53: int ifqmaxlen = IFQ_MAXLEN;
1.15 mycroft 54: void if_slowtimo __P((void *arg));
1.4 andrew 55:
1.1 cgd 56: /*
57: * Network interface utility routines.
58: *
59: * Routines with ifa_ifwith* names take sockaddr *'s as
60: * parameters.
61: */
1.4 andrew 62: void
1.1 cgd 63: ifinit()
64: {
65:
1.4 andrew 66: if_slowtimo(NULL);
1.1 cgd 67: }
68:
69: int if_index = 0;
70: struct ifaddr **ifnet_addrs;
71:
72: /*
73: * Attach an interface to the
74: * list of "active" interfaces.
75: */
1.15 mycroft 76: void
1.1 cgd 77: if_attach(ifp)
78: struct ifnet *ifp;
79: {
80: unsigned socksize, ifasize;
1.34 thorpej 81: int namelen, masklen;
1.1 cgd 82: register struct sockaddr_dl *sdl;
83: register struct ifaddr *ifa;
84: static int if_indexlim = 8;
85:
1.22 mycroft 86: if (if_index == 0)
87: TAILQ_INIT(&ifnet);
88: TAILQ_INIT(&ifp->if_addrlist);
1.21 mycroft 89: TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
1.1 cgd 90: ifp->if_index = ++if_index;
91: if (ifnet_addrs == 0 || if_index >= if_indexlim) {
92: unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
93: struct ifaddr **q = (struct ifaddr **)
94: malloc(n, M_IFADDR, M_WAITOK);
95: if (ifnet_addrs) {
96: bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
97: free((caddr_t)ifnet_addrs, M_IFADDR);
98: }
99: ifnet_addrs = q;
100: }
101: /*
102: * create a Link Level name for this device
103: */
1.34 thorpej 104: namelen = strlen(ifp->if_xname);
1.1 cgd 105: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
1.34 thorpej 106: masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
1.15 mycroft 107: socksize = masklen + ifp->if_addrlen;
1.1 cgd 108: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
109: if (socksize < sizeof(*sdl))
110: socksize = sizeof(*sdl);
1.20 cgd 111: socksize = ROUNDUP(socksize);
1.1 cgd 112: ifasize = sizeof(*ifa) + 2 * socksize;
113: ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
114: bzero((caddr_t)ifa, ifasize);
115: sdl = (struct sockaddr_dl *)(ifa + 1);
116: sdl->sdl_len = socksize;
117: sdl->sdl_family = AF_LINK;
1.34 thorpej 118: bcopy(ifp->if_xname, sdl->sdl_data, namelen);
119: sdl->sdl_nlen = namelen;
1.1 cgd 120: sdl->sdl_index = ifp->if_index;
1.15 mycroft 121: sdl->sdl_type = ifp->if_type;
122: ifnet_addrs[if_index - 1] = ifa;
123: ifa->ifa_ifp = ifp;
124: ifa->ifa_rtrequest = link_rtrequest;
1.21 mycroft 125: TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
1.15 mycroft 126: ifa->ifa_addr = (struct sockaddr *)sdl;
1.38 is 127: ifp->if_sadl = sdl;
1.1 cgd 128: sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
129: ifa->ifa_netmask = (struct sockaddr *)sdl;
1.15 mycroft 130: sdl->sdl_len = masklen;
1.1 cgd 131: while (namelen != 0)
132: sdl->sdl_data[--namelen] = 0xff;
1.39.4.1 marc 133: if (ifp->if_snd.ifq_maxlen == 0)
134: ifp->if_snd.ifq_maxlen = ifqmaxlen;
1.39.4.3! thorpej 135: ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
1.1 cgd 136: }
137: /*
138: * Locate an interface based on a complete address.
139: */
140: /*ARGSUSED*/
141: struct ifaddr *
142: ifa_ifwithaddr(addr)
143: register struct sockaddr *addr;
144: {
145: register struct ifnet *ifp;
146: register struct ifaddr *ifa;
147:
148: #define equal(a1, a2) \
149: (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
1.21 mycroft 150: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
151: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1.1 cgd 152: if (ifa->ifa_addr->sa_family != addr->sa_family)
153: continue;
154: if (equal(addr, ifa->ifa_addr))
155: return (ifa);
156: if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
157: equal(ifa->ifa_broadaddr, addr))
158: return (ifa);
159: }
160: return ((struct ifaddr *)0);
161: }
162: /*
163: * Locate the point to point interface with a given destination address.
164: */
165: /*ARGSUSED*/
166: struct ifaddr *
167: ifa_ifwithdstaddr(addr)
168: register struct sockaddr *addr;
169: {
170: register struct ifnet *ifp;
171: register struct ifaddr *ifa;
172:
1.21 mycroft 173: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
1.1 cgd 174: if (ifp->if_flags & IFF_POINTOPOINT)
1.21 mycroft 175: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1.30 mrg 176: if (ifa->ifa_addr->sa_family != addr->sa_family ||
177: ifa->ifa_dstaddr == NULL)
1.1 cgd 178: continue;
179: if (equal(addr, ifa->ifa_dstaddr))
180: return (ifa);
181: }
182: return ((struct ifaddr *)0);
183: }
184:
185: /*
186: * Find an interface on a specific network. If many, choice
1.15 mycroft 187: * is most specific found.
1.1 cgd 188: */
189: struct ifaddr *
190: ifa_ifwithnet(addr)
191: struct sockaddr *addr;
192: {
193: register struct ifnet *ifp;
194: register struct ifaddr *ifa;
1.15 mycroft 195: struct ifaddr *ifa_maybe = 0;
1.1 cgd 196: u_int af = addr->sa_family;
1.15 mycroft 197: char *addr_data = addr->sa_data, *cplim;
1.1 cgd 198:
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: }
1.21 mycroft 204: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
205: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1.15 mycroft 206: register char *cp, *cp2, *cp3;
207:
208: if (ifa->ifa_addr->sa_family != af ||
209: ifa->ifa_netmask == 0)
1.32 mrg 210: next: continue;
1.15 mycroft 211: cp = addr_data;
212: cp2 = ifa->ifa_addr->sa_data;
213: cp3 = ifa->ifa_netmask->sa_data;
214: cplim = (char *)ifa->ifa_netmask +
215: ifa->ifa_netmask->sa_len;
216: while (cp3 < cplim)
217: if ((*cp++ ^ *cp2++) & *cp3++)
1.32 mrg 218: /* want to continue for() loop */
219: goto next;
1.15 mycroft 220: if (ifa_maybe == 0 ||
221: rn_refines((caddr_t)ifa->ifa_netmask,
222: (caddr_t)ifa_maybe->ifa_netmask))
223: ifa_maybe = ifa;
224: }
225: return (ifa_maybe);
1.26 mrg 226: }
227: /*
228: * Find the interface of the addresss.
229: */
230: struct ifaddr *
231: ifa_ifwithladdr(addr)
232: struct sockaddr *addr;
233: {
234: struct ifaddr *ia;
235:
236: if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr))
237: || (ia = ifa_ifwithnet(addr)))
238: return (ia);
239: return (NULL);
1.1 cgd 240: }
241:
242: /*
243: * Find an interface using a specific address family
244: */
245: struct ifaddr *
246: ifa_ifwithaf(af)
247: register int af;
248: {
249: register struct ifnet *ifp;
250: register struct ifaddr *ifa;
251:
1.21 mycroft 252: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
253: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
254: if (ifa->ifa_addr->sa_family == af)
255: return (ifa);
1.1 cgd 256: return ((struct ifaddr *)0);
257: }
258:
259: /*
260: * Find an interface address specific to an interface best matching
261: * a given address.
262: */
263: struct ifaddr *
264: ifaof_ifpforaddr(addr, ifp)
265: struct sockaddr *addr;
266: register struct ifnet *ifp;
267: {
268: register struct ifaddr *ifa;
269: register char *cp, *cp2, *cp3;
270: register char *cplim;
271: struct ifaddr *ifa_maybe = 0;
272: u_int af = addr->sa_family;
273:
274: if (af >= AF_MAX)
275: return (0);
1.21 mycroft 276: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1.1 cgd 277: if (ifa->ifa_addr->sa_family != af)
278: continue;
279: ifa_maybe = ifa;
280: if (ifa->ifa_netmask == 0) {
281: if (equal(addr, ifa->ifa_addr) ||
282: (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
283: return (ifa);
284: continue;
285: }
286: cp = addr->sa_data;
287: cp2 = ifa->ifa_addr->sa_data;
288: cp3 = ifa->ifa_netmask->sa_data;
289: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
290: for (; cp3 < cplim; cp3++)
291: if ((*cp++ ^ *cp2++) & *cp3)
292: break;
293: if (cp3 == cplim)
294: return (ifa);
295: }
296: return (ifa_maybe);
297: }
1.9 mycroft 298:
1.15 mycroft 299: #include <net/route.h>
300:
1.1 cgd 301: /*
302: * Default action when installing a route with a Link Level gateway.
303: * Lookup an appropriate real ifa to point to.
304: * This should be moved to /sys/net/link.c eventually.
305: */
1.15 mycroft 306: void
1.1 cgd 307: link_rtrequest(cmd, rt, sa)
1.15 mycroft 308: int cmd;
309: register struct rtentry *rt;
310: struct sockaddr *sa;
1.1 cgd 311: {
312: register struct ifaddr *ifa;
313: struct sockaddr *dst;
1.15 mycroft 314: struct ifnet *ifp;
1.1 cgd 315:
316: if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
317: ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
318: return;
1.24 christos 319: if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
1.15 mycroft 320: IFAFREE(rt->rt_ifa);
1.1 cgd 321: rt->rt_ifa = ifa;
1.15 mycroft 322: ifa->ifa_refcnt++;
1.1 cgd 323: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
324: ifa->ifa_rtrequest(cmd, rt, sa);
325: }
326: }
327:
328: /*
329: * Mark an interface down and notify protocols of
330: * the transition.
1.23 mycroft 331: * NOTE: must be called at splsoftnet or equivalent.
1.1 cgd 332: */
1.15 mycroft 333: void
1.1 cgd 334: if_down(ifp)
335: register struct ifnet *ifp;
336: {
337: register struct ifaddr *ifa;
338:
339: ifp->if_flags &= ~IFF_UP;
1.21 mycroft 340: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
1.1 cgd 341: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
342: if_qflush(&ifp->if_snd);
1.15 mycroft 343: rt_ifmsg(ifp);
344: }
345:
346: /*
347: * Mark an interface up and notify protocols of
348: * the transition.
1.23 mycroft 349: * NOTE: must be called at splsoftnet or equivalent.
1.15 mycroft 350: */
351: void
352: if_up(ifp)
353: register struct ifnet *ifp;
354: {
1.24 christos 355: #ifdef notyet
1.15 mycroft 356: register struct ifaddr *ifa;
1.24 christos 357: #endif
1.15 mycroft 358:
359: ifp->if_flags |= IFF_UP;
360: #ifdef notyet
361: /* this has no effect on IP, and will kill all ISO connections XXX */
1.24 christos 362: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
363: ifa = ifa->ifa_list.tqe_next)
1.15 mycroft 364: pfctlinput(PRC_IFUP, ifa->ifa_addr);
365: #endif
366: rt_ifmsg(ifp);
1.1 cgd 367: }
368:
369: /*
370: * Flush an interface queue.
371: */
1.15 mycroft 372: void
1.1 cgd 373: if_qflush(ifq)
374: register struct ifqueue *ifq;
375: {
376: register struct mbuf *m, *n;
377:
378: n = ifq->ifq_head;
1.24 christos 379: while ((m = n) != NULL) {
1.1 cgd 380: n = m->m_act;
381: m_freem(m);
382: }
383: ifq->ifq_head = 0;
384: ifq->ifq_tail = 0;
385: ifq->ifq_len = 0;
386: }
387:
388: /*
389: * Handle interface watchdog timer routines. Called
390: * from softclock, we decrement timers (if set) and
391: * call the appropriate interface routine on expiration.
392: */
1.4 andrew 393: void
1.13 cgd 394: if_slowtimo(arg)
395: void *arg;
1.1 cgd 396: {
397: register struct ifnet *ifp;
398: int s = splimp();
399:
1.21 mycroft 400: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
1.1 cgd 401: if (ifp->if_timer == 0 || --ifp->if_timer)
402: continue;
403: if (ifp->if_watchdog)
1.34 thorpej 404: (*ifp->if_watchdog)(ifp);
1.1 cgd 405: }
406: splx(s);
1.14 mycroft 407: timeout(if_slowtimo, NULL, hz / IFNET_SLOWHZ);
1.1 cgd 408: }
409:
410: /*
411: * Map interface name to
412: * interface structure pointer.
413: */
414: struct ifnet *
415: ifunit(name)
416: register char *name;
417: {
418: register struct ifnet *ifp;
1.34 thorpej 419:
420: for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
1.35 thorpej 421: if (strcmp(ifp->if_xname, name) == 0)
1.34 thorpej 422: return (ifp);
423:
424: return (NULL);
1.1 cgd 425: }
426:
427: /*
428: * Interface ioctls.
429: */
1.15 mycroft 430: int
1.1 cgd 431: ifioctl(so, cmd, data, p)
432: struct socket *so;
1.18 cgd 433: u_long cmd;
1.1 cgd 434: caddr_t data;
435: struct proc *p;
436: {
437: register struct ifnet *ifp;
438: register struct ifreq *ifr;
439: int error;
440:
441: switch (cmd) {
442:
443: case SIOCGIFCONF:
444: case OSIOCGIFCONF:
445: return (ifconf(cmd, data));
446: }
447: ifr = (struct ifreq *)data;
448: ifp = ifunit(ifr->ifr_name);
449: if (ifp == 0)
450: return (ENXIO);
451: switch (cmd) {
452:
453: case SIOCGIFFLAGS:
454: ifr->ifr_flags = ifp->if_flags;
455: break;
456:
457: case SIOCGIFMETRIC:
458: ifr->ifr_metric = ifp->if_metric;
459: break;
1.7 hpeyerl 460:
1.36 mycroft 461: case SIOCGIFMTU:
1.37 cgd 462: ifr->ifr_mtu = ifp->if_mtu;
463: break;
1.36 mycroft 464:
1.1 cgd 465: case SIOCSIFFLAGS:
1.24 christos 466: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1 cgd 467: return (error);
468: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
469: int s = splimp();
470: if_down(ifp);
471: splx(s);
472: }
1.15 mycroft 473: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
474: int s = splimp();
475: if_up(ifp);
476: splx(s);
477: }
1.1 cgd 478: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
479: (ifr->ifr_flags &~ IFF_CANTCHANGE);
480: if (ifp->if_ioctl)
481: (void) (*ifp->if_ioctl)(ifp, cmd, data);
482: break;
483:
484: case SIOCSIFMETRIC:
1.24 christos 485: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1 cgd 486: return (error);
487: ifp->if_metric = ifr->ifr_metric;
1.5 deraadt 488: break;
489:
1.36 mycroft 490: case SIOCSIFMTU:
1.15 mycroft 491: case SIOCADDMULTI:
492: case SIOCDELMULTI:
1.39 thorpej 493: case SIOCSIFMEDIA:
1.24 christos 494: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.15 mycroft 495: return (error);
1.39 thorpej 496: /* FALLTHROUGH */
497: case SIOCGIFMEDIA:
1.15 mycroft 498: if (ifp->if_ioctl == 0)
1.5 deraadt 499: return (EOPNOTSUPP);
500: return ((*ifp->if_ioctl)(ifp, cmd, data));
1.1 cgd 501:
502: default:
503: if (so->so_proto == 0)
504: return (EOPNOTSUPP);
1.33 christos 505: #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
1.1 cgd 506: return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1.36 mycroft 507: (struct mbuf *)cmd, (struct mbuf *)data,
508: (struct mbuf *)ifp, p));
1.1 cgd 509: #else
510: {
511: int ocmd = cmd;
512:
513: switch (cmd) {
514:
1.28 mycroft 515: case SIOCSIFADDR:
1.1 cgd 516: case SIOCSIFDSTADDR:
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: }
1.24 christos 546: error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1.36 mycroft 547: (struct mbuf *)cmd, (struct mbuf *)data,
548: (struct mbuf *)ifp, p));
1.1 cgd 549: switch (ocmd) {
550:
551: case OSIOCGIFADDR:
552: case OSIOCGIFDSTADDR:
553: case OSIOCGIFBRDADDR:
554: case OSIOCGIFNETMASK:
1.20 cgd 555: *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1.1 cgd 556: }
557: return (error);
558:
559: }
560: #endif
561: }
562: return (0);
563: }
564:
565: /*
566: * Return interface configuration
567: * of system. List may be used
568: * in later ioctl's (above) to get
569: * other information.
570: */
571: /*ARGSUSED*/
1.15 mycroft 572: int
1.1 cgd 573: ifconf(cmd, data)
1.19 mycroft 574: u_long cmd;
1.1 cgd 575: caddr_t data;
576: {
577: register struct ifconf *ifc = (struct ifconf *)data;
1.21 mycroft 578: register struct ifnet *ifp;
1.1 cgd 579: register struct ifaddr *ifa;
580: struct ifreq ifr, *ifrp;
581: int space = ifc->ifc_len, error = 0;
582:
583: ifrp = ifc->ifc_req;
1.21 mycroft 584: for (ifp = ifnet.tqh_first;
1.33 christos 585: space >= sizeof (ifr) && ifp != 0; ifp = ifp->if_list.tqe_next) {
1.34 thorpej 586: bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
1.21 mycroft 587: if ((ifa = ifp->if_addrlist.tqh_first) == 0) {
1.1 cgd 588: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1.15 mycroft 589: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
590: sizeof(ifr));
1.1 cgd 591: if (error)
592: break;
593: space -= sizeof (ifr), ifrp++;
594: } else
1.33 christos 595: for (; space >= sizeof (ifr) && ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1.1 cgd 596: register struct sockaddr *sa = ifa->ifa_addr;
1.33 christos 597: #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
1.1 cgd 598: if (cmd == OSIOCGIFCONF) {
599: struct osockaddr *osa =
600: (struct osockaddr *)&ifr.ifr_addr;
601: ifr.ifr_addr = *sa;
602: osa->sa_family = sa->sa_family;
603: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
604: sizeof (ifr));
605: ifrp++;
606: } else
607: #endif
608: if (sa->sa_len <= sizeof(*sa)) {
609: ifr.ifr_addr = *sa;
610: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
611: sizeof (ifr));
612: ifrp++;
613: } else {
614: space -= sa->sa_len - sizeof(*sa);
615: if (space < sizeof (ifr))
616: break;
617: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
618: sizeof (ifr.ifr_name));
619: if (error == 0)
620: error = copyout((caddr_t)sa,
621: (caddr_t)&ifrp->ifr_addr, sa->sa_len);
622: ifrp = (struct ifreq *)
623: (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
624: }
625: if (error)
626: break;
627: space -= sizeof (ifr);
628: }
629: }
630: ifc->ifc_len -= space;
631: return (error);
632: }
CVSweb <webmaster@jp.NetBSD.org>