|
|
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.