1 /*
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)raw_usrreq.c 8.1 (Berkeley) 06/10/93
8 */
9
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>
17
18 #include <net/if.h>
19 #include <net/route.h>
20 #include <net/netisr.h>
21 #include <net/raw_cb.h>
22
23 /*
24 * Initialize raw connection block q.
25 */
26 void
raw_init()27 raw_init()
28 {
29
30 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
31 }
32
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 */
39 /*
40 * Raw protocol interface.
41 */
42 void
raw_input(m0,proto,src,dst)43 raw_input(m0, proto, src, dst)
44 struct mbuf *m0;
45 register struct sockproto *proto;
46 struct sockaddr *src, *dst;
47 {
48 register struct rawcb *rp;
49 register struct mbuf *m = m0;
50 register int sockets = 0;
51 struct socket *last;
52
53 last = 0;
54 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
55 if (rp->rcb_proto.sp_family != proto->sp_family)
56 continue;
57 if (rp->rcb_proto.sp_protocol &&
58 rp->rcb_proto.sp_protocol != proto->sp_protocol)
59 continue;
60 /*
61 * We assume the lower level routines have
62 * placed the address in a canonical format
63 * suitable for a structure comparison.
64 *
65 * Note that if the lengths are not the same
66 * the comparison will fail at the first byte.
67 */
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))
71 continue;
72 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
73 continue;
74 if (last) {
75 struct mbuf *n;
76 if (n = m_copy(m, 0, (int)M_COPYALL)) {
77 if (sbappendaddr(&last->so_rcv, src,
78 n, (struct mbuf *)0) == 0)
79 /* should notify about lost packet */
80 m_freem(n);
81 else {
82 sorwakeup(last);
83 sockets++;
84 }
85 }
86 }
87 last = rp->rcb_socket;
88 }
89 if (last) {
90 if (sbappendaddr(&last->so_rcv, src,
91 m, (struct mbuf *)0) == 0)
92 m_freem(m);
93 else {
94 sorwakeup(last);
95 sockets++;
96 }
97 } else
98 m_freem(m);
99 }
100
101 /*ARGSUSED*/
102 void
raw_ctlinput(cmd,arg)103 raw_ctlinput(cmd, arg)
104 int cmd;
105 struct sockaddr *arg;
106 {
107
108 if (cmd < 0 || cmd > PRC_NCMDS)
109 return;
110 /* INCOMPLETE */
111 }
112
113 /*ARGSUSED*/
114 int
raw_usrreq(so,req,m,nam,control)115 raw_usrreq(so, req, m, nam, control)
116 struct socket *so;
117 int req;
118 struct mbuf *m, *nam, *control;
119 {
120 register struct rawcb *rp = sotorawcb(so);
121 register int error = 0;
122 int len;
123
124 if (req == PRU_CONTROL)
125 return (EOPNOTSUPP);
126 if (control && control->m_len) {
127 error = EOPNOTSUPP;
128 goto release;
129 }
130 if (rp == 0) {
131 error = EINVAL;
132 goto release;
133 }
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:
142 if ((so->so_state & SS_PRIV) == 0) {
143 error = EACCES;
144 break;
145 }
146 error = raw_attach(so, (int)nam);
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:
154 if (rp == 0) {
155 error = ENOTCONN;
156 break;
157 }
158 raw_detach(rp);
159 break;
160
161 #ifdef notdef
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:
169 if (rp->rcb_faddr) {
170 error = EISCONN;
171 break;
172 }
173 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
174 rp->rcb_faddr = mtod(nam, struct sockaddr *);
175 soisconnected(so);
176 break;
177
178 case PRU_BIND:
179 if (rp->rcb_laddr) {
180 error = EINVAL; /* XXX */
181 break;
182 }
183 error = raw_bind(so, nam);
184 break;
185 #endif
186
187 case PRU_CONNECT2:
188 error = EOPNOTSUPP;
189 goto release;
190
191 case PRU_DISCONNECT:
192 if (rp->rcb_faddr == 0) {
193 error = ENOTCONN;
194 break;
195 }
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:
212 if (nam) {
213 if (rp->rcb_faddr) {
214 error = EISCONN;
215 break;
216 }
217 rp->rcb_faddr = mtod(nam, struct sockaddr *);
218 } else if (rp->rcb_faddr == 0) {
219 error = ENOTCONN;
220 break;
221 }
222 error = (*so->so_proto->pr_output)(m, so);
223 m = NULL;
224 if (nam)
225 rp->rcb_faddr = 0;
226 break;
227
228 case PRU_ABORT:
229 raw_disconnect(rp);
230 sofree(so);
231 soisdisconnected(so);
232 break;
233
234 case PRU_SENSE:
235 /*
236 * stat: don't bother with a blocksize.
237 */
238 return (0);
239
240 /*
241 * Not supported.
242 */
243 case PRU_RCVOOB:
244 case PRU_RCVD:
245 return(EOPNOTSUPP);
246
247 case PRU_LISTEN:
248 case PRU_ACCEPT:
249 case PRU_SENDOOB:
250 error = EOPNOTSUPP;
251 break;
252
253 case PRU_SOCKADDR:
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;
261 break;
262
263 case PRU_PEERADDR:
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;
271 break;
272
273 default:
274 panic("raw_usrreq");
275 }
276 release:
277 if (m != NULL)
278 m_freem(m);
279 return (error);
280 }
281