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