|
|
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;
354: ifa->ifa_refcnt++;
355: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
356: ifa->ifa_rtrequest(cmd, rt, sa);
357: }
358: }
359:
360: /*
361: * Mark an interface down and notify protocols of
362: * the transition.
363: * NOTE: must be called at splnet or eqivalent.
364: */
365: void
366: if_down(ifp)
367: register struct ifnet *ifp;
368: {
369: register struct ifaddr *ifa;
370: extern void pfctlinput(int, struct sockaddr *);
371:
372: ifp->if_flags &= ~IFF_UP;
373: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
374: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
375: if_qflush(&ifp->if_snd);
376: rt_ifmsg(ifp);
377: }
378:
379: /*
380: * Mark an interface up and notify protocols of
381: * the transition.
382: * NOTE: must be called at splnet or equivalent.
383: */
384: void
385: if_up(ifp)
386: register struct ifnet *ifp;
387: {
388: #ifdef notyet
389: register struct ifaddr *ifa;
390: #endif
391:
392: ifp->if_flags |= IFF_UP;
393: #ifdef notyet
394: /* this has no effect on IP, and will kill all ISO connections XXX */
395: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
396: pfctlinput(PRC_IFUP, ifa->ifa_addr);
397: #endif
398: rt_ifmsg(ifp);
399: }
400:
401: /*
402: * Flush an interface queue.
403: */
404: void
405: if_qflush(ifq)
406: register struct ifqueue *ifq;
407: {
408: register struct mbuf *m, *n;
409:
410: n = ifq->ifq_head;
411: while ((m = n)) {
412: n = m->m_act;
413: m_freem(m);
414: }
415: ifq->ifq_head = 0;
416: ifq->ifq_tail = 0;
417: ifq->ifq_len = 0;
418: }
419:
420: /*
421: * Handle interface watchdog timer routines. Called
422: * from softclock, we decrement timers (if set) and
423: * call the appropriate interface routine on expiration.
424: */
425: void
426: if_slowtimo(arg)
427: void *arg;
428: {
429: register struct ifnet *ifp;
430: int s = splimp();
431:
432: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
433: if (ifp->if_timer == 0 || --ifp->if_timer)
434: continue;
435: if (ifp->if_watchdog)
436: (*ifp->if_watchdog)(ifp->if_unit);
437: }
438: splx(s);
439: timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
440: }
441:
442: /*
443: * Map interface name to
444: * interface structure pointer.
445: */
446: struct ifnet *
447: ifunit(name)
448: register char *name;
449: {
450: register char *cp;
451: register struct ifnet *ifp;
452: int unit;
453: unsigned len;
454: char *ep, c;
455:
456: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
457: if (*cp >= '0' && *cp <= '9')
458: break;
459: if (*cp == '\0' || cp == name + IFNAMSIZ)
460: return ((struct ifnet *)0);
461: /*
462: * Save first char of unit, and pointer to it,
463: * so we can put a null there to avoid matching
464: * initial substrings of interface names.
465: */
466: len = cp - name + 1;
467: c = *cp;
468: ep = cp;
469: for (unit = 0; *cp >= '0' && *cp <= '9'; )
470: unit = unit * 10 + *cp++ - '0';
471: *ep = 0;
472: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
473: if (bcmp(ifp->if_name, name, len))
474: continue;
475: if (unit == ifp->if_unit)
476: break;
477: }
478: *ep = c;
479: return (ifp);
480: }
481:
482: /*
483: * Interface ioctls.
484: */
485: int
486: ifioctl(so, cmd, data, p)
487: struct socket *so;
488: u_long cmd;
489: caddr_t data;
490: struct proc *p;
491: {
492: register struct ifnet *ifp;
493: register struct ifreq *ifr;
494: int error;
495: #if defined(ppc)
496: extern int new_splitter(struct socket *);
497: void if_register(struct BlueFilter *);
498: #endif /* ppc */
499:
500: switch (cmd) {
501:
502: case SIOCGIFCONF:
503: case OSIOCGIFCONF:
504: return (ifconf(cmd, data));
505: }
506: ifr = (struct ifreq *)data;
507: ifp = ifunit(ifr->ifr_name);
508: if (ifp == 0)
509: return (ENXIO);
510: switch (cmd) {
511:
512: #if defined(ppc)
513: case SIOCSSPLITTER:
514: if ((error = new_splitter(so)))
515: return(error);
516: break;
517:
518: case SIOCGSPLITTER:
519: ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER);
520: break;
521: #endif /* ppc */
522:
523: case SIOCGIFFLAGS:
524: ifr->ifr_flags = ifp->if_flags;
525: break;
526:
527: case SIOCGIFMETRIC:
528: ifr->ifr_metric = ifp->if_metric;
529: break;
530:
531: case SIOCSIFFLAGS:
532: if ((error = suser(p->p_ucred, &p->p_acflag)))
533: return (error);
534:
535: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
536: int s = splimp();
537: if_down(ifp);
538: splx(s);
539: }
540:
541: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
542: int s = splimp();
543: if_up(ifp);
544: splx(s);
545: }
546:
547: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
548: (ifr->ifr_flags &~ IFF_CANTCHANGE);
549: if (ifp->if_ioctl)
550: (void) (*ifp->if_ioctl)(ifp, cmd, data);
551: break;
552:
553: case SIOCSIFMETRIC:
554: if ((error = suser(p->p_ucred, &p->p_acflag)))
555: return (error);
556: ifp->if_metric = ifr->ifr_metric;
557: break;
558:
559: case SIOCAUTOADDR:
560: case SIOCADDMULTI:
561: case SIOCDELMULTI:
562: if ((error = suser(p->p_ucred, &p->p_acflag)))
563: return (error);
564: if (ifp->if_ioctl == NULL)
565: return (EOPNOTSUPP);
566: return ((*ifp->if_ioctl)(ifp, cmd, data));
567:
568: default:
569: if (so->so_proto == 0)
570: return (EOPNOTSUPP);
571: #if !COMPAT_43
572: return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
573: cmd, data, ifp));
574: #else
575: {
576: int ocmd = cmd;
577:
578: switch (cmd) {
579:
580: case SIOCSIFDSTADDR:
581: case SIOCSIFADDR:
582: case SIOCSIFBRDADDR:
583: case SIOCSIFNETMASK:
584: #if BYTE_ORDER != BIG_ENDIAN
585: if (ifr->ifr_addr.sa_family == 0 &&
586: ifr->ifr_addr.sa_len < 16) {
587: ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
588: ifr->ifr_addr.sa_len = 16;
589: }
590: #else
591: if (ifr->ifr_addr.sa_len == 0)
592: ifr->ifr_addr.sa_len = 16;
593: #endif
594: #if defined(ppc)
595: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr
596: if (ifr->ifr_addr.sa_family == AF_INET)
597: { /*
598: * If we have an address, and we're 'splitting',
599: * register the address. Note that this
600: * is to handle the case of addresses
601: * registered after the Blue Box starts.
602: */
603: if ((ifp->if_flags & IFF_SPLITTER) &&
604: (IFR2IN(ifr) != 0))
605: { struct BlueFilter filter;
606:
607: filter.BF_flags = (BF_ALLOC|BF_IP);
608: filter.BF_address = IFR2IN(ifr);
609: log(LOG_WARNING,
610: "[2]IP registering %x",
611: filter.BF_address);
612: if_register(&filter);
613: }
614: }
615: #endif
616: /* Fall through! */
617: break;
618:
619: case OSIOCGIFADDR:
620: cmd = SIOCGIFADDR;
621: break;
622:
623: case OSIOCGIFDSTADDR:
624: cmd = SIOCGIFDSTADDR;
625: break;
626:
627: case OSIOCGIFBRDADDR:
628: cmd = SIOCGIFBRDADDR;
629: break;
630:
631: case OSIOCGIFNETMASK:
632: cmd = SIOCGIFNETMASK;
633: }
634: error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
635: cmd, data, ifp));
636: switch (ocmd) {
637:
638: case OSIOCGIFADDR:
639: case OSIOCGIFDSTADDR:
640: case OSIOCGIFBRDADDR:
641: case OSIOCGIFNETMASK:
642: *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
643: }
644: return (error);
645:
646: }
647: #endif
648: }
649: return (0);
650: }
651:
652: /*
653: * Return interface configuration
654: * of system. List may be used
655: * in later ioctl's (above) to get
656: * other information.
657: */
658: /*ARGSUSED*/
659: int
660: ifconf(cmd, data)
661: u_long cmd;
662: caddr_t data;
663: {
664: register struct ifconf *ifc = (struct ifconf *)data;
665: register struct ifnet *ifp = ifnet;
666: register struct ifaddr *ifa;
667: register char *cp, *ep;
668: struct ifreq ifr, *ifrp;
669: int space = ifc->ifc_len, error = 0;
670:
671: ifrp = ifc->ifc_req;
672: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
673: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
674: strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2);
675: for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
676: continue;
677: *cp++ = '0' + ifp->if_unit; *cp = '\0';
678: if ((ifa = ifp->if_addrlist) == 0) {
679: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
680: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
681: sizeof(ifr));
682: if (error)
683: break;
684: space -= sizeof (ifr), ifrp++;
685: } else
686: for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
687: register struct sockaddr *sa = ifa->ifa_addr;
688: #if COMPAT_43
689: #define OLD_AF_MAX 17
690: if (cmd == OSIOCGIFCONF) {
691: /* We don't want to return any unknown interfaces */
692: if (sa->sa_family < OLD_AF_MAX) {
693: struct osockaddr *osa =
694: (struct osockaddr *)&ifr.ifr_addr;
695: ifr.ifr_addr = *sa;
696: osa->sa_family = sa->sa_family;
697: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
698: sizeof (ifr));
699: }
700: ifrp++;
701: } else
702: #endif
703: if (sa->sa_len <= sizeof(*sa)) {
704: ifr.ifr_addr = *sa;
705: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
706: sizeof (ifr));
707: ifrp++;
708: } else {
709: space -= sa->sa_len - sizeof(*sa);
710: if (space < sizeof (ifr))
711: break;
712: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
713: sizeof (ifr.ifr_name));
714: if (error == 0)
715: error = copyout((caddr_t)sa,
716: (caddr_t)&ifrp->ifr_addr, sa->sa_len);
717: ifrp = (struct ifreq *)
718: (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
719: }
720: if (error)
721: break;
722: space -= sizeof (ifr);
723: }
724: }
725: ifc->ifc_len -= space;
726: return (error);
727: }
728:
729: static char *
730: sprint_d(n, buf, buflen)
731: u_int n;
732: char *buf;
733: int buflen;
734: {
735: register char *cp = buf + buflen - 1;
736:
737: *cp = 0;
738: do {
739: cp--;
740: *cp = "0123456789"[n % 10];
741: n /= 10;
742: } while (n != 0);
743: return (cp);
744: }
745:
746: /*
747: * Shutdown all network activity. Used boot() when halting
748: * system.
749: */
750: int if_down_all(void)
751: {
752: struct ifnet *ifp;
753: int s;
754:
755: s = splnet();
756: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
757: if_down(ifp);
758: }
759: splx(s);
760: return(0); /* Sheesh */
761: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.