xref: /csrg-svn/sys/netns/idp_usrreq.c (revision 21479)
1*21479Ssklower /*      idp_usrreq.c     6.1     85/05/30     */
2*21479Ssklower 
3*21479Ssklower #include "param.h"
4*21479Ssklower #include "dir.h"
5*21479Ssklower #include "user.h"
6*21479Ssklower #include "mbuf.h"
7*21479Ssklower #include "protosw.h"
8*21479Ssklower #include "socket.h"
9*21479Ssklower #include "socketvar.h"
10*21479Ssklower #include "errno.h"
11*21479Ssklower #include "stat.h"
12*21479Ssklower 
13*21479Ssklower #include "../net/if.h"
14*21479Ssklower #include "../net/route.h"
15*21479Ssklower 
16*21479Ssklower #include "ns.h"
17*21479Ssklower #include "ns_pcb.h"
18*21479Ssklower #include "idp.h"
19*21479Ssklower #include "idp_var.h"
20*21479Ssklower #include "ns_error.h"
21*21479Ssklower 
22*21479Ssklower /*
23*21479Ssklower  * IDP protocol implementation.
24*21479Ssklower  */
25*21479Ssklower 
26*21479Ssklower struct	sockaddr_ns idp_ns = { AF_NS };
27*21479Ssklower 
28*21479Ssklower int
29*21479Ssklower idp_input_panic = 1;
30*21479Ssklower idp_input(m, nsp)
31*21479Ssklower 	struct mbuf *m;
32*21479Ssklower 	register struct nspcb *nsp;
33*21479Ssklower {
34*21479Ssklower 	register struct idp *idp = mtod(m, struct idp *);
35*21479Ssklower 	if (idp_input_panic) {
36*21479Ssklower 		if ((nsp==0) || ((idp->idp_pt==5) && (!(nsp->nsp_flags&NSP_RAWIN))))
37*21479Ssklower 			panic("Impossible idp_input");
38*21479Ssklower 	}
39*21479Ssklower 
40*21479Ssklower 	/*
41*21479Ssklower 	 * Construct sockaddr format source address.
42*21479Ssklower 	 * Stuff source address and datagram in user buffer.
43*21479Ssklower 	 */
44*21479Ssklower 	idp_ns.sns_addr = idp->idp_sna;
45*21479Ssklower 	nsp->nsp_rpt = idp->idp_pt;
46*21479Ssklower 	if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
47*21479Ssklower 		m->m_len -= sizeof (struct idp);
48*21479Ssklower 		m->m_off += sizeof (struct idp);
49*21479Ssklower 	}
50*21479Ssklower 	if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
51*21479Ssklower 	    m, (struct mbuf *)0) == 0)
52*21479Ssklower 		goto bad;
53*21479Ssklower 	sorwakeup(nsp->nsp_socket);
54*21479Ssklower 	return;
55*21479Ssklower bad:
56*21479Ssklower 	m_freem(m);
57*21479Ssklower }
58*21479Ssklower 
59*21479Ssklower idp_abort(nsp)
60*21479Ssklower 	struct nspcb *nsp;
61*21479Ssklower {
62*21479Ssklower 	struct socket *so = nsp->nsp_socket;
63*21479Ssklower 
64*21479Ssklower 	ns_pcbdisconnect(nsp);
65*21479Ssklower 	soisdisconnected(so);
66*21479Ssklower }
67*21479Ssklower 
68*21479Ssklower idp_output(nsp, m0)
69*21479Ssklower 	struct nspcb *nsp;
70*21479Ssklower 	struct mbuf *m0;
71*21479Ssklower {
72*21479Ssklower 	register struct mbuf *m;
73*21479Ssklower 	register struct idp *idp;
74*21479Ssklower 	register struct socket *so;
75*21479Ssklower 	register int len = 0;
76*21479Ssklower 	register struct route *ro;
77*21479Ssklower 	struct mbuf *mprev;
78*21479Ssklower 	extern int idpcksum;
79*21479Ssklower 
80*21479Ssklower 	/*
81*21479Ssklower 	 * Calculate data length.
82*21479Ssklower 	 */
83*21479Ssklower 	for (m = m0; m; m = m->m_next) {
84*21479Ssklower 		mprev = m;
85*21479Ssklower 		len += m->m_len;
86*21479Ssklower 	}
87*21479Ssklower 	/*
88*21479Ssklower 	 * Make sure packet is actually of even length.
89*21479Ssklower 	 */
90*21479Ssklower 
91*21479Ssklower 	if (len & 1) {
92*21479Ssklower 		m = mprev;
93*21479Ssklower 		if (m->m_len + m->m_off < MMAXOFF) {
94*21479Ssklower 			m->m_len++;
95*21479Ssklower 		} else {
96*21479Ssklower 			struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
97*21479Ssklower 
98*21479Ssklower 			if (m1 == 0) return (ENOBUFS);
99*21479Ssklower 			m1->m_len = 1;
100*21479Ssklower 			m1->m_off = MMAXOFF - 1;
101*21479Ssklower 			* mtod(m1, char *) = 0;
102*21479Ssklower 			m->m_next = m1;
103*21479Ssklower 		}
104*21479Ssklower 	}
105*21479Ssklower 
106*21479Ssklower 	/*
107*21479Ssklower 	 * Fill in mbuf with extended IDP header
108*21479Ssklower 	 * and addresses and length put into network format.
109*21479Ssklower 	 */
110*21479Ssklower 	if (nsp->nsp_flags & NSP_RAWOUT) {
111*21479Ssklower 		m = m0;
112*21479Ssklower 		idp = mtod(m, struct idp *);
113*21479Ssklower 	} else {
114*21479Ssklower 		m = m_get(M_DONTWAIT, MT_HEADER);
115*21479Ssklower 		if (m == 0) {
116*21479Ssklower 			m_freem(m0);
117*21479Ssklower 			return (ENOBUFS);
118*21479Ssklower 		}
119*21479Ssklower 		m->m_off = MMAXOFF - sizeof (struct idp);
120*21479Ssklower 		m->m_len = sizeof (struct idp);
121*21479Ssklower 		m->m_next = m0;
122*21479Ssklower 		idp = mtod(m, struct idp *);
123*21479Ssklower 		idp->idp_tc = 0;
124*21479Ssklower 		idp->idp_pt = nsp->nsp_dpt;
125*21479Ssklower 		idp->idp_sna = nsp->nsp_laddr;
126*21479Ssklower 		idp->idp_dna = nsp->nsp_faddr;
127*21479Ssklower 		len += sizeof (struct idp);
128*21479Ssklower 	}
129*21479Ssklower 
130*21479Ssklower 	idp->idp_len = htons((u_short)len);
131*21479Ssklower 
132*21479Ssklower 	if (idpcksum) {
133*21479Ssklower 		idp->idp_sum = 0;
134*21479Ssklower 		len = ((len - 1) | 1) + 1;
135*21479Ssklower 		idp->idp_sum = ns_cksum(m, len);
136*21479Ssklower 	} else
137*21479Ssklower 		idp->idp_sum = 0xffff;
138*21479Ssklower 
139*21479Ssklower 	/*
140*21479Ssklower 	 * Output datagram.
141*21479Ssklower 	 */
142*21479Ssklower 	so = nsp->nsp_socket;
143*21479Ssklower 	if (so->so_options & SO_DONTROUTE)
144*21479Ssklower 		return (ns_output(m, (struct route *)0,
145*21479Ssklower 		    (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
146*21479Ssklower 	/*
147*21479Ssklower 	 * Use cached route for previous datagram if
148*21479Ssklower 	 * this is also to the same destination.
149*21479Ssklower 	 *
150*21479Ssklower 	 * NB: We don't handle broadcasts because that
151*21479Ssklower 	 *     would require 3 subroutine calls.
152*21479Ssklower 	 */
153*21479Ssklower 	ro = &nsp->nsp_route;
154*21479Ssklower 	if (ro->ro_rt &&
155*21479Ssklower 		((*(long *)&nsp->nsp_lastnet)!=ns_netof(idp->idp_dna)) &&
156*21479Ssklower 		!(ns_hosteq(satons_addr(ro->ro_dst), idp->idp_dna))) {
157*21479Ssklower 		RTFREE(ro->ro_rt);
158*21479Ssklower 		ro->ro_rt = (struct rtentry *)0;
159*21479Ssklower 		nsp->nsp_lastnet = idp->idp_dna.x_net;
160*21479Ssklower 	}
161*21479Ssklower 	return (ns_output(m, ro, so->so_options & SO_BROADCAST));
162*21479Ssklower }
163*21479Ssklower /*ARGSUSED*/
164*21479Ssklower idp_ctloutput(req, so, level, name, value)
165*21479Ssklower 	int req, level;
166*21479Ssklower 	struct socket *so;
167*21479Ssklower 	int name;
168*21479Ssklower 	struct mbuf **value;
169*21479Ssklower {
170*21479Ssklower 	register struct mbuf *m;
171*21479Ssklower 	struct nspcb *nsp = sotonspcb(so);
172*21479Ssklower 	int mask, error = 0;
173*21479Ssklower 
174*21479Ssklower 	if (nsp == NULL) {
175*21479Ssklower 		error = EINVAL;
176*21479Ssklower 		goto release;
177*21479Ssklower 	}
178*21479Ssklower 
179*21479Ssklower 	switch (req) {
180*21479Ssklower 	case PRCO_GETOPT:
181*21479Ssklower 		if (value==NULL) {
182*21479Ssklower 			error = EINVAL;
183*21479Ssklower 			goto release;
184*21479Ssklower 		}
185*21479Ssklower 		m = m_get(M_DONTWAIT, MT_DATA);
186*21479Ssklower 		switch (name) {
187*21479Ssklower 		case SO_HEADERS_ON_INPUT:
188*21479Ssklower 			mask = NSP_RAWIN;
189*21479Ssklower 			goto get_flags;
190*21479Ssklower 		case SO_HEADERS_ON_OUTPUT:
191*21479Ssklower 			mask = NSP_RAWOUT;
192*21479Ssklower 		get_flags:
193*21479Ssklower 			m->m_len = sizeof(short);
194*21479Ssklower 			m->m_off = MMAXOFF - sizeof(short);
195*21479Ssklower 			*mtod(m, short *) = nsp->nsp_flags & mask;
196*21479Ssklower 			break;
197*21479Ssklower 		case SO_DEFAULT_HEADERS:
198*21479Ssklower 			m->m_len = sizeof(struct idp);
199*21479Ssklower 			m->m_off = MMAXOFF - sizeof(struct idp);
200*21479Ssklower 			{
201*21479Ssklower 				register struct idp *idp = mtod(m, struct idp *);
202*21479Ssklower 				idp->idp_len = 0;
203*21479Ssklower 				idp->idp_sum = 0;
204*21479Ssklower 				idp->idp_tc = 0;
205*21479Ssklower 				idp->idp_pt = nsp->nsp_dpt;
206*21479Ssklower 				idp->idp_dna = nsp->nsp_faddr;
207*21479Ssklower 				idp->idp_sna = nsp->nsp_laddr;
208*21479Ssklower 			}
209*21479Ssklower 		}
210*21479Ssklower 		*value = m;
211*21479Ssklower 		break;
212*21479Ssklower 	case PRCO_SETOPT:
213*21479Ssklower 		switch (name) {
214*21479Ssklower 			int mask, *ok;
215*21479Ssklower 
216*21479Ssklower 		case SO_HEADERS_ON_INPUT:
217*21479Ssklower 			mask = NSP_RAWIN;
218*21479Ssklower 			goto set_head;
219*21479Ssklower 		case SO_HEADERS_ON_OUTPUT:
220*21479Ssklower 			mask = NSP_RAWOUT;
221*21479Ssklower 		set_head:
222*21479Ssklower 			if (value && *value) {
223*21479Ssklower 				ok = mtod(*value, int *);
224*21479Ssklower 				if (*ok)
225*21479Ssklower 					nsp->nsp_flags |= mask;
226*21479Ssklower 				else
227*21479Ssklower 					nsp->nsp_flags &= ~mask;
228*21479Ssklower 			} else error = EINVAL;
229*21479Ssklower 			break;
230*21479Ssklower 		case SO_DEFAULT_HEADERS:
231*21479Ssklower 			{
232*21479Ssklower 				register struct idp *idp
233*21479Ssklower 				    = mtod(*value, struct idp *);
234*21479Ssklower 				nsp->nsp_dpt = idp->idp_pt;
235*21479Ssklower 			}
236*21479Ssklower #ifdef NSIP
237*21479Ssklower 			break;
238*21479Ssklower 		case SO_NSIP_ROUTE:
239*21479Ssklower 			error = nsip_route(*value);
240*21479Ssklower 			break;
241*21479Ssklower #endif NSIP
242*21479Ssklower 		}
243*21479Ssklower 		if (value && *value)
244*21479Ssklower 			m_freem(*value);
245*21479Ssklower 		break;
246*21479Ssklower 	}
247*21479Ssklower 	release:
248*21479Ssklower 		return(error);
249*21479Ssklower }
250*21479Ssklower 
251*21479Ssklower /*ARGSUSED*/
252*21479Ssklower idp_usrreq(so, req, m, nam, rights)
253*21479Ssklower 	struct socket *so;
254*21479Ssklower 	int req;
255*21479Ssklower 	struct mbuf *m, *nam, *rights;
256*21479Ssklower {
257*21479Ssklower 	struct nspcb *nsp = sotonspcb(so);
258*21479Ssklower 	int error = 0;
259*21479Ssklower 
260*21479Ssklower 	if (req == PRU_CONTROL)
261*21479Ssklower                 return (ns_control(so, (int)m, (caddr_t)nam,
262*21479Ssklower 			(struct ifnet *)rights));
263*21479Ssklower 	if (rights && rights->m_len) {
264*21479Ssklower 		error = EINVAL;
265*21479Ssklower 		goto release;
266*21479Ssklower 	}
267*21479Ssklower 	if (nsp == NULL && req != PRU_ATTACH) {
268*21479Ssklower 		error = EINVAL;
269*21479Ssklower 		goto release;
270*21479Ssklower 	}
271*21479Ssklower 	switch (req) {
272*21479Ssklower 
273*21479Ssklower 	case PRU_ATTACH:
274*21479Ssklower 		if (nsp != NULL) {
275*21479Ssklower 			error = EINVAL;
276*21479Ssklower 			break;
277*21479Ssklower 		}
278*21479Ssklower 		error = ns_pcballoc(so, &nspcb);
279*21479Ssklower 		if (error)
280*21479Ssklower 			break;
281*21479Ssklower 		error = soreserve(so, 2048, 2048);
282*21479Ssklower 		if (error)
283*21479Ssklower 			break;
284*21479Ssklower 		break;
285*21479Ssklower 
286*21479Ssklower 	case PRU_DETACH:
287*21479Ssklower 		if (nsp == NULL) {
288*21479Ssklower 			error = ENOTCONN;
289*21479Ssklower 			break;
290*21479Ssklower 		}
291*21479Ssklower 		ns_pcbdetach(nsp);
292*21479Ssklower 		break;
293*21479Ssklower 
294*21479Ssklower 	case PRU_BIND:
295*21479Ssklower 		error = ns_pcbbind(nsp, nam);
296*21479Ssklower 		break;
297*21479Ssklower 
298*21479Ssklower 	case PRU_LISTEN:
299*21479Ssklower 		error = EOPNOTSUPP;
300*21479Ssklower 		break;
301*21479Ssklower 
302*21479Ssklower 	case PRU_CONNECT:
303*21479Ssklower 		if (!ns_nullhost(nsp->nsp_faddr)) {
304*21479Ssklower 			error = EISCONN;
305*21479Ssklower 			break;
306*21479Ssklower 		}
307*21479Ssklower 		error = ns_pcbconnect(nsp, nam);
308*21479Ssklower 		if (error == 0)
309*21479Ssklower 			soisconnected(so);
310*21479Ssklower 		break;
311*21479Ssklower 
312*21479Ssklower 	case PRU_CONNECT2:
313*21479Ssklower 		error = EOPNOTSUPP;
314*21479Ssklower 		break;
315*21479Ssklower 
316*21479Ssklower 	case PRU_ACCEPT:
317*21479Ssklower 		error = EOPNOTSUPP;
318*21479Ssklower 		break;
319*21479Ssklower 
320*21479Ssklower 	case PRU_DISCONNECT:
321*21479Ssklower 		if (ns_nullhost(nsp->nsp_faddr)) {
322*21479Ssklower 			error = ENOTCONN;
323*21479Ssklower 			break;
324*21479Ssklower 		}
325*21479Ssklower 		ns_pcbdisconnect(nsp);
326*21479Ssklower 		soisdisconnected(so);
327*21479Ssklower 		break;
328*21479Ssklower 
329*21479Ssklower 	case PRU_SHUTDOWN:
330*21479Ssklower 		socantsendmore(so);
331*21479Ssklower 		break;
332*21479Ssklower 
333*21479Ssklower 	case PRU_SEND:
334*21479Ssklower 	{
335*21479Ssklower 		struct ns_addr laddr;
336*21479Ssklower 		int s;
337*21479Ssklower 
338*21479Ssklower 		if (nam) {
339*21479Ssklower 			laddr = nsp->nsp_laddr;
340*21479Ssklower 			if (!ns_nullhost(nsp->nsp_faddr)) {
341*21479Ssklower 				error = EISCONN;
342*21479Ssklower 				break;
343*21479Ssklower 			}
344*21479Ssklower 			/*
345*21479Ssklower 			 * Must block input while temporarily connected.
346*21479Ssklower 			 */
347*21479Ssklower 			s = splnet();
348*21479Ssklower 			error = ns_pcbconnect(nsp, nam);
349*21479Ssklower 			if (error) {
350*21479Ssklower 				splx(s);
351*21479Ssklower 				break;
352*21479Ssklower 			}
353*21479Ssklower 		} else {
354*21479Ssklower 			if (ns_nullhost(nsp->nsp_faddr)) {
355*21479Ssklower 				error = ENOTCONN;
356*21479Ssklower 				break;
357*21479Ssklower 			}
358*21479Ssklower 		}
359*21479Ssklower 		error = idp_output(nsp, m);
360*21479Ssklower 		m = NULL;
361*21479Ssklower 		if (nam) {
362*21479Ssklower 			ns_pcbdisconnect(nsp);
363*21479Ssklower 			splx(s);
364*21479Ssklower 			nsp->nsp_laddr.x_host = laddr.x_host;
365*21479Ssklower 			nsp->nsp_laddr.x_port = laddr.x_port;
366*21479Ssklower 		}
367*21479Ssklower 	}
368*21479Ssklower 		break;
369*21479Ssklower 
370*21479Ssklower 	case PRU_ABORT:
371*21479Ssklower 		ns_pcbdetach(nsp);
372*21479Ssklower 		sofree(so);
373*21479Ssklower 		soisdisconnected(so);
374*21479Ssklower 		break;
375*21479Ssklower 
376*21479Ssklower 	case PRU_SOCKADDR:
377*21479Ssklower 		ns_setsockaddr(nsp, nam);
378*21479Ssklower 		break;
379*21479Ssklower 
380*21479Ssklower 	case PRU_PEERADDR:
381*21479Ssklower 		ns_setpeeraddr(nsp, nam);
382*21479Ssklower 		break;
383*21479Ssklower 
384*21479Ssklower 	case PRU_SENSE:
385*21479Ssklower 		/*
386*21479Ssklower 		 * stat: don't bother with a blocksize.
387*21479Ssklower 		 */
388*21479Ssklower 		return (0);
389*21479Ssklower 
390*21479Ssklower 	case PRU_SENDOOB:
391*21479Ssklower 	case PRU_FASTTIMO:
392*21479Ssklower 	case PRU_SLOWTIMO:
393*21479Ssklower 	case PRU_PROTORCV:
394*21479Ssklower 	case PRU_PROTOSEND:
395*21479Ssklower 		error =  EOPNOTSUPP;
396*21479Ssklower 		break;
397*21479Ssklower 
398*21479Ssklower 	case PRU_CONTROL:
399*21479Ssklower 	case PRU_RCVD:
400*21479Ssklower 	case PRU_RCVOOB:
401*21479Ssklower 		return (EOPNOTSUPP);	/* do not free mbuf's */
402*21479Ssklower 
403*21479Ssklower 	default:
404*21479Ssklower 		panic("idp_usrreq");
405*21479Ssklower 	}
406*21479Ssklower release:
407*21479Ssklower 	if (m != NULL)
408*21479Ssklower 		m_freem(m);
409*21479Ssklower 	return (error);
410*21479Ssklower }
411*21479Ssklower /*ARGSUSED*/
412*21479Ssklower idp_raw_usrreq(so, req, m, nam, rights)
413*21479Ssklower 	struct socket *so;
414*21479Ssklower 	int req;
415*21479Ssklower 	struct mbuf *m, *nam, *rights;
416*21479Ssklower {
417*21479Ssklower 	int error = 0;
418*21479Ssklower 	struct nspcb *nsp = sotonspcb(so);
419*21479Ssklower 	extern struct nspcb nsrawpcb;
420*21479Ssklower 
421*21479Ssklower 	switch (req) {
422*21479Ssklower 
423*21479Ssklower 	case PRU_ATTACH:
424*21479Ssklower 
425*21479Ssklower 		if (nsp != NULL) {
426*21479Ssklower 			error = EINVAL;
427*21479Ssklower 			break;
428*21479Ssklower 		}
429*21479Ssklower 		error = ns_pcballoc(so, &nsrawpcb);
430*21479Ssklower 		if (error)
431*21479Ssklower 			break;
432*21479Ssklower 		error = soreserve(so, 2048, 2048);
433*21479Ssklower 		if (error)
434*21479Ssklower 			break;
435*21479Ssklower 		nsp = sotonspcb(so);
436*21479Ssklower 		nsp->nsp_faddr.x_host = ns_broadhost;
437*21479Ssklower 		nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
438*21479Ssklower 		break;
439*21479Ssklower 	default:
440*21479Ssklower 		error = idp_usrreq(so, req, m, nam, rights);
441*21479Ssklower 	}
442*21479Ssklower 	return(error);
443*21479Ssklower }
444*21479Ssklower 
445