BSD 4_3_Net_1 release
[unix-history] / sys / net / raw_usrreq.c
CommitLineData
cb1c44c2 1/*
1810611d 2 * Copyright (c) 1980, 1986 Regents of the University of California.
5b519e94 3 * All rights reserved.
cb1c44c2 4 *
5b519e94 5 * Redistribution and use in source and binary forms are permitted
50c7758a
KB
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.
5b519e94 16 *
ca67e7b4 17 * @(#)raw_usrreq.c 7.4 (Berkeley) 6/27/88
cb1c44c2 18 */
8df9431e 19
a0369dcf
JB
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"
f4d55810 27
a0369dcf
JB
28#include "if.h"
29#include "route.h"
30#include "netisr.h"
31#include "raw_cb.h"
f4d55810 32
ca67e7b4 33#include "../machine/mtpr.h"
94a62155
BJ
34
35/*
36 * Initialize raw connection block q.
1e977657 37 */
94a62155
BJ
38raw_init()
39{
1e977657 40
94a62155 41 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
1e977657 42 rawintrq.ifq_maxlen = IFQ_MAXLEN;
94a62155 43}
8df9431e
BJ
44
45/*
46 * Raw protocol interface.
47 */
02122dcc 48raw_input(m0, proto, src, dst)
94a62155 49 struct mbuf *m0;
126472ab 50 struct sockproto *proto;
02122dcc 51 struct sockaddr *src, *dst;
8df9431e 52{
94a62155
BJ
53 register struct mbuf *m;
54 struct raw_header *rh;
8df9431e
BJ
55 int s;
56
94a62155
BJ
57 /*
58 * Rip off an mbuf for a generic header.
59 */
cce93e4b 60 m = m_get(M_DONTWAIT, MT_HEADER);
94a62155
BJ
61 if (m == 0) {
62 m_freem(m0);
63 return;
64 }
65 m->m_next = m0;
94a62155
BJ
66 m->m_len = sizeof(struct raw_header);
67 rh = mtod(m, struct raw_header *);
126472ab
SL
68 rh->raw_dst = *dst;
69 rh->raw_src = *src;
70 rh->raw_proto = *proto;
94a62155
BJ
71
72 /*
73 * Header now contains enough info to decide
74 * which socket to place packet in (if any).
75 * Queue it up for the raw protocol process
76 * running at software interrupt level.
77 */
8df9431e 78 s = splimp();
1e977657
BJ
79 if (IF_QFULL(&rawintrq))
80 m_freem(m);
81 else
82 IF_ENQUEUE(&rawintrq, m);
8df9431e 83 splx(s);
9c8692e9 84 schednetisr(NETISR_RAW);
8df9431e
BJ
85}
86
94a62155
BJ
87/*
88 * Raw protocol input routine. Process packets entered
89 * into the queue at interrupt time. Find the socket
90 * associated with the packet(s) and move them over. If
91 * nothing exists for this packet, drop it.
92 */
8df9431e
BJ
93rawintr()
94{
95 int s;
96 struct mbuf *m;
94a62155 97 register struct rawcb *rp;
02122dcc 98 register struct raw_header *rh;
94a62155 99 struct socket *last;
8df9431e 100
8df9431e
BJ
101next:
102 s = splimp();
8df9431e
BJ
103 IF_DEQUEUE(&rawintrq, m);
104 splx(s);
105 if (m == 0)
106 return;
126472ab 107 rh = mtod(m, struct raw_header *);
94a62155
BJ
108 last = 0;
109 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
829f867e 110 if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family)
94a62155 111 continue;
829f867e
MK
112 if (rp->rcb_proto.sp_protocol &&
113 rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol)
126472ab 114 continue;
94a62155
BJ
115 /*
116 * We assume the lower level routines have
117 * placed the address in a canonical format
126472ab 118 * suitable for a structure comparison.
94a62155 119 */
02122dcc
SL
120#define equal(a1, a2) \
121 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
126472ab 122 if ((rp->rcb_flags & RAW_LADDR) &&
02122dcc 123 !equal(rp->rcb_laddr, rh->raw_dst))
126472ab
SL
124 continue;
125 if ((rp->rcb_flags & RAW_FADDR) &&
02122dcc 126 !equal(rp->rcb_faddr, rh->raw_src))
94a62155 127 continue;
94a62155
BJ
128 if (last) {
129 struct mbuf *n;
fa1454d3
MK
130 if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) {
131 if (sbappendaddr(&last->so_rcv, &rh->raw_src,
132 n, (struct mbuf *)0) == 0)
133 /* should notify about lost packet */
134 m_freem(n);
135 else
136 sorwakeup(last);
faad37c0 137 }
94a62155 138 }
126472ab 139 last = rp->rcb_socket;
94a62155 140 }
72e4f44e 141 if (last) {
9e9695c7 142 if (sbappendaddr(&last->so_rcv, &rh->raw_src,
fa1454d3
MK
143 m->m_next, (struct mbuf *)0) == 0)
144 m_freem(m->m_next);
145 else
146 sorwakeup(last);
147 (void) m_free(m); /* header */
148 } else
149 m_freem(m);
8df9431e
BJ
150 goto next;
151}
152
a1edc12b 153/*ARGSUSED*/
72e4f44e
SL
154raw_ctlinput(cmd, arg)
155 int cmd;
8011f5df 156 struct sockaddr *arg;
72e4f44e 157{
39674d5f
SL
158
159 if (cmd < 0 || cmd > PRC_NCMDS)
160 return;
a1edc12b 161 /* INCOMPLETE */
72e4f44e
SL
162}
163
8df9431e 164/*ARGSUSED*/
9e9695c7 165raw_usrreq(so, req, m, nam, rights)
8df9431e
BJ
166 struct socket *so;
167 int req;
9e9695c7 168 struct mbuf *m, *nam, *rights;
8df9431e 169{
94a62155 170 register struct rawcb *rp = sotorawcb(so);
9e9695c7 171 register int error = 0;
94a62155 172
6624ec0b
MK
173 if (req == PRU_CONTROL)
174 return (EOPNOTSUPP);
9e9695c7
SL
175 if (rights && rights->m_len) {
176 error = EOPNOTSUPP;
177 goto release;
178 }
179 if (rp == 0 && req != PRU_ATTACH) {
180 error = EINVAL;
181 goto release;
182 }
94a62155
BJ
183 switch (req) {
184
185 /*
186 * Allocate a raw control block and fill in the
187 * necessary info to allow packets to be routed to
188 * the appropriate raw interface routine.
189 */
190 case PRU_ATTACH:
9e9695c7
SL
191 if ((so->so_state & SS_PRIV) == 0) {
192 error = EACCES;
4945768c 193 break;
9e9695c7
SL
194 }
195 if (rp) {
196 error = EINVAL;
4945768c 197 break;
9e9695c7 198 }
829f867e 199 error = raw_attach(so, (int)nam);
94a62155
BJ
200 break;
201
202 /*
203 * Destroy state just before socket deallocation.
204 * Flush data or not depending on the options.
205 */
206 case PRU_DETACH:
9e9695c7
SL
207 if (rp == 0) {
208 error = ENOTCONN;
4945768c 209 break;
9e9695c7 210 }
94a62155
BJ
211 raw_detach(rp);
212 break;
213
214 /*
215 * If a socket isn't bound to a single address,
216 * the raw input routine will hand it anything
217 * within that protocol family (assuming there's
218 * nothing else around it should go to).
219 */
220 case PRU_CONNECT:
9e9695c7
SL
221 if (rp->rcb_flags & RAW_FADDR) {
222 error = EISCONN;
4945768c 223 break;
9e9695c7 224 }
14fa60f2 225 raw_connaddr(rp, nam);
94a62155
BJ
226 soisconnected(so);
227 break;
228
4945768c
SL
229 case PRU_CONNECT2:
230 error = EOPNOTSUPP;
231 goto release;
232
9e9695c7
SL
233 case PRU_BIND:
234 if (rp->rcb_flags & RAW_LADDR) {
235 error = EINVAL; /* XXX */
4945768c 236 break;
9e9695c7
SL
237 }
238 error = raw_bind(so, nam);
239 break;
240
94a62155 241 case PRU_DISCONNECT:
9e9695c7
SL
242 if ((rp->rcb_flags & RAW_FADDR) == 0) {
243 error = ENOTCONN;
4945768c 244 break;
9e9695c7 245 }
94a62155
BJ
246 raw_disconnect(rp);
247 soisdisconnected(so);
248 break;
249
250 /*
251 * Mark the connection as being incapable of further input.
252 */
253 case PRU_SHUTDOWN:
254 socantsendmore(so);
255 break;
256
257 /*
258 * Ship a packet out. The appropriate raw output
259 * routine handles any massaging necessary.
260 */
261 case PRU_SEND:
14fa60f2 262 if (nam) {
9e9695c7
SL
263 if (rp->rcb_flags & RAW_FADDR) {
264 error = EISCONN;
4945768c 265 break;
9e9695c7 266 }
14fa60f2 267 raw_connaddr(rp, nam);
9e9695c7
SL
268 } else if ((rp->rcb_flags & RAW_FADDR) == 0) {
269 error = ENOTCONN;
4945768c 270 break;
9e9695c7 271 }
8a2f82db 272 error = (*so->so_proto->pr_output)(m, so);
9e9695c7 273 m = NULL;
14fa60f2 274 if (nam)
126472ab 275 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
276 break;
277
278 case PRU_ABORT:
279 raw_disconnect(rp);
280 sofree(so);
281 soisdisconnected(so);
282 break;
283
0f12c0aa
MK
284 case PRU_SENSE:
285 /*
286 * stat: don't bother with a blocksize.
287 */
288 return (0);
289
94a62155
BJ
290 /*
291 * Not supported.
292 */
799dcac1 293 case PRU_RCVOOB:
94a62155 294 case PRU_RCVD:
799dcac1
JB
295 return(EOPNOTSUPP);
296
1fe3d605 297 case PRU_LISTEN:
799dcac1 298 case PRU_ACCEPT:
94a62155
BJ
299 case PRU_SENDOOB:
300 error = EOPNOTSUPP;
301 break;
8df9431e 302
126472ab 303 case PRU_SOCKADDR:
ac76a23d 304 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
14fa60f2
BJ
305 sizeof (struct sockaddr));
306 nam->m_len = sizeof (struct sockaddr);
126472ab
SL
307 break;
308
a7343092
SL
309 case PRU_PEERADDR:
310 bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
311 sizeof (struct sockaddr));
312 nam->m_len = sizeof (struct sockaddr);
313 break;
314
94a62155
BJ
315 default:
316 panic("raw_usrreq");
317 }
9e9695c7
SL
318release:
319 if (m != NULL)
320 m_freem(m);
94a62155 321 return (error);
8df9431e 322}