watch for write failures to the net
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
9c8692e9 1/* raw_usrreq.c 4.11 82/03/19 */
8df9431e
BJ
2
3#include "../h/param.h"
4#include "../h/mbuf.h"
94a62155 5#include "../h/protosw.h"
8df9431e
BJ
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"
94a62155 12#include "../net/raw_cb.h"
1e25d807 13#include "../errno.h"
94a62155 14
1e977657
BJ
15int rawqmaxlen = IFQ_MAXLEN;
16
94a62155
BJ
17/*
18 * Initialize raw connection block q.
1e977657 19 */
94a62155
BJ
20raw_init()
21{
1e977657 22
94a62155
BJ
23COUNT(RAW_INIT);
24 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
1e977657 25 rawintrq.ifq_maxlen = IFQ_MAXLEN;
94a62155 26}
8df9431e
BJ
27
28/*
29 * Raw protocol interface.
30 */
faad37c0 31raw_input(m0, pf, daf, saf)
94a62155 32 struct mbuf *m0;
33406a9e
SL
33 struct sockproto *pf;
34 struct sockaddr *daf, *saf;
8df9431e 35{
94a62155
BJ
36 register struct mbuf *m;
37 struct raw_header *rh;
8df9431e
BJ
38 int s;
39
33406a9e 40COUNT(RAW_INPUT);
94a62155
BJ
41 /*
42 * Rip off an mbuf for a generic header.
43 */
44 m = m_get(M_DONTWAIT);
45 if (m == 0) {
46 m_freem(m0);
47 return;
48 }
49 m->m_next = m0;
50 m->m_off = MMINOFF;
51 m->m_len = sizeof(struct raw_header);
52 rh = mtod(m, struct raw_header *);
33406a9e
SL
53 rh->raw_dst = *daf;
54 rh->raw_src = *saf;
55 rh->raw_protocol = *pf;
94a62155
BJ
56
57 /*
58 * Header now contains enough info to decide
59 * which socket to place packet in (if any).
60 * Queue it up for the raw protocol process
61 * running at software interrupt level.
62 */
8df9431e 63 s = splimp();
1e977657
BJ
64 if (IF_QFULL(&rawintrq))
65 m_freem(m);
66 else
67 IF_ENQUEUE(&rawintrq, m);
8df9431e 68 splx(s);
9c8692e9 69 schednetisr(NETISR_RAW);
8df9431e
BJ
70}
71
94a62155
BJ
72/*
73 * Raw protocol input routine. Process packets entered
74 * into the queue at interrupt time. Find the socket
75 * associated with the packet(s) and move them over. If
76 * nothing exists for this packet, drop it.
77 */
8df9431e
BJ
78rawintr()
79{
80 int s;
81 struct mbuf *m;
94a62155
BJ
82 register struct rawcb *rp;
83 register struct socket *so;
84 register struct protosw *pr;
85 register struct sockproto *sp;
86 register struct sockaddr *sa;
faad37c0 87 struct raw_header *rawp;
94a62155 88 struct socket *last;
8df9431e
BJ
89
90COUNT(RAWINTR);
91next:
92 s = splimp();
8df9431e
BJ
93 IF_DEQUEUE(&rawintrq, m);
94 splx(s);
95 if (m == 0)
96 return;
faad37c0
SL
97 rawp = mtod(m, struct raw_header *);
98 sp = &rawp->raw_protocol;
99 sa = &rawp->raw_dst;
94a62155
BJ
100
101 /*
102 * Find the appropriate socket(s) in which to place this
103 * packet. This is done by matching the protocol and
104 * address information prepended by raw_input against
105 * the info stored in the control block structures.
106 */
107 last = 0;
108 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
109 so = rp->rcb_socket;
110 pr = so->so_proto;
94a62155 111 if (pr->pr_family != sp->sp_family ||
1e25d807 112 (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol))
94a62155 113 continue;
1e25d807
BJ
114 if (so->so_addr.sa_family &&
115 sa->sa_family != so->so_addr.sa_family)
94a62155
BJ
116 continue;
117 /*
118 * We assume the lower level routines have
119 * placed the address in a canonical format
120 * suitable for a structure comparison. Packets
121 * are duplicated for each receiving socket.
33406a9e
SL
122 *
123 * SHOULD HAVE A NUMBER OF MECHANISMS FOR
124 * MATCHING BASED ON rcb_flags
94a62155
BJ
125 */
126 if ((rp->rcb_flags & RAW_ADDR) &&
127 bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0)
128 continue;
129 /*
130 * To avoid extraneous packet copies, we keep
131 * track of the last socket the packet should be
132 * placed in, and make copies only after finding a
133 * socket which "collides".
134 */
135 if (last) {
136 struct mbuf *n;
137
668cc26d 138 if (n = m_copy(m->m_next, 0, (int)M_COPYALL))
94a62155 139 goto nospace;
faad37c0
SL
140 if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) {
141 /*
142 * Should drop notification of lost packet
143 * into this guy's queue, but...
144 */
145 m_freem(n);
146 goto nospace;
147 }
94a62155
BJ
148 sorwakeup(last);
149 }
150nospace:
151 last = so;
152 }
153 if (last == 0)
154 goto drop;
faad37c0 155 if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0)
1e25d807
BJ
156{
157printf("rawintr: sbappendaddr failed\n");
faad37c0 158 goto drop;
1e25d807 159}
faad37c0 160 (void) m_free(m); /* generic header */
94a62155
BJ
161 sorwakeup(last);
162 goto next;
8df9431e
BJ
163drop:
164 m_freem(m);
165 goto next;
166}
167
168/*ARGSUSED*/
169raw_usrreq(so, req, m, addr)
170 struct socket *so;
171 int req;
172 struct mbuf *m;
173 caddr_t addr;
174{
94a62155
BJ
175 register struct rawcb *rp = sotorawcb(so);
176 int error = 0;
8df9431e
BJ
177
178COUNT(RAW_USRREQ);
94a62155
BJ
179 if (rp == 0 && req != PRU_ATTACH)
180 return (EINVAL);
181
182 switch (req) {
183
184 /*
185 * Allocate a raw control block and fill in the
186 * necessary info to allow packets to be routed to
187 * the appropriate raw interface routine.
188 */
189 case PRU_ATTACH:
1e977657
BJ
190 if ((so->so_state & SS_PRIV) == 0)
191 return (EPERM);
94a62155 192 if (rp)
1e977657 193 return (EINVAL);
94a62155
BJ
194 error = raw_attach(so, (struct sockaddr *)addr);
195 break;
196
197 /*
198 * Destroy state just before socket deallocation.
199 * Flush data or not depending on the options.
200 */
201 case PRU_DETACH:
202 if (rp == 0)
203 return (ENOTCONN);
204 raw_detach(rp);
205 break;
206
207 /*
208 * If a socket isn't bound to a single address,
209 * the raw input routine will hand it anything
210 * within that protocol family (assuming there's
211 * nothing else around it should go to).
212 */
213 case PRU_CONNECT:
214 if (rp->rcb_flags & RAW_ADDR)
215 return (EISCONN);
216 raw_connaddr(rp, (struct sockaddr *)addr);
217 soisconnected(so);
218 break;
219
220 case PRU_DISCONNECT:
221 if ((rp->rcb_flags & RAW_ADDR) == 0)
222 return (ENOTCONN);
223 raw_disconnect(rp);
224 soisdisconnected(so);
225 break;
226
227 /*
228 * Mark the connection as being incapable of further input.
229 */
230 case PRU_SHUTDOWN:
231 socantsendmore(so);
232 break;
233
234 /*
235 * Ship a packet out. The appropriate raw output
236 * routine handles any massaging necessary.
237 */
238 case PRU_SEND:
239 if (addr) {
240 if (rp->rcb_flags & RAW_ADDR)
241 return (EISCONN);
242 raw_connaddr(rp, (struct sockaddr *)addr);
243 } else if ((rp->rcb_flags & RAW_ADDR) == 0)
244 return (ENOTCONN);
245 (void) (*so->so_proto->pr_output)(m, so);
246 if (addr)
247 rp->rcb_flags &= ~RAW_ADDR;
248 break;
249
250 case PRU_ABORT:
251 raw_disconnect(rp);
252 sofree(so);
253 soisdisconnected(so);
254 break;
255
256 /*
257 * Not supported.
258 */
259 case PRU_ACCEPT:
260 case PRU_RCVD:
261 case PRU_CONTROL:
262 case PRU_SENSE:
263 case PRU_RCVOOB:
264 case PRU_SENDOOB:
265 error = EOPNOTSUPP;
266 break;
8df9431e 267
94a62155
BJ
268 default:
269 panic("raw_usrreq");
270 }
271 return (error);
8df9431e 272}