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