Add copyright
[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 *
6 * @(#)raw_usrreq.c 6.8 (Berkeley) %G%
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
9e9695c7
SL
162 if (rights && rights->m_len) {
163 error = EOPNOTSUPP;
164 goto release;
165 }
166 if (rp == 0 && req != PRU_ATTACH) {
167 error = EINVAL;
168 goto release;
169 }
94a62155
BJ
170 switch (req) {
171
172 /*
173 * Allocate a raw control block and fill in the
174 * necessary info to allow packets to be routed to
175 * the appropriate raw interface routine.
176 */
177 case PRU_ATTACH:
9e9695c7
SL
178 if ((so->so_state & SS_PRIV) == 0) {
179 error = EACCES;
4945768c 180 break;
9e9695c7
SL
181 }
182 if (rp) {
183 error = EINVAL;
4945768c 184 break;
9e9695c7 185 }
829f867e 186 error = raw_attach(so, (int)nam);
94a62155
BJ
187 break;
188
189 /*
190 * Destroy state just before socket deallocation.
191 * Flush data or not depending on the options.
192 */
193 case PRU_DETACH:
9e9695c7
SL
194 if (rp == 0) {
195 error = ENOTCONN;
4945768c 196 break;
9e9695c7 197 }
94a62155
BJ
198 raw_detach(rp);
199 break;
200
201 /*
202 * If a socket isn't bound to a single address,
203 * the raw input routine will hand it anything
204 * within that protocol family (assuming there's
205 * nothing else around it should go to).
206 */
207 case PRU_CONNECT:
9e9695c7
SL
208 if (rp->rcb_flags & RAW_FADDR) {
209 error = EISCONN;
4945768c 210 break;
9e9695c7 211 }
14fa60f2 212 raw_connaddr(rp, nam);
94a62155
BJ
213 soisconnected(so);
214 break;
215
4945768c
SL
216 case PRU_CONNECT2:
217 error = EOPNOTSUPP;
218 goto release;
219
9e9695c7
SL
220 case PRU_BIND:
221 if (rp->rcb_flags & RAW_LADDR) {
222 error = EINVAL; /* XXX */
4945768c 223 break;
9e9695c7
SL
224 }
225 error = raw_bind(so, nam);
226 break;
227
94a62155 228 case PRU_DISCONNECT:
9e9695c7
SL
229 if ((rp->rcb_flags & RAW_FADDR) == 0) {
230 error = ENOTCONN;
4945768c 231 break;
9e9695c7 232 }
71fb71a3
SL
233 if (rp->rcb_route.ro_rt)
234 rtfree(rp->rcb_route.ro_rt);
94a62155
BJ
235 raw_disconnect(rp);
236 soisdisconnected(so);
237 break;
238
239 /*
240 * Mark the connection as being incapable of further input.
241 */
242 case PRU_SHUTDOWN:
243 socantsendmore(so);
244 break;
245
246 /*
247 * Ship a packet out. The appropriate raw output
248 * routine handles any massaging necessary.
249 */
250 case PRU_SEND:
14fa60f2 251 if (nam) {
9e9695c7
SL
252 if (rp->rcb_flags & RAW_FADDR) {
253 error = EISCONN;
4945768c 254 break;
9e9695c7 255 }
14fa60f2 256 raw_connaddr(rp, nam);
9e9695c7
SL
257 } else if ((rp->rcb_flags & RAW_FADDR) == 0) {
258 error = ENOTCONN;
4945768c 259 break;
9e9695c7 260 }
71fb71a3
SL
261 /*
262 * Check for routing. If new foreign address, or
263 * no route presently in use, try to allocate new
264 * route. On failure, just hand packet to output
265 * routine anyway in case it can handle it.
266 */
267 if ((rp->rcb_flags & RAW_DONTROUTE) == 0)
268 if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) ||
269 rp->rcb_route.ro_rt == 0) {
799dcac1
JB
270 if (rp->rcb_route.ro_rt) {
271 RTFREE(rp->rcb_route.ro_rt);
272 rp->rcb_route.ro_rt = NULL;
273 }
71fb71a3
SL
274 rp->rcb_route.ro_dst = rp->rcb_faddr;
275 rtalloc(&rp->rcb_route);
276 }
8a2f82db 277 error = (*so->so_proto->pr_output)(m, so);
9e9695c7 278 m = NULL;
14fa60f2 279 if (nam)
126472ab 280 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
281 break;
282
283 case PRU_ABORT:
284 raw_disconnect(rp);
285 sofree(so);
286 soisdisconnected(so);
287 break;
288
0f12c0aa
MK
289 case PRU_SENSE:
290 /*
291 * stat: don't bother with a blocksize.
292 */
293 return (0);
294
94a62155
BJ
295 /*
296 * Not supported.
297 */
799dcac1
JB
298 case PRU_CONTROL:
299 case PRU_RCVOOB:
94a62155 300 case PRU_RCVD:
799dcac1
JB
301 return(EOPNOTSUPP);
302
303 case PRU_ACCEPT:
94a62155
BJ
304 case PRU_SENDOOB:
305 error = EOPNOTSUPP;
306 break;
8df9431e 307
126472ab 308 case PRU_SOCKADDR:
ac76a23d 309 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
14fa60f2
BJ
310 sizeof (struct sockaddr));
311 nam->m_len = sizeof (struct sockaddr);
126472ab
SL
312 break;
313
a7343092
SL
314 case PRU_PEERADDR:
315 bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
316 sizeof (struct sockaddr));
317 nam->m_len = sizeof (struct sockaddr);
318 break;
319
94a62155
BJ
320 default:
321 panic("raw_usrreq");
322 }
9e9695c7
SL
323release:
324 if (m != NULL)
325 m_freem(m);
94a62155 326 return (error);
8df9431e 327}