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*23839Ssklower * @(#)ns_ip.c 6.3 (Berkeley) 07/02/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" 1821487Ssklower #include "errno.h" 1921487Ssklower #include "ioctl.h" 2021487Ssklower 2121487Ssklower #include "../net/if.h" 2221487Ssklower #include "../net/netisr.h" 2321487Ssklower #include "../net/route.h" 2421487Ssklower 2521487Ssklower #include "../netinet/in.h" 2621487Ssklower #include "../netinet/in_systm.h" 2721487Ssklower #include "../netinet/in_var.h" 2821487Ssklower #include "../netinet/ip.h" 2921487Ssklower #include "../netinet/ip_var.h" 3021487Ssklower 3121487Ssklower #ifdef vax 3221487Ssklower #include "../vax/mtpr.h" 3321487Ssklower #endif 3421487Ssklower 3521487Ssklower #include "../netns/ns.h" 3621487Ssklower #include "../netns/ns_if.h" 3721487Ssklower #include "../netns/idp.h" 3821487Ssklower 3921487Ssklower struct ifnet_en { 4021487Ssklower struct ifnet ifen_ifnet; 4121487Ssklower struct route ifen_route; 4221487Ssklower struct in_addr ifen_src; 4321487Ssklower struct in_addr ifen_dst; 4421487Ssklower }; 4521487Ssklower 4621487Ssklower int nsipoutput(), nsipioctl(); 4721487Ssklower #define LOMTU (1024+512); 4821487Ssklower 4921487Ssklower struct ifnet nsipif; 5021487Ssklower union ns_net nsip_net; 5121487Ssklower struct mbuf *nsip_list; /* list of all hosts and gateways or 5221487Ssklower broadcast addrs */ 5321487Ssklower 5421487Ssklower struct mbuf * 5521487Ssklower nsipattach() 5621487Ssklower { 5721487Ssklower register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); 5821487Ssklower register struct ifnet *ifp; 5921487Ssklower register struct sockaddr_in *sin; 6021487Ssklower 6121487Ssklower if (m==0) return (0); 6221487Ssklower m->m_off = MMINOFF; 6321487Ssklower m->m_len = sizeof(struct ifnet_en); 6421487Ssklower m->m_next = nsip_list; 6521487Ssklower nsip_list = m; 6621487Ssklower ifp = mtod(m, struct ifnet *); 6721487Ssklower 6821487Ssklower ifp->if_name = "nsip"; 6921487Ssklower ifp->if_mtu = LOMTU; 7021487Ssklower ifp->if_ioctl = nsipioctl; 7121487Ssklower ifp->if_output = nsipoutput; 7221487Ssklower ifp->if_flags = IFF_POINTOPOINT; 7321487Ssklower ifp->if_unit = nsipif.if_unit++; 7421487Ssklower if_attach(ifp); 7521487Ssklower return(dtom(ifp)); 7621487Ssklower } 7721487Ssklower 7821487Ssklower 7921487Ssklower /* 8021487Ssklower * Process an ioctl request. 8121487Ssklower */ 8221487Ssklower /* ARGSUSED */ 8321487Ssklower nsipioctl(ifp, cmd, data) 8421487Ssklower register struct ifnet *ifp; 8521487Ssklower int cmd; 8621487Ssklower caddr_t data; 8721487Ssklower { 8821487Ssklower int error = 0; 8921487Ssklower 9021487Ssklower switch (cmd) { 9121487Ssklower 9221487Ssklower case SIOCSIFADDR: 9321487Ssklower ifp->if_flags |= IFF_UP; 9421487Ssklower /* 9521487Ssklower * Everything else is done at a higher level. 9621487Ssklower */ 9721487Ssklower break; 9821487Ssklower 9921487Ssklower default: 10021487Ssklower error = EINVAL; 10121487Ssklower } 10221487Ssklower return (error); 10321487Ssklower } 10421487Ssklower 10521487Ssklower struct mbuf *nsip_badlen; 10621487Ssklower struct mbuf *nsip_lastin; 10721487Ssklower int nsip_hold_input; 10821487Ssklower 10921487Ssklower idpip_input(m0) 11021487Ssklower struct mbuf *m0; 11121487Ssklower { 11221487Ssklower register struct ip *ip; 11321487Ssklower register struct idp *idp; 11421487Ssklower register struct mbuf *m; 11521487Ssklower register struct ifqueue *ifq = &nsintrq; 11621487Ssklower int len, s; 11721487Ssklower 11821487Ssklower if(nsip_hold_input) { 11921487Ssklower if(nsip_lastin) { 12021487Ssklower m_free(nsip_lastin); 12121487Ssklower } 12221487Ssklower nsip_lastin = m_copy(m0, 0, M_COPYALL); 12321487Ssklower } 12421487Ssklower /* 12521487Ssklower * Get IP and IDP header together in first mbuf. 12621487Ssklower */ 12721487Ssklower nsipif.if_ipackets++; 12821487Ssklower m = m0; 12921487Ssklower s = sizeof (struct ip) + sizeof (struct idp); 13021487Ssklower if ((m->m_off > MMAXOFF || m->m_len < s) && 13121487Ssklower (m = m_pullup(m, s))==0) { 13221487Ssklower nsipif.if_ierrors++; 13321487Ssklower return; 13421487Ssklower } 13521487Ssklower ip = mtod(m, struct ip *); 13621487Ssklower if (ip->ip_hl > (sizeof (struct ip) >> 2)) 13721487Ssklower ip_stripoptions(ip, (struct mbuf *)0); 13821487Ssklower 13921487Ssklower /* 14021487Ssklower * Make mbuf data length reflect IDP length. 14121487Ssklower * If not enough data to reflect IDP length, drop. 14221487Ssklower */ 14321487Ssklower m->m_off += sizeof (struct ip); 14421487Ssklower m->m_len -= sizeof (struct ip); 14521487Ssklower idp = mtod(m, struct idp *); 14621487Ssklower len = ntohs(idp->idp_len); 147*23839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 14821487Ssklower if (ip->ip_len != len) { 14921487Ssklower if (len > ip->ip_len) { 15021487Ssklower nsipif.if_ierrors++; 15121487Ssklower if(nsip_badlen) m_freem(nsip_badlen); 15221487Ssklower nsip_badlen = m; 15321487Ssklower return; 15421487Ssklower } 15521487Ssklower m_adj(m, len - ip->ip_len); 15621487Ssklower /* ip->ip_len = len; */ 15721487Ssklower } 15821487Ssklower /* 15921487Ssklower * Deliver to NS 16021487Ssklower */ 16121487Ssklower s = splimp(); 16221487Ssklower if (IF_QFULL(ifq)) { 16321487Ssklower IF_DROP(ifq); 16421487Ssklower m_freem(m0); 16521487Ssklower splx(s); 16621487Ssklower return (ENOBUFS); 16721487Ssklower } 16821487Ssklower IF_ENQUEUE(ifq, m0); 16921487Ssklower schednetisr(NETISR_NS); 17021487Ssklower splx(s); 17121487Ssklower return (0); 17221487Ssklower bad: 17321487Ssklower m_freem(m); 17421487Ssklower return (0); 17521487Ssklower } 17621487Ssklower 17721487Ssklower nsipoutput(ifn, m0, dst) 17821487Ssklower struct ifnet_en *ifn; 17921487Ssklower struct mbuf *m0; 18021487Ssklower struct sockaddr *dst; 18121487Ssklower { 18221487Ssklower 18321487Ssklower register struct mbuf *m = dtom(ifn); 18421487Ssklower register struct ip *ip; 18521487Ssklower register struct route *ro = &(ifn->ifen_route); 18621487Ssklower register int len = 0; 18721487Ssklower struct in_addr in_src, in_dst; 18821487Ssklower register struct idp *idp = mtod(m0, struct idp *); 18921487Ssklower int error; 19021487Ssklower 19121487Ssklower if (m->m_len != sizeof(struct ifnet_en)) { 19221487Ssklower printf("nsipoutput: bad dst ifp %x\n", ifn); 19321487Ssklower goto bad; 19421487Ssklower } 19521487Ssklower ifn->ifen_ifnet.if_opackets++; 19621487Ssklower nsipif.if_opackets++; 19721487Ssklower 19821487Ssklower 19921487Ssklower /* 20021487Ssklower * Calculate data length and make space 20121487Ssklower * for IP header. 20221487Ssklower */ 20321487Ssklower len = ntohs(idp->idp_len); 204*23839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */ 20521487Ssklower m = m0; 20621487Ssklower if(m->m_off < MMINOFF + sizeof (struct ip)) { 20721487Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 20821487Ssklower if (m == 0) { 20921487Ssklower m_freem(m0); 21021487Ssklower return (ENOBUFS); 21121487Ssklower } 21221487Ssklower m->m_off = MMAXOFF - sizeof (struct ip); 21321487Ssklower m->m_len = sizeof (struct ip); 21421487Ssklower m->m_next = m0; 21521487Ssklower } else { 21621487Ssklower m->m_off -= sizeof (struct ip); 21721487Ssklower m->m_len += sizeof (struct ip); 21821487Ssklower } 21921487Ssklower /* 22021487Ssklower * Fill in IP header. 22121487Ssklower */ 22221487Ssklower ip = mtod(m, struct ip *); 22321487Ssklower *(long *)ip = 0; 22421487Ssklower ip->ip_p = IPPROTO_PUP; 22521487Ssklower ip->ip_src = ifn->ifen_src; 22621487Ssklower ip->ip_dst = ifn->ifen_dst; 22721487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip); 22821487Ssklower ip->ip_ttl = MAXTTL; 22921487Ssklower 23021487Ssklower /* 23121487Ssklower * Output final datagram. 23221487Ssklower */ 23321487Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 23421487Ssklower if (error) { 23521487Ssklower ifn->ifen_ifnet.if_oerrors++; 23621487Ssklower ifn->ifen_ifnet.if_ierrors = error; 23721487Ssklower } 23821487Ssklower return (error); 23921487Ssklower bad: 24021487Ssklower m_freem(m0); 24121487Ssklower return(ENETUNREACH); 24221487Ssklower } 24321487Ssklower 24421487Ssklower struct ifreq ifr = {"nsip0"}; 24521487Ssklower 24621487Ssklower nsip_route(m) 24721487Ssklower register struct mbuf *m; 24821487Ssklower { 24921487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *); 25021487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 25121487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 25221487Ssklower int flags = rq->rq_flags; 25321487Ssklower struct ifnet *ifp; 25421487Ssklower struct route ro; 25521487Ssklower struct ifnet_en *ifn; 25621487Ssklower int error; 25721487Ssklower struct sockaddr_in *dst; 25821487Ssklower struct sockaddr_in *src; 25921487Ssklower /* 26021487Ssklower * First, determine if we can get to the destination 26121487Ssklower */ 26221487Ssklower bzero((caddr_t)&ro, sizeof (ro)); 26321487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst; 26421487Ssklower dst = (struct sockaddr_in *)& ro.ro_dst; 26521487Ssklower rtalloc(&ro); 26621487Ssklower if (ro.ro_rt == 0 || (ifp = ro.ro_rt->rt_ifp) == 0) { 26721487Ssklower return (ENETUNREACH); 26821487Ssklower } 26921487Ssklower /* 27021487Ssklower * And see how he's going to get back to us: 27121487Ssklower */ 27221487Ssklower { 27321487Ssklower register struct in_ifaddr *ia; 27421487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp; 27521487Ssklower 27621487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next) 27721487Ssklower if (ia->ia_ifp == ifp) 27821487Ssklower break; 27921487Ssklower if (ia == 0) 28021487Ssklower ia = in_ifaddr; 28121487Ssklower if (ia == 0) { 28221487Ssklower return (EADDRNOTAVAIL); 28321487Ssklower } 28421487Ssklower src = (struct sockaddr_in *)&ia->ia_addr; 28521487Ssklower } 28621487Ssklower /* 28721487Ssklower * Is there space? 28821487Ssklower */ 28921487Ssklower m = nsipattach(); 29021487Ssklower if (m==NULL) {return (ENOBUFS);} 29121487Ssklower ifn = mtod(m, struct ifnet_en *); 29221487Ssklower 29321487Ssklower ro.ro_rt->rt_use++; 29421487Ssklower ifn->ifen_route = ro; 29521487Ssklower ifn->ifen_dst = ip_dst->sin_addr; 29621487Ssklower ifn->ifen_src = src->sin_addr; 29721487Ssklower 29821487Ssklower /* 29921487Ssklower * now configure this as a point to point link 30021487Ssklower */ 30121487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 30221487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 30321487Ssklower return(ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr, 30421487Ssklower (struct ifnet *)ifn)); 30521487Ssklower } 30621487Ssklower #endif 307