|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1980, 1986, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * Justin Walker ([email protected]) Tue Sep 16 20:05:39 PDT 1997
59: * - Add filtering scheme to cut down on traffic when Y-adapter
60: * enabled.
61: */
62:
63: #include <sys/param.h>
64: #include <sys/mbuf.h>
65: #include <sys/systm.h>
66: #include <sys/proc.h>
67: #include <sys/socket.h>
68: #include <sys/socketvar.h>
69: #include <sys/protosw.h>
70: #include <sys/kernel.h>
71: #include <sys/ioctl.h>
72: #include <sys/malloc.h>
73: #include <sys/syslog.h>
74:
75: #include <net/if.h>
76: #include <net/if_dl.h>
77: #include <net/if_types.h>
78:
79: #if defined(ppc)
80: #include <net/if_blue.h>
81: #include <netinet/in.h>
82: #endif /* ppc */
83:
84: #include <machine/spl.h>
85:
86: int ifqmaxlen = IFQ_MAXLEN;
87: struct ifnet *ifnet;
88:
89: void if_slowtimo __P((void *arg));
90:
91: /*
92: * Network interface utility routines.
93: *
94: * Routines with ifa_ifwith* names take sockaddr *'s as
95: * parameters.
96: */
97: void
98: ifinit()
99: {
100: register struct ifnet *ifp;
101:
102: for (ifp = ifnet; ifp; ifp = ifp->if_next)
103: if (ifp->if_snd.ifq_maxlen == 0)
104: ifp->if_snd.ifq_maxlen = ifqmaxlen;
105: #ifdef not_needed
106: if_slowtimo(NULL);
107: #endif
108:
109: }
110:
111: int if_index = 0;
112: struct ifaddr **ifnet_addrs;
113: static char *sprint_d __P((u_int, char *, int));
114:
115: /*
116: * Attach an interface to the
117: * list of "active" interfaces.
118: */
119: void
120: if_attach(ifp)
121: struct ifnet *ifp;
122: {
123: unsigned socksize, ifasize;
124: int namelen, unitlen, masklen, ether_output();
125: char workbuf[12], *unitname;
126: register struct ifnet **p = &ifnet;
127: register struct sockaddr_dl *sdl;
128: register struct ifaddr *ifa;
129: static int if_indexlim = 8;
130: extern void link_rtrequest();
131:
132: while (*p)
133: p = &((*p)->if_next);
134: *p = ifp;
135: ifp->if_index = ++if_index;
136: if (ifnet_addrs == 0 || if_index >= if_indexlim) {
137: unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
138: struct ifaddr **q = (struct ifaddr **)
139: _MALLOC(n, M_IFADDR, M_WAITOK);
140: if (ifnet_addrs) {
141: bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
142: _FREE((caddr_t)ifnet_addrs, M_IFADDR);
143: }
144: ifnet_addrs = q;
145: }
146: /*
147: * create a Link Level name for this device
148: */
149: unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
150: namelen = strlen(ifp->if_name);
151: unitlen = strlen(unitname);
152: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
153: masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
154: unitlen + namelen;
155: socksize = masklen + ifp->if_addrlen;
156: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
157: socksize = ROUNDUP(socksize);
158: if (socksize < sizeof(*sdl))
159: socksize = sizeof(*sdl);
160: ifasize = sizeof(*ifa) + 2 * socksize;
161: if ((ifa = (struct ifaddr *)_MALLOC(ifasize, M_IFADDR, M_WAITOK))) {
162: bzero((caddr_t) ifa, ifasize);
163: sdl = (struct sockaddr_dl *)(ifa + 1);
164: sdl->sdl_len = socksize;
165: sdl->sdl_family = AF_LINK;
166: bcopy(ifp->if_name, sdl->sdl_data, namelen);
167: bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
168: sdl->sdl_nlen = (namelen += unitlen);
169: sdl->sdl_index = ifp->if_index;
170: sdl->sdl_type = ifp->if_type;
171: ifnet_addrs[if_index - 1] = ifa;
172: ifa->ifa_ifp = ifp;
173: ifa->ifa_next = ifp->if_addrlist;
174: ifa->ifa_rtrequest = link_rtrequest;
175: ifp->if_addrlist = ifa;
176: ifa->ifa_addr = (struct sockaddr *)sdl;
177: sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
178: ifa->ifa_netmask = (struct sockaddr *)sdl;
179: sdl->sdl_len = masklen;
180: while (namelen != 0)
181: sdl->sdl_data[--namelen] = 0xff;
182: ifp->if_snd.ifq_maxlen = ifqmaxlen;
183: }
184: }
185: /*
186: * Locate an interface based on a complete address.
187: */
188: /*ARGSUSED*/
189: struct ifaddr *
190: ifa_ifwithaddr(addr)
191: register struct sockaddr *addr;
192: {
193: register struct ifnet *ifp;
194: register struct ifaddr *ifa;
195:
196: #define equal(a1, a2) \
197: (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
198: for (ifp = ifnet; ifp; ifp = ifp->if_next)
199: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
200: if (ifa->ifa_addr->sa_family != addr->sa_family)
201: continue;
202: if (equal(addr, ifa->ifa_addr))
203: return (ifa);
204: if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
205: equal(ifa->ifa_broadaddr, addr))
206: return (ifa);
207: }
208: return ((struct ifaddr *)0);
209: }
210: /*
211: * Locate the point to point interface with a given destination address.
212: */
213: /*ARGSUSED*/
214: struct ifaddr *
215: ifa_ifwithdstaddr(addr)
216: register struct sockaddr *addr;
217: {
218: register struct ifnet *ifp;
219: register struct ifaddr *ifa;
220:
221: for (ifp = ifnet; ifp; ifp = ifp->if_next)
222: if (ifp->if_flags & IFF_POINTOPOINT)
223: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
224: if (ifa->ifa_addr->sa_family != addr->sa_family ||
225: ifa->ifa_dstaddr == NULL)
226: continue;
227: if (equal(addr, ifa->ifa_dstaddr))
228: return (ifa);
229: }
230: return ((struct ifaddr *)0);
231: }
232:
233: /*
234: * Find an interface on a specific network. If many, choice
235: * is most specific found.
236: */
237: struct ifaddr *
238: ifa_ifwithnet(addr)
239: struct sockaddr *addr;
240: {
241: register struct ifnet *ifp;
242: register struct ifaddr *ifa;
243: struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
244: u_int af = addr->sa_family;
245: char *addr_data = addr->sa_data, *cplim;
246: extern int rn_refines(void *, void *);
247:
248: if (af == AF_LINK) {
249: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
250: if (sdl->sdl_index && sdl->sdl_index <= if_index)
251: return (ifnet_addrs[sdl->sdl_index - 1]);
252: }
253: for (ifp = ifnet; ifp; ifp = ifp->if_next)
254: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
255: register char *cp, *cp2, *cp3;
256:
257: if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
258: next: continue;
259: cp = addr_data;
260: cp2 = ifa->ifa_addr->sa_data;
261: cp3 = ifa->ifa_netmask->sa_data;
262: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
263: while (cp3 < cplim)
264: if ((*cp++ ^ *cp2++) & *cp3++)
265: goto next;
266: if (ifa_maybe == 0 ||
267: rn_refines((caddr_t)ifa->ifa_netmask,
268: (caddr_t)ifa_maybe->ifa_netmask))
269: ifa_maybe = ifa;
270: }
271: return (ifa_maybe);
272: }
273:
274: /*
275: * Find an interface using a specific address family
276: */
277: struct ifaddr *
278: ifa_ifwithaf(af)
279: register int af;
280: {
281: register struct ifnet *ifp;
282: register struct ifaddr *ifa;
283:
284: for (ifp = ifnet; ifp; ifp = ifp->if_next)
285: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
286: if (ifa->ifa_addr->sa_family == af)
287: return (ifa);
288: return ((struct ifaddr *)0);
289: }
290:
291: /*
292: * Find an interface address specific to an interface best matching
293: * a given address.
294: */
295: struct ifaddr *
296: ifaof_ifpforaddr(addr, ifp)
297: struct sockaddr *addr;
298: register struct ifnet *ifp;
299: {
300: register struct ifaddr *ifa;
301: register char *cp, *cp2, *cp3;
302: register char *cplim;
303: struct ifaddr *ifa_maybe = 0;
304: u_int af = addr->sa_family;
305:
306: if (af >= AF_MAX)
307: return (0);
308: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
309: if (ifa->ifa_addr->sa_family != af)
310: continue;
311: ifa_maybe = ifa;
312: if (ifa->ifa_netmask == 0) {
313: if (equal(addr, ifa->ifa_addr) ||
314: (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
315: return (ifa);
316: continue;
317: }
318: cp = addr->sa_data;
319: cp2 = ifa->ifa_addr->sa_data;
320: cp3 = ifa->ifa_netmask->sa_data;
321: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
322: for (; cp3 < cplim; cp3++)
323: if ((*cp++ ^ *cp2++) & *cp3)
324: break;
325: if (cp3 == cplim)
326: return (ifa);
327: }
328: return (ifa_maybe);
329: }
330:
331: #include <net/route.h>
332:
333: /*
334: * Default action when installing a route with a Link Level gateway.
335: * Lookup an appropriate real ifa to point to.
336: * This should be moved to /sys/net/link.c eventually.
337: */
338: void
339: link_rtrequest(cmd, rt, sa)
340: int cmd;
341: register struct rtentry *rt;
342: struct sockaddr *sa;
343: {
344: register struct ifaddr *ifa;
345: struct sockaddr *dst;
346: struct ifnet *ifp;
347:
348: if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
349: ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
350: return;
351: if ((ifa = ifaof_ifpforaddr(dst, ifp))) {
352: IFAFREE(rt->rt_ifa);
353: rt->rt_ifa = ifa;
1.1.1.2 ! root 354: if (++ifa->ifa_refcnt <= 0)
! 355: panic("link_rtrequest ifa_refcnt");
1.1 root 356: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
357: ifa->ifa_rtrequest(cmd, rt, sa);
358: }
359: }
360:
361: /*
362: * Mark an interface down and notify protocols of
363: * the transition.
364: * NOTE: must be called at splnet or eqivalent.
365: */
366: void
367: if_down(ifp)
368: register struct ifnet *ifp;
369: {
370: register struct ifaddr *ifa;
371: extern void pfctlinput(int, struct sockaddr *);
372:
373: ifp->if_flags &= ~IFF_UP;
374: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
375: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
376: if_qflush(&ifp->if_snd);
377: rt_ifmsg(ifp);
378: }
379:
380: /*
381: * Mark an interface up and notify protocols of
382: * the transition.
383: * NOTE: must be called at splnet or equivalent.
384: */
385: void
386: if_up(ifp)
387: register struct ifnet *ifp;
388: {
389: #ifdef notyet
390: register struct ifaddr *ifa;
391: #endif
392:
393: ifp->if_flags |= IFF_UP;
394: #ifdef notyet
395: /* this has no effect on IP, and will kill all ISO connections XXX */
396: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
397: pfctlinput(PRC_IFUP, ifa->ifa_addr);
398: #endif
399: rt_ifmsg(ifp);
400: }
401:
402: /*
403: * Flush an interface queue.
404: */
405: void
406: if_qflush(ifq)
407: register struct ifqueue *ifq;
408: {
409: register struct mbuf *m, *n;
410:
411: n = ifq->ifq_head;
412: while ((m = n)) {
413: n = m->m_act;
414: m_freem(m);
415: }
416: ifq->ifq_head = 0;
417: ifq->ifq_tail = 0;
418: ifq->ifq_len = 0;
419: }
420:
421: /*
422: * Handle interface watchdog timer routines. Called
423: * from softclock, we decrement timers (if set) and
424: * call the appropriate interface routine on expiration.
425: */
426: void
427: if_slowtimo(arg)
428: void *arg;
429: {
430: register struct ifnet *ifp;
431: int s = splimp();
432:
433: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
434: if (ifp->if_timer == 0 || --ifp->if_timer)
435: continue;
436: if (ifp->if_watchdog)
437: (*ifp->if_watchdog)(ifp->if_unit);
438: }
439: splx(s);
440: timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
441: }
442:
443: /*
444: * Map interface name to
445: * interface structure pointer.
446: */
447: struct ifnet *
448: ifunit(name)
449: register char *name;
450: {
451: register char *cp;
452: register struct ifnet *ifp;
453: int unit;
454: unsigned len;
455: char *ep, c;
456:
457: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
458: if (*cp >= '0' && *cp <= '9')
459: break;
460: if (*cp == '\0' || cp == name + IFNAMSIZ)
461: return ((struct ifnet *)0);
462: /*
463: * Save first char of unit, and pointer to it,
464: * so we can put a null there to avoid matching
465: * initial substrings of interface names.
466: */
467: len = cp - name + 1;
468: c = *cp;
469: ep = cp;
470: for (unit = 0; *cp >= '0' && *cp <= '9'; )
471: unit = unit * 10 + *cp++ - '0';
472: *ep = 0;
473: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
474: if (bcmp(ifp->if_name, name, len))
475: continue;
476: if (unit == ifp->if_unit)
477: break;
478: }
479: *ep = c;
480: return (ifp);
481: }
482:
483: /*
484: * Interface ioctls.
485: */
486: int
487: ifioctl(so, cmd, data, p)
488: struct socket *so;
489: u_long cmd;
490: caddr_t data;
491: struct proc *p;
492: {
493: register struct ifnet *ifp;
494: register struct ifreq *ifr;
495: int error;
496: #if defined(ppc)
497: extern int new_splitter(struct socket *);
498: void if_register(struct BlueFilter *);
499: #endif /* ppc */
500:
501: switch (cmd) {
502:
503: case SIOCGIFCONF:
504: case OSIOCGIFCONF:
505: return (ifconf(cmd, data));
506: }
507: ifr = (struct ifreq *)data;
508: ifp = ifunit(ifr->ifr_name);
509: if (ifp == 0)
510: return (ENXIO);
511: switch (cmd) {
512:
513: #if defined(ppc)
514: case SIOCSSPLITTER:
515: if ((error = new_splitter(so)))
516: return(error);
517: break;
518:
519: case SIOCGSPLITTER:
520: ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER);
521: break;
522: #endif /* ppc */
523:
524: case SIOCGIFFLAGS:
525: ifr->ifr_flags = ifp->if_flags;
526: break;
527:
528: case SIOCGIFMETRIC:
529: ifr->ifr_metric = ifp->if_metric;
530: break;
531:
532: case SIOCSIFFLAGS:
533: if ((error = suser(p->p_ucred, &p->p_acflag)))
534: return (error);
535:
536: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
537: int s = splimp();
538: if_down(ifp);
539: splx(s);
540: }
541:
542: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
543: int s = splimp();
544: if_up(ifp);
545: splx(s);
546: }
547:
548: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
549: (ifr->ifr_flags &~ IFF_CANTCHANGE);
550: if (ifp->if_ioctl)
551: (void) (*ifp->if_ioctl)(ifp, cmd, data);
552: break;
553:
554: case SIOCSIFMETRIC:
555: if ((error = suser(p->p_ucred, &p->p_acflag)))
556: return (error);
557: ifp->if_metric = ifr->ifr_metric;
558: break;
559:
560: case SIOCAUTOADDR:
561: case SIOCADDMULTI:
562: case SIOCDELMULTI:
563: if ((error = suser(p->p_ucred, &p->p_acflag)))
564: return (error);
565: if (ifp->if_ioctl == NULL)
566: return (EOPNOTSUPP);
567: return ((*ifp->if_ioctl)(ifp, cmd, data));
568:
569: default:
570: if (so->so_proto == 0)
571: return (EOPNOTSUPP);
572: #if !COMPAT_43
573: return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
574: cmd, data, ifp));
575: #else
576: {
577: int ocmd = cmd;
578:
579: switch (cmd) {
580:
581: case SIOCSIFDSTADDR:
582: case SIOCSIFADDR:
583: case SIOCSIFBRDADDR:
584: case SIOCSIFNETMASK:
585: #if BYTE_ORDER != BIG_ENDIAN
586: if (ifr->ifr_addr.sa_family == 0 &&
587: ifr->ifr_addr.sa_len < 16) {
588: ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
589: ifr->ifr_addr.sa_len = 16;
590: }
591: #else
592: if (ifr->ifr_addr.sa_len == 0)
593: ifr->ifr_addr.sa_len = 16;
594: #endif
595: #if defined(ppc)
596: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr
597: if (ifr->ifr_addr.sa_family == AF_INET)
598: { /*
599: * If we have an address, and we're 'splitting',
600: * register the address. Note that this
601: * is to handle the case of addresses
602: * registered after the Blue Box starts.
603: */
604: if ((ifp->if_flags & IFF_SPLITTER) &&
605: (IFR2IN(ifr) != 0))
606: { struct BlueFilter filter;
607:
608: filter.BF_flags = (BF_ALLOC|BF_IP);
609: filter.BF_address = IFR2IN(ifr);
610: log(LOG_WARNING,
611: "[2]IP registering %x",
612: filter.BF_address);
613: if_register(&filter);
614: }
615: }
616: #endif
617: /* Fall through! */
618: break;
619:
620: case OSIOCGIFADDR:
621: cmd = SIOCGIFADDR;
622: break;
623:
624: case OSIOCGIFDSTADDR:
625: cmd = SIOCGIFDSTADDR;
626: break;
627:
628: case OSIOCGIFBRDADDR:
629: cmd = SIOCGIFBRDADDR;
630: break;
631:
632: case OSIOCGIFNETMASK:
633: cmd = SIOCGIFNETMASK;
634: }
635: error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
636: cmd, data, ifp));
637: switch (ocmd) {
638:
639: case OSIOCGIFADDR:
640: case OSIOCGIFDSTADDR:
641: case OSIOCGIFBRDADDR:
642: case OSIOCGIFNETMASK:
643: *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
644: }
645: return (error);
646:
647: }
648: #endif
649: }
650: return (0);
651: }
652:
653: /*
654: * Return interface configuration
655: * of system. List may be used
656: * in later ioctl's (above) to get
657: * other information.
658: */
659: /*ARGSUSED*/
660: int
661: ifconf(cmd, data)
662: u_long cmd;
663: caddr_t data;
664: {
665: register struct ifconf *ifc = (struct ifconf *)data;
666: register struct ifnet *ifp = ifnet;
667: register struct ifaddr *ifa;
668: register char *cp, *ep;
669: struct ifreq ifr, *ifrp;
670: int space = ifc->ifc_len, error = 0;
671:
672: ifrp = ifc->ifc_req;
673: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
674: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
675: strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2);
676: for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
677: continue;
678: *cp++ = '0' + ifp->if_unit; *cp = '\0';
679: if ((ifa = ifp->if_addrlist) == 0) {
680: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
681: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
682: sizeof(ifr));
683: if (error)
684: break;
685: space -= sizeof (ifr), ifrp++;
686: } else
687: for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
688: register struct sockaddr *sa = ifa->ifa_addr;
689: #if COMPAT_43
690: #define OLD_AF_MAX 17
691: if (cmd == OSIOCGIFCONF) {
692: /* We don't want to return any unknown interfaces */
693: if (sa->sa_family < OLD_AF_MAX) {
694: struct osockaddr *osa =
695: (struct osockaddr *)&ifr.ifr_addr;
696: ifr.ifr_addr = *sa;
697: osa->sa_family = sa->sa_family;
698: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
699: sizeof (ifr));
700: }
701: ifrp++;
702: } else
703: #endif
704: if (sa->sa_len <= sizeof(*sa)) {
705: ifr.ifr_addr = *sa;
706: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
707: sizeof (ifr));
708: ifrp++;
709: } else {
710: space -= sa->sa_len - sizeof(*sa);
711: if (space < sizeof (ifr))
712: break;
713: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
714: sizeof (ifr.ifr_name));
715: if (error == 0)
716: error = copyout((caddr_t)sa,
717: (caddr_t)&ifrp->ifr_addr, sa->sa_len);
718: ifrp = (struct ifreq *)
719: (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
720: }
721: if (error)
722: break;
723: space -= sizeof (ifr);
724: }
725: }
726: ifc->ifc_len -= space;
727: return (error);
728: }
729:
730: static char *
731: sprint_d(n, buf, buflen)
732: u_int n;
733: char *buf;
734: int buflen;
735: {
736: register char *cp = buf + buflen - 1;
737:
738: *cp = 0;
739: do {
740: cp--;
741: *cp = "0123456789"[n % 10];
742: n /= 10;
743: } while (n != 0);
744: return (cp);
745: }
746:
747: /*
748: * Shutdown all network activity. Used boot() when halting
749: * system.
750: */
751: int if_down_all(void)
752: {
753: struct ifnet *ifp;
754: int s;
755:
756: s = splnet();
757: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
758: if_down(ifp);
759: }
760: splx(s);
761: return(0); /* Sheesh */
762: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.