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