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