xref: /original-bsd/sys/net/raw_usrreq.c (revision b001ed0c)
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.9 (Berkeley) 06/28/90
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 #include "machine/mtpr.h"
24 
25 /*
26  * Initialize raw connection block q.
27  */
28 raw_init()
29 {
30 
31 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
32 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
33 }
34 
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  */
41 /*
42  * Raw protocol interface.
43  */
44 raw_input(m0, proto, src, dst)
45 	struct mbuf *m0;
46 	register struct sockproto *proto;
47 	struct sockaddr *src, *dst;
48 {
49 	register struct rawcb *rp;
50 	register struct mbuf *m = m0;
51 	register int sockets = 0;
52 	struct socket *last;
53 
54 	last = 0;
55 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
56 		if (rp->rcb_proto.sp_family != proto->sp_family)
57 			continue;
58 		if (rp->rcb_proto.sp_protocol  &&
59 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
60 			continue;
61 		/*
62 		 * We assume the lower level routines have
63 		 * placed the address in a canonical format
64 		 * suitable for a structure comparison.
65 		 *
66 		 * Note that if the lengths are not the same
67 		 * the comparison will fail at the first byte.
68 		 */
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))
72 			continue;
73 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
74 			continue;
75 		if (last) {
76 			struct mbuf *n;
77 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
78 				if (sbappendaddr(&last->so_rcv, src,
79 				    n, (struct mbuf *)0) == 0)
80 					/* should notify about lost packet */
81 					m_freem(n);
82 				else {
83 					sorwakeup(last);
84 					sockets++;
85 				}
86 			}
87 		}
88 		last = rp->rcb_socket;
89 	}
90 	if (last) {
91 		if (sbappendaddr(&last->so_rcv, src,
92 		    m, (struct mbuf *)0) == 0)
93 			m_freem(m);
94 		else {
95 			sorwakeup(last);
96 			sockets++;
97 		}
98 	} else
99 		m_freem(m);
100 	return (sockets);
101 }
102 
103 /*ARGSUSED*/
104 raw_ctlinput(cmd, arg)
105 	int cmd;
106 	struct sockaddr *arg;
107 {
108 
109 	if (cmd < 0 || cmd > PRC_NCMDS)
110 		return;
111 	/* INCOMPLETE */
112 }
113 
114 /*ARGSUSED*/
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 
282 rawintr() {} /* XXX - referenced by locore.  will soon go away */
283