123210Smckusick /*
263231Sbostic * Copyright (c) 1984, 1985, 1986, 1987, 1993
363231Sbostic * The Regents of the University of California. All rights reserved.
423210Smckusick *
544505Sbostic * %sccs.include.redist.c%
633371Ssklower *
7*68167Scgd * @(#)ns_ip.c 8.2 (Berkeley) 01/09/95
823210Smckusick */
921487Ssklower
1021487Ssklower /*
1121487Ssklower * Software interface driver for encapsulating ns in ip.
1221487Ssklower */
1321487Ssklower
1421487Ssklower #ifdef NSIP
1556534Sbostic #include <sys/param.h>
1656534Sbostic #include <sys/systm.h>
1756534Sbostic #include <sys/malloc.h>
1856534Sbostic #include <sys/mbuf.h>
1956534Sbostic #include <sys/socket.h>
2056534Sbostic #include <sys/socketvar.h>
2156534Sbostic #include <sys/errno.h>
2256534Sbostic #include <sys/ioctl.h>
2356534Sbostic #include <sys/protosw.h>
2421487Ssklower
2556534Sbostic #include <net/if.h>
2656534Sbostic #include <net/netisr.h>
2756534Sbostic #include <net/route.h>
2821487Ssklower
2956534Sbostic #include <netinet/in.h>
3056534Sbostic #include <netinet/in_systm.h>
3156534Sbostic #include <netinet/in_var.h>
3256534Sbostic #include <netinet/ip.h>
3356534Sbostic #include <netinet/ip_var.h>
3421487Ssklower
3556534Sbostic #include <machine/mtpr.h>
3621487Ssklower
3756534Sbostic #include <netns/ns.h>
3856534Sbostic #include <netns/ns_if.h>
3956534Sbostic #include <netns/idp.h>
4021487Ssklower
4121487Ssklower struct ifnet_en {
4221487Ssklower struct ifnet ifen_ifnet;
4321487Ssklower struct route ifen_route;
4421487Ssklower struct in_addr ifen_src;
4521487Ssklower struct in_addr ifen_dst;
4637473Ssklower struct ifnet_en *ifen_next;
4721487Ssklower };
4821487Ssklower
4937473Ssklower int nsipoutput(), nsipioctl(), nsipstart();
5021487Ssklower #define LOMTU (1024+512);
5121487Ssklower
5221487Ssklower struct ifnet nsipif;
5337473Ssklower struct ifnet_en *nsip_list; /* list of all hosts and gateways or
5421487Ssklower broadcast addrs */
5521487Ssklower
5637473Ssklower struct ifnet_en *
nsipattach()5721487Ssklower nsipattach()
5821487Ssklower {
5937473Ssklower register struct ifnet_en *m;
6021487Ssklower register struct ifnet *ifp;
6121487Ssklower
6237473Ssklower if (nsipif.if_mtu == 0) {
6337473Ssklower ifp = &nsipif;
6437473Ssklower ifp->if_name = "nsip";
6537473Ssklower ifp->if_mtu = LOMTU;
6637473Ssklower ifp->if_ioctl = nsipioctl;
6737473Ssklower ifp->if_output = nsipoutput;
6837473Ssklower ifp->if_start = nsipstart;
6937473Ssklower ifp->if_flags = IFF_POINTOPOINT;
7037473Ssklower }
7137473Ssklower
7237473Ssklower MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);
7325454Ssklower if (m == NULL) return (NULL);
7437473Ssklower m->ifen_next = nsip_list;
7521487Ssklower nsip_list = m;
7637473Ssklower ifp = &m->ifen_ifnet;
7721487Ssklower
7821487Ssklower ifp->if_name = "nsip";
7921487Ssklower ifp->if_mtu = LOMTU;
8021487Ssklower ifp->if_ioctl = nsipioctl;
8121487Ssklower ifp->if_output = nsipoutput;
8237473Ssklower ifp->if_start = nsipstart;
8321487Ssklower ifp->if_flags = IFF_POINTOPOINT;
8421487Ssklower ifp->if_unit = nsipif.if_unit++;
8521487Ssklower if_attach(ifp);
8637473Ssklower
8737473Ssklower return (m);
8821487Ssklower }
8921487Ssklower
9021487Ssklower
9121487Ssklower /*
9221487Ssklower * Process an ioctl request.
9321487Ssklower */
9421487Ssklower /* ARGSUSED */
nsipioctl(ifp,cmd,data)9521487Ssklower nsipioctl(ifp, cmd, data)
9621487Ssklower register struct ifnet *ifp;
9721487Ssklower int cmd;
9821487Ssklower caddr_t data;
9921487Ssklower {
10021487Ssklower int error = 0;
10125055Ssklower struct ifreq *ifr;
10221487Ssklower
10321487Ssklower switch (cmd) {
10421487Ssklower
10521487Ssklower case SIOCSIFADDR:
10621487Ssklower ifp->if_flags |= IFF_UP;
10725454Ssklower /* fall into: */
10825454Ssklower
10925454Ssklower case SIOCSIFDSTADDR:
11021487Ssklower /*
11121487Ssklower * Everything else is done at a higher level.
11221487Ssklower */
11321487Ssklower break;
11421487Ssklower
11525055Ssklower case SIOCSIFFLAGS:
11625055Ssklower ifr = (struct ifreq *)data;
11725055Ssklower if ((ifr->ifr_flags & IFF_UP) == 0)
11825055Ssklower error = nsip_free(ifp);
11925055Ssklower
12025055Ssklower
12121487Ssklower default:
12221487Ssklower error = EINVAL;
12321487Ssklower }
12421487Ssklower return (error);
12521487Ssklower }
12621487Ssklower
12721487Ssklower struct mbuf *nsip_badlen;
12821487Ssklower struct mbuf *nsip_lastin;
12921487Ssklower int nsip_hold_input;
13021487Ssklower
idpip_input(m,ifp)13124562Skarels idpip_input(m, ifp)
13224562Skarels register struct mbuf *m;
13324562Skarels struct ifnet *ifp;
13421487Ssklower {
13521487Ssklower register struct ip *ip;
13621487Ssklower register struct idp *idp;
13721487Ssklower register struct ifqueue *ifq = &nsintrq;
13821487Ssklower int len, s;
13921487Ssklower
14025454Ssklower if (nsip_hold_input) {
14125454Ssklower if (nsip_lastin) {
14224226Ssklower m_freem(nsip_lastin);
14321487Ssklower }
14437473Ssklower nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
14521487Ssklower }
14621487Ssklower /*
14721487Ssklower * Get IP and IDP header together in first mbuf.
14821487Ssklower */
14921487Ssklower nsipif.if_ipackets++;
15021487Ssklower s = sizeof (struct ip) + sizeof (struct idp);
15137473Ssklower if (((m->m_flags & M_EXT) || m->m_len < s) &&
15225454Ssklower (m = m_pullup(m, s)) == 0) {
15321487Ssklower nsipif.if_ierrors++;
15421487Ssklower return;
15521487Ssklower }
15621487Ssklower ip = mtod(m, struct ip *);
15724827Skarels if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
15861653Ssklower ip_stripoptions(m, (struct mbuf *)0);
15924827Skarels if (m->m_len < s) {
16025454Ssklower if ((m = m_pullup(m, s)) == 0) {
16124827Skarels nsipif.if_ierrors++;
16224827Skarels return;
16324827Skarels }
16424827Skarels ip = mtod(m, struct ip *);
16524827Skarels }
16624827Skarels }
16721487Ssklower
16821487Ssklower /*
16921487Ssklower * Make mbuf data length reflect IDP length.
17021487Ssklower * If not enough data to reflect IDP length, drop.
17121487Ssklower */
17237473Ssklower m->m_data += sizeof (struct ip);
17321487Ssklower m->m_len -= sizeof (struct ip);
17437473Ssklower m->m_pkthdr.len -= sizeof (struct ip);
17521487Ssklower idp = mtod(m, struct idp *);
17621487Ssklower len = ntohs(idp->idp_len);
17723839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */
17821487Ssklower if (ip->ip_len != len) {
17921487Ssklower if (len > ip->ip_len) {
18021487Ssklower nsipif.if_ierrors++;
18125454Ssklower if (nsip_badlen) m_freem(nsip_badlen);
18221487Ssklower nsip_badlen = m;
18321487Ssklower return;
18421487Ssklower }
18524043Ssklower /* Any extra will be trimmed off by the NS routines */
18621487Ssklower }
18724562Skarels
18821487Ssklower /*
18924562Skarels * Place interface pointer before the data
19024562Skarels * for the receiving protocol.
19124562Skarels */
19237473Ssklower m->m_pkthdr.rcvif = ifp;
19324562Skarels /*
19421487Ssklower * Deliver to NS
19521487Ssklower */
19621487Ssklower s = splimp();
19721487Ssklower if (IF_QFULL(ifq)) {
19821487Ssklower IF_DROP(ifq);
19924562Skarels bad:
20024562Skarels m_freem(m);
20121487Ssklower splx(s);
20224226Ssklower return;
20321487Ssklower }
20424562Skarels IF_ENQUEUE(ifq, m);
20521487Ssklower schednetisr(NETISR_NS);
20621487Ssklower splx(s);
20724226Ssklower return;
20821487Ssklower }
20921487Ssklower
21024226Ssklower /* ARGSUSED */
21137473Ssklower nsipoutput(ifn, m, dst)
21221487Ssklower struct ifnet_en *ifn;
21337473Ssklower register struct mbuf *m;
21421487Ssklower struct sockaddr *dst;
21521487Ssklower {
21621487Ssklower
21721487Ssklower register struct ip *ip;
21821487Ssklower register struct route *ro = &(ifn->ifen_route);
21921487Ssklower register int len = 0;
22037473Ssklower register struct idp *idp = mtod(m, struct idp *);
22121487Ssklower int error;
22221487Ssklower
22321487Ssklower ifn->ifen_ifnet.if_opackets++;
22421487Ssklower nsipif.if_opackets++;
22521487Ssklower
22621487Ssklower
22721487Ssklower /*
22821487Ssklower * Calculate data length and make space
22921487Ssklower * for IP header.
23021487Ssklower */
23121487Ssklower len = ntohs(idp->idp_len);
23223839Ssklower if (len & 1) len++; /* Preserve Garbage Byte */
23337473Ssklower /* following clause not necessary on vax */
23437473Ssklower if (3 & (int)m->m_data) {
23537473Ssklower /* force longword alignment of ip hdr */
23637473Ssklower struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
23737473Ssklower if (m0 == 0) {
23837473Ssklower m_freem(m);
23921487Ssklower return (ENOBUFS);
24021487Ssklower }
24137473Ssklower MH_ALIGN(m0, sizeof (struct ip));
24237473Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS;
24337473Ssklower m0->m_next = m;
24437473Ssklower m0->m_len = sizeof (struct ip);
24537473Ssklower m0->m_pkthdr.len = m0->m_len + m->m_len;
24637473Ssklower m->m_flags &= ~M_PKTHDR;
24721487Ssklower } else {
24837473Ssklower M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
24937473Ssklower if (m == 0)
25037473Ssklower return (ENOBUFS);
25121487Ssklower }
25221487Ssklower /*
25321487Ssklower * Fill in IP header.
25421487Ssklower */
25521487Ssklower ip = mtod(m, struct ip *);
25621487Ssklower *(long *)ip = 0;
25724043Ssklower ip->ip_p = IPPROTO_IDP;
25821487Ssklower ip->ip_src = ifn->ifen_src;
25921487Ssklower ip->ip_dst = ifn->ifen_dst;
26021487Ssklower ip->ip_len = (u_short)len + sizeof (struct ip);
26121487Ssklower ip->ip_ttl = MAXTTL;
26221487Ssklower
26321487Ssklower /*
26421487Ssklower * Output final datagram.
26521487Ssklower */
26661653Ssklower error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));
26721487Ssklower if (error) {
26821487Ssklower ifn->ifen_ifnet.if_oerrors++;
26921487Ssklower ifn->ifen_ifnet.if_ierrors = error;
27021487Ssklower }
27121487Ssklower return (error);
27221487Ssklower bad:
27337473Ssklower m_freem(m);
27425454Ssklower return (ENETUNREACH);
27521487Ssklower }
27621487Ssklower
27737473Ssklower nsipstart(ifp)
27837473Ssklower struct ifnet *ifp;
27937473Ssklower {
28037473Ssklower panic("nsip_start called\n");
28137473Ssklower }
28237473Ssklower
28321487Ssklower struct ifreq ifr = {"nsip0"};
28421487Ssklower
nsip_route(m)28521487Ssklower nsip_route(m)
28621487Ssklower register struct mbuf *m;
28721487Ssklower {
28821487Ssklower register struct nsip_req *rq = mtod(m, struct nsip_req *);
28921487Ssklower struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
29021487Ssklower struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
29121487Ssklower struct route ro;
29221487Ssklower struct ifnet_en *ifn;
29321487Ssklower struct sockaddr_in *src;
29425454Ssklower
29521487Ssklower /*
29625454Ssklower * First, make sure we already have an ns address:
29721487Ssklower */
29825454Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost))
29925454Ssklower return (EADDRNOTAVAIL);
30025454Ssklower /*
30125454Ssklower * Now, determine if we can get to the destination
30225454Ssklower */
30321487Ssklower bzero((caddr_t)&ro, sizeof (ro));
30421487Ssklower ro.ro_dst = *(struct sockaddr *)ip_dst;
30521487Ssklower rtalloc(&ro);
30624226Ssklower if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
30721487Ssklower return (ENETUNREACH);
30821487Ssklower }
30925454Ssklower
31021487Ssklower /*
31121487Ssklower * And see how he's going to get back to us:
31225454Ssklower * i.e., what return ip address do we use?
31321487Ssklower */
31421487Ssklower {
31521487Ssklower register struct in_ifaddr *ia;
31621487Ssklower struct ifnet *ifp = ro.ro_rt->rt_ifp;
31721487Ssklower
31821487Ssklower for (ia = in_ifaddr; ia; ia = ia->ia_next)
31921487Ssklower if (ia->ia_ifp == ifp)
32021487Ssklower break;
32121487Ssklower if (ia == 0)
32221487Ssklower ia = in_ifaddr;
32321487Ssklower if (ia == 0) {
32425454Ssklower RTFREE(ro.ro_rt);
32521487Ssklower return (EADDRNOTAVAIL);
32621487Ssklower }
32721487Ssklower src = (struct sockaddr_in *)&ia->ia_addr;
32821487Ssklower }
32925454Ssklower
33021487Ssklower /*
33125055Ssklower * Is there a free (pseudo-)interface or space?
33221487Ssklower */
33337473Ssklower for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
33437473Ssklower if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)
33525055Ssklower break;
33625055Ssklower }
33737473Ssklower if (ifn == NULL)
33837473Ssklower ifn = nsipattach();
33937473Ssklower if (ifn == NULL) {
34025454Ssklower RTFREE(ro.ro_rt);
34125454Ssklower return (ENOBUFS);
34225454Ssklower }
34321487Ssklower ifn->ifen_route = ro;
34421487Ssklower ifn->ifen_dst = ip_dst->sin_addr;
34521487Ssklower ifn->ifen_src = src->sin_addr;
34621487Ssklower
34721487Ssklower /*
34821487Ssklower * now configure this as a point to point link
34921487Ssklower */
35021487Ssklower ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
35121487Ssklower ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
352*68167Scgd (void)ns_control((struct socket *)0, SIOCSIFDSTADDR, (caddr_t)&ifr,
35325454Ssklower (struct ifnet *)ifn);
35425454Ssklower satons_addr(ifr.ifr_addr).x_host = ns_thishost;
355*68167Scgd return (ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr,
35621487Ssklower (struct ifnet *)ifn));
35721487Ssklower }
35825055Ssklower
35925055Ssklower nsip_free(ifp)
36025055Ssklower struct ifnet *ifp;
36125055Ssklower {
36225055Ssklower register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
36325055Ssklower struct route *ro = & ifn->ifen_route;
36425055Ssklower
36525055Ssklower if (ro->ro_rt) {
36625055Ssklower RTFREE(ro->ro_rt);
36725055Ssklower ro->ro_rt = 0;
36825055Ssklower }
36925055Ssklower ifp->if_flags &= ~IFF_UP;
37025055Ssklower return (0);
37125055Ssklower }
37225055Ssklower
nsip_ctlinput(cmd,sa)37325055Ssklower nsip_ctlinput(cmd, sa)
37425055Ssklower int cmd;
37525055Ssklower struct sockaddr *sa;
37625055Ssklower {
37725055Ssklower extern u_char inetctlerrmap[];
37825055Ssklower struct sockaddr_in *sin;
37925055Ssklower int in_rtchange();
38025055Ssklower
38125454Ssklower if ((unsigned)cmd >= PRC_NCMDS)
38225055Ssklower return;
38325055Ssklower if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
38425055Ssklower return;
38525055Ssklower sin = (struct sockaddr_in *)sa;
38625055Ssklower if (sin->sin_addr.s_addr == INADDR_ANY)
38725055Ssklower return;
38825055Ssklower
38925055Ssklower switch (cmd) {
39025055Ssklower
39125055Ssklower case PRC_ROUTEDEAD:
39225055Ssklower case PRC_REDIRECT_NET:
39325055Ssklower case PRC_REDIRECT_HOST:
39425055Ssklower case PRC_REDIRECT_TOSNET:
39525055Ssklower case PRC_REDIRECT_TOSHOST:
39625055Ssklower nsip_rtchange(&sin->sin_addr);
39725055Ssklower break;
39825055Ssklower }
39925055Ssklower }
40025055Ssklower
nsip_rtchange(dst)40125055Ssklower nsip_rtchange(dst)
40225055Ssklower register struct in_addr *dst;
40325055Ssklower {
40425055Ssklower register struct ifnet_en *ifn;
40525055Ssklower
40637473Ssklower for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
40725055Ssklower if (ifn->ifen_dst.s_addr == dst->s_addr &&
40825055Ssklower ifn->ifen_route.ro_rt) {
40925055Ssklower RTFREE(ifn->ifen_route.ro_rt);
41025055Ssklower ifn->ifen_route.ro_rt = 0;
41125055Ssklower }
41225211Smckusick }
41325055Ssklower }
41421487Ssklower #endif
415