xref: /csrg-svn/sys/net/raw_usrreq.c (revision 8693)
1 /*	raw_usrreq.c	4.21	82/10/20	*/
2 
3 #include "../h/param.h"
4 #include "../h/mbuf.h"
5 #include "../h/protosw.h"
6 #include "../h/socket.h"
7 #include "../h/socketvar.h"
8 #include "../vax/mtpr.h"
9 #include "../net/if.h"
10 #include "../net/netisr.h"
11 #include "../net/raw_cb.h"
12 #include <errno.h>
13 
14 /*
15  * Initialize raw connection block q.
16  */
17 raw_init()
18 {
19 
20 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
21 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
22 }
23 
24 /*
25  * Raw protocol interface.
26  */
27 raw_input(m0, proto, src, dst)
28 	struct mbuf *m0;
29 	struct sockproto *proto;
30 	struct sockaddr *src, *dst;
31 {
32 	register struct mbuf *m;
33 	struct raw_header *rh;
34 	int s;
35 
36 	/*
37 	 * Rip off an mbuf for a generic header.
38 	 */
39 	m = m_get(M_DONTWAIT);
40 	if (m == 0) {
41 		m_freem(m0);
42 		return;
43 	}
44 	m->m_next = m0;
45 	m->m_len = sizeof(struct raw_header);
46 	rh = mtod(m, struct raw_header *);
47 	rh->raw_dst = *dst;
48 	rh->raw_src = *src;
49 	rh->raw_proto = *proto;
50 
51 	/*
52 	 * Header now contains enough info to decide
53 	 * which socket to place packet in (if any).
54 	 * Queue it up for the raw protocol process
55 	 * running at software interrupt level.
56 	 */
57 	s = splimp();
58 	if (IF_QFULL(&rawintrq))
59 		m_freem(m);
60 	else
61 		IF_ENQUEUE(&rawintrq, m);
62 	splx(s);
63 	schednetisr(NETISR_RAW);
64 }
65 
66 /*
67  * Raw protocol input routine.  Process packets entered
68  * into the queue at interrupt time.  Find the socket
69  * associated with the packet(s) and move them over.  If
70  * nothing exists for this packet, drop it.
71  */
72 rawintr()
73 {
74 	int s;
75 	struct mbuf *m;
76 	register struct rawcb *rp;
77 	register struct protosw *lproto;
78 	register struct raw_header *rh;
79 	struct socket *last;
80 
81 next:
82 	s = splimp();
83 	IF_DEQUEUE(&rawintrq, m);
84 	splx(s);
85 	if (m == 0)
86 		return;
87 	rh = mtod(m, struct raw_header *);
88 	last = 0;
89 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
90 		lproto = rp->rcb_socket->so_proto;
91 		if (lproto->pr_family != rh->raw_proto.sp_family)
92 			continue;
93 		if (lproto->pr_protocol &&
94 		    lproto->pr_protocol != rh->raw_proto.sp_protocol)
95 			continue;
96 		/*
97 		 * We assume the lower level routines have
98 		 * placed the address in a canonical format
99 		 * suitable for a structure comparison.
100 		 */
101 #define equal(a1, a2) \
102 	(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
103 		if ((rp->rcb_flags & RAW_LADDR) &&
104 		    !equal(rp->rcb_laddr, rh->raw_dst))
105 			continue;
106 		if ((rp->rcb_flags & RAW_FADDR) &&
107 		    !equal(rp->rcb_faddr, rh->raw_src))
108 			continue;
109 		if (last) {
110 			struct mbuf *n;
111 			if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
112 				goto nospace;
113 			if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
114 				/* should notify about lost packet */
115 				m_freem(n);
116 				goto nospace;
117 			}
118 			sorwakeup(last);
119 		}
120 nospace:
121 		last = rp->rcb_socket;
122 	}
123 	if (last) {
124 		m = m_free(m);		/* header */
125 		if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
126 			goto drop;
127 		sorwakeup(last);
128 		goto next;
129 	}
130 drop:
131 	m_freem(m);
132 	goto next;
133 }
134 
135 /*ARGSUSED*/
136 raw_ctlinput(cmd, arg)
137 	int cmd;
138 	caddr_t arg;
139 {
140 
141 	if (cmd < 0 || cmd > PRC_NCMDS)
142 		return;
143 	/* INCOMPLETE */
144 }
145 
146 /*ARGSUSED*/
147 raw_usrreq(so, req, m, nam, opt)
148 	struct socket *so;
149 	int req;
150 	struct mbuf *m, *nam;
151 	struct socketopt *opt;
152 {
153 	register struct rawcb *rp = sotorawcb(so);
154 	int error = 0;
155 
156 	if (rp == 0 && req != PRU_ATTACH)
157 		return (EINVAL);
158 
159 	switch (req) {
160 
161 	/*
162 	 * Allocate a raw control block and fill in the
163 	 * necessary info to allow packets to be routed to
164 	 * the appropriate raw interface routine.
165 	 */
166 	case PRU_ATTACH:
167 		if ((so->so_state & SS_PRIV) == 0)
168 			return (EACCES);
169 		if (rp)
170 			return (EINVAL);
171 		error = raw_attach(so);
172 		break;
173 
174 	/*
175 	 * Destroy state just before socket deallocation.
176 	 * Flush data or not depending on the options.
177 	 */
178 	case PRU_DETACH:
179 		if (rp == 0)
180 			return (ENOTCONN);
181 		raw_detach(rp);
182 		break;
183 
184 	/*
185 	 * If a socket isn't bound to a single address,
186 	 * the raw input routine will hand it anything
187 	 * within that protocol family (assuming there's
188 	 * nothing else around it should go to).
189 	 */
190 	case PRU_CONNECT:
191 		if (rp->rcb_flags & RAW_FADDR)
192 			return (EISCONN);
193 		raw_connaddr(rp, nam);
194 		soisconnected(so);
195 		break;
196 
197 	case PRU_DISCONNECT:
198 		if ((rp->rcb_flags & RAW_FADDR) == 0)
199 			return (ENOTCONN);
200 		raw_disconnect(rp);
201 		soisdisconnected(so);
202 		break;
203 
204 	/*
205 	 * Mark the connection as being incapable of further input.
206 	 */
207 	case PRU_SHUTDOWN:
208 		socantsendmore(so);
209 		break;
210 
211 	/*
212 	 * Ship a packet out.  The appropriate raw output
213 	 * routine handles any massaging necessary.
214 	 */
215 	case PRU_SEND:
216 		if (nam) {
217 			if (rp->rcb_flags & RAW_FADDR)
218 				return (EISCONN);
219 			raw_connaddr(rp, nam);
220 		} else if ((rp->rcb_flags & RAW_FADDR) == 0)
221 			return (ENOTCONN);
222 		error = (*so->so_proto->pr_output)(m, so);
223 		if (nam)
224 			rp->rcb_flags &= ~RAW_FADDR;
225 		break;
226 
227 	case PRU_ABORT:
228 		raw_disconnect(rp);
229 		sofree(so);
230 		soisdisconnected(so);
231 		break;
232 
233 	/*
234 	 * Not supported.
235 	 */
236 	case PRU_ACCEPT:
237 	case PRU_RCVD:
238 	case PRU_CONTROL:
239 	case PRU_SENSE:
240 	case PRU_RCVOOB:
241 	case PRU_SENDOOB:
242 		error = EOPNOTSUPP;
243 		break;
244 
245 	case PRU_SOCKADDR:
246 		bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, struct sockaddr *),
247 		    sizeof (struct sockaddr));
248 		nam->m_len = sizeof (struct sockaddr);
249 		break;
250 
251 	default:
252 		panic("raw_usrreq");
253 	}
254 	return (error);
255 }
256