xref: /csrg-svn/sys/netns/ns_ip.c (revision 25055)
123210Smckusick /*
2*25055Ssklower  * Copyright (c) 1985 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*25055Ssklower  *	@(#)ns_ip.c	6.9 (Berkeley) 10/01/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"
21*25055Ssklower #include "protosw.h"
2221487Ssklower 
2321487Ssklower #include "../net/if.h"
2421487Ssklower #include "../net/netisr.h"
2521487Ssklower #include "../net/route.h"
2621487Ssklower 
2721487Ssklower #include "../netinet/in.h"
2821487Ssklower #include "../netinet/in_systm.h"
2921487Ssklower #include "../netinet/in_var.h"
3021487Ssklower #include "../netinet/ip.h"
3121487Ssklower #include "../netinet/ip_var.h"
3221487Ssklower 
3321487Ssklower #ifdef vax
3421487Ssklower #include "../vax/mtpr.h"
3521487Ssklower #endif
3621487Ssklower 
3721487Ssklower #include "../netns/ns.h"
3821487Ssklower #include "../netns/ns_if.h"
3921487Ssklower #include "../netns/idp.h"
4021487Ssklower 
4124414Swalsh #ifdef BBNNET
4224414Swalsh #include "../bbnnet/in_pcb.h"
4324414Swalsh #include "../bbnnet/nopcb.h"
4424414Swalsh #endif
4524414Swalsh 
4621487Ssklower struct ifnet_en {
4721487Ssklower 	struct ifnet ifen_ifnet;
4821487Ssklower 	struct route ifen_route;
4921487Ssklower 	struct in_addr ifen_src;
5021487Ssklower 	struct in_addr ifen_dst;
5121487Ssklower };
5221487Ssklower 
5321487Ssklower int	nsipoutput(), nsipioctl();
5421487Ssklower #define LOMTU	(1024+512);
5521487Ssklower 
5621487Ssklower struct ifnet nsipif;
5721487Ssklower union ns_net nsip_net;
5821487Ssklower struct mbuf *nsip_list;		/* list of all hosts and gateways or
5921487Ssklower 					broadcast addrs */
6021487Ssklower 
6121487Ssklower struct mbuf *
6221487Ssklower nsipattach()
6321487Ssklower {
6421487Ssklower 	register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
6521487Ssklower 	register struct ifnet *ifp;
6621487Ssklower 
6721487Ssklower 	if (m==0) return (0);
6821487Ssklower 	m->m_off = MMINOFF;
6921487Ssklower 	m->m_len = sizeof(struct ifnet_en);
7021487Ssklower 	m->m_next = nsip_list;
7121487Ssklower 	nsip_list = m;
7221487Ssklower 	ifp = mtod(m, struct ifnet *);
7321487Ssklower 
7421487Ssklower 	ifp->if_name = "nsip";
7521487Ssklower 	ifp->if_mtu = LOMTU;
7621487Ssklower 	ifp->if_ioctl = nsipioctl;
7721487Ssklower 	ifp->if_output = nsipoutput;
7821487Ssklower 	ifp->if_flags = IFF_POINTOPOINT;
7921487Ssklower 	ifp->if_unit = nsipif.if_unit++;
8021487Ssklower 	if_attach(ifp);
8121487Ssklower 	return(dtom(ifp));
8221487Ssklower }
8321487Ssklower 
8421487Ssklower 
8521487Ssklower /*
8621487Ssklower  * Process an ioctl request.
8721487Ssklower  */
8821487Ssklower /* ARGSUSED */
8921487Ssklower nsipioctl(ifp, cmd, data)
9021487Ssklower 	register struct ifnet *ifp;
9121487Ssklower 	int cmd;
9221487Ssklower 	caddr_t data;
9321487Ssklower {
9421487Ssklower 	int error = 0;
95*25055Ssklower 	struct ifreq *ifr;
9621487Ssklower 
9721487Ssklower 	switch (cmd) {
9821487Ssklower 
9921487Ssklower 	case SIOCSIFADDR:
10021487Ssklower 		ifp->if_flags |= IFF_UP;
10121487Ssklower 		/*
10221487Ssklower 		 * Everything else is done at a higher level.
10321487Ssklower 		 */
10421487Ssklower 		break;
10521487Ssklower 
106*25055Ssklower 	case SIOCSIFFLAGS:
107*25055Ssklower 		ifr = (struct ifreq *)data;
108*25055Ssklower 		if ((ifr->ifr_flags & IFF_UP) == 0)
109*25055Ssklower 			error = nsip_free(ifp);
110*25055Ssklower 
111*25055Ssklower 
11221487Ssklower 	default:
11321487Ssklower 		error = EINVAL;
11421487Ssklower 	}
11521487Ssklower 	return (error);
11621487Ssklower }
11721487Ssklower 
11821487Ssklower struct mbuf *nsip_badlen;
11921487Ssklower struct mbuf *nsip_lastin;
12021487Ssklower int nsip_hold_input;
12121487Ssklower 
12224562Skarels idpip_input(m, ifp)
12324562Skarels 	register struct mbuf *m;
12424562Skarels 	struct ifnet *ifp;
12521487Ssklower {
12621487Ssklower 	register struct ip *ip;
12721487Ssklower 	register struct idp *idp;
12821487Ssklower 	register struct ifqueue *ifq = &nsintrq;
12921487Ssklower 	int len, s;
13021487Ssklower 
13121487Ssklower 	if(nsip_hold_input) {
13221487Ssklower 		if(nsip_lastin) {
13324226Ssklower 			m_freem(nsip_lastin);
13421487Ssklower 		}
13524562Skarels 		nsip_lastin = m_copy(m, 0, (int)M_COPYALL);
13621487Ssklower 	}
13721487Ssklower 	/*
13821487Ssklower 	 * Get IP and IDP header together in first mbuf.
13921487Ssklower 	 */
14021487Ssklower 	nsipif.if_ipackets++;
14121487Ssklower 	s = sizeof (struct ip) + sizeof (struct idp);
14221487Ssklower 	if ((m->m_off > MMAXOFF || m->m_len < s) &&
14321487Ssklower 	    (m = m_pullup(m, s))==0) {
14421487Ssklower 		nsipif.if_ierrors++;
14521487Ssklower 		return;
14621487Ssklower 	}
14721487Ssklower 	ip = mtod(m, struct ip *);
14824827Skarels 	if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
14924827Skarels 		ip_stripoptions(ip, (struct mbuf *)0);
15024827Skarels 		if (m->m_len < s) {
15124827Skarels 			if ((m = m_pullup(m, s))==0) {
15224827Skarels 				nsipif.if_ierrors++;
15324827Skarels 				return;
15424827Skarels 			}
15524827Skarels 			ip = mtod(m, struct ip *);
15624827Skarels 		}
15724827Skarels 	}
15821487Ssklower 
15921487Ssklower 	/*
16021487Ssklower 	 * Make mbuf data length reflect IDP length.
16121487Ssklower 	 * If not enough data to reflect IDP length, drop.
16221487Ssklower 	 */
16321487Ssklower 	m->m_off += sizeof (struct ip);
16421487Ssklower 	m->m_len -= sizeof (struct ip);
16521487Ssklower 	idp = mtod(m, struct idp *);
16621487Ssklower 	len = ntohs(idp->idp_len);
16723839Ssklower 	if (len & 1) len++;		/* Preserve Garbage Byte */
16821487Ssklower 	if (ip->ip_len != len) {
16921487Ssklower 		if (len > ip->ip_len) {
17021487Ssklower 			nsipif.if_ierrors++;
17121487Ssklower 			if(nsip_badlen) m_freem(nsip_badlen);
17221487Ssklower 			nsip_badlen = m;
17321487Ssklower 			return;
17421487Ssklower 		}
17524043Ssklower 		/* Any extra will be trimmed off by the NS routines */
17621487Ssklower 	}
17724562Skarels 
17821487Ssklower 	/*
17924562Skarels 	 * Place interface pointer before the data
18024562Skarels 	 * for the receiving protocol.
18124562Skarels 	 */
18224562Skarels 	if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) {
18324562Skarels 		m->m_off -= sizeof(struct ifnet *);
18424562Skarels 		m->m_len += sizeof(struct ifnet *);
18524562Skarels 	} else {
18624562Skarels 		struct mbuf *n;
18724562Skarels 
18824562Skarels 		n = m_get(M_DONTWAIT, MT_HEADER);
18924562Skarels 		if (n == (struct mbuf *)0)
19024562Skarels 			goto bad;
19124562Skarels 		n->m_off = MMINOFF;
19224562Skarels 		n->m_len = sizeof(struct ifnet *);
19324562Skarels 		n->m_next = m;
19424562Skarels 		m = n;
19524562Skarels 	}
19624562Skarels 	*(mtod(m, struct ifnet **)) = ifp;
19724562Skarels 
19824562Skarels 	/*
19921487Ssklower 	 * Deliver to NS
20021487Ssklower 	 */
20121487Ssklower 	s = splimp();
20221487Ssklower 	if (IF_QFULL(ifq)) {
20321487Ssklower 		IF_DROP(ifq);
20424562Skarels bad:
20524562Skarels 		m_freem(m);
20621487Ssklower 		splx(s);
20724226Ssklower 		return;
20821487Ssklower 	}
20924562Skarels 	IF_ENQUEUE(ifq, m);
21021487Ssklower 	schednetisr(NETISR_NS);
21121487Ssklower 	splx(s);
21224226Ssklower 	return;
21321487Ssklower }
21421487Ssklower 
21524226Ssklower /* ARGSUSED */
21621487Ssklower nsipoutput(ifn, m0, dst)
21721487Ssklower 	struct ifnet_en *ifn;
21821487Ssklower 	struct mbuf *m0;
21921487Ssklower 	struct sockaddr *dst;
22021487Ssklower {
22121487Ssklower 
22221487Ssklower 	register struct mbuf *m = dtom(ifn);
22321487Ssklower 	register struct ip *ip;
22421487Ssklower 	register struct route *ro = &(ifn->ifen_route);
22521487Ssklower 	register int len = 0;
22621487Ssklower 	register struct idp *idp = mtod(m0, struct idp *);
22721487Ssklower 	int error;
22821487Ssklower 
22921487Ssklower 	if (m->m_len != sizeof(struct ifnet_en)) {
23021487Ssklower 		printf("nsipoutput: bad dst ifp %x\n", ifn);
23121487Ssklower 		goto bad;
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 */
24321487Ssklower 	m = m0;
24421487Ssklower 	if(m->m_off < MMINOFF + sizeof (struct ip)) {
24521487Ssklower 		m = m_get(M_DONTWAIT, MT_HEADER);
24621487Ssklower 		if (m == 0) {
24721487Ssklower 			m_freem(m0);
24821487Ssklower 			return (ENOBUFS);
24921487Ssklower 		}
25021487Ssklower 		m->m_off = MMAXOFF - sizeof (struct ip);
25121487Ssklower 		m->m_len = sizeof (struct ip);
25221487Ssklower 		m->m_next = m0;
25321487Ssklower 	} else {
25421487Ssklower 		m->m_off -= sizeof (struct ip);
25521487Ssklower 		m->m_len += sizeof (struct ip);
25621487Ssklower 	}
25721487Ssklower 	/*
25821487Ssklower 	 * Fill in IP header.
25921487Ssklower 	 */
26021487Ssklower 	ip = mtod(m, struct ip *);
26121487Ssklower 	*(long *)ip = 0;
26224043Ssklower 	ip->ip_p = IPPROTO_IDP;
26321487Ssklower 	ip->ip_src = ifn->ifen_src;
26421487Ssklower 	ip->ip_dst = ifn->ifen_dst;
26524414Swalsh #ifdef BBNNET
26624414Swalsh 	ip->ip_tos = 0;
26724414Swalsh 	NOPCB_IPSEND(m, len, 0, error);
26824414Swalsh #else
26921487Ssklower 	ip->ip_len = (u_short)len + sizeof (struct ip);
27021487Ssklower 	ip->ip_ttl = MAXTTL;
27121487Ssklower 
27221487Ssklower 	/*
27321487Ssklower 	 * Output final datagram.
27421487Ssklower 	 */
27521487Ssklower 	error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST));
27624414Swalsh #endif
27721487Ssklower 	if (error) {
27821487Ssklower 		ifn->ifen_ifnet.if_oerrors++;
27921487Ssklower 		ifn->ifen_ifnet.if_ierrors = error;
28021487Ssklower 	}
28121487Ssklower 	return (error);
28221487Ssklower bad:
28321487Ssklower 	m_freem(m0);
28421487Ssklower 	return(ENETUNREACH);
28521487Ssklower }
28621487Ssklower 
28721487Ssklower struct ifreq ifr = {"nsip0"};
28821487Ssklower 
28921487Ssklower nsip_route(m)
29021487Ssklower 	register struct mbuf *m;
29121487Ssklower {
29221487Ssklower 	register struct nsip_req *rq = mtod(m, struct nsip_req *);
29321487Ssklower 	struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
29421487Ssklower 	struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
29521487Ssklower 	struct route ro;
29621487Ssklower 	struct ifnet_en *ifn;
29721487Ssklower 	struct sockaddr_in *src;
29821487Ssklower 	/*
29921487Ssklower 	 * First, determine if we can get to the destination
30021487Ssklower 	 */
30121487Ssklower 	bzero((caddr_t)&ro, sizeof (ro));
30221487Ssklower 	ro.ro_dst = *(struct sockaddr *)ip_dst;
30321487Ssklower 	rtalloc(&ro);
30424226Ssklower 	if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
30521487Ssklower 		return (ENETUNREACH);
30621487Ssklower 	}
30721487Ssklower 	/*
30821487Ssklower 	 * And see how he's going to get back to us:
30921487Ssklower 	 */
31021487Ssklower 	{
31121487Ssklower 		register struct in_ifaddr *ia;
31221487Ssklower 		struct ifnet *ifp = ro.ro_rt->rt_ifp;
31321487Ssklower 
31421487Ssklower 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
31521487Ssklower 			if (ia->ia_ifp == ifp)
31621487Ssklower 				break;
31721487Ssklower 		if (ia == 0)
31821487Ssklower 			ia = in_ifaddr;
31921487Ssklower 		if (ia == 0) {
32021487Ssklower 			return (EADDRNOTAVAIL);
32121487Ssklower 		}
32221487Ssklower 		src = (struct sockaddr_in *)&ia->ia_addr;
32321487Ssklower 	}
32421487Ssklower 	/*
325*25055Ssklower 	 * Is there a free (pseudo-)interface or space?
32621487Ssklower 	 */
327*25055Ssklower 	for (m = nsip_list; m; m = m->m_next) {
328*25055Ssklower 		struct ifnet *ifp = mtod(m, struct ifnet *);
329*25055Ssklower 		if ((ifp->if_flags & IFF_UP) == 0)
330*25055Ssklower 			break;
331*25055Ssklower 	}
332*25055Ssklower 	if (m == (struct mbuf *) 0)
333*25055Ssklower 		m = nsipattach();
33421487Ssklower 	if (m==NULL) {return (ENOBUFS);}
33521487Ssklower 	ifn = mtod(m, struct ifnet_en *);
33621487Ssklower 
33721487Ssklower 	ro.ro_rt->rt_use++;
33821487Ssklower 	ifn->ifen_route = ro;
33921487Ssklower 	ifn->ifen_dst =  ip_dst->sin_addr;
34021487Ssklower 	ifn->ifen_src = src->sin_addr;
34121487Ssklower 
34221487Ssklower 	/*
34321487Ssklower 	 * now configure this as a point to point link
34421487Ssklower 	 */
34521487Ssklower 	ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
34621487Ssklower 	ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
34724226Ssklower 	return(ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
34821487Ssklower 			(struct ifnet *)ifn));
34921487Ssklower }
350*25055Ssklower 
351*25055Ssklower nsip_free(ifp)
352*25055Ssklower struct ifnet *ifp;
353*25055Ssklower {
354*25055Ssklower 	register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
355*25055Ssklower 	struct route *ro = & ifn->ifen_route;
356*25055Ssklower 
357*25055Ssklower 	if (ro->ro_rt) {
358*25055Ssklower 		RTFREE(ro->ro_rt);
359*25055Ssklower 		ro->ro_rt = 0;
360*25055Ssklower 	}
361*25055Ssklower 	ifp->if_flags &= ~IFF_UP;
362*25055Ssklower 	return (0);
363*25055Ssklower }
364*25055Ssklower 
365*25055Ssklower nsip_ctlinput(cmd, sa)
366*25055Ssklower 	int cmd;
367*25055Ssklower 	struct sockaddr *sa;
368*25055Ssklower {
369*25055Ssklower 	extern u_char inetctlerrmap[];
370*25055Ssklower 	struct sockaddr_in *sin;
371*25055Ssklower 	int in_rtchange();
372*25055Ssklower 
373*25055Ssklower 	if ((unsigned)cmd > PRC_NCMDS)
374*25055Ssklower 		return;
375*25055Ssklower 	if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
376*25055Ssklower 		return;
377*25055Ssklower 	sin = (struct sockaddr_in *)sa;
378*25055Ssklower 	if (sin->sin_addr.s_addr == INADDR_ANY)
379*25055Ssklower 		return;
380*25055Ssklower 
381*25055Ssklower 	switch (cmd) {
382*25055Ssklower 
383*25055Ssklower 	case PRC_ROUTEDEAD:
384*25055Ssklower 	case PRC_REDIRECT_NET:
385*25055Ssklower 	case PRC_REDIRECT_HOST:
386*25055Ssklower 	case PRC_REDIRECT_TOSNET:
387*25055Ssklower 	case PRC_REDIRECT_TOSHOST:
388*25055Ssklower 		nsip_rtchange(&sin->sin_addr);
389*25055Ssklower 		break;
390*25055Ssklower 	}
391*25055Ssklower }
392*25055Ssklower 
393*25055Ssklower nsip_rtchange(dst)
394*25055Ssklower 	register struct in_addr *dst;
395*25055Ssklower {
396*25055Ssklower 	register struct mbuf *m;
397*25055Ssklower 	register struct ifnet_en *ifn;
398*25055Ssklower 
399*25055Ssklower 	for (m = nsip_list; m; m = m->m_next)
400*25055Ssklower 		if (ifn->ifen_dst.s_addr == dst->s_addr &&
401*25055Ssklower 			ifn->ifen_route.ro_rt) {
402*25055Ssklower 				RTFREE(ifn->ifen_route.ro_rt);
403*25055Ssklower 				ifn->ifen_route.ro_rt = 0;
404*25055Ssklower 		}
405*25055Ssklower }
40621487Ssklower #endif
407