xref: /csrg-svn/sys/netns/ns_ip.c (revision 21487)
1*21487Ssklower /*      ns_ip.c     6.1     85/05/30     */
2*21487Ssklower 
3*21487Ssklower /*
4*21487Ssklower  * Software interface driver for encapsulating ns in ip.
5*21487Ssklower  */
6*21487Ssklower 
7*21487Ssklower #ifdef NSIP
8*21487Ssklower #include "param.h"
9*21487Ssklower #include "systm.h"
10*21487Ssklower #include "mbuf.h"
11*21487Ssklower #include "socket.h"
12*21487Ssklower #include "errno.h"
13*21487Ssklower #include "ioctl.h"
14*21487Ssklower 
15*21487Ssklower #include "../net/if.h"
16*21487Ssklower #include "../net/netisr.h"
17*21487Ssklower #include "../net/route.h"
18*21487Ssklower 
19*21487Ssklower #include "../netinet/in.h"
20*21487Ssklower #include "../netinet/in_systm.h"
21*21487Ssklower #include "../netinet/in_var.h"
22*21487Ssklower #include "../netinet/ip.h"
23*21487Ssklower #include "../netinet/ip_var.h"
24*21487Ssklower 
25*21487Ssklower #ifdef vax
26*21487Ssklower #include "../vax/mtpr.h"
27*21487Ssklower #endif
28*21487Ssklower 
29*21487Ssklower #include "../netns/ns.h"
30*21487Ssklower #include "../netns/ns_if.h"
31*21487Ssklower #include "../netns/idp.h"
32*21487Ssklower 
33*21487Ssklower struct ifnet_en {
34*21487Ssklower 	struct ifnet ifen_ifnet;
35*21487Ssklower 	struct route ifen_route;
36*21487Ssklower 	struct in_addr ifen_src;
37*21487Ssklower 	struct in_addr ifen_dst;
38*21487Ssklower };
39*21487Ssklower 
40*21487Ssklower int	nsipoutput(), nsipioctl();
41*21487Ssklower #define LOMTU	(1024+512);
42*21487Ssklower 
43*21487Ssklower struct ifnet nsipif;
44*21487Ssklower union ns_net nsip_net;
45*21487Ssklower struct mbuf *nsip_list;		/* list of all hosts and gateways or
46*21487Ssklower 					broadcast addrs */
47*21487Ssklower 
48*21487Ssklower struct mbuf *
49*21487Ssklower nsipattach()
50*21487Ssklower {
51*21487Ssklower 	register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
52*21487Ssklower 	register struct ifnet *ifp;
53*21487Ssklower 	register struct sockaddr_in *sin;
54*21487Ssklower 
55*21487Ssklower 	if (m==0) return (0);
56*21487Ssklower 	m->m_off = MMINOFF;
57*21487Ssklower 	m->m_len = sizeof(struct ifnet_en);
58*21487Ssklower 	m->m_next = nsip_list;
59*21487Ssklower 	nsip_list = m;
60*21487Ssklower 	ifp = mtod(m, struct ifnet *);
61*21487Ssklower 
62*21487Ssklower 	ifp->if_name = "nsip";
63*21487Ssklower 	ifp->if_mtu = LOMTU;
64*21487Ssklower 	ifp->if_ioctl = nsipioctl;
65*21487Ssklower 	ifp->if_output = nsipoutput;
66*21487Ssklower 	ifp->if_flags = IFF_POINTOPOINT;
67*21487Ssklower 	ifp->if_unit = nsipif.if_unit++;
68*21487Ssklower 	if_attach(ifp);
69*21487Ssklower 	return(dtom(ifp));
70*21487Ssklower }
71*21487Ssklower 
72*21487Ssklower 
73*21487Ssklower /*
74*21487Ssklower  * Process an ioctl request.
75*21487Ssklower  */
76*21487Ssklower /* ARGSUSED */
77*21487Ssklower nsipioctl(ifp, cmd, data)
78*21487Ssklower 	register struct ifnet *ifp;
79*21487Ssklower 	int cmd;
80*21487Ssklower 	caddr_t data;
81*21487Ssklower {
82*21487Ssklower 	int error = 0;
83*21487Ssklower 
84*21487Ssklower 	switch (cmd) {
85*21487Ssklower 
86*21487Ssklower 	case SIOCSIFADDR:
87*21487Ssklower 		ifp->if_flags |= IFF_UP;
88*21487Ssklower 		/*
89*21487Ssklower 		 * Everything else is done at a higher level.
90*21487Ssklower 		 */
91*21487Ssklower 		break;
92*21487Ssklower 
93*21487Ssklower 	default:
94*21487Ssklower 		error = EINVAL;
95*21487Ssklower 	}
96*21487Ssklower 	return (error);
97*21487Ssklower }
98*21487Ssklower 
99*21487Ssklower struct mbuf *nsip_badlen;
100*21487Ssklower struct mbuf *nsip_lastin;
101*21487Ssklower int nsip_hold_input;
102*21487Ssklower 
103*21487Ssklower idpip_input(m0)
104*21487Ssklower 	struct mbuf *m0;
105*21487Ssklower {
106*21487Ssklower 	register struct ip *ip;
107*21487Ssklower 	register struct idp *idp;
108*21487Ssklower 	register struct mbuf *m;
109*21487Ssklower 	register struct ifqueue *ifq = &nsintrq;
110*21487Ssklower 	int len, s;
111*21487Ssklower 
112*21487Ssklower 	if(nsip_hold_input) {
113*21487Ssklower 		if(nsip_lastin) {
114*21487Ssklower 			m_free(nsip_lastin);
115*21487Ssklower 		}
116*21487Ssklower 		nsip_lastin = m_copy(m0, 0, M_COPYALL);
117*21487Ssklower 	}
118*21487Ssklower 	/*
119*21487Ssklower 	 * Get IP and IDP header together in first mbuf.
120*21487Ssklower 	 */
121*21487Ssklower 	nsipif.if_ipackets++;
122*21487Ssklower 	m = m0;
123*21487Ssklower 	s = sizeof (struct ip) + sizeof (struct idp);
124*21487Ssklower 	if ((m->m_off > MMAXOFF || m->m_len < s) &&
125*21487Ssklower 	    (m = m_pullup(m, s))==0) {
126*21487Ssklower 		nsipif.if_ierrors++;
127*21487Ssklower 		return;
128*21487Ssklower 	}
129*21487Ssklower 	ip = mtod(m, struct ip *);
130*21487Ssklower 	if (ip->ip_hl > (sizeof (struct ip) >> 2))
131*21487Ssklower 		ip_stripoptions(ip, (struct mbuf *)0);
132*21487Ssklower 
133*21487Ssklower 	/*
134*21487Ssklower 	 * Make mbuf data length reflect IDP length.
135*21487Ssklower 	 * If not enough data to reflect IDP length, drop.
136*21487Ssklower 	 */
137*21487Ssklower 	m->m_off += sizeof (struct ip);
138*21487Ssklower 	m->m_len -= sizeof (struct ip);
139*21487Ssklower 	idp = mtod(m, struct idp *);
140*21487Ssklower 	len = ntohs(idp->idp_len);
141*21487Ssklower 	if (ip->ip_len != len) {
142*21487Ssklower 		if (len > ip->ip_len) {
143*21487Ssklower 			nsipif.if_ierrors++;
144*21487Ssklower 			if(nsip_badlen) m_freem(nsip_badlen);
145*21487Ssklower 			nsip_badlen = m;
146*21487Ssklower 			return;
147*21487Ssklower 		}
148*21487Ssklower 		m_adj(m, len - ip->ip_len);
149*21487Ssklower 		/* ip->ip_len = len; */
150*21487Ssklower 	}
151*21487Ssklower 	/*
152*21487Ssklower 	 * Deliver to NS
153*21487Ssklower 	 */
154*21487Ssklower 	s = splimp();
155*21487Ssklower 	if (IF_QFULL(ifq)) {
156*21487Ssklower 		IF_DROP(ifq);
157*21487Ssklower 		m_freem(m0);
158*21487Ssklower 		splx(s);
159*21487Ssklower 		return (ENOBUFS);
160*21487Ssklower 	}
161*21487Ssklower 	IF_ENQUEUE(ifq, m0);
162*21487Ssklower 	schednetisr(NETISR_NS);
163*21487Ssklower 	splx(s);
164*21487Ssklower 	return (0);
165*21487Ssklower bad:
166*21487Ssklower 	m_freem(m);
167*21487Ssklower 	return (0);
168*21487Ssklower }
169*21487Ssklower 
170*21487Ssklower nsipoutput(ifn, m0, dst)
171*21487Ssklower 	struct ifnet_en *ifn;
172*21487Ssklower 	struct mbuf *m0;
173*21487Ssklower 	struct sockaddr *dst;
174*21487Ssklower {
175*21487Ssklower 
176*21487Ssklower 	register struct mbuf *m = dtom(ifn);
177*21487Ssklower 	register struct ip *ip;
178*21487Ssklower 	register struct route *ro = &(ifn->ifen_route);
179*21487Ssklower 	register int len = 0;
180*21487Ssklower 	struct in_addr in_src, in_dst;
181*21487Ssklower 	register struct idp *idp = mtod(m0, struct idp *);
182*21487Ssklower 	int error;
183*21487Ssklower 
184*21487Ssklower 	if (m->m_len != sizeof(struct ifnet_en)) {
185*21487Ssklower 		printf("nsipoutput: bad dst ifp %x\n", ifn);
186*21487Ssklower 		goto bad;
187*21487Ssklower 	}
188*21487Ssklower 	ifn->ifen_ifnet.if_opackets++;
189*21487Ssklower 	nsipif.if_opackets++;
190*21487Ssklower 
191*21487Ssklower 
192*21487Ssklower 	/*
193*21487Ssklower 	 * Calculate data length and make space
194*21487Ssklower 	 * for IP header.
195*21487Ssklower 	 */
196*21487Ssklower 	len =  ntohs(idp->idp_len);
197*21487Ssklower 	m = m0;
198*21487Ssklower 	if(m->m_off < MMINOFF + sizeof (struct ip)) {
199*21487Ssklower 		m = m_get(M_DONTWAIT, MT_HEADER);
200*21487Ssklower 		if (m == 0) {
201*21487Ssklower 			m_freem(m0);
202*21487Ssklower 			return (ENOBUFS);
203*21487Ssklower 		}
204*21487Ssklower 		m->m_off = MMAXOFF - sizeof (struct ip);
205*21487Ssklower 		m->m_len = sizeof (struct ip);
206*21487Ssklower 		m->m_next = m0;
207*21487Ssklower 	} else {
208*21487Ssklower 		m->m_off -= sizeof (struct ip);
209*21487Ssklower 		m->m_len += sizeof (struct ip);
210*21487Ssklower 	}
211*21487Ssklower 	/*
212*21487Ssklower 	 * Fill in IP header.
213*21487Ssklower 	 */
214*21487Ssklower 	ip = mtod(m, struct ip *);
215*21487Ssklower 	*(long *)ip = 0;
216*21487Ssklower 	ip->ip_p = IPPROTO_PUP;
217*21487Ssklower 	ip->ip_src = ifn->ifen_src;
218*21487Ssklower 	ip->ip_dst = ifn->ifen_dst;
219*21487Ssklower 	ip->ip_len = (u_short)len + sizeof (struct ip);
220*21487Ssklower 	ip->ip_ttl = MAXTTL;
221*21487Ssklower 
222*21487Ssklower 	/*
223*21487Ssklower 	 * Output final datagram.
224*21487Ssklower 	 */
225*21487Ssklower 	error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST));
226*21487Ssklower 	if (error) {
227*21487Ssklower 		ifn->ifen_ifnet.if_oerrors++;
228*21487Ssklower 		ifn->ifen_ifnet.if_ierrors = error;
229*21487Ssklower 	}
230*21487Ssklower 	return (error);
231*21487Ssklower bad:
232*21487Ssklower 	m_freem(m0);
233*21487Ssklower 	return(ENETUNREACH);
234*21487Ssklower }
235*21487Ssklower 
236*21487Ssklower struct ifreq ifr = {"nsip0"};
237*21487Ssklower 
238*21487Ssklower nsip_route(m)
239*21487Ssklower 	register struct mbuf *m;
240*21487Ssklower {
241*21487Ssklower 	register struct nsip_req *rq = mtod(m, struct nsip_req *);
242*21487Ssklower 	struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
243*21487Ssklower 	struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
244*21487Ssklower 	int flags = rq->rq_flags;
245*21487Ssklower 	struct ifnet *ifp;
246*21487Ssklower 	struct route ro;
247*21487Ssklower 	struct ifnet_en *ifn;
248*21487Ssklower 	int error;
249*21487Ssklower 	struct sockaddr_in *dst;
250*21487Ssklower 	struct sockaddr_in *src;
251*21487Ssklower 	/*
252*21487Ssklower 	 * First, determine if we can get to the destination
253*21487Ssklower 	 */
254*21487Ssklower 	bzero((caddr_t)&ro, sizeof (ro));
255*21487Ssklower 	ro.ro_dst = *(struct sockaddr *)ip_dst;
256*21487Ssklower 	dst = (struct sockaddr_in *)& ro.ro_dst;
257*21487Ssklower 	rtalloc(&ro);
258*21487Ssklower 	if (ro.ro_rt == 0 || (ifp = ro.ro_rt->rt_ifp) == 0) {
259*21487Ssklower 		return (ENETUNREACH);
260*21487Ssklower 	}
261*21487Ssklower 	/*
262*21487Ssklower 	 * And see how he's going to get back to us:
263*21487Ssklower 	 */
264*21487Ssklower 	{
265*21487Ssklower 		register struct in_ifaddr *ia;
266*21487Ssklower 		struct ifnet *ifp = ro.ro_rt->rt_ifp;
267*21487Ssklower 
268*21487Ssklower 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
269*21487Ssklower 			if (ia->ia_ifp == ifp)
270*21487Ssklower 				break;
271*21487Ssklower 		if (ia == 0)
272*21487Ssklower 			ia = in_ifaddr;
273*21487Ssklower 		if (ia == 0) {
274*21487Ssklower 			return (EADDRNOTAVAIL);
275*21487Ssklower 		}
276*21487Ssklower 		src = (struct sockaddr_in *)&ia->ia_addr;
277*21487Ssklower 	}
278*21487Ssklower 	/*
279*21487Ssklower 	 * Is there space?
280*21487Ssklower 	 */
281*21487Ssklower 	m = nsipattach();
282*21487Ssklower 	if (m==NULL) {return (ENOBUFS);}
283*21487Ssklower 	ifn = mtod(m, struct ifnet_en *);
284*21487Ssklower 
285*21487Ssklower 	ro.ro_rt->rt_use++;
286*21487Ssklower 	ifn->ifen_route = ro;
287*21487Ssklower 	ifn->ifen_dst =  ip_dst->sin_addr;
288*21487Ssklower 	ifn->ifen_src = src->sin_addr;
289*21487Ssklower 
290*21487Ssklower 	/*
291*21487Ssklower 	 * now configure this as a point to point link
292*21487Ssklower 	 */
293*21487Ssklower 	ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
294*21487Ssklower 	ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
295*21487Ssklower 	return(ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr,
296*21487Ssklower 			(struct ifnet *)ifn));
297*21487Ssklower }
298*21487Ssklower #endif
299