xref: /original-bsd/sys/net/raw_usrreq.c (revision 54e6d6c7)
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.6 (Berkeley) 04/25/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 	struct sockproto *proto;
57 	struct sockaddr *src, *dst;
58 {
59 	register struct rawcb *rp;
60 	register struct mbuf *m = m0;
61 	struct socket *last;
62 
63 	last = 0;
64 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
65 		if (rp->rcb_proto.sp_family != proto->sp_family)
66 			continue;
67 		if (rp->rcb_proto.sp_protocol  &&
68 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
69 			continue;
70 		/*
71 		 * We assume the lower level routines have
72 		 * placed the address in a canonical format
73 		 * suitable for a structure comparison.
74 		 *
75 		 * Note that if the lengths are not the same
76 		 * the comparison will fail at the first byte.
77 		 */
78 #define	equal(a1, a2) \
79   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
80 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
81 			continue;
82 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
83 			continue;
84 		if (last) {
85 			struct mbuf *n;
86 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
87 				if (sbappendaddr(&last->so_rcv, src,
88 				    n, (struct mbuf *)0) == 0)
89 					/* should notify about lost packet */
90 					m_freem(n);
91 				else
92 					sorwakeup(last);
93 			}
94 		}
95 		last = rp->rcb_socket;
96 	}
97 	if (last) {
98 		if (sbappendaddr(&last->so_rcv, src,
99 		    m, (struct mbuf *)0) == 0)
100 			m_freem(m);
101 		else
102 			sorwakeup(last);
103 	} else
104 		m_freem(m);
105 }
106 
107 /*ARGSUSED*/
108 raw_ctlinput(cmd, arg)
109 	int cmd;
110 	struct sockaddr *arg;
111 {
112 
113 	if (cmd < 0 || cmd > PRC_NCMDS)
114 		return;
115 	/* INCOMPLETE */
116 }
117 
118 /*ARGSUSED*/
119 raw_usrreq(so, req, m, nam, rights, control)
120 	struct socket *so;
121 	int req;
122 	struct mbuf *m, *nam, *rights, *control;
123 {
124 	register struct rawcb *rp = sotorawcb(so);
125 	register int error = 0;
126 	int len;
127 
128 	if (req == PRU_CONTROL)
129 		return (EOPNOTSUPP);
130 	if (rights && rights->m_len) {
131 		error = EOPNOTSUPP;
132 		goto release;
133 	}
134 	if (rp == 0) {
135 		error = EINVAL;
136 		goto release;
137 	}
138 	switch (req) {
139 
140 	/*
141 	 * Allocate a raw control block and fill in the
142 	 * necessary info to allow packets to be routed to
143 	 * the appropriate raw interface routine.
144 	 */
145 	case PRU_ATTACH:
146 		if ((so->so_state & SS_PRIV) == 0) {
147 			error = EACCES;
148 			break;
149 		}
150 		error = raw_attach(so, (int)nam);
151 		break;
152 
153 	/*
154 	 * Destroy state just before socket deallocation.
155 	 * Flush data or not depending on the options.
156 	 */
157 	case PRU_DETACH:
158 		if (rp == 0) {
159 			error = ENOTCONN;
160 			break;
161 		}
162 		raw_detach(rp);
163 		break;
164 
165 #ifdef notdef
166 	/*
167 	 * If a socket isn't bound to a single address,
168 	 * the raw input routine will hand it anything
169 	 * within that protocol family (assuming there's
170 	 * nothing else around it should go to).
171 	 */
172 	case PRU_CONNECT:
173 		if (rp->rcb_faddr) {
174 			error = EISCONN;
175 			break;
176 		}
177 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
178 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
179 		soisconnected(so);
180 		break;
181 
182 	case PRU_BIND:
183 		if (rp->rcb_laddr) {
184 			error = EINVAL;			/* XXX */
185 			break;
186 		}
187 		error = raw_bind(so, nam);
188 		break;
189 #endif
190 
191 	case PRU_CONNECT2:
192 		error = EOPNOTSUPP;
193 		goto release;
194 
195 	case PRU_DISCONNECT:
196 		if (rp->rcb_faddr == 0) {
197 			error = ENOTCONN;
198 			break;
199 		}
200 		raw_disconnect(rp);
201 		soisdisconnected(so);
202 		break;
203 
204 	/*
205 	 * Mark the connection as being incapable of further input.
206 	 */
207 	case PRU_SHUTDOWN:
208 		socantsendmore(so);
209 		break;
210 
211 	/*
212 	 * Ship a packet out.  The appropriate raw output
213 	 * routine handles any massaging necessary.
214 	 */
215 	case PRU_SEND:
216 		if (nam) {
217 			if (rp->rcb_faddr) {
218 				error = EISCONN;
219 				break;
220 			}
221 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
222 		} else if (rp->rcb_faddr == 0) {
223 			error = ENOTCONN;
224 			break;
225 		}
226 		error = (*so->so_proto->pr_output)(m, so);
227 		m = NULL;
228 		if (nam)
229 			rp->rcb_faddr = 0;
230 		break;
231 
232 	case PRU_ABORT:
233 		raw_disconnect(rp);
234 		sofree(so);
235 		soisdisconnected(so);
236 		break;
237 
238 	case PRU_SENSE:
239 		/*
240 		 * stat: don't bother with a blocksize.
241 		 */
242 		return (0);
243 
244 	/*
245 	 * Not supported.
246 	 */
247 	case PRU_RCVOOB:
248 	case PRU_RCVD:
249 		return(EOPNOTSUPP);
250 
251 	case PRU_LISTEN:
252 	case PRU_ACCEPT:
253 	case PRU_SENDOOB:
254 		error = EOPNOTSUPP;
255 		break;
256 
257 	case PRU_SOCKADDR:
258 		if (rp->rcb_laddr == 0) {
259 			error = EINVAL;
260 			break;
261 		}
262 		len = rp->rcb_laddr->sa_len;
263 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
264 		nam->m_len = len;
265 		break;
266 
267 	case PRU_PEERADDR:
268 		if (rp->rcb_faddr == 0) {
269 			error = ENOTCONN;
270 			break;
271 		}
272 		len = rp->rcb_faddr->sa_len;
273 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
274 		nam->m_len = len;
275 		break;
276 
277 	default:
278 		panic("raw_usrreq");
279 	}
280 release:
281 	if (m != NULL)
282 		m_freem(m);
283 	return (error);
284 }
285 
286 rawintr() {} /* XXX - referenced by locore.  will soon go away */
287