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