xref: /original-bsd/sys/net/raw_usrreq.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1980, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)raw_usrreq.c	7.13 (Berkeley) 06/04/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
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
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
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
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