reverse src and dst to raw_input
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
126472ab 1/* raw_usrreq.c 4.13 82/04/10 */
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"
126472ab 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 */
126472ab 31raw_input(m0, proto, dst, src)
94a62155 32 struct mbuf *m0;
126472ab
SL
33 struct sockproto *proto;
34 struct sockaddr *dst, *src;
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 *);
126472ab
SL
53 rh->raw_dst = *dst;
54 rh->raw_src = *src;
55 rh->raw_proto = *proto;
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 82 register struct rawcb *rp;
126472ab
SL
83 register struct sockaddr *laddr;
84 register struct protosw *lproto;
85 struct raw_header *rh;
94a62155 86 struct socket *last;
8df9431e
BJ
87
88COUNT(RAWINTR);
89next:
90 s = splimp();
8df9431e
BJ
91 IF_DEQUEUE(&rawintrq, m);
92 splx(s);
93 if (m == 0)
94 return;
126472ab 95 rh = mtod(m, struct raw_header *);
94a62155
BJ
96
97 /*
98 * Find the appropriate socket(s) in which to place this
99 * packet. This is done by matching the protocol and
100 * address information prepended by raw_input against
101 * the info stored in the control block structures.
102 */
103 last = 0;
104 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
126472ab
SL
105 lproto = rp->rcb_socket->so_proto;
106 if (lproto->pr_family != rh->raw_proto.sp_family)
94a62155 107 continue;
126472ab
SL
108 if (lproto->pr_protocol &&
109 lproto->pr_protocol != rh->raw_proto.sp_protocol)
110 continue;
111 laddr = &rp->rcb_laddr;
112 if (laddr->sa_family &&
113 laddr->sa_family != rh->raw_dst.sa_family)
94a62155
BJ
114 continue;
115 /*
116 * We assume the lower level routines have
117 * placed the address in a canonical format
126472ab 118 * suitable for a structure comparison.
94a62155 119 */
126472ab
SL
120 if ((rp->rcb_flags & RAW_LADDR) &&
121 bcmp(laddr->sa_data, rh->raw_dst.sa_data, 14) != 0)
122 continue;
123 if ((rp->rcb_flags & RAW_FADDR) &&
124 bcmp(rp->rcb_faddr.sa_data, rh->raw_src.sa_data, 14) != 0)
94a62155
BJ
125 continue;
126 /*
127 * To avoid extraneous packet copies, we keep
128 * track of the last socket the packet should be
129 * placed in, and make copies only after finding a
130 * socket which "collides".
131 */
132 if (last) {
133 struct mbuf *n;
134
668cc26d 135 if (n = m_copy(m->m_next, 0, (int)M_COPYALL))
94a62155 136 goto nospace;
126472ab
SL
137 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
138 /* should notify about lost packet */
faad37c0
SL
139 m_freem(n);
140 goto nospace;
141 }
94a62155
BJ
142 sorwakeup(last);
143 }
144nospace:
126472ab 145 last = rp->rcb_socket;
94a62155
BJ
146 }
147 if (last == 0)
148 goto drop;
126472ab
SL
149 m = m_free(m); /* header */
150 if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
faad37c0 151 goto drop;
94a62155
BJ
152 sorwakeup(last);
153 goto next;
8df9431e
BJ
154drop:
155 m_freem(m);
156 goto next;
157}
158
159/*ARGSUSED*/
160raw_usrreq(so, req, m, addr)
161 struct socket *so;
162 int req;
163 struct mbuf *m;
164 caddr_t addr;
165{
94a62155
BJ
166 register struct rawcb *rp = sotorawcb(so);
167 int error = 0;
8df9431e
BJ
168
169COUNT(RAW_USRREQ);
94a62155
BJ
170 if (rp == 0 && req != PRU_ATTACH)
171 return (EINVAL);
172
173 switch (req) {
174
175 /*
176 * Allocate a raw control block and fill in the
177 * necessary info to allow packets to be routed to
178 * the appropriate raw interface routine.
179 */
180 case PRU_ATTACH:
1e977657
BJ
181 if ((so->so_state & SS_PRIV) == 0)
182 return (EPERM);
94a62155 183 if (rp)
1e977657 184 return (EINVAL);
94a62155
BJ
185 error = raw_attach(so, (struct sockaddr *)addr);
186 break;
187
188 /*
189 * Destroy state just before socket deallocation.
190 * Flush data or not depending on the options.
191 */
192 case PRU_DETACH:
193 if (rp == 0)
194 return (ENOTCONN);
195 raw_detach(rp);
196 break;
197
198 /*
199 * If a socket isn't bound to a single address,
200 * the raw input routine will hand it anything
201 * within that protocol family (assuming there's
202 * nothing else around it should go to).
203 */
204 case PRU_CONNECT:
126472ab 205 if (rp->rcb_flags & RAW_FADDR)
94a62155
BJ
206 return (EISCONN);
207 raw_connaddr(rp, (struct sockaddr *)addr);
208 soisconnected(so);
209 break;
210
211 case PRU_DISCONNECT:
126472ab 212 if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155
BJ
213 return (ENOTCONN);
214 raw_disconnect(rp);
215 soisdisconnected(so);
216 break;
217
218 /*
219 * Mark the connection as being incapable of further input.
220 */
221 case PRU_SHUTDOWN:
222 socantsendmore(so);
223 break;
224
225 /*
226 * Ship a packet out. The appropriate raw output
227 * routine handles any massaging necessary.
228 */
229 case PRU_SEND:
230 if (addr) {
126472ab 231 if (rp->rcb_flags & RAW_FADDR)
94a62155
BJ
232 return (EISCONN);
233 raw_connaddr(rp, (struct sockaddr *)addr);
126472ab 234 } else if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155 235 return (ENOTCONN);
8a2f82db 236 error = (*so->so_proto->pr_output)(m, so);
94a62155 237 if (addr)
126472ab 238 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
239 break;
240
241 case PRU_ABORT:
242 raw_disconnect(rp);
243 sofree(so);
244 soisdisconnected(so);
245 break;
246
247 /*
248 * Not supported.
249 */
250 case PRU_ACCEPT:
251 case PRU_RCVD:
252 case PRU_CONTROL:
253 case PRU_SENSE:
254 case PRU_RCVOOB:
255 case PRU_SENDOOB:
256 error = EOPNOTSUPP;
257 break;
8df9431e 258
126472ab
SL
259 case PRU_SOCKADDR:
260 bcopy(addr, (caddr_t)&rp->rcb_laddr, sizeof (struct sockaddr));
261 break;
262
94a62155
BJ
263 default:
264 panic("raw_usrreq");
265 }
266 return (error);
8df9431e 267}