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