123210Smckusick /* 223210Smckusick * Copyright (c) 1982 Regents of the University of California. 323210Smckusick * All rights reserved. The Berkeley software License Agreement 423210Smckusick * specifies the terms and conditions for redistribution. 523210Smckusick * 6*24827Skarels * @(#)ns_ip.c 6.8 (Berkeley) 09/17/85 723210Smckusick */ 821487Ssklower 921487Ssklower /* 1021487Ssklower * Software interface driver for encapsulating ns in ip. 1121487Ssklower */ 1221487Ssklower 1321487Ssklower #ifdef NSIP 1421487Ssklower #include "param.h" 1521487Ssklower #include "systm.h" 1621487Ssklower #include "mbuf.h" 1721487Ssklower #include "socket.h" 1824226Ssklower #include "socketvar.h" 1921487Ssklower #include "errno.h" 2021487Ssklower #include "ioctl.h" 2121487Ssklower 2221487Ssklower #include "../net/if.h" 2321487Ssklower #include "../net/netisr.h" 2421487Ssklower #include "../net/route.h" 2521487Ssklower 2621487Ssklower #include "../netinet/in.h" 2721487Ssklower #include "../netinet/in_systm.h" 2821487Ssklower #include "../netinet/in_var.h" 2921487Ssklower #include "../netinet/ip.h" 3021487Ssklower #include "../netinet/ip_var.h" 3121487Ssklower 3221487Ssklower #ifdef vax 3321487Ssklower #include "../vax/mtpr.h" 3421487Ssklower #endif 3521487Ssklower 3621487Ssklower #include "../netns/ns.h" 3721487Ssklower #include "../netns/ns_if.h" 3821487Ssklower #include "../netns/idp.h" 3921487Ssklower 4024414Swalsh #ifdef BBNNET 4124414Swalsh #include "../bbnnet/in_pcb.h" 4224414Swalsh #include "../bbnnet/nopcb.h" 4324414Swalsh #endif 4424414Swalsh 4521487Ssklower struct ifnet_en { 4621487Ssklower struct ifnet ifen_ifnet; 4721487Ssklower struct route ifen_route; 4821487Ssklower struct in_addr ifen_src; 4921487Ssklower struct in_addr ifen_dst; 5021487Ssklower }; 5121487Ssklower 5221487Ssklower int nsipoutput(), nsipioctl(); 5321487Ssklower #define LOMTU (1024+512); 5421487Ssklower 5521487Ssklower struct ifnet nsipif; 5621487Ssklower union ns_net nsip_net; 5721487Ssklower struct mbuf *nsip_list; /* list of all hosts and gateways or 5821487Ssklower broadcast addrs */ 5921487Ssklower 6021487Ssklower struct mbuf * 6121487Ssklower nsipattach() 6221487Ssklower { 6321487Ssklower register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); 6421487Ssklower register struct ifnet *ifp; 6521487Ssklower 6621487Ssklower if (m==0) return (0); 6721487Ssklower m->m_off = MMINOFF; 6821487Ssklower m->m_len = sizeof(struct ifnet_en); 6921487Ssklower m->m_next = nsip_list; 7021487Ssklower nsip_list = m; 7121487Ssklower ifp = mtod(m, struct ifnet *); 7221487Ssklower 7321487Ssklower ifp->if_name = "nsip"; 7421487Ssklower ifp->if_mtu = LOMTU; 7521487Ssklower ifp->if_ioctl = nsipioctl; 7621487Ssklower ifp->if_output = nsipoutput; 7721487Ssklower ifp->if_flags = IFF_POINTOPOINT; 7821487Ssklower ifp->if_unit = nsipif.if_unit++; 7921487Ssklower if_attach(ifp); 8021487Ssklower return(dtom(ifp)); 8121487Ssklower } 8221487Ssklower 8321487Ssklower 8421487Ssklower /* 8521487Ssklower * Process an ioctl request. 8621487Ssklower */ 8721487Ssklower /* ARGSUSED */ 8821487Ssklower nsipioctl(ifp, cmd, data) 8921487Ssklower register struct ifnet *ifp; 9021487Ssklower int cmd; 9121487Ssklower caddr_t data; 9221487Ssklower { 9321487Ssklower int error = 0; 9421487Ssklower 9521487Ssklower switch (cmd) { 9621487Ssklower 9721487Ssklower case SIOCSIFADDR: 9821487Ssklower ifp->if_flags |= IFF_UP; 9921487Ssklower /* 10021487Ssklower * Everything else is done at a higher level. 10121487Ssklower */ 10221487Ssklower break; 10321487Ssklower 10421487Ssklower default: 10521487Ssklower error = EINVAL; 10621487Ssklower } 10721487Ssklower return (error); 10821487Ssklower } 10921487Ssklower 11021487Ssklower struct mbuf *nsip_badlen; 11121487Ssklower struct mbuf *nsip_lastin; 11221487Ssklower int nsip_hold_input; 11321487Ssklower 11424562Skarels idpip_input(m, ifp) 11524562Skarels register struct mbuf *m; 11624562Skarels struct ifnet *ifp; 11721487Ssklower { 11821487Ssklower register struct ip *ip; 11921487Ssklower register struct idp *idp; 12021487Ssklower register struct ifqueue *ifq = &nsintrq; 12121487Ssklower int len, s; 12221487Ssklower 12321487Ssklower if(nsip_hold_input) { 12421487Ssklower if(nsip_lastin) { 12524226Ssklower m_freem(nsip_lastin); 12621487Ssklower } 12724562Skarels nsip_lastin = m_copy(m, 0, (int)M_COPYALL); 12821487Ssklower } 12921487Ssklower /* 13021487Ssklower * Get IP and IDP header together in first mbuf. 13121487Ssklower */ 13221487Ssklower nsipif.if_ipackets++; 13321487Ssklower s = sizeof (struct ip) + sizeof (struct idp); 13421487Ssklower if ((m->m_off > MMAXOFF || m->m_len < s) && 13521487Ssklower (m = m_pullup(m, s))==0) { 13621487Ssklower nsipif.if_ierrors++; 13721487Ssklower return; 13821487Ssklower } 13921487Ssklower ip = mtod(m, struct ip *); 140*24827Skarels if (ip->ip_hl > (sizeof (struct ip) >> 2)) { 141*24827Skarels ip_stripoptions(ip, (struct mbuf *)0); 142*24827Skarels if (m->m_len < s) { 143*24827Skarels if ((m = m_pullup(m, s))==0) { 144*24827Skarels nsipif.if_ierrors++; 145*24827Skarels return; 146*24827Skarels } 147*24827Skarels ip = mtod(m, struct ip *); 148*24827Skarels } 149*24827Skarels } 15021487Ssklower 15121487Ssklower /* 15221487Ssklower * Make mbuf data length reflect IDP length. 15321487Ssklower * If not enough data to reflect IDP length, drop. 15421487Ssklower */ 15521487Ssklower m->m_off += sizeof (struct ip); 15621487Ssklower m->m_len -= sizeof (struct ip); 15721487Ssklower idp = mtod(m, struct idp *); 15821487Ssklower len = ntohs(idp->idp_len); 15923839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 16021487Ssklower if (ip->ip_len != len) { 16121487Ssklower if (len > ip->ip_len) { 16221487Ssklower nsipif.if_ierrors++; 16321487Ssklower if(nsip_badlen) m_freem(nsip_badlen); 16421487Ssklower nsip_badlen = m; 16521487Ssklower return; 16621487Ssklower } 16724043Ssklower /* Any extra will be trimmed off by the NS routines */ 16821487Ssklower } 16924562Skarels 17021487Ssklower /* 17124562Skarels * Place interface pointer before the data 17224562Skarels * for the receiving protocol. 17324562Skarels */ 17424562Skarels if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) { 17524562Skarels m->m_off -= sizeof(struct ifnet *); 17624562Skarels m->m_len += sizeof(struct ifnet *); 17724562Skarels } else { 17824562Skarels struct mbuf *n; 17924562Skarels 18024562Skarels n = m_get(M_DONTWAIT, MT_HEADER); 18124562Skarels if (n == (struct mbuf *)0) 18224562Skarels goto bad; 18324562Skarels n->m_off = MMINOFF; 18424562Skarels n->m_len = sizeof(struct ifnet *); 18524562Skarels n->m_next = m; 18624562Skarels m = n; 18724562Skarels } 18824562Skarels *(mtod(m, struct ifnet **)) = ifp; 18924562Skarels 19024562Skarels /* 19121487Ssklower * Deliver to NS 19221487Ssklower */ 19321487Ssklower s = splimp(); 19421487Ssklower if (IF_QFULL(ifq)) { 19521487Ssklower IF_DROP(ifq); 19624562Skarels bad: 19724562Skarels m_freem(m); 19821487Ssklower splx(s); 19924226Ssklower return; 20021487Ssklower } 20124562Skarels IF_ENQUEUE(ifq, m); 20221487Ssklower schednetisr(NETISR_NS); 20321487Ssklower splx(s); 20424226Ssklower return; 20521487Ssklower } 20621487Ssklower 20724226Ssklower /* ARGSUSED */ 20821487Ssklower nsipoutput(ifn, m0, dst) 20921487Ssklower struct ifnet_en *ifn; 21021487Ssklower struct mbuf *m0; 21121487Ssklower struct sockaddr *dst; 21221487Ssklower { 21321487Ssklower 21421487Ssklower register struct mbuf *m = dtom(ifn); 21521487Ssklower register struct ip *ip; 21621487Ssklower register struct route *ro = &(ifn->ifen_route); 21721487Ssklower register int len = 0; 21821487Ssklower register struct idp *idp = mtod(m0, struct idp *); 21921487Ssklower int error; 22021487Ssklower 22121487Ssklower if (m->m_len != sizeof(struct ifnet_en)) { 22221487Ssklower printf("nsipoutput: bad dst ifp %x\n", ifn); 22321487Ssklower goto bad; 22421487Ssklower } 22521487Ssklower ifn->ifen_ifnet.if_opackets++; 22621487Ssklower nsipif.if_opackets++; 22721487Ssklower 22821487Ssklower 22921487Ssklower /* 23021487Ssklower * Calculate data length and make space 23121487Ssklower * for IP header. 23221487Ssklower */ 23321487Ssklower len = ntohs(idp->idp_len); 23423839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 23521487Ssklower m = m0; 23621487Ssklower if(m->m_off < MMINOFF + sizeof (struct ip)) { 23721487Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 23821487Ssklower if (m == 0) { 23921487Ssklower m_freem(m0); 24021487Ssklower return (ENOBUFS); 24121487Ssklower } 24221487Ssklower m->m_off = MMAXOFF - sizeof (struct ip); 24321487Ssklower m->m_len = sizeof (struct ip); 24421487Ssklower m->m_next = m0; 24521487Ssklower } else { 24621487Ssklower m->m_off -= sizeof (struct ip); 24721487Ssklower m->m_len += sizeof (struct ip); 24821487Ssklower } 24921487Ssklower /* 25021487Ssklower * Fill in IP header. 25121487Ssklower */ 25221487Ssklower ip = mtod(m, struct ip *); 25321487Ssklower *(long *)ip = 0; 25424043Ssklower ip->ip_p = IPPROTO_IDP; 25521487Ssklower ip->ip_src = ifn->ifen_src; 25621487Ssklower ip->ip_dst = ifn->ifen_dst; 25724414Swalsh #ifdef BBNNET 25824414Swalsh ip->ip_tos = 0; 25924414Swalsh NOPCB_IPSEND(m, len, 0, error); 26024414Swalsh #else 26121487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip); 26221487Ssklower ip->ip_ttl = MAXTTL; 26321487Ssklower 26421487Ssklower /* 26521487Ssklower * Output final datagram. 26621487Ssklower */ 26721487Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 26824414Swalsh #endif 26921487Ssklower if (error) { 27021487Ssklower ifn->ifen_ifnet.if_oerrors++; 27121487Ssklower ifn->ifen_ifnet.if_ierrors = error; 27221487Ssklower } 27321487Ssklower return (error); 27421487Ssklower bad: 27521487Ssklower m_freem(m0); 27621487Ssklower return(ENETUNREACH); 27721487Ssklower } 27821487Ssklower 27921487Ssklower struct ifreq ifr = {"nsip0"}; 28021487Ssklower 28121487Ssklower nsip_route(m) 28221487Ssklower register struct mbuf *m; 28321487Ssklower { 28421487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *); 28521487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 28621487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 28721487Ssklower struct route ro; 28821487Ssklower struct ifnet_en *ifn; 28921487Ssklower struct sockaddr_in *src; 29021487Ssklower /* 29121487Ssklower * First, determine if we can get to the destination 29221487Ssklower */ 29321487Ssklower bzero((caddr_t)&ro, sizeof (ro)); 29421487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst; 29521487Ssklower rtalloc(&ro); 29624226Ssklower if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { 29721487Ssklower return (ENETUNREACH); 29821487Ssklower } 29921487Ssklower /* 30021487Ssklower * And see how he's going to get back to us: 30121487Ssklower */ 30221487Ssklower { 30321487Ssklower register struct in_ifaddr *ia; 30421487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp; 30521487Ssklower 30621487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 30721487Ssklower if (ia->ia_ifp == ifp) 30821487Ssklower break; 30921487Ssklower if (ia == 0) 31021487Ssklower ia = in_ifaddr; 31121487Ssklower if (ia == 0) { 31221487Ssklower return (EADDRNOTAVAIL); 31321487Ssklower } 31421487Ssklower src = (struct sockaddr_in *)&ia->ia_addr; 31521487Ssklower } 31621487Ssklower /* 31721487Ssklower * Is there space? 31821487Ssklower */ 31921487Ssklower m = nsipattach(); 32021487Ssklower if (m==NULL) {return (ENOBUFS);} 32121487Ssklower ifn = mtod(m, struct ifnet_en *); 32221487Ssklower 32321487Ssklower ro.ro_rt->rt_use++; 32421487Ssklower ifn->ifen_route = ro; 32521487Ssklower ifn->ifen_dst = ip_dst->sin_addr; 32621487Ssklower ifn->ifen_src = src->sin_addr; 32721487Ssklower 32821487Ssklower /* 32921487Ssklower * now configure this as a point to point link 33021487Ssklower */ 33121487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 33221487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 33324226Ssklower return(ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr, 33421487Ssklower (struct ifnet *)ifn)); 33521487Ssklower } 33621487Ssklower #endif 337