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