Commit | Line | Data |
---|---|---|
cb1c44c2 | 1 | /* |
1810611d | 2 | * Copyright (c) 1980, 1986 Regents of the University of California. |
5b519e94 | 3 | * All rights reserved. |
cb1c44c2 | 4 | * |
dbf0c423 | 5 | * %sccs.include.redist.c% |
5b519e94 | 6 | * |
dbf0c423 | 7 | * @(#)raw_usrreq.c 7.9 (Berkeley) %G% |
cb1c44c2 | 8 | */ |
8df9431e | 9 | |
a0369dcf JB |
10 | #include "param.h" |
11 | #include "mbuf.h" | |
12 | #include "domain.h" | |
13 | #include "protosw.h" | |
14 | #include "socket.h" | |
15 | #include "socketvar.h" | |
16 | #include "errno.h" | |
f4d55810 | 17 | |
a0369dcf JB |
18 | #include "if.h" |
19 | #include "route.h" | |
20 | #include "netisr.h" | |
21 | #include "raw_cb.h" | |
f4d55810 | 22 | |
0e6c0944 | 23 | #include "machine/mtpr.h" |
94a62155 BJ |
24 | |
25 | /* | |
26 | * Initialize raw connection block q. | |
1e977657 | 27 | */ |
94a62155 BJ |
28 | raw_init() |
29 | { | |
1e977657 | 30 | |
94a62155 | 31 | rawcb.rcb_next = rawcb.rcb_prev = &rawcb; |
1e977657 | 32 | rawintrq.ifq_maxlen = IFQ_MAXLEN; |
94a62155 | 33 | } |
8df9431e | 34 | |
b72a6efb KS |
35 | |
36 | /* | |
37 | * Raw protocol input routine. Find the socket | |
38 | * associated with the packet(s) and move them over. If | |
39 | * nothing exists for this packet, drop it. | |
40 | */ | |
8df9431e BJ |
41 | /* |
42 | * Raw protocol interface. | |
43 | */ | |
02122dcc | 44 | raw_input(m0, proto, src, dst) |
94a62155 | 45 | struct mbuf *m0; |
ad2ef60c | 46 | register struct sockproto *proto; |
02122dcc | 47 | struct sockaddr *src, *dst; |
8df9431e | 48 | { |
94a62155 | 49 | register struct rawcb *rp; |
b72a6efb | 50 | register struct mbuf *m = m0; |
ad2ef60c | 51 | register int sockets = 0; |
94a62155 | 52 | struct socket *last; |
8df9431e | 53 | |
94a62155 BJ |
54 | last = 0; |
55 | for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { | |
b72a6efb | 56 | if (rp->rcb_proto.sp_family != proto->sp_family) |
94a62155 | 57 | continue; |
829f867e | 58 | if (rp->rcb_proto.sp_protocol && |
b72a6efb | 59 | rp->rcb_proto.sp_protocol != proto->sp_protocol) |
126472ab | 60 | continue; |
94a62155 BJ |
61 | /* |
62 | * We assume the lower level routines have | |
63 | * placed the address in a canonical format | |
126472ab | 64 | * suitable for a structure comparison. |
b72a6efb KS |
65 | * |
66 | * Note that if the lengths are not the same | |
67 | * the comparison will fail at the first byte. | |
94a62155 | 68 | */ |
b72a6efb KS |
69 | #define equal(a1, a2) \ |
70 | (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) | |
71 | if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) | |
126472ab | 72 | continue; |
b72a6efb | 73 | if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) |
94a62155 | 74 | continue; |
94a62155 BJ |
75 | if (last) { |
76 | struct mbuf *n; | |
b72a6efb KS |
77 | if (n = m_copy(m, 0, (int)M_COPYALL)) { |
78 | if (sbappendaddr(&last->so_rcv, src, | |
fa1454d3 MK |
79 | n, (struct mbuf *)0) == 0) |
80 | /* should notify about lost packet */ | |
81 | m_freem(n); | |
ad2ef60c | 82 | else { |
fa1454d3 | 83 | sorwakeup(last); |
ad2ef60c KS |
84 | sockets++; |
85 | } | |
faad37c0 | 86 | } |
94a62155 | 87 | } |
126472ab | 88 | last = rp->rcb_socket; |
94a62155 | 89 | } |
72e4f44e | 90 | if (last) { |
b72a6efb KS |
91 | if (sbappendaddr(&last->so_rcv, src, |
92 | m, (struct mbuf *)0) == 0) | |
93 | m_freem(m); | |
ad2ef60c | 94 | else { |
fa1454d3 | 95 | sorwakeup(last); |
ad2ef60c KS |
96 | sockets++; |
97 | } | |
fa1454d3 MK |
98 | } else |
99 | m_freem(m); | |
ad2ef60c | 100 | return (sockets); |
8df9431e BJ |
101 | } |
102 | ||
a1edc12b | 103 | /*ARGSUSED*/ |
72e4f44e SL |
104 | raw_ctlinput(cmd, arg) |
105 | int cmd; | |
8011f5df | 106 | struct sockaddr *arg; |
72e4f44e | 107 | { |
39674d5f SL |
108 | |
109 | if (cmd < 0 || cmd > PRC_NCMDS) | |
110 | return; | |
a1edc12b | 111 | /* INCOMPLETE */ |
72e4f44e SL |
112 | } |
113 | ||
8df9431e | 114 | /*ARGSUSED*/ |
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 | } |
b72a6efb KS |
281 | |
282 | rawintr() {} /* XXX - referenced by locore. will soon go away */ |