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