|
|
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: /* ! 26: * Copyright (c) 1984, 1985, 1986, 1987, 1993 ! 27: * The Regents of the University of California. 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 the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)ns_ip.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: /* ! 61: * Software interface driver for encapsulating ns in ip. ! 62: */ ! 63: ! 64: #ifdef NSIP ! 65: #include <sys/param.h> ! 66: #include <sys/systm.h> ! 67: #include <sys/malloc.h> ! 68: #include <sys/mbuf.h> ! 69: #include <sys/socket.h> ! 70: #include <sys/socketvar.h> ! 71: #include <sys/errno.h> ! 72: #include <sys/ioctl.h> ! 73: #include <sys/protosw.h> ! 74: ! 75: #include <net/if.h> ! 76: #include <net/netisr.h> ! 77: #include <net/route.h> ! 78: ! 79: #include <netinet/in.h> ! 80: #include <netinet/in_systm.h> ! 81: #include <netinet/in_var.h> ! 82: #include <netinet/ip.h> ! 83: #include <netinet/ip_var.h> ! 84: ! 85: #include <machine/mtpr.h> ! 86: ! 87: #include <netns/ns.h> ! 88: #include <netns/ns_if.h> ! 89: #include <netns/idp.h> ! 90: ! 91: struct ifnet_en { ! 92: struct ifnet ifen_ifnet; ! 93: struct route ifen_route; ! 94: struct in_addr ifen_src; ! 95: struct in_addr ifen_dst; ! 96: struct ifnet_en *ifen_next; ! 97: }; ! 98: ! 99: int nsipoutput(), nsipioctl(), nsipstart(); ! 100: #define LOMTU (1024+512); ! 101: ! 102: struct ifnet nsipif; ! 103: struct ifnet_en *nsip_list; /* list of all hosts and gateways or ! 104: broadcast addrs */ ! 105: ! 106: struct ifnet_en * ! 107: nsipattach() ! 108: { ! 109: register struct ifnet_en *m; ! 110: register struct ifnet *ifp; ! 111: ! 112: if (nsipif.if_mtu == 0) { ! 113: ifp = &nsipif; ! 114: ifp->if_name = "nsip"; ! 115: ifp->if_mtu = LOMTU; ! 116: ifp->if_ioctl = nsipioctl; ! 117: ifp->if_output = nsipoutput; ! 118: ifp->if_start = nsipstart; ! 119: ifp->if_flags = IFF_POINTOPOINT; ! 120: } ! 121: ! 122: MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT); ! 123: if (m == NULL) return (NULL); ! 124: m->ifen_next = nsip_list; ! 125: nsip_list = m; ! 126: ifp = &m->ifen_ifnet; ! 127: ! 128: ifp->if_name = "nsip"; ! 129: ifp->if_mtu = LOMTU; ! 130: ifp->if_ioctl = nsipioctl; ! 131: ifp->if_output = nsipoutput; ! 132: ifp->if_start = nsipstart; ! 133: ifp->if_flags = IFF_POINTOPOINT; ! 134: ifp->if_unit = nsipif.if_unit++; ! 135: if_attach(ifp); ! 136: ! 137: return (m); ! 138: } ! 139: ! 140: ! 141: /* ! 142: * Process an ioctl request. ! 143: */ ! 144: /* ARGSUSED */ ! 145: nsipioctl(ifp, cmd, data) ! 146: register struct ifnet *ifp; ! 147: int cmd; ! 148: caddr_t data; ! 149: { ! 150: int error = 0; ! 151: struct ifreq *ifr; ! 152: ! 153: switch (cmd) { ! 154: ! 155: case SIOCSIFADDR: ! 156: ifp->if_flags |= IFF_UP; ! 157: /* fall into: */ ! 158: ! 159: case SIOCSIFDSTADDR: ! 160: /* ! 161: * Everything else is done at a higher level. ! 162: */ ! 163: break; ! 164: ! 165: case SIOCSIFFLAGS: ! 166: ifr = (struct ifreq *)data; ! 167: if ((ifr->ifr_flags & IFF_UP) == 0) ! 168: error = nsip_free(ifp); ! 169: ! 170: ! 171: default: ! 172: error = EINVAL; ! 173: } ! 174: return (error); ! 175: } ! 176: ! 177: struct mbuf *nsip_badlen; ! 178: struct mbuf *nsip_lastin; ! 179: int nsip_hold_input; ! 180: ! 181: idpip_input(m, ifp) ! 182: register struct mbuf *m; ! 183: struct ifnet *ifp; ! 184: { ! 185: register struct ip *ip; ! 186: register struct idp *idp; ! 187: register struct ifqueue *ifq = &nsintrq; ! 188: int len, s; ! 189: ! 190: if (nsip_hold_input) { ! 191: if (nsip_lastin) { ! 192: m_freem(nsip_lastin); ! 193: } ! 194: nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT); ! 195: } ! 196: /* ! 197: * Get IP and IDP header together in first mbuf. ! 198: */ ! 199: nsipif.if_ipackets++; ! 200: s = sizeof (struct ip) + sizeof (struct idp); ! 201: if (((m->m_flags & M_EXT) || m->m_len < s) && ! 202: (m = m_pullup(m, s)) == 0) { ! 203: nsipif.if_ierrors++; ! 204: return; ! 205: } ! 206: ip = mtod(m, struct ip *); ! 207: if (ip->ip_hl > (sizeof (struct ip) >> 2)) { ! 208: ip_stripoptions(m, (struct mbuf *)0); ! 209: if (m->m_len < s) { ! 210: if ((m = m_pullup(m, s)) == 0) { ! 211: nsipif.if_ierrors++; ! 212: return; ! 213: } ! 214: ip = mtod(m, struct ip *); ! 215: } ! 216: } ! 217: ! 218: /* ! 219: * Make mbuf data length reflect IDP length. ! 220: * If not enough data to reflect IDP length, drop. ! 221: */ ! 222: m->m_data += sizeof (struct ip); ! 223: m->m_len -= sizeof (struct ip); ! 224: m->m_pkthdr.len -= sizeof (struct ip); ! 225: idp = mtod(m, struct idp *); ! 226: len = ntohs(idp->idp_len); ! 227: if (len & 1) len++; /* Preserve Garbage Byte */ ! 228: if (ip->ip_len != len) { ! 229: if (len > ip->ip_len) { ! 230: nsipif.if_ierrors++; ! 231: if (nsip_badlen) m_freem(nsip_badlen); ! 232: nsip_badlen = m; ! 233: return; ! 234: } ! 235: /* Any extra will be trimmed off by the NS routines */ ! 236: } ! 237: ! 238: /* ! 239: * Place interface pointer before the data ! 240: * for the receiving protocol. ! 241: */ ! 242: m->m_pkthdr.rcvif = ifp; ! 243: /* ! 244: * Deliver to NS ! 245: */ ! 246: s = splimp(); ! 247: if (IF_QFULL(ifq)) { ! 248: IF_DROP(ifq); ! 249: bad: ! 250: m_freem(m); ! 251: splx(s); ! 252: return; ! 253: } ! 254: IF_ENQUEUE(ifq, m); ! 255: schednetisr(NETISR_NS); ! 256: splx(s); ! 257: return; ! 258: } ! 259: ! 260: /* ARGSUSED */ ! 261: nsipoutput(ifn, m, dst) ! 262: struct ifnet_en *ifn; ! 263: register struct mbuf *m; ! 264: struct sockaddr *dst; ! 265: { ! 266: ! 267: register struct ip *ip; ! 268: register struct route *ro = &(ifn->ifen_route); ! 269: register int len = 0; ! 270: register struct idp *idp = mtod(m, struct idp *); ! 271: int error; ! 272: ! 273: ifn->ifen_ifnet.if_opackets++; ! 274: nsipif.if_opackets++; ! 275: ! 276: ! 277: /* ! 278: * Calculate data length and make space ! 279: * for IP header. ! 280: */ ! 281: len = ntohs(idp->idp_len); ! 282: if (len & 1) len++; /* Preserve Garbage Byte */ ! 283: /* following clause not necessary on vax */ ! 284: if (3 & (int)m->m_data) { ! 285: /* force longword alignment of ip hdr */ ! 286: struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT); ! 287: if (m0 == 0) { ! 288: m_freem(m); ! 289: return (ENOBUFS); ! 290: } ! 291: MH_ALIGN(m0, sizeof (struct ip)); ! 292: m0->m_flags = m->m_flags & M_COPYFLAGS; ! 293: m0->m_next = m; ! 294: m0->m_len = sizeof (struct ip); ! 295: m0->m_pkthdr.len = m0->m_len + m->m_len; ! 296: m->m_flags &= ~M_PKTHDR; ! 297: } else { ! 298: M_PREPEND(m, sizeof (struct ip), M_DONTWAIT); ! 299: if (m == 0) ! 300: return (ENOBUFS); ! 301: } ! 302: /* ! 303: * Fill in IP header. ! 304: */ ! 305: ip = mtod(m, struct ip *); ! 306: *(long *)ip = 0; ! 307: ip->ip_p = IPPROTO_IDP; ! 308: ip->ip_src = ifn->ifen_src; ! 309: ip->ip_dst = ifn->ifen_dst; ! 310: ip->ip_len = (u_short)len + sizeof (struct ip); ! 311: ip->ip_ttl = MAXTTL; ! 312: ! 313: /* ! 314: * Output final datagram. ! 315: */ ! 316: error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL)); ! 317: if (error) { ! 318: ifn->ifen_ifnet.if_oerrors++; ! 319: ifn->ifen_ifnet.if_ierrors = error; ! 320: } ! 321: return (error); ! 322: bad: ! 323: m_freem(m); ! 324: return (ENETUNREACH); ! 325: } ! 326: ! 327: nsipstart(ifp) ! 328: struct ifnet *ifp; ! 329: { ! 330: panic("nsip_start called\n"); ! 331: } ! 332: ! 333: struct ifreq ifr = {"nsip0"}; ! 334: ! 335: nsip_route(m) ! 336: register struct mbuf *m; ! 337: { ! 338: register struct nsip_req *rq = mtod(m, struct nsip_req *); ! 339: struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; ! 340: struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; ! 341: struct route ro; ! 342: struct ifnet_en *ifn; ! 343: struct sockaddr_in *src; ! 344: ! 345: /* ! 346: * First, make sure we already have an ns address: ! 347: */ ! 348: if (ns_hosteqnh(ns_thishost, ns_zerohost)) ! 349: return (EADDRNOTAVAIL); ! 350: /* ! 351: * Now, determine if we can get to the destination ! 352: */ ! 353: bzero((caddr_t)&ro, sizeof (ro)); ! 354: ro.ro_dst = *(struct sockaddr *)ip_dst; ! 355: rtalloc(&ro); ! 356: if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { ! 357: return (ENETUNREACH); ! 358: } ! 359: ! 360: /* ! 361: * And see how he's going to get back to us: ! 362: * i.e., what return ip address do we use? ! 363: */ ! 364: { ! 365: register struct in_ifaddr *ia; ! 366: struct ifnet *ifp = ro.ro_rt->rt_ifp; ! 367: ! 368: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 369: if (ia->ia_ifp == ifp) ! 370: break; ! 371: if (ia == 0) ! 372: ia = in_ifaddr; ! 373: if (ia == 0) { ! 374: RTFREE(ro.ro_rt); ! 375: return (EADDRNOTAVAIL); ! 376: } ! 377: src = (struct sockaddr_in *)&ia->ia_addr; ! 378: } ! 379: ! 380: /* ! 381: * Is there a free (pseudo-)interface or space? ! 382: */ ! 383: for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) { ! 384: if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0) ! 385: break; ! 386: } ! 387: if (ifn == NULL) ! 388: ifn = nsipattach(); ! 389: if (ifn == NULL) { ! 390: RTFREE(ro.ro_rt); ! 391: return (ENOBUFS); ! 392: } ! 393: ifn->ifen_route = ro; ! 394: ifn->ifen_dst = ip_dst->sin_addr; ! 395: ifn->ifen_src = src->sin_addr; ! 396: ! 397: /* ! 398: * now configure this as a point to point link ! 399: */ ! 400: ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; ! 401: ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; ! 402: (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr, ! 403: (struct ifnet *)ifn); ! 404: satons_addr(ifr.ifr_addr).x_host = ns_thishost; ! 405: return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr, ! 406: (struct ifnet *)ifn)); ! 407: } ! 408: ! 409: nsip_free(ifp) ! 410: struct ifnet *ifp; ! 411: { ! 412: register struct ifnet_en *ifn = (struct ifnet_en *)ifp; ! 413: struct route *ro = & ifn->ifen_route; ! 414: ! 415: if (ro->ro_rt) { ! 416: RTFREE(ro->ro_rt); ! 417: ro->ro_rt = 0; ! 418: } ! 419: ifp->if_flags &= ~IFF_UP; ! 420: return (0); ! 421: } ! 422: ! 423: nsip_ctlinput(cmd, sa) ! 424: int cmd; ! 425: struct sockaddr *sa; ! 426: { ! 427: extern u_char inetctlerrmap[]; ! 428: struct sockaddr_in *sin; ! 429: int in_rtchange(); ! 430: ! 431: if ((unsigned)cmd >= PRC_NCMDS) ! 432: return; ! 433: if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) ! 434: return; ! 435: sin = (struct sockaddr_in *)sa; ! 436: if (sin->sin_addr.s_addr == INADDR_ANY) ! 437: return; ! 438: ! 439: switch (cmd) { ! 440: ! 441: case PRC_ROUTEDEAD: ! 442: case PRC_REDIRECT_NET: ! 443: case PRC_REDIRECT_HOST: ! 444: case PRC_REDIRECT_TOSNET: ! 445: case PRC_REDIRECT_TOSHOST: ! 446: nsip_rtchange(&sin->sin_addr); ! 447: break; ! 448: } ! 449: } ! 450: ! 451: nsip_rtchange(dst) ! 452: register struct in_addr *dst; ! 453: { ! 454: register struct ifnet_en *ifn; ! 455: ! 456: for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) { ! 457: if (ifn->ifen_dst.s_addr == dst->s_addr && ! 458: ifn->ifen_route.ro_rt) { ! 459: RTFREE(ifn->ifen_route.ro_rt); ! 460: ifn->ifen_route.ro_rt = 0; ! 461: } ! 462: } ! 463: } ! 464: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.