xref: /csrg-svn/sys/net/raw_usrreq.c (revision 39181)
1 /*
2  * Copyright (c) 1980, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)raw_usrreq.c	7.7 (Berkeley) 09/20/89
18  */
19 
20 #include "param.h"
21 #include "mbuf.h"
22 #include "domain.h"
23 #include "protosw.h"
24 #include "socket.h"
25 #include "socketvar.h"
26 #include "errno.h"
27 
28 #include "if.h"
29 #include "route.h"
30 #include "netisr.h"
31 #include "raw_cb.h"
32 
33 #include "machine/mtpr.h"
34 
35 /*
36  * Initialize raw connection block q.
37  */
38 raw_init()
39 {
40 
41 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
42 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
43 }
44 
45 
46 /*
47  * Raw protocol input routine.  Find the socket
48  * associated with the packet(s) and move them over.  If
49  * nothing exists for this packet, drop it.
50  */
51 /*
52  * Raw protocol interface.
53  */
54 raw_input(m0, proto, src, dst)
55 	struct mbuf *m0;
56 	register struct sockproto *proto;
57 	struct sockaddr *src, *dst;
58 {
59 	register struct rawcb *rp;
60 	register struct mbuf *m = m0;
61 	register int sockets = 0;
62 	struct socket *last;
63 
64 	last = 0;
65 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
66 		if (rp->rcb_proto.sp_family != proto->sp_family)
67 			continue;
68 		if (rp->rcb_proto.sp_protocol  &&
69 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
70 			continue;
71 		/*
72 		 * We assume the lower level routines have
73 		 * placed the address in a canonical format
74 		 * suitable for a structure comparison.
75 		 *
76 		 * Note that if the lengths are not the same
77 		 * the comparison will fail at the first byte.
78 		 */
79 #define	equal(a1, a2) \
80   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
81 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
82 			continue;
83 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
84 			continue;
85 		if (last) {
86 			struct mbuf *n;
87 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
88 				if (sbappendaddr(&last->so_rcv, src,
89 				    n, (struct mbuf *)0) == 0)
90 					/* should notify about lost packet */
91 					m_freem(n);
92 				else {
93 					sorwakeup(last);
94 					sockets++;
95 				}
96 			}
97 		}
98 		last = rp->rcb_socket;
99 	}
100 	if (last) {
101 		if (sbappendaddr(&last->so_rcv, src,
102 		    m, (struct mbuf *)0) == 0)
103 			m_freem(m);
104 		else {
105 			sorwakeup(last);
106 			sockets++;
107 		}
108 	} else
109 		m_freem(m);
110 	return (sockets);
111 }
112 
113 /*ARGSUSED*/
114 raw_ctlinput(cmd, arg)
115 	int cmd;
116 	struct sockaddr *arg;
117 {
118 
119 	if (cmd < 0 || cmd > PRC_NCMDS)
120 		return;
121 	/* INCOMPLETE */
122 }
123 
124 /*ARGSUSED*/
125 raw_usrreq(so, req, m, nam, rights, control)
126 	struct socket *so;
127 	int req;
128 	struct mbuf *m, *nam, *rights, *control;
129 {
130 	register struct rawcb *rp = sotorawcb(so);
131 	register int error = 0;
132 	int len;
133 
134 	if (req == PRU_CONTROL)
135 		return (EOPNOTSUPP);
136 	if (rights && rights->m_len) {
137 		error = EOPNOTSUPP;
138 		goto release;
139 	}
140 	if (rp == 0) {
141 		error = EINVAL;
142 		goto release;
143 	}
144 	switch (req) {
145 
146 	/*
147 	 * Allocate a raw control block and fill in the
148 	 * necessary info to allow packets to be routed to
149 	 * the appropriate raw interface routine.
150 	 */
151 	case PRU_ATTACH:
152 		if ((so->so_state & SS_PRIV) == 0) {
153 			error = EACCES;
154 			break;
155 		}
156 		error = raw_attach(so, (int)nam);
157 		break;
158 
159 	/*
160 	 * Destroy state just before socket deallocation.
161 	 * Flush data or not depending on the options.
162 	 */
163 	case PRU_DETACH:
164 		if (rp == 0) {
165 			error = ENOTCONN;
166 			break;
167 		}
168 		raw_detach(rp);
169 		break;
170 
171 #ifdef notdef
172 	/*
173 	 * If a socket isn't bound to a single address,
174 	 * the raw input routine will hand it anything
175 	 * within that protocol family (assuming there's
176 	 * nothing else around it should go to).
177 	 */
178 	case PRU_CONNECT:
179 		if (rp->rcb_faddr) {
180 			error = EISCONN;
181 			break;
182 		}
183 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
184 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
185 		soisconnected(so);
186 		break;
187 
188 	case PRU_BIND:
189 		if (rp->rcb_laddr) {
190 			error = EINVAL;			/* XXX */
191 			break;
192 		}
193 		error = raw_bind(so, nam);
194 		break;
195 #endif
196 
197 	case PRU_CONNECT2:
198 		error = EOPNOTSUPP;
199 		goto release;
200 
201 	case PRU_DISCONNECT:
202 		if (rp->rcb_faddr == 0) {
203 			error = ENOTCONN;
204 			break;
205 		}
206 		raw_disconnect(rp);
207 		soisdisconnected(so);
208 		break;
209 
210 	/*
211 	 * Mark the connection as being incapable of further input.
212 	 */
213 	case PRU_SHUTDOWN:
214 		socantsendmore(so);
215 		break;
216 
217 	/*
218 	 * Ship a packet out.  The appropriate raw output
219 	 * routine handles any massaging necessary.
220 	 */
221 	case PRU_SEND:
222 		if (nam) {
223 			if (rp->rcb_faddr) {
224 				error = EISCONN;
225 				break;
226 			}
227 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
228 		} else if (rp->rcb_faddr == 0) {
229 			error = ENOTCONN;
230 			break;
231 		}
232 		error = (*so->so_proto->pr_output)(m, so);
233 		m = NULL;
234 		if (nam)
235 			rp->rcb_faddr = 0;
236 		break;
237 
238 	case PRU_ABORT:
239 		raw_disconnect(rp);
240 		sofree(so);
241 		soisdisconnected(so);
242 		break;
243 
244 	case PRU_SENSE:
245 		/*
246 		 * stat: don't bother with a blocksize.
247 		 */
248 		return (0);
249 
250 	/*
251 	 * Not supported.
252 	 */
253 	case PRU_RCVOOB:
254 	case PRU_RCVD:
255 		return(EOPNOTSUPP);
256 
257 	case PRU_LISTEN:
258 	case PRU_ACCEPT:
259 	case PRU_SENDOOB:
260 		error = EOPNOTSUPP;
261 		break;
262 
263 	case PRU_SOCKADDR:
264 		if (rp->rcb_laddr == 0) {
265 			error = EINVAL;
266 			break;
267 		}
268 		len = rp->rcb_laddr->sa_len;
269 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
270 		nam->m_len = len;
271 		break;
272 
273 	case PRU_PEERADDR:
274 		if (rp->rcb_faddr == 0) {
275 			error = ENOTCONN;
276 			break;
277 		}
278 		len = rp->rcb_faddr->sa_len;
279 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
280 		nam->m_len = len;
281 		break;
282 
283 	default:
284 		panic("raw_usrreq");
285 	}
286 release:
287 	if (m != NULL)
288 		m_freem(m);
289 	return (error);
290 }
291 
292 rawintr() {} /* XXX - referenced by locore.  will soon go away */
293