123210Smckusick /* 2*33371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 3*33371Ssklower * All rights reserved. 423210Smckusick * 5*33371Ssklower * Redistribution and use in source and binary forms are permitted 6*33371Ssklower * provided that this notice is preserved and that due credit is given 7*33371Ssklower * to the University of California at Berkeley. The name of the University 8*33371Ssklower * may not be used to endorse or promote products derived from this 9*33371Ssklower * software without specific prior written permission. This software 10*33371Ssklower * is provided ``as is'' without express or implied warranty. 11*33371Ssklower * 12*33371Ssklower * @(#)ns_ip.c 7.2 (Berkeley) 01/20/88 1323210Smckusick */ 1421487Ssklower 1521487Ssklower /* 1621487Ssklower * Software interface driver for encapsulating ns in ip. 1721487Ssklower */ 1821487Ssklower 1921487Ssklower #ifdef NSIP 2021487Ssklower #include "param.h" 2121487Ssklower #include "systm.h" 2221487Ssklower #include "mbuf.h" 2321487Ssklower #include "socket.h" 2424226Ssklower #include "socketvar.h" 2521487Ssklower #include "errno.h" 2621487Ssklower #include "ioctl.h" 2725055Ssklower #include "protosw.h" 2821487Ssklower 2921487Ssklower #include "../net/if.h" 3021487Ssklower #include "../net/netisr.h" 3121487Ssklower #include "../net/route.h" 3221487Ssklower 3321487Ssklower #include "../netinet/in.h" 3421487Ssklower #include "../netinet/in_systm.h" 3521487Ssklower #include "../netinet/in_var.h" 3621487Ssklower #include "../netinet/ip.h" 3721487Ssklower #include "../netinet/ip_var.h" 3821487Ssklower 3921487Ssklower #ifdef vax 4021487Ssklower #include "../vax/mtpr.h" 4121487Ssklower #endif 4221487Ssklower 4321487Ssklower #include "../netns/ns.h" 4421487Ssklower #include "../netns/ns_if.h" 4521487Ssklower #include "../netns/idp.h" 4621487Ssklower 4721487Ssklower struct ifnet_en { 4821487Ssklower struct ifnet ifen_ifnet; 4921487Ssklower struct route ifen_route; 5021487Ssklower struct in_addr ifen_src; 5121487Ssklower struct in_addr ifen_dst; 5221487Ssklower }; 5321487Ssklower 5421487Ssklower int nsipoutput(), nsipioctl(); 5521487Ssklower #define LOMTU (1024+512); 5621487Ssklower 5721487Ssklower struct ifnet nsipif; 5821487Ssklower struct mbuf *nsip_list; /* list of all hosts and gateways or 5921487Ssklower broadcast addrs */ 6021487Ssklower 6121487Ssklower struct mbuf * 6221487Ssklower nsipattach() 6321487Ssklower { 6421487Ssklower register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); 6521487Ssklower register struct ifnet *ifp; 6621487Ssklower 6725454Ssklower if (m == NULL) return (NULL); 6821487Ssklower m->m_off = MMINOFF; 6921487Ssklower m->m_len = sizeof(struct ifnet_en); 7021487Ssklower m->m_next = nsip_list; 7121487Ssklower nsip_list = m; 7221487Ssklower ifp = mtod(m, struct ifnet *); 7321487Ssklower 7421487Ssklower ifp->if_name = "nsip"; 7521487Ssklower ifp->if_mtu = LOMTU; 7621487Ssklower ifp->if_ioctl = nsipioctl; 7721487Ssklower ifp->if_output = nsipoutput; 7821487Ssklower ifp->if_flags = IFF_POINTOPOINT; 7921487Ssklower ifp->if_unit = nsipif.if_unit++; 8021487Ssklower if_attach(ifp); 8125454Ssklower return (dtom(ifp)); 8221487Ssklower } 8321487Ssklower 8421487Ssklower 8521487Ssklower /* 8621487Ssklower * Process an ioctl request. 8721487Ssklower */ 8821487Ssklower /* ARGSUSED */ 8921487Ssklower nsipioctl(ifp, cmd, data) 9021487Ssklower register struct ifnet *ifp; 9121487Ssklower int cmd; 9221487Ssklower caddr_t data; 9321487Ssklower { 9421487Ssklower int error = 0; 9525055Ssklower struct ifreq *ifr; 9621487Ssklower 9721487Ssklower switch (cmd) { 9821487Ssklower 9921487Ssklower case SIOCSIFADDR: 10021487Ssklower ifp->if_flags |= IFF_UP; 10125454Ssklower /* fall into: */ 10225454Ssklower 10325454Ssklower case SIOCSIFDSTADDR: 10421487Ssklower /* 10521487Ssklower * Everything else is done at a higher level. 10621487Ssklower */ 10721487Ssklower break; 10821487Ssklower 10925055Ssklower case SIOCSIFFLAGS: 11025055Ssklower ifr = (struct ifreq *)data; 11125055Ssklower if ((ifr->ifr_flags & IFF_UP) == 0) 11225055Ssklower error = nsip_free(ifp); 11325055Ssklower 11425055Ssklower 11521487Ssklower default: 11621487Ssklower error = EINVAL; 11721487Ssklower } 11821487Ssklower return (error); 11921487Ssklower } 12021487Ssklower 12121487Ssklower struct mbuf *nsip_badlen; 12221487Ssklower struct mbuf *nsip_lastin; 12321487Ssklower int nsip_hold_input; 12421487Ssklower 12524562Skarels idpip_input(m, ifp) 12624562Skarels register struct mbuf *m; 12724562Skarels struct ifnet *ifp; 12821487Ssklower { 12921487Ssklower register struct ip *ip; 13021487Ssklower register struct idp *idp; 13121487Ssklower register struct ifqueue *ifq = &nsintrq; 13221487Ssklower int len, s; 13321487Ssklower 13425454Ssklower if (nsip_hold_input) { 13525454Ssklower if (nsip_lastin) { 13624226Ssklower m_freem(nsip_lastin); 13721487Ssklower } 13824562Skarels nsip_lastin = m_copy(m, 0, (int)M_COPYALL); 13921487Ssklower } 14021487Ssklower /* 14121487Ssklower * Get IP and IDP header together in first mbuf. 14221487Ssklower */ 14321487Ssklower nsipif.if_ipackets++; 14421487Ssklower s = sizeof (struct ip) + sizeof (struct idp); 14521487Ssklower if ((m->m_off > MMAXOFF || m->m_len < s) && 14625454Ssklower (m = m_pullup(m, s)) == 0) { 14721487Ssklower nsipif.if_ierrors++; 14821487Ssklower return; 14921487Ssklower } 15021487Ssklower ip = mtod(m, struct ip *); 15124827Skarels if (ip->ip_hl > (sizeof (struct ip) >> 2)) { 15224827Skarels ip_stripoptions(ip, (struct mbuf *)0); 15324827Skarels if (m->m_len < s) { 15425454Ssklower if ((m = m_pullup(m, s)) == 0) { 15524827Skarels nsipif.if_ierrors++; 15624827Skarels return; 15724827Skarels } 15824827Skarels ip = mtod(m, struct ip *); 15924827Skarels } 16024827Skarels } 16121487Ssklower 16221487Ssklower /* 16321487Ssklower * Make mbuf data length reflect IDP length. 16421487Ssklower * If not enough data to reflect IDP length, drop. 16521487Ssklower */ 16621487Ssklower m->m_off += sizeof (struct ip); 16721487Ssklower m->m_len -= sizeof (struct ip); 16821487Ssklower idp = mtod(m, struct idp *); 16921487Ssklower len = ntohs(idp->idp_len); 17023839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 17121487Ssklower if (ip->ip_len != len) { 17221487Ssklower if (len > ip->ip_len) { 17321487Ssklower nsipif.if_ierrors++; 17425454Ssklower if (nsip_badlen) m_freem(nsip_badlen); 17521487Ssklower nsip_badlen = m; 17621487Ssklower return; 17721487Ssklower } 17824043Ssklower /* Any extra will be trimmed off by the NS routines */ 17921487Ssklower } 18024562Skarels 18121487Ssklower /* 18224562Skarels * Place interface pointer before the data 18324562Skarels * for the receiving protocol. 18424562Skarels */ 18524562Skarels if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) { 18624562Skarels m->m_off -= sizeof(struct ifnet *); 18724562Skarels m->m_len += sizeof(struct ifnet *); 18824562Skarels } else { 18924562Skarels struct mbuf *n; 19024562Skarels 19124562Skarels n = m_get(M_DONTWAIT, MT_HEADER); 19224562Skarels if (n == (struct mbuf *)0) 19324562Skarels goto bad; 19424562Skarels n->m_off = MMINOFF; 19524562Skarels n->m_len = sizeof(struct ifnet *); 19624562Skarels n->m_next = m; 19724562Skarels m = n; 19824562Skarels } 19924562Skarels *(mtod(m, struct ifnet **)) = ifp; 20024562Skarels 20124562Skarels /* 20221487Ssklower * Deliver to NS 20321487Ssklower */ 20421487Ssklower s = splimp(); 20521487Ssklower if (IF_QFULL(ifq)) { 20621487Ssklower IF_DROP(ifq); 20724562Skarels bad: 20824562Skarels m_freem(m); 20921487Ssklower splx(s); 21024226Ssklower return; 21121487Ssklower } 21224562Skarels IF_ENQUEUE(ifq, m); 21321487Ssklower schednetisr(NETISR_NS); 21421487Ssklower splx(s); 21524226Ssklower return; 21621487Ssklower } 21721487Ssklower 21824226Ssklower /* ARGSUSED */ 21921487Ssklower nsipoutput(ifn, m0, dst) 22021487Ssklower struct ifnet_en *ifn; 22121487Ssklower struct mbuf *m0; 22221487Ssklower struct sockaddr *dst; 22321487Ssklower { 22421487Ssklower 22521487Ssklower register struct mbuf *m = dtom(ifn); 22621487Ssklower register struct ip *ip; 22721487Ssklower register struct route *ro = &(ifn->ifen_route); 22821487Ssklower register int len = 0; 22921487Ssklower register struct idp *idp = mtod(m0, struct idp *); 23021487Ssklower int error; 23121487Ssklower 23221487Ssklower if (m->m_len != sizeof(struct ifnet_en)) { 23321487Ssklower printf("nsipoutput: bad dst ifp %x\n", ifn); 23421487Ssklower goto bad; 23521487Ssklower } 23621487Ssklower ifn->ifen_ifnet.if_opackets++; 23721487Ssklower nsipif.if_opackets++; 23821487Ssklower 23921487Ssklower 24021487Ssklower /* 24121487Ssklower * Calculate data length and make space 24221487Ssklower * for IP header. 24321487Ssklower */ 24421487Ssklower len = ntohs(idp->idp_len); 24523839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 24621487Ssklower m = m0; 24725454Ssklower if (m->m_off < MMINOFF + sizeof (struct ip)) { 24821487Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 24921487Ssklower if (m == 0) { 25021487Ssklower m_freem(m0); 25121487Ssklower return (ENOBUFS); 25221487Ssklower } 25321487Ssklower m->m_off = MMAXOFF - sizeof (struct ip); 25421487Ssklower m->m_len = sizeof (struct ip); 25521487Ssklower m->m_next = m0; 25621487Ssklower } else { 25721487Ssklower m->m_off -= sizeof (struct ip); 25821487Ssklower m->m_len += sizeof (struct ip); 25921487Ssklower } 26021487Ssklower /* 26121487Ssklower * Fill in IP header. 26221487Ssklower */ 26321487Ssklower ip = mtod(m, struct ip *); 26421487Ssklower *(long *)ip = 0; 26524043Ssklower ip->ip_p = IPPROTO_IDP; 26621487Ssklower ip->ip_src = ifn->ifen_src; 26721487Ssklower ip->ip_dst = ifn->ifen_dst; 26821487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip); 26921487Ssklower ip->ip_ttl = MAXTTL; 27021487Ssklower 27121487Ssklower /* 27221487Ssklower * Output final datagram. 27321487Ssklower */ 27421487Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 27521487Ssklower if (error) { 27621487Ssklower ifn->ifen_ifnet.if_oerrors++; 27721487Ssklower ifn->ifen_ifnet.if_ierrors = error; 27821487Ssklower } 27921487Ssklower return (error); 28021487Ssklower bad: 28121487Ssklower m_freem(m0); 28225454Ssklower return (ENETUNREACH); 28321487Ssklower } 28421487Ssklower 28521487Ssklower struct ifreq ifr = {"nsip0"}; 28621487Ssklower 28721487Ssklower nsip_route(m) 28821487Ssklower register struct mbuf *m; 28921487Ssklower { 29021487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *); 29121487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 29221487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 29321487Ssklower struct route ro; 29421487Ssklower struct ifnet_en *ifn; 29521487Ssklower struct sockaddr_in *src; 29625454Ssklower 29721487Ssklower /* 29825454Ssklower * First, make sure we already have an ns address: 29921487Ssklower */ 30025454Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) 30125454Ssklower return (EADDRNOTAVAIL); 30225454Ssklower /* 30325454Ssklower * Now, determine if we can get to the destination 30425454Ssklower */ 30521487Ssklower bzero((caddr_t)&ro, sizeof (ro)); 30621487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst; 30721487Ssklower rtalloc(&ro); 30824226Ssklower if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { 30921487Ssklower return (ENETUNREACH); 31021487Ssklower } 31125454Ssklower 31221487Ssklower /* 31321487Ssklower * And see how he's going to get back to us: 31425454Ssklower * i.e., what return ip address do we use? 31521487Ssklower */ 31621487Ssklower { 31721487Ssklower register struct in_ifaddr *ia; 31821487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp; 31921487Ssklower 32021487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 32121487Ssklower if (ia->ia_ifp == ifp) 32221487Ssklower break; 32321487Ssklower if (ia == 0) 32421487Ssklower ia = in_ifaddr; 32521487Ssklower if (ia == 0) { 32625454Ssklower RTFREE(ro.ro_rt); 32721487Ssklower return (EADDRNOTAVAIL); 32821487Ssklower } 32921487Ssklower src = (struct sockaddr_in *)&ia->ia_addr; 33021487Ssklower } 33125454Ssklower 33221487Ssklower /* 33325055Ssklower * Is there a free (pseudo-)interface or space? 33421487Ssklower */ 33525055Ssklower for (m = nsip_list; m; m = m->m_next) { 33625055Ssklower struct ifnet *ifp = mtod(m, struct ifnet *); 33725055Ssklower if ((ifp->if_flags & IFF_UP) == 0) 33825055Ssklower break; 33925055Ssklower } 34025055Ssklower if (m == (struct mbuf *) 0) 34125055Ssklower m = nsipattach(); 34225454Ssklower if (m == NULL) { 34325454Ssklower RTFREE(ro.ro_rt); 34425454Ssklower return (ENOBUFS); 34525454Ssklower } 34621487Ssklower ifn = mtod(m, struct ifnet_en *); 34721487Ssklower 34821487Ssklower ifn->ifen_route = ro; 34921487Ssklower ifn->ifen_dst = ip_dst->sin_addr; 35021487Ssklower ifn->ifen_src = src->sin_addr; 35121487Ssklower 35221487Ssklower /* 35321487Ssklower * now configure this as a point to point link 35421487Ssklower */ 35521487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 35621487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 35725454Ssklower (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr, 35825454Ssklower (struct ifnet *)ifn); 35925454Ssklower satons_addr(ifr.ifr_addr).x_host = ns_thishost; 36025454Ssklower return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr, 36121487Ssklower (struct ifnet *)ifn)); 36221487Ssklower } 36325055Ssklower 36425055Ssklower nsip_free(ifp) 36525055Ssklower struct ifnet *ifp; 36625055Ssklower { 36725055Ssklower register struct ifnet_en *ifn = (struct ifnet_en *)ifp; 36825055Ssklower struct route *ro = & ifn->ifen_route; 36925055Ssklower 37025055Ssklower if (ro->ro_rt) { 37125055Ssklower RTFREE(ro->ro_rt); 37225055Ssklower ro->ro_rt = 0; 37325055Ssklower } 37425055Ssklower ifp->if_flags &= ~IFF_UP; 37525055Ssklower return (0); 37625055Ssklower } 37725055Ssklower 37825055Ssklower nsip_ctlinput(cmd, sa) 37925055Ssklower int cmd; 38025055Ssklower struct sockaddr *sa; 38125055Ssklower { 38225055Ssklower extern u_char inetctlerrmap[]; 38325055Ssklower struct sockaddr_in *sin; 38425055Ssklower int in_rtchange(); 38525055Ssklower 38625454Ssklower if ((unsigned)cmd >= PRC_NCMDS) 38725055Ssklower return; 38825055Ssklower if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) 38925055Ssklower return; 39025055Ssklower sin = (struct sockaddr_in *)sa; 39125055Ssklower if (sin->sin_addr.s_addr == INADDR_ANY) 39225055Ssklower return; 39325055Ssklower 39425055Ssklower switch (cmd) { 39525055Ssklower 39625055Ssklower case PRC_ROUTEDEAD: 39725055Ssklower case PRC_REDIRECT_NET: 39825055Ssklower case PRC_REDIRECT_HOST: 39925055Ssklower case PRC_REDIRECT_TOSNET: 40025055Ssklower case PRC_REDIRECT_TOSHOST: 40125055Ssklower nsip_rtchange(&sin->sin_addr); 40225055Ssklower break; 40325055Ssklower } 40425055Ssklower } 40525055Ssklower 40625055Ssklower nsip_rtchange(dst) 40725055Ssklower register struct in_addr *dst; 40825055Ssklower { 40925055Ssklower register struct mbuf *m; 41025055Ssklower register struct ifnet_en *ifn; 41125055Ssklower 41225211Smckusick for (m = nsip_list; m; m = m->m_next) { 41325211Smckusick ifn = mtod(m, struct ifnet_en *); 41425055Ssklower if (ifn->ifen_dst.s_addr == dst->s_addr && 41525055Ssklower ifn->ifen_route.ro_rt) { 41625055Ssklower RTFREE(ifn->ifen_route.ro_rt); 41725055Ssklower ifn->ifen_route.ro_rt = 0; 41825055Ssklower } 41925211Smckusick } 42025055Ssklower } 42121487Ssklower #endif 422