Commit | Line | Data |
---|---|---|
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 | * |
50c7758a | 17 | * @(#)raw_usrreq.c 7.4 (Berkeley) %G% |
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 | |
2e62d00d | 33 | #include "../machine/mtpr.h" |
94a62155 BJ |
34 | |
35 | /* | |
36 | * Initialize raw connection block q. | |
1e977657 | 37 | */ |
94a62155 BJ |
38 | raw_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 | 48 | raw_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 |
93 | rawintr() |
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 |
101 | next: |
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 |
154 | raw_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 | 165 | raw_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 |
318 | release: |
319 | if (m != NULL) | |
320 | m_freem(m); | |
94a62155 | 321 | return (error); |
8df9431e | 322 | } |