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