123210Smckusick /* 233371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 333371Ssklower * All rights reserved. 423210Smckusick * 533371Ssklower * Redistribution and use in source and binary forms are permitted 634856Sbostic * provided that the above copyright notice and this paragraph are 734856Sbostic * duplicated in all such forms and that any documentation, 834856Sbostic * advertising materials, and other materials related to such 934856Sbostic * distribution and use acknowledge that the software was developed 1034856Sbostic * by the University of California, Berkeley. The name of the 1134856Sbostic * University may not be used to endorse or promote products derived 1234856Sbostic * from this software without specific prior written permission. 1334856Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434856Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534856Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633371Ssklower * 17*37473Ssklower * @(#)ns_ip.c 7.4 (Berkeley) 04/22/89 1823210Smckusick */ 1921487Ssklower 2021487Ssklower /* 2121487Ssklower * Software interface driver for encapsulating ns in ip. 2221487Ssklower */ 2321487Ssklower 2421487Ssklower #ifdef NSIP 2521487Ssklower #include "param.h" 2621487Ssklower #include "systm.h" 27*37473Ssklower #include "malloc.h" 2821487Ssklower #include "mbuf.h" 2921487Ssklower #include "socket.h" 3024226Ssklower #include "socketvar.h" 3121487Ssklower #include "errno.h" 3221487Ssklower #include "ioctl.h" 3325055Ssklower #include "protosw.h" 3421487Ssklower 3521487Ssklower #include "../net/if.h" 3621487Ssklower #include "../net/netisr.h" 3721487Ssklower #include "../net/route.h" 3821487Ssklower 3921487Ssklower #include "../netinet/in.h" 4021487Ssklower #include "../netinet/in_systm.h" 4121487Ssklower #include "../netinet/in_var.h" 4221487Ssklower #include "../netinet/ip.h" 4321487Ssklower #include "../netinet/ip_var.h" 4421487Ssklower 45*37473Ssklower #include "../machine/mtpr.h" 4621487Ssklower 4721487Ssklower #include "../netns/ns.h" 4821487Ssklower #include "../netns/ns_if.h" 4921487Ssklower #include "../netns/idp.h" 5021487Ssklower 5121487Ssklower struct ifnet_en { 5221487Ssklower struct ifnet ifen_ifnet; 5321487Ssklower struct route ifen_route; 5421487Ssklower struct in_addr ifen_src; 5521487Ssklower struct in_addr ifen_dst; 56*37473Ssklower struct ifnet_en *ifen_next; 5721487Ssklower }; 5821487Ssklower 59*37473Ssklower int nsipoutput(), nsipioctl(), nsipstart(); 6021487Ssklower #define LOMTU (1024+512); 6121487Ssklower 6221487Ssklower struct ifnet nsipif; 63*37473Ssklower struct ifnet_en *nsip_list; /* list of all hosts and gateways or 6421487Ssklower broadcast addrs */ 6521487Ssklower 66*37473Ssklower struct ifnet_en * 6721487Ssklower nsipattach() 6821487Ssklower { 69*37473Ssklower register struct ifnet_en *m; 7021487Ssklower register struct ifnet *ifp; 7121487Ssklower 72*37473Ssklower if (nsipif.if_mtu == 0) { 73*37473Ssklower ifp = &nsipif; 74*37473Ssklower ifp->if_name = "nsip"; 75*37473Ssklower ifp->if_mtu = LOMTU; 76*37473Ssklower ifp->if_ioctl = nsipioctl; 77*37473Ssklower ifp->if_output = nsipoutput; 78*37473Ssklower ifp->if_start = nsipstart; 79*37473Ssklower ifp->if_flags = IFF_POINTOPOINT; 80*37473Ssklower } 81*37473Ssklower 82*37473Ssklower MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT); 8325454Ssklower if (m == NULL) return (NULL); 84*37473Ssklower m->ifen_next = nsip_list; 8521487Ssklower nsip_list = m; 86*37473Ssklower ifp = &m->ifen_ifnet; 8721487Ssklower 8821487Ssklower ifp->if_name = "nsip"; 8921487Ssklower ifp->if_mtu = LOMTU; 9021487Ssklower ifp->if_ioctl = nsipioctl; 9121487Ssklower ifp->if_output = nsipoutput; 92*37473Ssklower ifp->if_start = nsipstart; 9321487Ssklower ifp->if_flags = IFF_POINTOPOINT; 9421487Ssklower ifp->if_unit = nsipif.if_unit++; 9521487Ssklower if_attach(ifp); 96*37473Ssklower 97*37473Ssklower return (m); 9821487Ssklower } 9921487Ssklower 10021487Ssklower 10121487Ssklower /* 10221487Ssklower * Process an ioctl request. 10321487Ssklower */ 10421487Ssklower /* ARGSUSED */ 10521487Ssklower nsipioctl(ifp, cmd, data) 10621487Ssklower register struct ifnet *ifp; 10721487Ssklower int cmd; 10821487Ssklower caddr_t data; 10921487Ssklower { 11021487Ssklower int error = 0; 11125055Ssklower struct ifreq *ifr; 11221487Ssklower 11321487Ssklower switch (cmd) { 11421487Ssklower 11521487Ssklower case SIOCSIFADDR: 11621487Ssklower ifp->if_flags |= IFF_UP; 11725454Ssklower /* fall into: */ 11825454Ssklower 11925454Ssklower case SIOCSIFDSTADDR: 12021487Ssklower /* 12121487Ssklower * Everything else is done at a higher level. 12221487Ssklower */ 12321487Ssklower break; 12421487Ssklower 12525055Ssklower case SIOCSIFFLAGS: 12625055Ssklower ifr = (struct ifreq *)data; 12725055Ssklower if ((ifr->ifr_flags & IFF_UP) == 0) 12825055Ssklower error = nsip_free(ifp); 12925055Ssklower 13025055Ssklower 13121487Ssklower default: 13221487Ssklower error = EINVAL; 13321487Ssklower } 13421487Ssklower return (error); 13521487Ssklower } 13621487Ssklower 13721487Ssklower struct mbuf *nsip_badlen; 13821487Ssklower struct mbuf *nsip_lastin; 13921487Ssklower int nsip_hold_input; 14021487Ssklower 14124562Skarels idpip_input(m, ifp) 14224562Skarels register struct mbuf *m; 14324562Skarels struct ifnet *ifp; 14421487Ssklower { 14521487Ssklower register struct ip *ip; 14621487Ssklower register struct idp *idp; 14721487Ssklower register struct ifqueue *ifq = &nsintrq; 14821487Ssklower int len, s; 14921487Ssklower 15025454Ssklower if (nsip_hold_input) { 15125454Ssklower if (nsip_lastin) { 15224226Ssklower m_freem(nsip_lastin); 15321487Ssklower } 154*37473Ssklower nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT); 15521487Ssklower } 15621487Ssklower /* 15721487Ssklower * Get IP and IDP header together in first mbuf. 15821487Ssklower */ 15921487Ssklower nsipif.if_ipackets++; 16021487Ssklower s = sizeof (struct ip) + sizeof (struct idp); 161*37473Ssklower if (((m->m_flags & M_EXT) || m->m_len < s) && 16225454Ssklower (m = m_pullup(m, s)) == 0) { 16321487Ssklower nsipif.if_ierrors++; 16421487Ssklower return; 16521487Ssklower } 16621487Ssklower ip = mtod(m, struct ip *); 16724827Skarels if (ip->ip_hl > (sizeof (struct ip) >> 2)) { 16824827Skarels ip_stripoptions(ip, (struct mbuf *)0); 16924827Skarels if (m->m_len < s) { 17025454Ssklower if ((m = m_pullup(m, s)) == 0) { 17124827Skarels nsipif.if_ierrors++; 17224827Skarels return; 17324827Skarels } 17424827Skarels ip = mtod(m, struct ip *); 17524827Skarels } 17624827Skarels } 17721487Ssklower 17821487Ssklower /* 17921487Ssklower * Make mbuf data length reflect IDP length. 18021487Ssklower * If not enough data to reflect IDP length, drop. 18121487Ssklower */ 182*37473Ssklower m->m_data += sizeof (struct ip); 18321487Ssklower m->m_len -= sizeof (struct ip); 184*37473Ssklower m->m_pkthdr.len -= sizeof (struct ip); 18521487Ssklower idp = mtod(m, struct idp *); 18621487Ssklower len = ntohs(idp->idp_len); 18723839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 18821487Ssklower if (ip->ip_len != len) { 18921487Ssklower if (len > ip->ip_len) { 19021487Ssklower nsipif.if_ierrors++; 19125454Ssklower if (nsip_badlen) m_freem(nsip_badlen); 19221487Ssklower nsip_badlen = m; 19321487Ssklower return; 19421487Ssklower } 19524043Ssklower /* Any extra will be trimmed off by the NS routines */ 19621487Ssklower } 19724562Skarels 19821487Ssklower /* 19924562Skarels * Place interface pointer before the data 20024562Skarels * for the receiving protocol. 20124562Skarels */ 202*37473Ssklower m->m_pkthdr.rcvif = ifp; 20324562Skarels /* 20421487Ssklower * Deliver to NS 20521487Ssklower */ 20621487Ssklower s = splimp(); 20721487Ssklower if (IF_QFULL(ifq)) { 20821487Ssklower IF_DROP(ifq); 20924562Skarels bad: 21024562Skarels m_freem(m); 21121487Ssklower splx(s); 21224226Ssklower return; 21321487Ssklower } 21424562Skarels IF_ENQUEUE(ifq, m); 21521487Ssklower schednetisr(NETISR_NS); 21621487Ssklower splx(s); 21724226Ssklower return; 21821487Ssklower } 21921487Ssklower 22024226Ssklower /* ARGSUSED */ 221*37473Ssklower nsipoutput(ifn, m, dst) 22221487Ssklower struct ifnet_en *ifn; 223*37473Ssklower register struct mbuf *m; 22421487Ssklower struct sockaddr *dst; 22521487Ssklower { 22621487Ssklower 22721487Ssklower register struct ip *ip; 22821487Ssklower register struct route *ro = &(ifn->ifen_route); 22921487Ssklower register int len = 0; 230*37473Ssklower register struct idp *idp = mtod(m, struct idp *); 23121487Ssklower int error; 23221487Ssklower 23321487Ssklower ifn->ifen_ifnet.if_opackets++; 23421487Ssklower nsipif.if_opackets++; 23521487Ssklower 23621487Ssklower 23721487Ssklower /* 23821487Ssklower * Calculate data length and make space 23921487Ssklower * for IP header. 24021487Ssklower */ 24121487Ssklower len = ntohs(idp->idp_len); 24223839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 243*37473Ssklower /* following clause not necessary on vax */ 244*37473Ssklower if (3 & (int)m->m_data) { 245*37473Ssklower /* force longword alignment of ip hdr */ 246*37473Ssklower struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT); 247*37473Ssklower if (m0 == 0) { 248*37473Ssklower m_freem(m); 24921487Ssklower return (ENOBUFS); 25021487Ssklower } 251*37473Ssklower MH_ALIGN(m0, sizeof (struct ip)); 252*37473Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS; 253*37473Ssklower m0->m_next = m; 254*37473Ssklower m0->m_len = sizeof (struct ip); 255*37473Ssklower m0->m_pkthdr.len = m0->m_len + m->m_len; 256*37473Ssklower m->m_flags &= ~M_PKTHDR; 25721487Ssklower } else { 258*37473Ssklower M_PREPEND(m, sizeof (struct ip), M_DONTWAIT); 259*37473Ssklower if (m == 0) 260*37473Ssklower return (ENOBUFS); 26121487Ssklower } 26221487Ssklower /* 26321487Ssklower * Fill in IP header. 26421487Ssklower */ 26521487Ssklower ip = mtod(m, struct ip *); 26621487Ssklower *(long *)ip = 0; 26724043Ssklower ip->ip_p = IPPROTO_IDP; 26821487Ssklower ip->ip_src = ifn->ifen_src; 26921487Ssklower ip->ip_dst = ifn->ifen_dst; 27021487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip); 27121487Ssklower ip->ip_ttl = MAXTTL; 27221487Ssklower 27321487Ssklower /* 27421487Ssklower * Output final datagram. 27521487Ssklower */ 27621487Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 27721487Ssklower if (error) { 27821487Ssklower ifn->ifen_ifnet.if_oerrors++; 27921487Ssklower ifn->ifen_ifnet.if_ierrors = error; 28021487Ssklower } 28121487Ssklower return (error); 28221487Ssklower bad: 283*37473Ssklower m_freem(m); 28425454Ssklower return (ENETUNREACH); 28521487Ssklower } 28621487Ssklower 287*37473Ssklower nsipstart(ifp) 288*37473Ssklower struct ifnet *ifp; 289*37473Ssklower { 290*37473Ssklower panic("nsip_start called\n"); 291*37473Ssklower } 292*37473Ssklower 29321487Ssklower struct ifreq ifr = {"nsip0"}; 29421487Ssklower 29521487Ssklower nsip_route(m) 29621487Ssklower register struct mbuf *m; 29721487Ssklower { 29821487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *); 29921487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 30021487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 30121487Ssklower struct route ro; 30221487Ssklower struct ifnet_en *ifn; 30321487Ssklower struct sockaddr_in *src; 30425454Ssklower 30521487Ssklower /* 30625454Ssklower * First, make sure we already have an ns address: 30721487Ssklower */ 30825454Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) 30925454Ssklower return (EADDRNOTAVAIL); 31025454Ssklower /* 31125454Ssklower * Now, determine if we can get to the destination 31225454Ssklower */ 31321487Ssklower bzero((caddr_t)&ro, sizeof (ro)); 31421487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst; 31521487Ssklower rtalloc(&ro); 31624226Ssklower if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { 31721487Ssklower return (ENETUNREACH); 31821487Ssklower } 31925454Ssklower 32021487Ssklower /* 32121487Ssklower * And see how he's going to get back to us: 32225454Ssklower * i.e., what return ip address do we use? 32321487Ssklower */ 32421487Ssklower { 32521487Ssklower register struct in_ifaddr *ia; 32621487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp; 32721487Ssklower 32821487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 32921487Ssklower if (ia->ia_ifp == ifp) 33021487Ssklower break; 33121487Ssklower if (ia == 0) 33221487Ssklower ia = in_ifaddr; 33321487Ssklower if (ia == 0) { 33425454Ssklower RTFREE(ro.ro_rt); 33521487Ssklower return (EADDRNOTAVAIL); 33621487Ssklower } 33721487Ssklower src = (struct sockaddr_in *)&ia->ia_addr; 33821487Ssklower } 33925454Ssklower 34021487Ssklower /* 34125055Ssklower * Is there a free (pseudo-)interface or space? 34221487Ssklower */ 343*37473Ssklower for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) { 344*37473Ssklower if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0) 34525055Ssklower break; 34625055Ssklower } 347*37473Ssklower if (ifn == NULL) 348*37473Ssklower ifn = nsipattach(); 349*37473Ssklower if (ifn == NULL) { 35025454Ssklower RTFREE(ro.ro_rt); 35125454Ssklower return (ENOBUFS); 35225454Ssklower } 35321487Ssklower ifn->ifen_route = ro; 35421487Ssklower ifn->ifen_dst = ip_dst->sin_addr; 35521487Ssklower ifn->ifen_src = src->sin_addr; 35621487Ssklower 35721487Ssklower /* 35821487Ssklower * now configure this as a point to point link 35921487Ssklower */ 36021487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 36121487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 36225454Ssklower (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr, 36325454Ssklower (struct ifnet *)ifn); 36425454Ssklower satons_addr(ifr.ifr_addr).x_host = ns_thishost; 36525454Ssklower return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr, 36621487Ssklower (struct ifnet *)ifn)); 36721487Ssklower } 36825055Ssklower 36925055Ssklower nsip_free(ifp) 37025055Ssklower struct ifnet *ifp; 37125055Ssklower { 37225055Ssklower register struct ifnet_en *ifn = (struct ifnet_en *)ifp; 37325055Ssklower struct route *ro = & ifn->ifen_route; 37425055Ssklower 37525055Ssklower if (ro->ro_rt) { 37625055Ssklower RTFREE(ro->ro_rt); 37725055Ssklower ro->ro_rt = 0; 37825055Ssklower } 37925055Ssklower ifp->if_flags &= ~IFF_UP; 38025055Ssklower return (0); 38125055Ssklower } 38225055Ssklower 38325055Ssklower nsip_ctlinput(cmd, sa) 38425055Ssklower int cmd; 38525055Ssklower struct sockaddr *sa; 38625055Ssklower { 38725055Ssklower extern u_char inetctlerrmap[]; 38825055Ssklower struct sockaddr_in *sin; 38925055Ssklower int in_rtchange(); 39025055Ssklower 39125454Ssklower if ((unsigned)cmd >= PRC_NCMDS) 39225055Ssklower return; 39325055Ssklower if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) 39425055Ssklower return; 39525055Ssklower sin = (struct sockaddr_in *)sa; 39625055Ssklower if (sin->sin_addr.s_addr == INADDR_ANY) 39725055Ssklower return; 39825055Ssklower 39925055Ssklower switch (cmd) { 40025055Ssklower 40125055Ssklower case PRC_ROUTEDEAD: 40225055Ssklower case PRC_REDIRECT_NET: 40325055Ssklower case PRC_REDIRECT_HOST: 40425055Ssklower case PRC_REDIRECT_TOSNET: 40525055Ssklower case PRC_REDIRECT_TOSHOST: 40625055Ssklower nsip_rtchange(&sin->sin_addr); 40725055Ssklower break; 40825055Ssklower } 40925055Ssklower } 41025055Ssklower 41125055Ssklower nsip_rtchange(dst) 41225055Ssklower register struct in_addr *dst; 41325055Ssklower { 41425055Ssklower register struct ifnet_en *ifn; 41525055Ssklower 416*37473Ssklower for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) { 41725055Ssklower if (ifn->ifen_dst.s_addr == dst->s_addr && 41825055Ssklower ifn->ifen_route.ro_rt) { 41925055Ssklower RTFREE(ifn->ifen_route.ro_rt); 42025055Ssklower ifn->ifen_route.ro_rt = 0; 42125055Ssklower } 42225211Smckusick } 42325055Ssklower } 42421487Ssklower #endif 425