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 | * |
93790f32 | 17 | * @(#)raw_usrreq.c 7.8 (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 | |
0e6c0944 | 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 | 44 | |
b72a6efb KS |
45 | |
46 | /* | |
47 | * Raw protocol input routine. Find the socket | |
48 | * associated with the packet(s) and move them over. If | |
49 | * nothing exists for this packet, drop it. | |
50 | */ | |
8df9431e BJ |
51 | /* |
52 | * Raw protocol interface. | |
53 | */ | |
02122dcc | 54 | raw_input(m0, proto, src, dst) |
94a62155 | 55 | struct mbuf *m0; |
ad2ef60c | 56 | register struct sockproto *proto; |
02122dcc | 57 | struct sockaddr *src, *dst; |
8df9431e | 58 | { |
94a62155 | 59 | register struct rawcb *rp; |
b72a6efb | 60 | register struct mbuf *m = m0; |
ad2ef60c | 61 | register int sockets = 0; |
94a62155 | 62 | struct socket *last; |
8df9431e | 63 | |
94a62155 BJ |
64 | last = 0; |
65 | for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { | |
b72a6efb | 66 | if (rp->rcb_proto.sp_family != proto->sp_family) |
94a62155 | 67 | continue; |
829f867e | 68 | if (rp->rcb_proto.sp_protocol && |
b72a6efb | 69 | rp->rcb_proto.sp_protocol != proto->sp_protocol) |
126472ab | 70 | continue; |
94a62155 BJ |
71 | /* |
72 | * We assume the lower level routines have | |
73 | * placed the address in a canonical format | |
126472ab | 74 | * suitable for a structure comparison. |
b72a6efb KS |
75 | * |
76 | * Note that if the lengths are not the same | |
77 | * the comparison will fail at the first byte. | |
94a62155 | 78 | */ |
b72a6efb KS |
79 | #define equal(a1, a2) \ |
80 | (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) | |
81 | if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) | |
126472ab | 82 | continue; |
b72a6efb | 83 | if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) |
94a62155 | 84 | continue; |
94a62155 BJ |
85 | if (last) { |
86 | struct mbuf *n; | |
b72a6efb KS |
87 | if (n = m_copy(m, 0, (int)M_COPYALL)) { |
88 | if (sbappendaddr(&last->so_rcv, src, | |
fa1454d3 MK |
89 | n, (struct mbuf *)0) == 0) |
90 | /* should notify about lost packet */ | |
91 | m_freem(n); | |
ad2ef60c | 92 | else { |
fa1454d3 | 93 | sorwakeup(last); |
ad2ef60c KS |
94 | sockets++; |
95 | } | |
faad37c0 | 96 | } |
94a62155 | 97 | } |
126472ab | 98 | last = rp->rcb_socket; |
94a62155 | 99 | } |
72e4f44e | 100 | if (last) { |
b72a6efb KS |
101 | if (sbappendaddr(&last->so_rcv, src, |
102 | m, (struct mbuf *)0) == 0) | |
103 | m_freem(m); | |
ad2ef60c | 104 | else { |
fa1454d3 | 105 | sorwakeup(last); |
ad2ef60c KS |
106 | sockets++; |
107 | } | |
fa1454d3 MK |
108 | } else |
109 | m_freem(m); | |
ad2ef60c | 110 | return (sockets); |
8df9431e BJ |
111 | } |
112 | ||
a1edc12b | 113 | /*ARGSUSED*/ |
72e4f44e SL |
114 | raw_ctlinput(cmd, arg) |
115 | int cmd; | |
8011f5df | 116 | struct sockaddr *arg; |
72e4f44e | 117 | { |
39674d5f SL |
118 | |
119 | if (cmd < 0 || cmd > PRC_NCMDS) | |
120 | return; | |
a1edc12b | 121 | /* INCOMPLETE */ |
72e4f44e SL |
122 | } |
123 | ||
8df9431e | 124 | /*ARGSUSED*/ |
93790f32 | 125 | raw_usrreq(so, req, m, nam, control) |
8df9431e BJ |
126 | struct socket *so; |
127 | int req; | |
93790f32 | 128 | struct mbuf *m, *nam, *control; |
8df9431e | 129 | { |
94a62155 | 130 | register struct rawcb *rp = sotorawcb(so); |
9e9695c7 | 131 | register int error = 0; |
b72a6efb | 132 | int len; |
94a62155 | 133 | |
6624ec0b MK |
134 | if (req == PRU_CONTROL) |
135 | return (EOPNOTSUPP); | |
93790f32 | 136 | if (control && control->m_len) { |
9e9695c7 SL |
137 | error = EOPNOTSUPP; |
138 | goto release; | |
139 | } | |
b72a6efb | 140 | if (rp == 0) { |
9e9695c7 SL |
141 | error = EINVAL; |
142 | goto release; | |
143 | } | |
94a62155 BJ |
144 | switch (req) { |
145 | ||
146 | /* | |
147 | * Allocate a raw control block and fill in the | |
148 | * necessary info to allow packets to be routed to | |
149 | * the appropriate raw interface routine. | |
150 | */ | |
151 | case PRU_ATTACH: | |
9e9695c7 SL |
152 | if ((so->so_state & SS_PRIV) == 0) { |
153 | error = EACCES; | |
4945768c | 154 | break; |
9e9695c7 | 155 | } |
829f867e | 156 | error = raw_attach(so, (int)nam); |
94a62155 BJ |
157 | break; |
158 | ||
159 | /* | |
160 | * Destroy state just before socket deallocation. | |
161 | * Flush data or not depending on the options. | |
162 | */ | |
163 | case PRU_DETACH: | |
9e9695c7 SL |
164 | if (rp == 0) { |
165 | error = ENOTCONN; | |
4945768c | 166 | break; |
9e9695c7 | 167 | } |
94a62155 BJ |
168 | raw_detach(rp); |
169 | break; | |
170 | ||
b72a6efb | 171 | #ifdef notdef |
94a62155 BJ |
172 | /* |
173 | * If a socket isn't bound to a single address, | |
174 | * the raw input routine will hand it anything | |
175 | * within that protocol family (assuming there's | |
176 | * nothing else around it should go to). | |
177 | */ | |
178 | case PRU_CONNECT: | |
b72a6efb | 179 | if (rp->rcb_faddr) { |
9e9695c7 | 180 | error = EISCONN; |
4945768c | 181 | break; |
9e9695c7 | 182 | } |
b72a6efb KS |
183 | nam = m_copym(nam, 0, M_COPYALL, M_WAIT); |
184 | rp->rcb_faddr = mtod(nam, struct sockaddr *); | |
94a62155 BJ |
185 | soisconnected(so); |
186 | break; | |
187 | ||
9e9695c7 | 188 | case PRU_BIND: |
b72a6efb | 189 | if (rp->rcb_laddr) { |
9e9695c7 | 190 | error = EINVAL; /* XXX */ |
4945768c | 191 | break; |
9e9695c7 SL |
192 | } |
193 | error = raw_bind(so, nam); | |
194 | break; | |
b72a6efb KS |
195 | #endif |
196 | ||
197 | case PRU_CONNECT2: | |
198 | error = EOPNOTSUPP; | |
199 | goto release; | |
9e9695c7 | 200 | |
94a62155 | 201 | case PRU_DISCONNECT: |
b72a6efb | 202 | if (rp->rcb_faddr == 0) { |
9e9695c7 | 203 | error = ENOTCONN; |
4945768c | 204 | break; |
9e9695c7 | 205 | } |
94a62155 BJ |
206 | raw_disconnect(rp); |
207 | soisdisconnected(so); | |
208 | break; | |
209 | ||
210 | /* | |
211 | * Mark the connection as being incapable of further input. | |
212 | */ | |
213 | case PRU_SHUTDOWN: | |
214 | socantsendmore(so); | |
215 | break; | |
216 | ||
217 | /* | |
218 | * Ship a packet out. The appropriate raw output | |
219 | * routine handles any massaging necessary. | |
220 | */ | |
221 | case PRU_SEND: | |
14fa60f2 | 222 | if (nam) { |
b72a6efb | 223 | if (rp->rcb_faddr) { |
9e9695c7 | 224 | error = EISCONN; |
4945768c | 225 | break; |
9e9695c7 | 226 | } |
b72a6efb KS |
227 | rp->rcb_faddr = mtod(nam, struct sockaddr *); |
228 | } else if (rp->rcb_faddr == 0) { | |
9e9695c7 | 229 | error = ENOTCONN; |
4945768c | 230 | break; |
9e9695c7 | 231 | } |
8a2f82db | 232 | error = (*so->so_proto->pr_output)(m, so); |
9e9695c7 | 233 | m = NULL; |
14fa60f2 | 234 | if (nam) |
b72a6efb | 235 | rp->rcb_faddr = 0; |
94a62155 BJ |
236 | break; |
237 | ||
238 | case PRU_ABORT: | |
239 | raw_disconnect(rp); | |
240 | sofree(so); | |
241 | soisdisconnected(so); | |
242 | break; | |
243 | ||
0f12c0aa MK |
244 | case PRU_SENSE: |
245 | /* | |
246 | * stat: don't bother with a blocksize. | |
247 | */ | |
248 | return (0); | |
249 | ||
94a62155 BJ |
250 | /* |
251 | * Not supported. | |
252 | */ | |
799dcac1 | 253 | case PRU_RCVOOB: |
94a62155 | 254 | case PRU_RCVD: |
799dcac1 JB |
255 | return(EOPNOTSUPP); |
256 | ||
1fe3d605 | 257 | case PRU_LISTEN: |
799dcac1 | 258 | case PRU_ACCEPT: |
94a62155 BJ |
259 | case PRU_SENDOOB: |
260 | error = EOPNOTSUPP; | |
261 | break; | |
8df9431e | 262 | |
126472ab | 263 | case PRU_SOCKADDR: |
b72a6efb KS |
264 | if (rp->rcb_laddr == 0) { |
265 | error = EINVAL; | |
266 | break; | |
267 | } | |
268 | len = rp->rcb_laddr->sa_len; | |
269 | bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); | |
270 | nam->m_len = len; | |
126472ab SL |
271 | break; |
272 | ||
a7343092 | 273 | case PRU_PEERADDR: |
b72a6efb KS |
274 | if (rp->rcb_faddr == 0) { |
275 | error = ENOTCONN; | |
276 | break; | |
277 | } | |
278 | len = rp->rcb_faddr->sa_len; | |
279 | bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); | |
280 | nam->m_len = len; | |
a7343092 SL |
281 | break; |
282 | ||
94a62155 BJ |
283 | default: |
284 | panic("raw_usrreq"); | |
285 | } | |
9e9695c7 SL |
286 | release: |
287 | if (m != NULL) | |
288 | m_freem(m); | |
94a62155 | 289 | return (error); |
8df9431e | 290 | } |
b72a6efb KS |
291 | |
292 | rawintr() {} /* XXX - referenced by locore. will soon go away */ |