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