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