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