|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1980, 1986, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)if.c 8.3 (Berkeley) 1/4/94 ! 55: */ ! 56: ! 57: /* ! 58: #include "opt_compat.h" ! 59: */ ! 60: ! 61: #include <sys/param.h> ! 62: #include <sys/malloc.h> ! 63: #include <sys/mbuf.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/proc.h> ! 66: #include <sys/socket.h> ! 67: #include <sys/socketvar.h> ! 68: #include <sys/protosw.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/sockio.h> ! 71: #include <sys/syslog.h> ! 72: #include <sys/sysctl.h> ! 73: #include <net/if.h> ! 74: #include <net/if_dl.h> ! 75: #include <net/radix.h> ! 76: #include <net/if_blue.h> ! 77: #include <netinet/in.h> ! 78: #include <net/dlil.h> ! 79: ! 80: /* ! 81: * System initialization ! 82: */ ! 83: ! 84: static int ifconf __P((u_long, caddr_t)); ! 85: static void if_qflush __P((struct ifqueue *)); ! 86: static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); ! 87: ! 88: MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); ! 89: MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); ! 90: ! 91: int ifqmaxlen = IFQ_MAXLEN; ! 92: struct ifnethead ifnet; /* depend on static init XXX */ ! 93: ! 94: /* ! 95: * Network interface utility routines. ! 96: * ! 97: * Routines with ifa_ifwith* names take sockaddr *'s as ! 98: * parameters. ! 99: * ! 100: * This routine assumes that it will be called at splimp() or higher. ! 101: */ ! 102: /* ARGSUSED*/ ! 103: ! 104: ! 105: int if_index = 0; ! 106: struct ifaddr **ifnet_addrs; ! 107: ! 108: ! 109: /* ! 110: * Attach an interface to the ! 111: * list of "active" interfaces. ! 112: */ ! 113: void ! 114: old_if_attach(ifp) ! 115: struct ifnet *ifp; ! 116: { ! 117: unsigned socksize, ifasize; ! 118: int namelen, masklen; ! 119: char workbuf[64]; ! 120: register struct sockaddr_dl *sdl; ! 121: register struct ifaddr *ifa; ! 122: static int if_indexlim = 8; ! 123: ! 124: ! 125: if (ifp->if_snd.ifq_maxlen == 0) ! 126: ifp->if_snd.ifq_maxlen = ifqmaxlen; ! 127: ! 128: TAILQ_INSERT_TAIL(&ifnet, ifp, if_link); ! 129: ifp->if_index = ++if_index; ! 130: /* ! 131: * XXX - ! 132: * The old code would work if the interface passed a pre-existing ! 133: * chain of ifaddrs to this code. We don't trust our callers to ! 134: * properly initialize the tailq, however, so we no longer allow ! 135: * this unlikely case. ! 136: */ ! 137: TAILQ_INIT(&ifp->if_addrhead); ! 138: LIST_INIT(&ifp->if_multiaddrs); ! 139: getmicrotime(&ifp->if_lastchange); ! 140: if (ifnet_addrs == 0 || if_index >= if_indexlim) { ! 141: unsigned n = (if_indexlim <<= 1) * sizeof(ifa); ! 142: struct ifaddr **q = (struct ifaddr **) ! 143: _MALLOC(n, M_IFADDR, M_WAITOK); ! 144: bzero((caddr_t)q, n); ! 145: if (ifnet_addrs) { ! 146: bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); ! 147: FREE((caddr_t)ifnet_addrs, M_IFADDR); ! 148: } ! 149: ifnet_addrs = q; ! 150: } ! 151: /* ! 152: * create a Link Level name for this device ! 153: */ ! 154: namelen = snprintf(workbuf, sizeof(workbuf), ! 155: "%s%d", ifp->if_name, ifp->if_unit); ! 156: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) ! 157: masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; ! 158: socksize = masklen + ifp->if_addrlen; ! 159: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) ! 160: if (socksize < sizeof(*sdl)) ! 161: socksize = sizeof(*sdl); ! 162: socksize = ROUNDUP(socksize); ! 163: ifasize = sizeof(*ifa) + 2 * socksize; ! 164: ifa = (struct ifaddr *) _MALLOC(ifasize, M_IFADDR, M_WAITOK); ! 165: if (ifa) { ! 166: bzero((caddr_t)ifa, ifasize); ! 167: sdl = (struct sockaddr_dl *)(ifa + 1); ! 168: sdl->sdl_len = socksize; ! 169: sdl->sdl_family = AF_LINK; ! 170: bcopy(workbuf, sdl->sdl_data, namelen); ! 171: sdl->sdl_nlen = namelen; ! 172: sdl->sdl_index = ifp->if_index; ! 173: sdl->sdl_type = ifp->if_type; ! 174: ifnet_addrs[if_index - 1] = ifa; ! 175: ifa->ifa_ifp = ifp; ! 176: ifa->ifa_rtrequest = link_rtrequest; ! 177: ifa->ifa_addr = (struct sockaddr *)sdl; ! 178: sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); ! 179: ifa->ifa_netmask = (struct sockaddr *)sdl; ! 180: sdl->sdl_len = masklen; ! 181: while (namelen != 0) ! 182: sdl->sdl_data[--namelen] = 0xff; ! 183: TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); ! 184: } ! 185: } ! 186: /* ! 187: * Locate an interface based on a complete address. ! 188: */ ! 189: /*ARGSUSED*/ ! 190: struct ifaddr * ! 191: ifa_ifwithaddr(addr) ! 192: register struct sockaddr *addr; ! 193: { ! 194: register struct ifnet *ifp; ! 195: register struct ifaddr *ifa; ! 196: ! 197: #define equal(a1, a2) \ ! 198: (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) ! 199: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) ! 200: for (ifa = ifp->if_addrhead.tqh_first; ifa; ! 201: ifa = ifa->ifa_link.tqe_next) { ! 202: if (ifa->ifa_addr->sa_family != addr->sa_family) ! 203: continue; ! 204: if (equal(addr, ifa->ifa_addr)) ! 205: return (ifa); ! 206: if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ! 207: equal(ifa->ifa_broadaddr, addr)) ! 208: return (ifa); ! 209: } ! 210: return ((struct ifaddr *)0); ! 211: } ! 212: /* ! 213: * Locate the point to point interface with a given destination address. ! 214: */ ! 215: /*ARGSUSED*/ ! 216: struct ifaddr * ! 217: ifa_ifwithdstaddr(addr) ! 218: register struct sockaddr *addr; ! 219: { ! 220: register struct ifnet *ifp; ! 221: register struct ifaddr *ifa; ! 222: ! 223: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) ! 224: if (ifp->if_flags & IFF_POINTOPOINT) ! 225: for (ifa = ifp->if_addrhead.tqh_first; ifa; ! 226: ifa = ifa->ifa_link.tqe_next) { ! 227: if (ifa->ifa_addr->sa_family != addr->sa_family) ! 228: continue; ! 229: if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) ! 230: return (ifa); ! 231: } ! 232: return ((struct ifaddr *)0); ! 233: } ! 234: ! 235: /* ! 236: * Find an interface on a specific network. If many, choice ! 237: * is most specific found. ! 238: */ ! 239: struct ifaddr * ! 240: ifa_ifwithnet(addr) ! 241: struct sockaddr *addr; ! 242: { ! 243: register struct ifnet *ifp; ! 244: register struct ifaddr *ifa; ! 245: struct ifaddr *ifa_maybe = (struct ifaddr *) 0; ! 246: u_int af = addr->sa_family; ! 247: char *addr_data = addr->sa_data, *cplim; ! 248: ! 249: /* ! 250: * AF_LINK addresses can be looked up directly by their index number, ! 251: * so do that if we can. ! 252: */ ! 253: if (af == AF_LINK) { ! 254: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; ! 255: if (sdl->sdl_index && sdl->sdl_index <= if_index) ! 256: return (ifnet_addrs[sdl->sdl_index - 1]); ! 257: } ! 258: ! 259: /* ! 260: * Scan though each interface, looking for ones that have ! 261: * addresses in this address family. ! 262: */ ! 263: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { ! 264: for (ifa = ifp->if_addrhead.tqh_first; ifa; ! 265: ifa = ifa->ifa_link.tqe_next) { ! 266: register char *cp, *cp2, *cp3; ! 267: ! 268: if (ifa->ifa_addr->sa_family != af) ! 269: next: continue; ! 270: if (ifp->if_flags & IFF_POINTOPOINT) { ! 271: /* ! 272: * This is a bit broken as it doesn't ! 273: * take into account that the remote end may ! 274: * be a single node in the network we are ! 275: * looking for. ! 276: * The trouble is that we don't know the ! 277: * netmask for the remote end. ! 278: */ ! 279: if (ifa->ifa_dstaddr != 0 ! 280: && equal(addr, ifa->ifa_dstaddr)) ! 281: return (ifa); ! 282: } else { ! 283: /* ! 284: * if we have a special address handler, ! 285: * then use it instead of the generic one. ! 286: */ ! 287: if (ifa->ifa_claim_addr) { ! 288: if ((*ifa->ifa_claim_addr)(ifa, addr)) { ! 289: return (ifa); ! 290: } else { ! 291: continue; ! 292: } ! 293: } ! 294: ! 295: /* ! 296: * Scan all the bits in the ifa's address. ! 297: * If a bit dissagrees with what we are ! 298: * looking for, mask it with the netmask ! 299: * to see if it really matters. ! 300: * (A byte at a time) ! 301: */ ! 302: if (ifa->ifa_netmask == 0) ! 303: continue; ! 304: cp = addr_data; ! 305: cp2 = ifa->ifa_addr->sa_data; ! 306: cp3 = ifa->ifa_netmask->sa_data; ! 307: cplim = ifa->ifa_netmask->sa_len ! 308: + (char *)ifa->ifa_netmask; ! 309: while (cp3 < cplim) ! 310: if ((*cp++ ^ *cp2++) & *cp3++) ! 311: goto next; /* next address! */ ! 312: /* ! 313: * If the netmask of what we just found ! 314: * is more specific than what we had before ! 315: * (if we had one) then remember the new one ! 316: * before continuing to search ! 317: * for an even better one. ! 318: */ ! 319: if (ifa_maybe == 0 || ! 320: rn_refines((caddr_t)ifa->ifa_netmask, ! 321: (caddr_t)ifa_maybe->ifa_netmask)) ! 322: ifa_maybe = ifa; ! 323: } ! 324: } ! 325: } ! 326: return (ifa_maybe); ! 327: } ! 328: ! 329: /* ! 330: * Find an interface address specific to an interface best matching ! 331: * a given address. ! 332: */ ! 333: struct ifaddr * ! 334: ifaof_ifpforaddr(addr, ifp) ! 335: struct sockaddr *addr; ! 336: register struct ifnet *ifp; ! 337: { ! 338: register struct ifaddr *ifa; ! 339: register char *cp, *cp2, *cp3; ! 340: register char *cplim; ! 341: struct ifaddr *ifa_maybe = 0; ! 342: u_int af = addr->sa_family; ! 343: ! 344: if (af >= AF_MAX) ! 345: return (0); ! 346: for (ifa = ifp->if_addrhead.tqh_first; ifa; ! 347: ifa = ifa->ifa_link.tqe_next) { ! 348: if (ifa->ifa_addr->sa_family != af) ! 349: continue; ! 350: if (ifa_maybe == 0) ! 351: ifa_maybe = ifa; ! 352: if (ifa->ifa_netmask == 0) { ! 353: if (equal(addr, ifa->ifa_addr) || ! 354: (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) ! 355: return (ifa); ! 356: continue; ! 357: } ! 358: if (ifp->if_flags & IFF_POINTOPOINT) { ! 359: if (equal(addr, ifa->ifa_dstaddr)) ! 360: return (ifa); ! 361: } else { ! 362: cp = addr->sa_data; ! 363: cp2 = ifa->ifa_addr->sa_data; ! 364: cp3 = ifa->ifa_netmask->sa_data; ! 365: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; ! 366: for (; cp3 < cplim; cp3++) ! 367: if ((*cp++ ^ *cp2++) & *cp3) ! 368: break; ! 369: if (cp3 == cplim) ! 370: return (ifa); ! 371: } ! 372: } ! 373: return (ifa_maybe); ! 374: } ! 375: ! 376: #include <net/route.h> ! 377: ! 378: /* ! 379: * Default action when installing a route with a Link Level gateway. ! 380: * Lookup an appropriate real ifa to point to. ! 381: * This should be moved to /sys/net/link.c eventually. ! 382: */ ! 383: static void ! 384: link_rtrequest(cmd, rt, sa) ! 385: int cmd; ! 386: register struct rtentry *rt; ! 387: struct sockaddr *sa; ! 388: { ! 389: register struct ifaddr *ifa; ! 390: struct sockaddr *dst; ! 391: struct ifnet *ifp; ! 392: ! 393: if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || ! 394: ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) ! 395: return; ! 396: ifa = ifaof_ifpforaddr(dst, ifp); ! 397: if (ifa) { ! 398: IFAFREE(rt->rt_ifa); ! 399: rt->rt_ifa = ifa; ! 400: ifa->ifa_refcnt++; ! 401: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ! 402: ifa->ifa_rtrequest(cmd, rt, sa); ! 403: } ! 404: } ! 405: ! 406: /* ! 407: * Mark an interface down and notify protocols of ! 408: * the transition. ! 409: * NOTE: must be called at splnet or eqivalent. ! 410: */ ! 411: void ! 412: if_unroute(ifp, flag, fam) ! 413: register struct ifnet *ifp; ! 414: int flag, fam; ! 415: { ! 416: register struct ifaddr *ifa; ! 417: ! 418: ifp->if_flags &= ~flag; ! 419: getmicrotime(&ifp->if_lastchange); ! 420: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) ! 421: if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) ! 422: pfctlinput(PRC_IFDOWN, ifa->ifa_addr); ! 423: if_qflush(&ifp->if_snd); ! 424: rt_ifmsg(ifp); ! 425: } ! 426: ! 427: /* ! 428: * Mark an interface up and notify protocols of ! 429: * the transition. ! 430: * NOTE: must be called at splnet or eqivalent. ! 431: */ ! 432: void ! 433: if_route(ifp, flag, fam) ! 434: register struct ifnet *ifp; ! 435: int flag, fam; ! 436: { ! 437: register struct ifaddr *ifa; ! 438: ! 439: ifp->if_flags |= flag; ! 440: getmicrotime(&ifp->if_lastchange); ! 441: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) ! 442: if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) ! 443: pfctlinput(PRC_IFUP, ifa->ifa_addr); ! 444: rt_ifmsg(ifp); ! 445: } ! 446: ! 447: /* ! 448: * Mark an interface down and notify protocols of ! 449: * the transition. ! 450: * NOTE: must be called at splnet or eqivalent. ! 451: */ ! 452: void ! 453: if_down(ifp) ! 454: register struct ifnet *ifp; ! 455: { ! 456: ! 457: if_unroute(ifp, IFF_UP, AF_UNSPEC); ! 458: } ! 459: ! 460: /* ! 461: * Mark an interface up and notify protocols of ! 462: * the transition. ! 463: * NOTE: must be called at splnet or eqivalent. ! 464: */ ! 465: void ! 466: if_up(ifp) ! 467: register struct ifnet *ifp; ! 468: { ! 469: ! 470: if_route(ifp, IFF_UP, AF_UNSPEC); ! 471: } ! 472: ! 473: /* ! 474: * Flush an interface queue. ! 475: */ ! 476: static void ! 477: if_qflush(ifq) ! 478: register struct ifqueue *ifq; ! 479: { ! 480: register struct mbuf *m, *n; ! 481: ! 482: n = ifq->ifq_head; ! 483: while ((m = n) != 0) { ! 484: n = m->m_act; ! 485: m_freem(m); ! 486: } ! 487: ifq->ifq_head = 0; ! 488: ifq->ifq_tail = 0; ! 489: ifq->ifq_len = 0; ! 490: } ! 491: ! 492: ! 493: /* ! 494: * Map interface name to ! 495: * interface structure pointer. ! 496: */ ! 497: struct ifnet * ! 498: ifunit(name) ! 499: register char *name; ! 500: { ! 501: char namebuf[IFNAMSIZ + 1]; ! 502: register char *cp, *cp2; ! 503: char *end; ! 504: register struct ifnet *ifp; ! 505: int unit; ! 506: unsigned len; ! 507: register char c = '\0'; ! 508: ! 509: /* ! 510: * Look for a non numeric part ! 511: */ ! 512: end = name + IFNAMSIZ; ! 513: cp2 = namebuf; ! 514: cp = name; ! 515: while ((cp < end) && (c = *cp)) { ! 516: if (c >= '0' && c <= '9') ! 517: break; ! 518: *cp2++ = c; ! 519: cp++; ! 520: } ! 521: if ((cp == end) || (c == '\0') || (cp == name)) ! 522: return ((struct ifnet *)0); ! 523: *cp2 = '\0'; ! 524: /* ! 525: * check we have a legal number (limit to 7 digits?) ! 526: */ ! 527: len = cp - name + 1; ! 528: for (unit = 0; ! 529: ((c = *cp) >= '0') && (c <= '9') && (unit < 1000000); cp++ ) ! 530: unit = (unit * 10) + (c - '0'); ! 531: if (*cp != '\0') ! 532: return 0; /* no trailing garbage allowed */ ! 533: /* ! 534: * Now search all the interfaces for this name/number ! 535: */ ! 536: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { ! 537: if (bcmp(ifp->if_name, namebuf, len)) ! 538: continue; ! 539: if (unit == ifp->if_unit) ! 540: break; ! 541: } ! 542: return (ifp); ! 543: } ! 544: ! 545: /* ! 546: * Interface ioctls. ! 547: */ ! 548: int ! 549: ifioctl(so, cmd, data, p) ! 550: struct socket *so; ! 551: u_long cmd; ! 552: caddr_t data; ! 553: struct proc *p; ! 554: { ! 555: register struct ifnet *ifp; ! 556: register struct ifreq *ifr; ! 557: int error; ! 558: extern int new_splitter(struct socket *); ! 559: void if_register(struct BlueFilter *); ! 560: ! 561: switch (cmd) { ! 562: ! 563: case SIOCGIFCONF: ! 564: case OSIOCGIFCONF: ! 565: return (ifconf(cmd, data)); ! 566: } ! 567: ifr = (struct ifreq *)data; ! 568: ifp = ifunit(ifr->ifr_name); ! 569: if (ifp == 0) ! 570: return (ENXIO); ! 571: switch (cmd) { ! 572: ! 573: case SIOCSSPLITTER: ! 574: if ((error = new_splitter(so))) ! 575: return(error); ! 576: break; ! 577: ! 578: case SIOCGSPLITTER: ! 579: ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER); ! 580: break; ! 581: ! 582: case SIOCGIFFLAGS: ! 583: ifr->ifr_flags = ifp->if_flags; ! 584: break; ! 585: ! 586: case SIOCGIFMETRIC: ! 587: ifr->ifr_metric = ifp->if_metric; ! 588: break; ! 589: ! 590: case SIOCGIFMTU: ! 591: ifr->ifr_mtu = ifp->if_mtu; ! 592: break; ! 593: ! 594: case SIOCGIFPHYS: ! 595: ifr->ifr_phys = ifp->if_physical; ! 596: break; ! 597: ! 598: case SIOCSIFFLAGS: ! 599: error = suser(p->p_ucred, &p->p_acflag); ! 600: if (error) ! 601: return (error); ! 602: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { ! 603: int s = splimp(); ! 604: if_down(ifp); ! 605: splx(s); ! 606: } ! 607: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { ! 608: int s = splimp(); ! 609: if_up(ifp); ! 610: splx(s); ! 611: } ! 612: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | ! 613: (ifr->ifr_flags &~ IFF_CANTCHANGE); ! 614: if (ifp->if_ioctl) ! 615: dlil_ioctl(0, ifp, cmd, (caddr_t) data); ! 616: getmicrotime(&ifp->if_lastchange); ! 617: break; ! 618: ! 619: case SIOCSIFMETRIC: ! 620: error = suser(p->p_ucred, &p->p_acflag); ! 621: if (error) ! 622: return (error); ! 623: ifp->if_metric = ifr->ifr_metric; ! 624: getmicrotime(&ifp->if_lastchange); ! 625: break; ! 626: ! 627: case SIOCSIFPHYS: ! 628: error = suser(p->p_ucred, &p->p_acflag); ! 629: if (error) ! 630: return error; ! 631: if (!ifp->if_ioctl) ! 632: return EOPNOTSUPP; ! 633: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data); ! 634: if (error == 0) ! 635: getmicrotime(&ifp->if_lastchange); ! 636: return(error); ! 637: ! 638: case SIOCSIFMTU: ! 639: error = suser(p->p_ucred, &p->p_acflag); ! 640: if (error) ! 641: return (error); ! 642: if (ifp->if_ioctl == NULL) ! 643: return (EOPNOTSUPP); ! 644: /* ! 645: * 72 was chosen below because it is the size of a TCP/IP ! 646: * header (40) + the minimum mss (32). ! 647: */ ! 648: if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) ! 649: return (EINVAL); ! 650: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data); ! 651: if (error == 0) ! 652: getmicrotime(&ifp->if_lastchange); ! 653: return(error); ! 654: ! 655: case SIOCADDMULTI: ! 656: case SIOCDELMULTI: ! 657: error = suser(p->p_ucred, &p->p_acflag); ! 658: if (error) ! 659: return (error); ! 660: ! 661: /* Don't allow group membership on non-multicast interfaces. */ ! 662: if ((ifp->if_flags & IFF_MULTICAST) == 0) ! 663: return EOPNOTSUPP; ! 664: ! 665: #if 0 ! 666: /* ! 667: * Don't let users change protocols' entries. ! 668: */ ! 669: if (ifr->ifr_addr.sa_family != AF_LINK) ! 670: return EINVAL; ! 671: #endif ! 672: if (cmd == SIOCADDMULTI) { ! 673: struct ifmultiaddr *ifma; ! 674: error = if_addmulti(ifp, &ifr->ifr_addr, &ifma); ! 675: } else { ! 676: error = if_delmulti(ifp, &ifr->ifr_addr); ! 677: } ! 678: if (error == 0) ! 679: getmicrotime(&ifp->if_lastchange); ! 680: return error; ! 681: ! 682: case SIOCSIFMEDIA: ! 683: case SIOCSIFGENERIC: ! 684: error = suser(p->p_ucred, &p->p_acflag); ! 685: if (error) ! 686: return (error); ! 687: if (ifp->if_ioctl == 0) ! 688: return (EOPNOTSUPP); ! 689: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data); ! 690: if (error == 0) ! 691: getmicrotime(&ifp->if_lastchange); ! 692: return error; ! 693: ! 694: case SIOCGIFMEDIA: ! 695: case SIOCGIFGENERIC: ! 696: if (ifp->if_ioctl == 0) ! 697: return (EOPNOTSUPP); ! 698: return dlil_ioctl(0, ifp, cmd, (caddr_t) data); ! 699: ! 700: default: ! 701: if (so->so_proto == 0) ! 702: return (EOPNOTSUPP); ! 703: #if !COMPAT_43 ! 704: return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, ! 705: data, ! 706: ifp, p)); ! 707: #else ! 708: { ! 709: int ocmd = cmd; ! 710: ! 711: switch (cmd) { ! 712: ! 713: case SIOCSIFDSTADDR: ! 714: case SIOCSIFADDR: ! 715: case SIOCSIFBRDADDR: ! 716: case SIOCSIFNETMASK: ! 717: #if BYTE_ORDER != BIG_ENDIAN ! 718: if (ifr->ifr_addr.sa_family == 0 && ! 719: ifr->ifr_addr.sa_len < 16) { ! 720: ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; ! 721: ifr->ifr_addr.sa_len = 16; ! 722: } ! 723: #else ! 724: if (ifr->ifr_addr.sa_len == 0) ! 725: ifr->ifr_addr.sa_len = 16; ! 726: #endif ! 727: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr ! 728: if (ifr->ifr_addr.sa_family == AF_INET) ! 729: { /* ! 730: * If we have an address, and we're 'splitting', ! 731: * register the address. Note that this ! 732: * is to handle the case of addresses ! 733: * registered after the Blue Box starts. ! 734: */ ! 735: if ((ifp->if_flags & IFF_SPLITTER) && ! 736: (IFR2IN(ifr) != 0)) ! 737: { struct BlueFilter filter; ! 738: ! 739: filter.BF_flags = (BF_ALLOC|BF_IP); ! 740: filter.BF_address = IFR2IN(ifr); ! 741: log(LOG_WARNING, ! 742: "[2]IP registering %x", ! 743: filter.BF_address); ! 744: if_register(&filter); ! 745: } ! 746: } ! 747: /* Fall through! */ ! 748: break; ! 749: ! 750: case OSIOCGIFADDR: ! 751: cmd = SIOCGIFADDR; ! 752: break; ! 753: ! 754: case OSIOCGIFDSTADDR: ! 755: cmd = SIOCGIFDSTADDR; ! 756: break; ! 757: ! 758: case OSIOCGIFBRDADDR: ! 759: cmd = SIOCGIFBRDADDR; ! 760: break; ! 761: ! 762: case OSIOCGIFNETMASK: ! 763: cmd = SIOCGIFNETMASK; ! 764: } ! 765: error = ((*so->so_proto->pr_usrreqs->pru_control)(so, ! 766: cmd, ! 767: data, ! 768: ifp, p)); ! 769: switch (ocmd) { ! 770: ! 771: case OSIOCGIFADDR: ! 772: case OSIOCGIFDSTADDR: ! 773: case OSIOCGIFBRDADDR: ! 774: case OSIOCGIFNETMASK: ! 775: *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; ! 776: } ! 777: return (error); ! 778: ! 779: } ! 780: #endif ! 781: } ! 782: return (0); ! 783: } ! 784: ! 785: /* ! 786: * Set/clear promiscuous mode on interface ifp based on the truth value ! 787: * of pswitch. The calls are reference counted so that only the first ! 788: * "on" request actually has an effect, as does the final "off" request. ! 789: * Results are undefined if the "off" and "on" requests are not matched. ! 790: */ ! 791: int ! 792: ifpromisc(ifp, pswitch) ! 793: struct ifnet *ifp; ! 794: int pswitch; ! 795: { ! 796: struct ifreq ifr; ! 797: int error; ! 798: ! 799: if (pswitch) { ! 800: /* ! 801: * If the device is not configured up, we cannot put it in ! 802: * promiscuous mode. ! 803: */ ! 804: if ((ifp->if_flags & IFF_UP) == 0) ! 805: return (ENETDOWN); ! 806: if (ifp->if_pcount++ != 0) ! 807: return (0); ! 808: ifp->if_flags |= IFF_PROMISC; ! 809: log(LOG_INFO, "%s%d: promiscuous mode enabled\n", ! 810: ifp->if_name, ifp->if_unit); ! 811: } else { ! 812: if (--ifp->if_pcount > 0) ! 813: return (0); ! 814: ifp->if_flags &= ~IFF_PROMISC; ! 815: } ! 816: ifr.ifr_flags = ifp->if_flags; ! 817: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t)&ifr); ! 818: if (error == 0) ! 819: rt_ifmsg(ifp); ! 820: return error; ! 821: } ! 822: ! 823: /* ! 824: * Return interface configuration ! 825: * of system. List may be used ! 826: * in later ioctl's (above) to get ! 827: * other information. ! 828: */ ! 829: /*ARGSUSED*/ ! 830: static int ! 831: ifconf(cmd, data) ! 832: u_long cmd; ! 833: caddr_t data; ! 834: { ! 835: register struct ifconf *ifc = (struct ifconf *)data; ! 836: register struct ifnet *ifp = ifnet.tqh_first; ! 837: register struct ifaddr *ifa; ! 838: struct ifreq ifr, *ifrp; ! 839: int space = ifc->ifc_len, error = 0; ! 840: ! 841: ifrp = ifc->ifc_req; ! 842: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) { ! 843: char workbuf[64]; ! 844: int ifnlen; ! 845: ! 846: ifnlen = snprintf(workbuf, sizeof(workbuf), ! 847: "%s%d", ifp->if_name, ifp->if_unit); ! 848: if(ifnlen + 1 > sizeof ifr.ifr_name) { ! 849: error = ENAMETOOLONG; ! 850: } else { ! 851: strcpy(ifr.ifr_name, workbuf); ! 852: } ! 853: ! 854: if ((ifa = ifp->if_addrhead.tqh_first) == 0) { ! 855: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); ! 856: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, ! 857: sizeof (ifr)); ! 858: if (error) ! 859: break; ! 860: space -= sizeof (ifr), ifrp++; ! 861: } else ! 862: for ( ; space > sizeof (ifr) && ifa; ! 863: ifa = ifa->ifa_link.tqe_next) { ! 864: register struct sockaddr *sa = ifa->ifa_addr; ! 865: #if COMPAT_43 ! 866: if (cmd == OSIOCGIFCONF) { ! 867: struct osockaddr *osa = ! 868: (struct osockaddr *)&ifr.ifr_addr; ! 869: ifr.ifr_addr = *sa; ! 870: osa->sa_family = sa->sa_family; ! 871: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, ! 872: sizeof (ifr)); ! 873: ifrp++; ! 874: } else ! 875: #endif ! 876: if (sa->sa_len <= sizeof(*sa)) { ! 877: ifr.ifr_addr = *sa; ! 878: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, ! 879: sizeof (ifr)); ! 880: ifrp++; ! 881: } else { ! 882: space -= sa->sa_len - sizeof(*sa); ! 883: if (space < sizeof (ifr)) ! 884: break; ! 885: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, ! 886: sizeof (ifr.ifr_name)); ! 887: if (error == 0) ! 888: error = copyout((caddr_t)sa, ! 889: (caddr_t)&ifrp->ifr_addr, sa->sa_len); ! 890: ifrp = (struct ifreq *) ! 891: (sa->sa_len + (caddr_t)&ifrp->ifr_addr); ! 892: } ! 893: if (error) ! 894: break; ! 895: space -= sizeof (ifr); ! 896: } ! 897: } ! 898: ifc->ifc_len -= space; ! 899: return (error); ! 900: } ! 901: ! 902: /* ! 903: * Just like if_promisc(), but for all-multicast-reception mode. ! 904: */ ! 905: int ! 906: if_allmulti(ifp, onswitch) ! 907: struct ifnet *ifp; ! 908: int onswitch; ! 909: { ! 910: int error = 0; ! 911: int s = splimp(); ! 912: ! 913: if (onswitch) { ! 914: if (ifp->if_amcount++ == 0) { ! 915: ifp->if_flags |= IFF_ALLMULTI; ! 916: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0); ! 917: } ! 918: } else { ! 919: if (ifp->if_amcount > 1) { ! 920: ifp->if_amcount--; ! 921: } else { ! 922: ifp->if_amcount = 0; ! 923: ifp->if_flags &= ~IFF_ALLMULTI; ! 924: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0); ! 925: } ! 926: } ! 927: splx(s); ! 928: ! 929: if (error == 0) ! 930: rt_ifmsg(ifp); ! 931: return error; ! 932: } ! 933: ! 934: /* ! 935: * Add a multicast listenership to the interface in question. ! 936: * The link layer provides a routine which converts ! 937: */ ! 938: int ! 939: if_addmulti(ifp, sa, retifma) ! 940: struct ifnet *ifp; /* interface to manipulate */ ! 941: struct sockaddr *sa; /* address to add */ ! 942: struct ifmultiaddr **retifma; ! 943: { ! 944: struct sockaddr *llsa, *dupsa; ! 945: int error, s; ! 946: struct ifmultiaddr *ifma; ! 947: ! 948: /* ! 949: * If the matching multicast address already exists ! 950: * then don't add a new one, just add a reference ! 951: */ ! 952: for (ifma = ifp->if_multiaddrs.lh_first; ifma; ! 953: ifma = ifma->ifma_link.le_next) { ! 954: if (equal(sa, ifma->ifma_addr)) { ! 955: ifma->ifma_refcount++; ! 956: if (retifma) ! 957: *retifma = ifma; ! 958: return 0; ! 959: } ! 960: } ! 961: ! 962: /* ! 963: * Give the link layer a chance to accept/reject it, and also ! 964: * find out which AF_LINK address this maps to, if it isn't one ! 965: * already. ! 966: */ ! 967: if (ifp->if_resolvemulti) { ! 968: error = ifp->if_resolvemulti(ifp, &llsa, sa); ! 969: if (error) return error; ! 970: } else { ! 971: llsa = 0; ! 972: } ! 973: ! 974: MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK); ! 975: MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK); ! 976: bcopy(sa, dupsa, sa->sa_len); ! 977: ! 978: ifma->ifma_addr = dupsa; ! 979: ifma->ifma_lladdr = llsa; ! 980: ifma->ifma_ifp = ifp; ! 981: ifma->ifma_refcount = 1; ! 982: ifma->ifma_protospec = 0; ! 983: rt_newmaddrmsg(RTM_NEWMADDR, ifma); ! 984: ! 985: /* ! 986: * Some network interfaces can scan the address list at ! 987: * interrupt time; lock them out. ! 988: */ ! 989: s = splimp(); ! 990: LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); ! 991: splx(s); ! 992: if (retifma) ! 993: *retifma = ifma; ! 994: ! 995: if (llsa != 0) { ! 996: for (ifma = ifp->if_multiaddrs.lh_first; ifma; ! 997: ifma = ifma->ifma_link.le_next) { ! 998: if (equal(ifma->ifma_addr, llsa)) ! 999: break; ! 1000: } ! 1001: if (ifma) { ! 1002: ifma->ifma_refcount++; ! 1003: } else { ! 1004: MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, ! 1005: M_IFMADDR, M_WAITOK); ! 1006: MALLOC(dupsa, struct sockaddr *, llsa->sa_len, ! 1007: M_IFMADDR, M_WAITOK); ! 1008: bcopy(llsa, dupsa, llsa->sa_len); ! 1009: ifma->ifma_addr = dupsa; ! 1010: ifma->ifma_ifp = ifp; ! 1011: ifma->ifma_refcount = 1; ! 1012: s = splimp(); ! 1013: LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); ! 1014: splx(s); ! 1015: } ! 1016: } ! 1017: /* ! 1018: * We are certain we have added something, so call down to the ! 1019: * interface to let them know about it. ! 1020: */ ! 1021: s = splimp(); ! 1022: ! 1023: dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t) 0); ! 1024: splx(s); ! 1025: ! 1026: return 0; ! 1027: } ! 1028: ! 1029: /* ! 1030: * Remove a reference to a multicast address on this interface. Yell ! 1031: * if the request does not match an existing membership. ! 1032: */ ! 1033: int ! 1034: if_delmulti(ifp, sa) ! 1035: struct ifnet *ifp; ! 1036: struct sockaddr *sa; ! 1037: { ! 1038: struct ifmultiaddr *ifma; ! 1039: int s; ! 1040: ! 1041: for (ifma = ifp->if_multiaddrs.lh_first; ifma; ! 1042: ifma = ifma->ifma_link.le_next) ! 1043: if (equal(sa, ifma->ifma_addr)) ! 1044: break; ! 1045: if (ifma == 0) ! 1046: return ENOENT; ! 1047: ! 1048: if (ifma->ifma_refcount > 1) { ! 1049: ifma->ifma_refcount--; ! 1050: return 0; ! 1051: } ! 1052: ! 1053: rt_newmaddrmsg(RTM_DELMADDR, ifma); ! 1054: sa = ifma->ifma_lladdr; ! 1055: s = splimp(); ! 1056: LIST_REMOVE(ifma, ifma_link); ! 1057: splx(s); ! 1058: FREE(ifma->ifma_addr, M_IFMADDR); ! 1059: FREE(ifma, M_IFMADDR); ! 1060: if (sa == 0) ! 1061: return 0; ! 1062: ! 1063: /* ! 1064: * Now look for the link-layer address which corresponds to ! 1065: * this network address. It had been squirreled away in ! 1066: * ifma->ifma_lladdr for this purpose (so we don't have ! 1067: * to call ifp->if_resolvemulti() again), and we saved that ! 1068: * value in sa above. If some nasty deleted the ! 1069: * link-layer address out from underneath us, we can deal because ! 1070: * the address we stored was is not the same as the one which was ! 1071: * in the record for the link-layer address. (So we don't complain ! 1072: * in that case.) ! 1073: */ ! 1074: for (ifma = ifp->if_multiaddrs.lh_first; ifma; ! 1075: ifma = ifma->ifma_link.le_next) ! 1076: if (equal(sa, ifma->ifma_addr)) ! 1077: break; ! 1078: if (ifma == 0) ! 1079: return 0; ! 1080: ! 1081: if (ifma->ifma_refcount > 1) { ! 1082: ifma->ifma_refcount--; ! 1083: return 0; ! 1084: } ! 1085: ! 1086: s = splimp(); ! 1087: LIST_REMOVE(ifma, ifma_link); ! 1088: dlil_ioctl(0, ifp, SIOCDELMULTI, (caddr_t) 0); ! 1089: splx(s); ! 1090: FREE(ifma->ifma_addr, M_IFMADDR); ! 1091: FREE(sa, M_IFMADDR); ! 1092: FREE(ifma, M_IFMADDR); ! 1093: ! 1094: return 0; ! 1095: } ! 1096: ! 1097: struct ifmultiaddr * ! 1098: ifmaof_ifpforaddr(sa, ifp) ! 1099: struct sockaddr *sa; ! 1100: struct ifnet *ifp; ! 1101: { ! 1102: struct ifmultiaddr *ifma; ! 1103: ! 1104: for (ifma = ifp->if_multiaddrs.lh_first; ifma; ! 1105: ifma = ifma->ifma_link.le_next) ! 1106: if (equal(ifma->ifma_addr, sa)) ! 1107: break; ! 1108: ! 1109: return ifma; ! 1110: } ! 1111: ! 1112: SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); ! 1113: SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); ! 1114: ! 1115: ! 1116: /* ! 1117: * Shutdown all network activity. Used boot() when halting ! 1118: * system. ! 1119: */ ! 1120: int if_down_all(void) ! 1121: { ! 1122: struct ifnet *ifp; ! 1123: int s; ! 1124: ! 1125: s = splnet(); ! 1126: TAILQ_FOREACH(ifp, &ifnet, if_link) ! 1127: if_down(ifp); ! 1128: ! 1129: splx(s); ! 1130: return(0); /* Sheesh */ ! 1131: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.