1*21487Ssklower /* ns_ip.c 6.1 85/05/30 */ 2*21487Ssklower 3*21487Ssklower /* 4*21487Ssklower * Software interface driver for encapsulating ns in ip. 5*21487Ssklower */ 6*21487Ssklower 7*21487Ssklower #ifdef NSIP 8*21487Ssklower #include "param.h" 9*21487Ssklower #include "systm.h" 10*21487Ssklower #include "mbuf.h" 11*21487Ssklower #include "socket.h" 12*21487Ssklower #include "errno.h" 13*21487Ssklower #include "ioctl.h" 14*21487Ssklower 15*21487Ssklower #include "../net/if.h" 16*21487Ssklower #include "../net/netisr.h" 17*21487Ssklower #include "../net/route.h" 18*21487Ssklower 19*21487Ssklower #include "../netinet/in.h" 20*21487Ssklower #include "../netinet/in_systm.h" 21*21487Ssklower #include "../netinet/in_var.h" 22*21487Ssklower #include "../netinet/ip.h" 23*21487Ssklower #include "../netinet/ip_var.h" 24*21487Ssklower 25*21487Ssklower #ifdef vax 26*21487Ssklower #include "../vax/mtpr.h" 27*21487Ssklower #endif 28*21487Ssklower 29*21487Ssklower #include "../netns/ns.h" 30*21487Ssklower #include "../netns/ns_if.h" 31*21487Ssklower #include "../netns/idp.h" 32*21487Ssklower 33*21487Ssklower struct ifnet_en { 34*21487Ssklower struct ifnet ifen_ifnet; 35*21487Ssklower struct route ifen_route; 36*21487Ssklower struct in_addr ifen_src; 37*21487Ssklower struct in_addr ifen_dst; 38*21487Ssklower }; 39*21487Ssklower 40*21487Ssklower int nsipoutput(), nsipioctl(); 41*21487Ssklower #define LOMTU (1024+512); 42*21487Ssklower 43*21487Ssklower struct ifnet nsipif; 44*21487Ssklower union ns_net nsip_net; 45*21487Ssklower struct mbuf *nsip_list; /* list of all hosts and gateways or 46*21487Ssklower broadcast addrs */ 47*21487Ssklower 48*21487Ssklower struct mbuf * 49*21487Ssklower nsipattach() 50*21487Ssklower { 51*21487Ssklower register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); 52*21487Ssklower register struct ifnet *ifp; 53*21487Ssklower register struct sockaddr_in *sin; 54*21487Ssklower 55*21487Ssklower if (m==0) return (0); 56*21487Ssklower m->m_off = MMINOFF; 57*21487Ssklower m->m_len = sizeof(struct ifnet_en); 58*21487Ssklower m->m_next = nsip_list; 59*21487Ssklower nsip_list = m; 60*21487Ssklower ifp = mtod(m, struct ifnet *); 61*21487Ssklower 62*21487Ssklower ifp->if_name = "nsip"; 63*21487Ssklower ifp->if_mtu = LOMTU; 64*21487Ssklower ifp->if_ioctl = nsipioctl; 65*21487Ssklower ifp->if_output = nsipoutput; 66*21487Ssklower ifp->if_flags = IFF_POINTOPOINT; 67*21487Ssklower ifp->if_unit = nsipif.if_unit++; 68*21487Ssklower if_attach(ifp); 69*21487Ssklower return(dtom(ifp)); 70*21487Ssklower } 71*21487Ssklower 72*21487Ssklower 73*21487Ssklower /* 74*21487Ssklower * Process an ioctl request. 75*21487Ssklower */ 76*21487Ssklower /* ARGSUSED */ 77*21487Ssklower nsipioctl(ifp, cmd, data) 78*21487Ssklower register struct ifnet *ifp; 79*21487Ssklower int cmd; 80*21487Ssklower caddr_t data; 81*21487Ssklower { 82*21487Ssklower int error = 0; 83*21487Ssklower 84*21487Ssklower switch (cmd) { 85*21487Ssklower 86*21487Ssklower case SIOCSIFADDR: 87*21487Ssklower ifp->if_flags |= IFF_UP; 88*21487Ssklower /* 89*21487Ssklower * Everything else is done at a higher level. 90*21487Ssklower */ 91*21487Ssklower break; 92*21487Ssklower 93*21487Ssklower default: 94*21487Ssklower error = EINVAL; 95*21487Ssklower } 96*21487Ssklower return (error); 97*21487Ssklower } 98*21487Ssklower 99*21487Ssklower struct mbuf *nsip_badlen; 100*21487Ssklower struct mbuf *nsip_lastin; 101*21487Ssklower int nsip_hold_input; 102*21487Ssklower 103*21487Ssklower idpip_input(m0) 104*21487Ssklower struct mbuf *m0; 105*21487Ssklower { 106*21487Ssklower register struct ip *ip; 107*21487Ssklower register struct idp *idp; 108*21487Ssklower register struct mbuf *m; 109*21487Ssklower register struct ifqueue *ifq = &nsintrq; 110*21487Ssklower int len, s; 111*21487Ssklower 112*21487Ssklower if(nsip_hold_input) { 113*21487Ssklower if(nsip_lastin) { 114*21487Ssklower m_free(nsip_lastin); 115*21487Ssklower } 116*21487Ssklower nsip_lastin = m_copy(m0, 0, M_COPYALL); 117*21487Ssklower } 118*21487Ssklower /* 119*21487Ssklower * Get IP and IDP header together in first mbuf. 120*21487Ssklower */ 121*21487Ssklower nsipif.if_ipackets++; 122*21487Ssklower m = m0; 123*21487Ssklower s = sizeof (struct ip) + sizeof (struct idp); 124*21487Ssklower if ((m->m_off > MMAXOFF || m->m_len < s) && 125*21487Ssklower (m = m_pullup(m, s))==0) { 126*21487Ssklower nsipif.if_ierrors++; 127*21487Ssklower return; 128*21487Ssklower } 129*21487Ssklower ip = mtod(m, struct ip *); 130*21487Ssklower if (ip->ip_hl > (sizeof (struct ip) >> 2)) 131*21487Ssklower ip_stripoptions(ip, (struct mbuf *)0); 132*21487Ssklower 133*21487Ssklower /* 134*21487Ssklower * Make mbuf data length reflect IDP length. 135*21487Ssklower * If not enough data to reflect IDP length, drop. 136*21487Ssklower */ 137*21487Ssklower m->m_off += sizeof (struct ip); 138*21487Ssklower m->m_len -= sizeof (struct ip); 139*21487Ssklower idp = mtod(m, struct idp *); 140*21487Ssklower len = ntohs(idp->idp_len); 141*21487Ssklower if (ip->ip_len != len) { 142*21487Ssklower if (len > ip->ip_len) { 143*21487Ssklower nsipif.if_ierrors++; 144*21487Ssklower if(nsip_badlen) m_freem(nsip_badlen); 145*21487Ssklower nsip_badlen = m; 146*21487Ssklower return; 147*21487Ssklower } 148*21487Ssklower m_adj(m, len - ip->ip_len); 149*21487Ssklower /* ip->ip_len = len; */ 150*21487Ssklower } 151*21487Ssklower /* 152*21487Ssklower * Deliver to NS 153*21487Ssklower */ 154*21487Ssklower s = splimp(); 155*21487Ssklower if (IF_QFULL(ifq)) { 156*21487Ssklower IF_DROP(ifq); 157*21487Ssklower m_freem(m0); 158*21487Ssklower splx(s); 159*21487Ssklower return (ENOBUFS); 160*21487Ssklower } 161*21487Ssklower IF_ENQUEUE(ifq, m0); 162*21487Ssklower schednetisr(NETISR_NS); 163*21487Ssklower splx(s); 164*21487Ssklower return (0); 165*21487Ssklower bad: 166*21487Ssklower m_freem(m); 167*21487Ssklower return (0); 168*21487Ssklower } 169*21487Ssklower 170*21487Ssklower nsipoutput(ifn, m0, dst) 171*21487Ssklower struct ifnet_en *ifn; 172*21487Ssklower struct mbuf *m0; 173*21487Ssklower struct sockaddr *dst; 174*21487Ssklower { 175*21487Ssklower 176*21487Ssklower register struct mbuf *m = dtom(ifn); 177*21487Ssklower register struct ip *ip; 178*21487Ssklower register struct route *ro = &(ifn->ifen_route); 179*21487Ssklower register int len = 0; 180*21487Ssklower struct in_addr in_src, in_dst; 181*21487Ssklower register struct idp *idp = mtod(m0, struct idp *); 182*21487Ssklower int error; 183*21487Ssklower 184*21487Ssklower if (m->m_len != sizeof(struct ifnet_en)) { 185*21487Ssklower printf("nsipoutput: bad dst ifp %x\n", ifn); 186*21487Ssklower goto bad; 187*21487Ssklower } 188*21487Ssklower ifn->ifen_ifnet.if_opackets++; 189*21487Ssklower nsipif.if_opackets++; 190*21487Ssklower 191*21487Ssklower 192*21487Ssklower /* 193*21487Ssklower * Calculate data length and make space 194*21487Ssklower * for IP header. 195*21487Ssklower */ 196*21487Ssklower len = ntohs(idp->idp_len); 197*21487Ssklower m = m0; 198*21487Ssklower if(m->m_off < MMINOFF + sizeof (struct ip)) { 199*21487Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 200*21487Ssklower if (m == 0) { 201*21487Ssklower m_freem(m0); 202*21487Ssklower return (ENOBUFS); 203*21487Ssklower } 204*21487Ssklower m->m_off = MMAXOFF - sizeof (struct ip); 205*21487Ssklower m->m_len = sizeof (struct ip); 206*21487Ssklower m->m_next = m0; 207*21487Ssklower } else { 208*21487Ssklower m->m_off -= sizeof (struct ip); 209*21487Ssklower m->m_len += sizeof (struct ip); 210*21487Ssklower } 211*21487Ssklower /* 212*21487Ssklower * Fill in IP header. 213*21487Ssklower */ 214*21487Ssklower ip = mtod(m, struct ip *); 215*21487Ssklower *(long *)ip = 0; 216*21487Ssklower ip->ip_p = IPPROTO_PUP; 217*21487Ssklower ip->ip_src = ifn->ifen_src; 218*21487Ssklower ip->ip_dst = ifn->ifen_dst; 219*21487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip); 220*21487Ssklower ip->ip_ttl = MAXTTL; 221*21487Ssklower 222*21487Ssklower /* 223*21487Ssklower * Output final datagram. 224*21487Ssklower */ 225*21487Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 226*21487Ssklower if (error) { 227*21487Ssklower ifn->ifen_ifnet.if_oerrors++; 228*21487Ssklower ifn->ifen_ifnet.if_ierrors = error; 229*21487Ssklower } 230*21487Ssklower return (error); 231*21487Ssklower bad: 232*21487Ssklower m_freem(m0); 233*21487Ssklower return(ENETUNREACH); 234*21487Ssklower } 235*21487Ssklower 236*21487Ssklower struct ifreq ifr = {"nsip0"}; 237*21487Ssklower 238*21487Ssklower nsip_route(m) 239*21487Ssklower register struct mbuf *m; 240*21487Ssklower { 241*21487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *); 242*21487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 243*21487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 244*21487Ssklower int flags = rq->rq_flags; 245*21487Ssklower struct ifnet *ifp; 246*21487Ssklower struct route ro; 247*21487Ssklower struct ifnet_en *ifn; 248*21487Ssklower int error; 249*21487Ssklower struct sockaddr_in *dst; 250*21487Ssklower struct sockaddr_in *src; 251*21487Ssklower /* 252*21487Ssklower * First, determine if we can get to the destination 253*21487Ssklower */ 254*21487Ssklower bzero((caddr_t)&ro, sizeof (ro)); 255*21487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst; 256*21487Ssklower dst = (struct sockaddr_in *)& ro.ro_dst; 257*21487Ssklower rtalloc(&ro); 258*21487Ssklower if (ro.ro_rt == 0 || (ifp = ro.ro_rt->rt_ifp) == 0) { 259*21487Ssklower return (ENETUNREACH); 260*21487Ssklower } 261*21487Ssklower /* 262*21487Ssklower * And see how he's going to get back to us: 263*21487Ssklower */ 264*21487Ssklower { 265*21487Ssklower register struct in_ifaddr *ia; 266*21487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp; 267*21487Ssklower 268*21487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 269*21487Ssklower if (ia->ia_ifp == ifp) 270*21487Ssklower break; 271*21487Ssklower if (ia == 0) 272*21487Ssklower ia = in_ifaddr; 273*21487Ssklower if (ia == 0) { 274*21487Ssklower return (EADDRNOTAVAIL); 275*21487Ssklower } 276*21487Ssklower src = (struct sockaddr_in *)&ia->ia_addr; 277*21487Ssklower } 278*21487Ssklower /* 279*21487Ssklower * Is there space? 280*21487Ssklower */ 281*21487Ssklower m = nsipattach(); 282*21487Ssklower if (m==NULL) {return (ENOBUFS);} 283*21487Ssklower ifn = mtod(m, struct ifnet_en *); 284*21487Ssklower 285*21487Ssklower ro.ro_rt->rt_use++; 286*21487Ssklower ifn->ifen_route = ro; 287*21487Ssklower ifn->ifen_dst = ip_dst->sin_addr; 288*21487Ssklower ifn->ifen_src = src->sin_addr; 289*21487Ssklower 290*21487Ssklower /* 291*21487Ssklower * now configure this as a point to point link 292*21487Ssklower */ 293*21487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 294*21487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 295*21487Ssklower return(ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr, 296*21487Ssklower (struct ifnet *)ifn)); 297*21487Ssklower } 298*21487Ssklower #endif 299