xref: /csrg-svn/sys/netns/ns_ip.c (revision 37473)
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