|
|
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: /* $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $ */ ! 23: ! 24: /* ! 25: * ! 26: * Copyright (c) 1996 Charles D. Cranor and Washington University. ! 27: * All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by Charles D. Cranor and ! 40: * Washington University. ! 41: * 4. The name of the author may not be used to endorse or promote products ! 42: * derived from this software without specific prior written permission. ! 43: * ! 44: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 45: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ! 46: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ! 47: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ! 48: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ! 49: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ! 50: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ! 51: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ! 52: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ! 53: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! 54: */ ! 55: ! 56: /* ! 57: * if_atmsubr.c ! 58: */ ! 59: ! 60: #include "opt_inet.h" ! 61: #include "opt_natm.h" ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/mbuf.h> ! 66: #include <sys/socket.h> ! 67: #include <sys/sockio.h> ! 68: #include <sys/malloc.h> ! 69: #include <sys/errno.h> ! 70: ! 71: ! 72: #include <net/if.h> ! 73: #include <net/netisr.h> ! 74: #include <net/route.h> ! 75: #include <net/if_dl.h> ! 76: #include <net/if_types.h> ! 77: #include <net/if_atm.h> ! 78: ! 79: #include <netinet/in.h> ! 80: #include <netinet/if_atm.h> ! 81: #include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */ ! 82: #if defined(INET) || defined(INET6) ! 83: #include <netinet/in_var.h> ! 84: #endif ! 85: #if NATM ! 86: #include <netnatm/natm.h> ! 87: #endif ! 88: ! 89: #ifndef ETHERTYPE_IPV6 ! 90: #define ETHERTYPE_IPV6 0x86dd ! 91: #endif ! 92: ! 93: #define senderr(e) { error = (e); goto bad;} ! 94: ! 95: /* ! 96: * atm_output: ATM output routine ! 97: * inputs: ! 98: * "ifp" = ATM interface to output to ! 99: * "m0" = the packet to output ! 100: * "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI) ! 101: * "rt0" = the route to use ! 102: * returns: error code [0 == ok] ! 103: * ! 104: * note: special semantic: if (dst == NULL) then we assume "m" already ! 105: * has an atm_pseudohdr on it and just send it directly. ! 106: * [for native mode ATM output] if dst is null, then ! 107: * rt0 must also be NULL. ! 108: */ ! 109: ! 110: int ! 111: atm_output(ifp, m0, dst, rt0) ! 112: register struct ifnet *ifp; ! 113: struct mbuf *m0; ! 114: struct sockaddr *dst; ! 115: struct rtentry *rt0; ! 116: { ! 117: u_int16_t etype = 0; /* if using LLC/SNAP */ ! 118: int s, error = 0, sz; ! 119: struct atm_pseudohdr atmdst, *ad; ! 120: register struct mbuf *m = m0; ! 121: register struct rtentry *rt; ! 122: struct atmllc *atmllc; ! 123: struct atmllc *llc_hdr = NULL; ! 124: u_int32_t atm_flags; ! 125: ! 126: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 127: senderr(ENETDOWN); ! 128: ! 129: /* ! 130: * check route ! 131: */ ! 132: if ((rt = rt0) != NULL) { ! 133: ! 134: if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */ ! 135: if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL) ! 136: rt->rt_refcnt--; ! 137: else ! 138: senderr(EHOSTUNREACH); ! 139: } ! 140: ! 141: if (rt->rt_flags & RTF_GATEWAY) { ! 142: if (rt->rt_gwroute == 0) ! 143: goto lookup; ! 144: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { ! 145: rtfree(rt); rt = rt0; ! 146: lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0); ! 147: if ((rt = rt->rt_gwroute) == 0) ! 148: senderr(EHOSTUNREACH); ! 149: } ! 150: } ! 151: ! 152: /* XXX: put RTF_REJECT code here if doing ATMARP */ ! 153: ! 154: } ! 155: ! 156: /* ! 157: * check for non-native ATM traffic (dst != NULL) ! 158: */ ! 159: if (dst) { ! 160: switch (dst->sa_family) { ! 161: #if defined(INET) || defined(INET6) ! 162: case AF_INET: ! 163: case AF_INET6: ! 164: if (!atmresolve(rt, m, dst, &atmdst)) { ! 165: m = NULL; ! 166: /* XXX: atmresolve already free'd it */ ! 167: senderr(EHOSTUNREACH); ! 168: /* XXX: put ATMARP stuff here */ ! 169: /* XXX: watch who frees m on failure */ ! 170: } ! 171: if (dst->sa_family == AF_INET6) ! 172: etype = htons(ETHERTYPE_IPV6); ! 173: else ! 174: etype = htons(ETHERTYPE_IP); ! 175: break; ! 176: #endif /* INET || INET6 */ ! 177: ! 178: case AF_UNSPEC: ! 179: /* ! 180: * XXX: bpfwrite or output from a pvc shadow if. ! 181: * assuming dst contains 12 bytes (atm pseudo ! 182: * header (4) + LLC/SNAP (8)) ! 183: */ ! 184: bcopy(dst->sa_data, &atmdst, sizeof(atmdst)); ! 185: llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst)); ! 186: break; ! 187: ! 188: default: ! 189: #if defined(__NetBSD__) || defined(__OpenBSD__) ! 190: printf("%s: can't handle af%d\n", ifp->if_xname, ! 191: dst->sa_family); ! 192: #elif defined(__FreeBSD__) || defined(__bsdi__) ! 193: printf("%s%d: can't handle af%d\n", ifp->if_name, ! 194: ifp->if_unit, dst->sa_family); ! 195: #endif ! 196: senderr(EAFNOSUPPORT); ! 197: } ! 198: ! 199: /* ! 200: * must add atm_pseudohdr to data ! 201: */ ! 202: sz = sizeof(atmdst); ! 203: atm_flags = ATM_PH_FLAGS(&atmdst); ! 204: if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */ ! 205: M_PREPEND(m, sz, M_DONTWAIT); ! 206: if (m == 0) ! 207: senderr(ENOBUFS); ! 208: ad = mtod(m, struct atm_pseudohdr *); ! 209: *ad = atmdst; ! 210: if (atm_flags & ATM_PH_LLCSNAP) { ! 211: atmllc = (struct atmllc *)(ad + 1); ! 212: if (llc_hdr == NULL) { ! 213: bcopy(ATMLLC_HDR, atmllc->llchdr, ! 214: sizeof(atmllc->llchdr)); ! 215: ATM_LLC_SETTYPE(atmllc, etype); ! 216: /* note: already in network order */ ! 217: } ! 218: else ! 219: bcopy(llc_hdr, atmllc, sizeof(struct atmllc)); ! 220: } ! 221: } ! 222: ! 223: /* ! 224: * Queue message on interface, and start output if interface ! 225: * not yet active. ! 226: */ ! 227: s = splimp(); ! 228: if (IF_QFULL(&ifp->if_snd)) { ! 229: IF_DROP(&ifp->if_snd); ! 230: splx(s); ! 231: senderr(ENOBUFS); ! 232: } ! 233: ifp->if_obytes += m->m_pkthdr.len; ! 234: IF_ENQUEUE(&ifp->if_snd, m); ! 235: if ((ifp->if_flags & IFF_OACTIVE) == 0) ! 236: (*ifp->if_start)(ifp); ! 237: splx(s); ! 238: return (error); ! 239: ! 240: bad: ! 241: if (m) ! 242: m_freem(m); ! 243: return (error); ! 244: } ! 245: ! 246: /* ! 247: * Process a received ATM packet; ! 248: * the packet is in the mbuf chain m. ! 249: */ ! 250: void ! 251: atm_input(ifp, ah, m, rxhand) ! 252: struct ifnet *ifp; ! 253: register struct atm_pseudohdr *ah; ! 254: struct mbuf *m; ! 255: void *rxhand; ! 256: { ! 257: register struct ifqueue *inq; ! 258: u_int16_t etype = ETHERTYPE_IP; /* default */ ! 259: int s; ! 260: ! 261: if ((ifp->if_flags & IFF_UP) == 0) { ! 262: m_freem(m); ! 263: return; ! 264: } ! 265: ifp->if_ibytes += m->m_pkthdr.len; ! 266: ! 267: #if ATM_PVCEXT ! 268: if (ATM_PH_FLAGS(ah) & ATM_PH_PVCSIF) { ! 269: /* ! 270: * when PVC shadow interface is used, pointer to ! 271: * the shadow interface is passed as rxhand. ! 272: * override the receive interface of the packet. ! 273: */ ! 274: m->m_pkthdr.rcvif = (struct ifnet *)rxhand; ! 275: rxhand = NULL; ! 276: } ! 277: #endif /* ATM_PVCEXT */ ! 278: ! 279: if (rxhand) { ! 280: #if NATM ! 281: struct natmpcb *npcb = rxhand; ! 282: s = splimp(); /* in case 2 atm cards @ diff lvls */ ! 283: npcb->npcb_inq++; /* count # in queue */ ! 284: splx(s); ! 285: schednetisr(NETISR_NATM); ! 286: inq = &natmintrq; ! 287: m->m_pkthdr.rcvif = rxhand; /* XXX: overload */ ! 288: #else ! 289: printf("atm_input: NATM detected but not configured in kernel\n"); ! 290: m_freem(m); ! 291: return; ! 292: #endif ! 293: } else { ! 294: /* ! 295: * handle LLC/SNAP header, if present ! 296: */ ! 297: if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) { ! 298: struct atmllc *alc; ! 299: if (m->m_len < sizeof(*alc) && ! 300: (m = m_pullup(m, sizeof(*alc))) == 0) ! 301: return; /* failed */ ! 302: alc = mtod(m, struct atmllc *); ! 303: if (bcmp(alc, ATMLLC_HDR, 6)) { ! 304: #if defined(__NetBSD__) || defined(__OpenBSD__) ! 305: printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n", ! 306: ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah)); ! 307: #elif defined(__FreeBSD__) || defined(__bsdi__) ! 308: printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n", ! 309: ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah)); ! 310: #endif ! 311: m_freem(m); ! 312: return; ! 313: } ! 314: etype = ATM_LLC_TYPE(alc); ! 315: m_adj(m, sizeof(*alc)); ! 316: } ! 317: ! 318: switch (etype) { ! 319: #if INET ! 320: case ETHERTYPE_IP: ! 321: schednetisr(NETISR_IP); ! 322: inq = &ipintrq; ! 323: break; ! 324: #endif ! 325: #if INET6 ! 326: case ETHERTYPE_IPV6: ! 327: schednetisr(NETISR_IPV6); ! 328: inq = &ip6intrq; ! 329: break; ! 330: #endif ! 331: default: ! 332: m_freem(m); ! 333: return; ! 334: } ! 335: } ! 336: ! 337: s = splimp(); ! 338: if (IF_QFULL(inq)) { ! 339: IF_DROP(inq); ! 340: m_freem(m); ! 341: } else ! 342: IF_ENQUEUE(inq, m); ! 343: splx(s); ! 344: } ! 345: ! 346: /* ! 347: * Perform common duties while attaching to interface list ! 348: */ ! 349: void ! 350: atm_ifattach(ifp) ! 351: register struct ifnet *ifp; ! 352: { ! 353: register struct ifaddr *ifa; ! 354: register struct sockaddr_dl *sdl; ! 355: ! 356: ifp->if_type = IFT_ATM; ! 357: ifp->if_addrlen = 0; ! 358: ifp->if_hdrlen = 0; ! 359: ifp->if_mtu = ATMMTU; ! 360: ifp->if_output = atm_output; ! 361: ! 362: #if defined(__NetBSD__) || defined(__OpenBSD__) ! 363: for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ! 364: ifa = ifa->ifa_list.tqe_next) ! 365: #elif defined(__FreeBSD__) && (__FreeBSD__ > 2) ! 366: for (ifa = ifp->if_addrhead.tqh_first; ifa; ! 367: ifa = ifa->ifa_link.tqe_next) ! 368: #elif defined(__FreeBSD__) || defined(__bsdi__) ! 369: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 370: #endif ! 371: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && ! 372: sdl->sdl_family == AF_LINK) { ! 373: sdl->sdl_type = IFT_ATM; ! 374: sdl->sdl_alen = ifp->if_addrlen; ! 375: #ifdef notyet /* if using ATMARP, store hardware address using the next line */ ! 376: bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen); ! 377: #endif ! 378: break; ! 379: } ! 380: ! 381: } ! 382: ! 383: #if ATM_PVCEXT ! 384: /* ! 385: * ATM PVC shadow interface: a trick to assign a shadow interface ! 386: * to a PVC. ! 387: * with shadow interface, each PVC looks like an individual ! 388: * Point-to-Point interface. ! 389: * as oposed to the NBMA model, a shadow interface is inherently ! 390: * multicast capable (no LANE/MARS required). ! 391: */ ! 392: struct pvcsif { ! 393: struct ifnet sif_shadow; /* shadow ifnet structure per pvc */ ! 394: struct atm_pseudohdr sif_aph; /* flags + vpi:vci */ ! 395: struct ifnet *sif_ifp; /* pointer to the genuine interface */ ! 396: }; ! 397: ! 398: static int pvc_output __P((struct ifnet *, struct mbuf *, ! 399: struct sockaddr *, struct rtentry *)); ! 400: static int pvc_ioctl __P((struct ifnet *, u_long, caddr_t)); ! 401: ! 402: /* ! 403: * create and attach per pvc shadow interface ! 404: * (currently detach is not supported) ! 405: */ ! 406: static int pvc_number = 0; ! 407: ! 408: struct ifnet * ! 409: pvc_attach(ifp) ! 410: struct ifnet *ifp; ! 411: { ! 412: struct pvcsif *pvcsif; ! 413: struct ifnet *shadow; ! 414: struct ifaddr *ifa; ! 415: struct sockaddr_dl *sdl; ! 416: int s; ! 417: ! 418: MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif), ! 419: M_DEVBUF, M_WAITOK); ! 420: bzero(pvcsif, sizeof(struct pvcsif)); ! 421: ! 422: pvcsif->sif_ifp = ifp; ! 423: shadow = &pvcsif->sif_shadow; ! 424: ! 425: shadow->if_name = "pvc"; ! 426: shadow->if_family = APPLE_IF_FAM_PVC; ! 427: shadow->if_unit = pvc_number++; ! 428: shadow->if_flags = ifp->if_flags | (IFF_POINTOPOINT | IFF_MULTICAST); ! 429: shadow->if_ioctl = pvc_ioctl; ! 430: shadow->if_output = pvc_output; ! 431: shadow->if_start = NULL; ! 432: shadow->if_mtu = ifp->if_mtu; ! 433: shadow->if_type = ifp->if_type; ! 434: shadow->if_addrlen = ifp->if_addrlen; ! 435: shadow->if_hdrlen = ifp->if_hdrlen; ! 436: shadow->if_softc = pvcsif; ! 437: shadow->if_snd.ifq_maxlen = 50; /* dummy */ ! 438: ! 439: s = splimp(); ! 440: if_attach(shadow); ! 441: ! 442: #if defined(__NetBSD__) || defined(__OpenBSD__) ! 443: for (ifa = shadow->if_addrlist.tqh_first; ifa != 0; ! 444: ifa = ifa->ifa_list.tqe_next) ! 445: #elif defined(__FreeBSD__) && (__FreeBSD__ > 2) ! 446: for (ifa = shadow->if_addrhead.tqh_first; ifa; ! 447: ifa = ifa->ifa_link.tqe_next) ! 448: #elif defined(__FreeBSD__) || defined(__bsdi__) ! 449: for (ifa = shadow->if_addrlist; ifa; ifa = ifa->ifa_next) ! 450: #endif ! 451: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && ! 452: sdl->sdl_family == AF_LINK) { ! 453: sdl->sdl_type = IFT_ATM; ! 454: sdl->sdl_alen = shadow->if_addrlen; ! 455: break; ! 456: } ! 457: splx(s); ! 458: ! 459: return (shadow); ! 460: } ! 461: ! 462: /* ! 463: * pvc_output relays the packet to atm_output along with vpi:vci info. ! 464: */ ! 465: static int ! 466: pvc_output(shadow, m, dst, rt) ! 467: struct ifnet *shadow; ! 468: struct mbuf *m; ! 469: struct sockaddr *dst; ! 470: struct rtentry *rt; ! 471: { ! 472: struct pvcsif *pvcsif; ! 473: struct sockaddr dst_addr; ! 474: struct atmllc *atmllc; ! 475: u_int16_t etype = 0; ! 476: int error = 0; ! 477: ! 478: if ((shadow->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 479: senderr(ENETDOWN); ! 480: ! 481: pvcsif = shadow->if_softc; ! 482: if (ATM_PH_VCI(&pvcsif->sif_aph) == 0) ! 483: senderr(ENETDOWN); ! 484: ! 485: /* ! 486: * create a dummy sockaddr: (using bpfwrite interface) ! 487: * put atm pseudo header and llc/snap into sa_data (12 bytes) ! 488: * and mark it as AF_UNSPEC. ! 489: */ ! 490: if (dst) { ! 491: switch (dst->sa_family) { ! 492: #if defined(INET) || defined(INET6) ! 493: case AF_INET: ! 494: case AF_INET6: ! 495: if (dst->sa_family == AF_INET6) ! 496: etype = htons(ETHERTYPE_IPV6); ! 497: else ! 498: etype = htons(ETHERTYPE_IP); ! 499: break; ! 500: #endif ! 501: ! 502: default: ! 503: printf("%s%d: can't handle af%d\n", shadow->if_name, ! 504: shadow->if_unit, dst->sa_family); ! 505: senderr(EAFNOSUPPORT); ! 506: } ! 507: } ! 508: ! 509: dst_addr.sa_family = AF_UNSPEC; ! 510: bcopy(&pvcsif->sif_aph, dst_addr.sa_data, ! 511: sizeof(struct atm_pseudohdr)); ! 512: atmllc = (struct atmllc *) ! 513: (dst_addr.sa_data + sizeof(struct atm_pseudohdr)); ! 514: bcopy(ATMLLC_HDR, atmllc->llchdr, sizeof(atmllc->llchdr)); ! 515: ATM_LLC_SETTYPE(atmllc, etype); /* note: already in network order */ ! 516: ! 517: return atm_output(pvcsif->sif_ifp, m, &dst_addr, rt); ! 518: ! 519: bad: ! 520: if (m) ! 521: m_freem(m); ! 522: return (error); ! 523: } ! 524: ! 525: static int ! 526: pvc_ioctl(shadow, cmd, data) ! 527: struct ifnet *shadow; ! 528: u_long cmd; ! 529: caddr_t data; ! 530: { ! 531: struct ifnet *ifp; ! 532: struct pvcsif *pvcsif; ! 533: struct ifreq *ifr = (struct ifreq *) data; ! 534: void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *) = NULL; ! 535: int error = 0; ! 536: ! 537: pvcsif = (struct pvcsif *)shadow->if_softc; ! 538: ifp = pvcsif->sif_ifp; ! 539: if (ifp == 0 || ifp->if_ioctl == 0) ! 540: return (EOPNOTSUPP); ! 541: ! 542: /* ! 543: * pre process ! 544: */ ! 545: switch (cmd) { ! 546: case SIOCGPVCSIF: ! 547: snprintf(ifr->ifr_name, sizeof(ifr->ifr_name), ! 548: "%s%d", ifp->if_name, ifp->if_unit); ! 549: return (0); ! 550: ! 551: case SIOCGPVCTX: ! 552: do { ! 553: struct pvctxreq *pvcreq = (struct pvctxreq *)data; ! 554: ! 555: snprintf(pvcreq->pvc_ifname, ! 556: sizeof(pvcreq->pvc_ifname), "%s%d", ! 557: ifp->if_name, ifp->if_unit); ! 558: pvcreq->pvc_aph = pvcsif->sif_aph; ! 559: } while (0); ! 560: break; ! 561: ! 562: case SIOCADDMULTI: ! 563: case SIOCDELMULTI: ! 564: if (ifr == 0) ! 565: return (EAFNOSUPPORT); /* XXX */ ! 566: switch (ifr->ifr_addr.sa_family) { ! 567: #if INET ! 568: case AF_INET: ! 569: return (0); ! 570: #endif ! 571: #if INET6 ! 572: case AF_INET6: ! 573: return (0); ! 574: #endif ! 575: default: ! 576: return (EAFNOSUPPORT); ! 577: } ! 578: break; ! 579: case SIOCSIFADDR: ! 580: if (ifp->if_flags & IFF_UP) { ! 581: /* real if is already up */ ! 582: shadow->if_flags = ifp->if_flags | ! 583: (IFF_POINTOPOINT|IFF_MULTICAST); ! 584: return (0); ! 585: } ! 586: /* ! 587: * XXX: save the rtrequest field since the atm driver ! 588: * overwrites this field. ! 589: */ ! 590: ifa_rtrequest = ((struct ifaddr *)data)->ifa_rtrequest; ! 591: break; ! 592: ! 593: case SIOCSIFFLAGS: ! 594: if ((shadow->if_flags & IFF_UP) == 0) { ! 595: /* ! 596: * interface down. don't pass this to ! 597: * the real interface. ! 598: */ ! 599: return (0); ! 600: } ! 601: if (shadow->if_flags & IFF_UP) { ! 602: /* ! 603: * interface up. if the real if is already up, ! 604: * nothing to do. ! 605: */ ! 606: if (ifp->if_flags & IFF_UP) { ! 607: shadow->if_flags = ifp->if_flags | ! 608: (IFF_POINTOPOINT|IFF_MULTICAST); ! 609: return (0); ! 610: } ! 611: } ! 612: break; ! 613: } ! 614: ! 615: /* ! 616: * pass the ioctl to the genuine interface ! 617: */ ! 618: error = (*ifp->if_ioctl)(ifp, cmd, data); ! 619: ! 620: /* ! 621: * post process ! 622: */ ! 623: switch (cmd) { ! 624: case SIOCSIFMTU: ! 625: shadow->if_mtu = ifp->if_mtu; ! 626: break; ! 627: case SIOCSIFADDR: ! 628: /* restore rtrequest */ ! 629: ((struct ifaddr *)data)->ifa_rtrequest = ifa_rtrequest; ! 630: /* fall into... */ ! 631: case SIOCSIFFLAGS: ! 632: /* update if_flags */ ! 633: shadow->if_flags = ifp->if_flags ! 634: | (IFF_POINTOPOINT|IFF_MULTICAST); ! 635: break; ! 636: } ! 637: ! 638: return (error); ! 639: } ! 640: ! 641: int pvc_setaph(shadow, aph) ! 642: struct ifnet *shadow; ! 643: struct atm_pseudohdr *aph; ! 644: { ! 645: struct pvcsif *pvcsif; ! 646: ! 647: pvcsif = shadow->if_softc; ! 648: bcopy(aph, &pvcsif->sif_aph, sizeof(struct atm_pseudohdr)); ! 649: return (0); ! 650: } ! 651: ! 652: #endif /* ATM_PVCEXT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.