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