xref: /csrg-svn/sys/netns/idp_usrreq.c (revision 41921)
123202Smckusick /*
233371Ssklower  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
333371Ssklower  * All rights reserved.
423202Smckusick  *
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*41921Ssklower  *	@(#)idp_usrreq.c	7.9 (Berkeley) 05/14/90
1823202Smckusick  */
1921479Ssklower 
2021479Ssklower #include "param.h"
2121479Ssklower #include "user.h"
2235797Ssklower #include "malloc.h"
2321479Ssklower #include "mbuf.h"
2421479Ssklower #include "protosw.h"
2521479Ssklower #include "socket.h"
2621479Ssklower #include "socketvar.h"
2721479Ssklower #include "errno.h"
2821479Ssklower #include "stat.h"
2921479Ssklower 
3021479Ssklower #include "../net/if.h"
3121479Ssklower #include "../net/route.h"
3221479Ssklower 
3321479Ssklower #include "ns.h"
3421479Ssklower #include "ns_pcb.h"
3524611Ssklower #include "ns_if.h"
3621479Ssklower #include "idp.h"
3721479Ssklower #include "idp_var.h"
3821479Ssklower #include "ns_error.h"
3921479Ssklower 
4021479Ssklower /*
4121479Ssklower  * IDP protocol implementation.
4221479Ssklower  */
4321479Ssklower 
4437473Ssklower struct	sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS };
4521479Ssklower 
4623977Ssklower /*
4723977Ssklower  *  This may also be called for raw listeners.
4823977Ssklower  */
4935797Ssklower idp_input(m, nsp)
5021479Ssklower 	struct mbuf *m;
5121479Ssklower 	register struct nspcb *nsp;
5221479Ssklower {
5321479Ssklower 	register struct idp *idp = mtod(m, struct idp *);
5435797Ssklower 	struct ifnet *ifp = m->m_pkthdr.rcvif;
5521479Ssklower 
5624611Ssklower 	if (nsp==0)
5724049Ssklower 		panic("No nspcb");
5821479Ssklower 	/*
5921479Ssklower 	 * Construct sockaddr format source address.
6021479Ssklower 	 * Stuff source address and datagram in user buffer.
6121479Ssklower 	 */
6221479Ssklower 	idp_ns.sns_addr = idp->idp_sna;
6326055Ssklower 	if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
6437473Ssklower 		register struct ifaddr *ifa;
6524611Ssklower 
6637473Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
6737473Ssklower 			if (ifa->ifa_addr->sa_family == AF_NS) {
6824611Ssklower 				idp_ns.sns_addr.x_net =
6937473Ssklower 					IA_SNS(ifa)->sns_addr.x_net;
7024611Ssklower 				break;
7124611Ssklower 			}
7224611Ssklower 		}
7324611Ssklower 	}
7421479Ssklower 	nsp->nsp_rpt = idp->idp_pt;
7521479Ssklower 	if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
7621479Ssklower 		m->m_len -= sizeof (struct idp);
7735797Ssklower 		m->m_pkthdr.len -= sizeof (struct idp);
7835797Ssklower 		m->m_data += sizeof (struct idp);
7921479Ssklower 	}
8021479Ssklower 	if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
8121479Ssklower 	    m, (struct mbuf *)0) == 0)
8221479Ssklower 		goto bad;
8321479Ssklower 	sorwakeup(nsp->nsp_socket);
8421479Ssklower 	return;
8521479Ssklower bad:
8621479Ssklower 	m_freem(m);
8721479Ssklower }
8821479Ssklower 
8921479Ssklower idp_abort(nsp)
9021479Ssklower 	struct nspcb *nsp;
9121479Ssklower {
9221479Ssklower 	struct socket *so = nsp->nsp_socket;
9321479Ssklower 
9421479Ssklower 	ns_pcbdisconnect(nsp);
9521479Ssklower 	soisdisconnected(so);
9621479Ssklower }
9723977Ssklower /*
9823977Ssklower  * Drop connection, reporting
9923977Ssklower  * the specified error.
10023977Ssklower  */
10123977Ssklower struct nspcb *
10223977Ssklower idp_drop(nsp, errno)
10323977Ssklower 	register struct nspcb *nsp;
10423977Ssklower 	int errno;
10523977Ssklower {
10623977Ssklower 	struct socket *so = nsp->nsp_socket;
10721479Ssklower 
10823977Ssklower 	/*
10923977Ssklower 	 * someday, in the xerox world
11023977Ssklower 	 * we will generate error protocol packets
11123977Ssklower 	 * announcing that the socket has gone away.
11223977Ssklower 	 */
11323977Ssklower 	/*if (TCPS_HAVERCVDSYN(tp->t_state)) {
11423977Ssklower 		tp->t_state = TCPS_CLOSED;
11523977Ssklower 		(void) tcp_output(tp);
11623977Ssklower 	}*/
11723977Ssklower 	so->so_error = errno;
11823977Ssklower 	ns_pcbdisconnect(nsp);
11923977Ssklower 	soisdisconnected(so);
12023977Ssklower }
12123977Ssklower 
12225042Ssklower int noIdpRoute;
12321479Ssklower idp_output(nsp, m0)
12421479Ssklower 	struct nspcb *nsp;
12521479Ssklower 	struct mbuf *m0;
12621479Ssklower {
12721479Ssklower 	register struct mbuf *m;
12821479Ssklower 	register struct idp *idp;
12921479Ssklower 	register struct socket *so;
13021479Ssklower 	register int len = 0;
13121479Ssklower 	register struct route *ro;
13221479Ssklower 	struct mbuf *mprev;
13321479Ssklower 	extern int idpcksum;
13421479Ssklower 
13521479Ssklower 	/*
13621479Ssklower 	 * Calculate data length.
13721479Ssklower 	 */
13821479Ssklower 	for (m = m0; m; m = m->m_next) {
13921479Ssklower 		mprev = m;
14021479Ssklower 		len += m->m_len;
14121479Ssklower 	}
14221479Ssklower 	/*
14321479Ssklower 	 * Make sure packet is actually of even length.
14421479Ssklower 	 */
14521479Ssklower 
14621479Ssklower 	if (len & 1) {
14721479Ssklower 		m = mprev;
14835797Ssklower 		if ((m->m_flags & M_EXT) == 0 &&
14935797Ssklower 			(m->m_len + m->m_data < &m->m_dat[MLEN])) {
15021479Ssklower 			m->m_len++;
15121479Ssklower 		} else {
15221479Ssklower 			struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
15321479Ssklower 
15421699Ssklower 			if (m1 == 0) {
15521699Ssklower 				m_freem(m0);
15621699Ssklower 				return (ENOBUFS);
15721699Ssklower 			}
15821479Ssklower 			m1->m_len = 1;
15921479Ssklower 			* mtod(m1, char *) = 0;
16021479Ssklower 			m->m_next = m1;
16121479Ssklower 		}
16235797Ssklower 		m0->m_pkthdr.len++;
16321479Ssklower 	}
16421479Ssklower 
16521479Ssklower 	/*
16621479Ssklower 	 * Fill in mbuf with extended IDP header
16721479Ssklower 	 * and addresses and length put into network format.
16821479Ssklower 	 */
16935797Ssklower 	m = m0;
17021479Ssklower 	if (nsp->nsp_flags & NSP_RAWOUT) {
17121479Ssklower 		idp = mtod(m, struct idp *);
17221479Ssklower 	} else {
17335797Ssklower 		M_PREPEND(m, sizeof (struct idp), M_DONTWAIT);
17435797Ssklower 		if (m == 0)
17521479Ssklower 			return (ENOBUFS);
17621479Ssklower 		idp = mtod(m, struct idp *);
17721479Ssklower 		idp->idp_tc = 0;
17821479Ssklower 		idp->idp_pt = nsp->nsp_dpt;
17921479Ssklower 		idp->idp_sna = nsp->nsp_laddr;
18021479Ssklower 		idp->idp_dna = nsp->nsp_faddr;
18121479Ssklower 		len += sizeof (struct idp);
18221479Ssklower 	}
18321479Ssklower 
18421479Ssklower 	idp->idp_len = htons((u_short)len);
18521479Ssklower 
18621479Ssklower 	if (idpcksum) {
18721479Ssklower 		idp->idp_sum = 0;
18821479Ssklower 		len = ((len - 1) | 1) + 1;
18921479Ssklower 		idp->idp_sum = ns_cksum(m, len);
19021479Ssklower 	} else
19121479Ssklower 		idp->idp_sum = 0xffff;
19221479Ssklower 
19321479Ssklower 	/*
19421479Ssklower 	 * Output datagram.
19521479Ssklower 	 */
19621479Ssklower 	so = nsp->nsp_socket;
19721479Ssklower 	if (so->so_options & SO_DONTROUTE)
19821479Ssklower 		return (ns_output(m, (struct route *)0,
19921479Ssklower 		    (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
20021479Ssklower 	/*
20121479Ssklower 	 * Use cached route for previous datagram if
20225042Ssklower 	 * possible.  If the previous net was the same
20325042Ssklower 	 * and the interface was a broadcast medium, or
20425042Ssklower 	 * if the previous destination was identical,
20525042Ssklower 	 * then we are ok.
20621479Ssklower 	 *
20721479Ssklower 	 * NB: We don't handle broadcasts because that
20821479Ssklower 	 *     would require 3 subroutine calls.
20921479Ssklower 	 */
21021479Ssklower 	ro = &nsp->nsp_route;
21125042Ssklower #ifdef ancient_history
21225042Ssklower 	/*
21325042Ssklower 	 * I think that this will all be handled in ns_pcbconnect!
21425042Ssklower 	 */
21525042Ssklower 	if (ro->ro_rt) {
21625042Ssklower 		if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
21725042Ssklower 			/*
21825042Ssklower 			 * This assumes we have no GH type routes
21925042Ssklower 			 */
22025042Ssklower 			if (ro->ro_rt->rt_flags & RTF_HOST) {
22125042Ssklower 				if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
22225042Ssklower 					goto re_route;
22325042Ssklower 
22425042Ssklower 			}
22525042Ssklower 			if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
22625042Ssklower 				register struct ns_addr *dst =
22725042Ssklower 						&satons_addr(ro->ro_dst);
22825042Ssklower 				dst->x_host = idp->idp_dna.x_host;
22925042Ssklower 			}
23025042Ssklower 			/*
23125042Ssklower 			 * Otherwise, we go through the same gateway
23225042Ssklower 			 * and dst is already set up.
23325042Ssklower 			 */
23425042Ssklower 		} else {
23525042Ssklower 		re_route:
23625042Ssklower 			RTFREE(ro->ro_rt);
23725042Ssklower 			ro->ro_rt = (struct rtentry *)0;
23825042Ssklower 		}
23921479Ssklower 	}
24025042Ssklower 	nsp->nsp_lastdst = idp->idp_dna;
24125042Ssklower #endif ancient_history
24225042Ssklower 	if (noIdpRoute) ro = 0;
24321479Ssklower 	return (ns_output(m, ro, so->so_options & SO_BROADCAST));
24421479Ssklower }
24524225Ssklower /* ARGSUSED */
24621479Ssklower idp_ctloutput(req, so, level, name, value)
24721479Ssklower 	int req, level;
24821479Ssklower 	struct socket *so;
24921479Ssklower 	int name;
25021479Ssklower 	struct mbuf **value;
25121479Ssklower {
25221479Ssklower 	register struct mbuf *m;
25321479Ssklower 	struct nspcb *nsp = sotonspcb(so);
25421479Ssklower 	int mask, error = 0;
25523977Ssklower 	extern long ns_pexseq;
25621479Ssklower 
25723500Ssklower 	if (nsp == NULL)
25823500Ssklower 		return (EINVAL);
25921479Ssklower 
26021479Ssklower 	switch (req) {
26123500Ssklower 
26221479Ssklower 	case PRCO_GETOPT:
26323500Ssklower 		if (value==NULL)
26423500Ssklower 			return (EINVAL);
26521479Ssklower 		m = m_get(M_DONTWAIT, MT_DATA);
26623500Ssklower 		if (m==NULL)
26723500Ssklower 			return (ENOBUFS);
26821479Ssklower 		switch (name) {
26923500Ssklower 
27024049Ssklower 		case SO_ALL_PACKETS:
27124049Ssklower 			mask = NSP_ALL_PACKETS;
27224049Ssklower 			goto get_flags;
27324049Ssklower 
27421479Ssklower 		case SO_HEADERS_ON_INPUT:
27521479Ssklower 			mask = NSP_RAWIN;
27621479Ssklower 			goto get_flags;
27723500Ssklower 
27821479Ssklower 		case SO_HEADERS_ON_OUTPUT:
27921479Ssklower 			mask = NSP_RAWOUT;
28021479Ssklower 		get_flags:
28121479Ssklower 			m->m_len = sizeof(short);
28221479Ssklower 			*mtod(m, short *) = nsp->nsp_flags & mask;
28321479Ssklower 			break;
28423500Ssklower 
28521479Ssklower 		case SO_DEFAULT_HEADERS:
28621479Ssklower 			m->m_len = sizeof(struct idp);
28721479Ssklower 			{
28821479Ssklower 				register struct idp *idp = mtod(m, struct idp *);
28921479Ssklower 				idp->idp_len = 0;
29021479Ssklower 				idp->idp_sum = 0;
29121479Ssklower 				idp->idp_tc = 0;
29221479Ssklower 				idp->idp_pt = nsp->nsp_dpt;
29321479Ssklower 				idp->idp_dna = nsp->nsp_faddr;
29421479Ssklower 				idp->idp_sna = nsp->nsp_laddr;
29521479Ssklower 			}
29623977Ssklower 			break;
29723977Ssklower 
29823977Ssklower 		case SO_SEQNO:
29923977Ssklower 			m->m_len = sizeof(long);
30023977Ssklower 			*mtod(m, long *) = ns_pexseq++;
30125335Ssklower 			break;
30225335Ssklower 
30325335Ssklower 		default:
30425335Ssklower 			error = EINVAL;
30521479Ssklower 		}
30621479Ssklower 		*value = m;
30721479Ssklower 		break;
30823500Ssklower 
30921479Ssklower 	case PRCO_SETOPT:
31021479Ssklower 		switch (name) {
31124225Ssklower 			int *ok;
31221479Ssklower 
31324049Ssklower 		case SO_ALL_PACKETS:
31424049Ssklower 			mask = NSP_ALL_PACKETS;
31524049Ssklower 			goto set_head;
31624049Ssklower 
31721479Ssklower 		case SO_HEADERS_ON_INPUT:
31821479Ssklower 			mask = NSP_RAWIN;
31921479Ssklower 			goto set_head;
32023500Ssklower 
32121479Ssklower 		case SO_HEADERS_ON_OUTPUT:
32221479Ssklower 			mask = NSP_RAWOUT;
32321479Ssklower 		set_head:
32421479Ssklower 			if (value && *value) {
32521479Ssklower 				ok = mtod(*value, int *);
32621479Ssklower 				if (*ok)
32721479Ssklower 					nsp->nsp_flags |= mask;
32821479Ssklower 				else
32921479Ssklower 					nsp->nsp_flags &= ~mask;
33021479Ssklower 			} else error = EINVAL;
33121479Ssklower 			break;
33223500Ssklower 
33321479Ssklower 		case SO_DEFAULT_HEADERS:
33421479Ssklower 			{
33521479Ssklower 				register struct idp *idp
33621479Ssklower 				    = mtod(*value, struct idp *);
33721479Ssklower 				nsp->nsp_dpt = idp->idp_pt;
33821479Ssklower 			}
33925335Ssklower 			break;
34021479Ssklower #ifdef NSIP
34123500Ssklower 
34221479Ssklower 		case SO_NSIP_ROUTE:
34321479Ssklower 			error = nsip_route(*value);
34425335Ssklower 			break;
34521479Ssklower #endif NSIP
34625335Ssklower 		default:
34725335Ssklower 			error = EINVAL;
34821479Ssklower 		}
34921479Ssklower 		if (value && *value)
35021479Ssklower 			m_freem(*value);
35121479Ssklower 		break;
35221479Ssklower 	}
35323500Ssklower 	return (error);
35421479Ssklower }
35521479Ssklower 
35621479Ssklower /*ARGSUSED*/
357*41921Ssklower idp_usrreq(so, req, m, nam, control)
35821479Ssklower 	struct socket *so;
35921479Ssklower 	int req;
360*41921Ssklower 	struct mbuf *m, *nam, *control;
36121479Ssklower {
36221479Ssklower 	struct nspcb *nsp = sotonspcb(so);
36321479Ssklower 	int error = 0;
36421479Ssklower 
36521479Ssklower 	if (req == PRU_CONTROL)
36621479Ssklower                 return (ns_control(so, (int)m, (caddr_t)nam,
367*41921Ssklower 			(struct ifnet *)control));
368*41921Ssklower 	if (control && control->m_len) {
36921479Ssklower 		error = EINVAL;
37021479Ssklower 		goto release;
37121479Ssklower 	}
37221479Ssklower 	if (nsp == NULL && req != PRU_ATTACH) {
37321479Ssklower 		error = EINVAL;
37421479Ssklower 		goto release;
37521479Ssklower 	}
37621479Ssklower 	switch (req) {
37721479Ssklower 
37821479Ssklower 	case PRU_ATTACH:
37921479Ssklower 		if (nsp != NULL) {
38021479Ssklower 			error = EINVAL;
38121479Ssklower 			break;
38221479Ssklower 		}
38321479Ssklower 		error = ns_pcballoc(so, &nspcb);
38421479Ssklower 		if (error)
38521479Ssklower 			break;
38634500Skarels 		error = soreserve(so, (u_long) 2048, (u_long) 2048);
38721479Ssklower 		if (error)
38821479Ssklower 			break;
38921479Ssklower 		break;
39021479Ssklower 
39121479Ssklower 	case PRU_DETACH:
39221479Ssklower 		if (nsp == NULL) {
39321479Ssklower 			error = ENOTCONN;
39421479Ssklower 			break;
39521479Ssklower 		}
39621479Ssklower 		ns_pcbdetach(nsp);
39721479Ssklower 		break;
39821479Ssklower 
39921479Ssklower 	case PRU_BIND:
40021479Ssklower 		error = ns_pcbbind(nsp, nam);
40121479Ssklower 		break;
40221479Ssklower 
40321479Ssklower 	case PRU_LISTEN:
40421479Ssklower 		error = EOPNOTSUPP;
40521479Ssklower 		break;
40621479Ssklower 
40721479Ssklower 	case PRU_CONNECT:
40821479Ssklower 		if (!ns_nullhost(nsp->nsp_faddr)) {
40921479Ssklower 			error = EISCONN;
41021479Ssklower 			break;
41121479Ssklower 		}
41221479Ssklower 		error = ns_pcbconnect(nsp, nam);
41321479Ssklower 		if (error == 0)
41421479Ssklower 			soisconnected(so);
41521479Ssklower 		break;
41621479Ssklower 
41721479Ssklower 	case PRU_CONNECT2:
41821479Ssklower 		error = EOPNOTSUPP;
41921479Ssklower 		break;
42021479Ssklower 
42121479Ssklower 	case PRU_ACCEPT:
42221479Ssklower 		error = EOPNOTSUPP;
42321479Ssklower 		break;
42421479Ssklower 
42521479Ssklower 	case PRU_DISCONNECT:
42621479Ssklower 		if (ns_nullhost(nsp->nsp_faddr)) {
42721479Ssklower 			error = ENOTCONN;
42821479Ssklower 			break;
42921479Ssklower 		}
43021479Ssklower 		ns_pcbdisconnect(nsp);
43121479Ssklower 		soisdisconnected(so);
43221479Ssklower 		break;
43321479Ssklower 
43421479Ssklower 	case PRU_SHUTDOWN:
43521479Ssklower 		socantsendmore(so);
43621479Ssklower 		break;
43721479Ssklower 
43821479Ssklower 	case PRU_SEND:
43921479Ssklower 	{
44021479Ssklower 		struct ns_addr laddr;
44121479Ssklower 		int s;
44221479Ssklower 
44321479Ssklower 		if (nam) {
44421479Ssklower 			laddr = nsp->nsp_laddr;
44521479Ssklower 			if (!ns_nullhost(nsp->nsp_faddr)) {
44621479Ssklower 				error = EISCONN;
44721479Ssklower 				break;
44821479Ssklower 			}
44921479Ssklower 			/*
45021479Ssklower 			 * Must block input while temporarily connected.
45121479Ssklower 			 */
45221479Ssklower 			s = splnet();
45321479Ssklower 			error = ns_pcbconnect(nsp, nam);
45421479Ssklower 			if (error) {
45521479Ssklower 				splx(s);
45621479Ssklower 				break;
45721479Ssklower 			}
45821479Ssklower 		} else {
45921479Ssklower 			if (ns_nullhost(nsp->nsp_faddr)) {
46021479Ssklower 				error = ENOTCONN;
46121479Ssklower 				break;
46221479Ssklower 			}
46321479Ssklower 		}
46421479Ssklower 		error = idp_output(nsp, m);
46521479Ssklower 		m = NULL;
46621479Ssklower 		if (nam) {
46721479Ssklower 			ns_pcbdisconnect(nsp);
46821479Ssklower 			splx(s);
46921479Ssklower 			nsp->nsp_laddr.x_host = laddr.x_host;
47021479Ssklower 			nsp->nsp_laddr.x_port = laddr.x_port;
47121479Ssklower 		}
47221479Ssklower 	}
47321479Ssklower 		break;
47421479Ssklower 
47521479Ssklower 	case PRU_ABORT:
47621479Ssklower 		ns_pcbdetach(nsp);
47721479Ssklower 		sofree(so);
47821479Ssklower 		soisdisconnected(so);
47921479Ssklower 		break;
48021479Ssklower 
48121479Ssklower 	case PRU_SOCKADDR:
48221479Ssklower 		ns_setsockaddr(nsp, nam);
48321479Ssklower 		break;
48421479Ssklower 
48521479Ssklower 	case PRU_PEERADDR:
48621479Ssklower 		ns_setpeeraddr(nsp, nam);
48721479Ssklower 		break;
48821479Ssklower 
48921479Ssklower 	case PRU_SENSE:
49021479Ssklower 		/*
49121479Ssklower 		 * stat: don't bother with a blocksize.
49221479Ssklower 		 */
49321479Ssklower 		return (0);
49421479Ssklower 
49521479Ssklower 	case PRU_SENDOOB:
49621479Ssklower 	case PRU_FASTTIMO:
49721479Ssklower 	case PRU_SLOWTIMO:
49821479Ssklower 	case PRU_PROTORCV:
49921479Ssklower 	case PRU_PROTOSEND:
50021479Ssklower 		error =  EOPNOTSUPP;
50121479Ssklower 		break;
50221479Ssklower 
50321479Ssklower 	case PRU_CONTROL:
50421479Ssklower 	case PRU_RCVD:
50521479Ssklower 	case PRU_RCVOOB:
50621479Ssklower 		return (EOPNOTSUPP);	/* do not free mbuf's */
50721479Ssklower 
50821479Ssklower 	default:
50921479Ssklower 		panic("idp_usrreq");
51021479Ssklower 	}
51121479Ssklower release:
512*41921Ssklower 	if (control != NULL)
513*41921Ssklower 		m_freem(control);
51421479Ssklower 	if (m != NULL)
51521479Ssklower 		m_freem(m);
51621479Ssklower 	return (error);
51721479Ssklower }
51821479Ssklower /*ARGSUSED*/
519*41921Ssklower idp_raw_usrreq(so, req, m, nam, control)
52021479Ssklower 	struct socket *so;
52121479Ssklower 	int req;
522*41921Ssklower 	struct mbuf *m, *nam, *control;
52321479Ssklower {
52421479Ssklower 	int error = 0;
52521479Ssklower 	struct nspcb *nsp = sotonspcb(so);
52621479Ssklower 	extern struct nspcb nsrawpcb;
52721479Ssklower 
52821479Ssklower 	switch (req) {
52921479Ssklower 
53021479Ssklower 	case PRU_ATTACH:
53121479Ssklower 
53237546Smckusick 		if (suser(u.u_cred, &u.u_acflag) || (nsp != NULL)) {
53321479Ssklower 			error = EINVAL;
53421479Ssklower 			break;
53521479Ssklower 		}
53621479Ssklower 		error = ns_pcballoc(so, &nsrawpcb);
53721479Ssklower 		if (error)
53821479Ssklower 			break;
53934500Skarels 		error = soreserve(so, (u_long) 2048, (u_long) 2048);
54021479Ssklower 		if (error)
54121479Ssklower 			break;
54221479Ssklower 		nsp = sotonspcb(so);
54321479Ssklower 		nsp->nsp_faddr.x_host = ns_broadhost;
54421479Ssklower 		nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
54521479Ssklower 		break;
54621479Ssklower 	default:
547*41921Ssklower 		error = idp_usrreq(so, req, m, nam, control);
54821479Ssklower 	}
54923500Ssklower 	return (error);
55021479Ssklower }
55121479Ssklower 
552