Handle Reverse-Path in some reasonable way. You must put the 'X'
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
14fa60f2 1/* raw_usrreq.c 4.19 82/10/09 */
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"
8df9431e 9#include "../net/if.h"
14fa60f2 10#include "../net/netisr.h"
94a62155 11#include "../net/raw_cb.h"
126472ab 12#include <errno.h>
94a62155 13
1e977657
BJ
14int rawqmaxlen = IFQ_MAXLEN;
15
94a62155
BJ
16/*
17 * Initialize raw connection block q.
1e977657 18 */
94a62155
BJ
19raw_init()
20{
1e977657 21
94a62155 22 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
1e977657 23 rawintrq.ifq_maxlen = IFQ_MAXLEN;
94a62155 24}
8df9431e
BJ
25
26/*
27 * Raw protocol interface.
28 */
02122dcc 29raw_input(m0, proto, src, dst)
94a62155 30 struct mbuf *m0;
126472ab 31 struct sockproto *proto;
02122dcc 32 struct sockaddr *src, *dst;
8df9431e 33{
94a62155
BJ
34 register struct mbuf *m;
35 struct raw_header *rh;
8df9431e
BJ
36 int s;
37
94a62155
BJ
38 /*
39 * Rip off an mbuf for a generic header.
40 */
41 m = m_get(M_DONTWAIT);
42 if (m == 0) {
43 m_freem(m0);
44 return;
45 }
46 m->m_next = m0;
94a62155
BJ
47 m->m_len = sizeof(struct raw_header);
48 rh = mtod(m, struct raw_header *);
126472ab
SL
49 rh->raw_dst = *dst;
50 rh->raw_src = *src;
51 rh->raw_proto = *proto;
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();
1e977657
BJ
60 if (IF_QFULL(&rawintrq))
61 m_freem(m);
62 else
63 IF_ENQUEUE(&rawintrq, m);
8df9431e 64 splx(s);
9c8692e9 65 schednetisr(NETISR_RAW);
8df9431e
BJ
66}
67
94a62155
BJ
68/*
69 * Raw protocol input routine. Process packets entered
70 * into the queue at interrupt time. Find the socket
71 * associated with the packet(s) and move them over. If
72 * nothing exists for this packet, drop it.
73 */
8df9431e
BJ
74rawintr()
75{
76 int s;
77 struct mbuf *m;
94a62155 78 register struct rawcb *rp;
126472ab 79 register struct protosw *lproto;
02122dcc 80 register struct raw_header *rh;
94a62155 81 struct socket *last;
8df9431e 82
8df9431e
BJ
83next:
84 s = splimp();
8df9431e
BJ
85 IF_DEQUEUE(&rawintrq, m);
86 splx(s);
87 if (m == 0)
88 return;
126472ab 89 rh = mtod(m, struct raw_header *);
94a62155
BJ
90 last = 0;
91 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
126472ab
SL
92 lproto = rp->rcb_socket->so_proto;
93 if (lproto->pr_family != rh->raw_proto.sp_family)
94a62155 94 continue;
126472ab
SL
95 if (lproto->pr_protocol &&
96 lproto->pr_protocol != rh->raw_proto.sp_protocol)
97 continue;
94a62155
BJ
98 /*
99 * We assume the lower level routines have
100 * placed the address in a canonical format
126472ab 101 * suitable for a structure comparison.
94a62155 102 */
02122dcc
SL
103#define equal(a1, a2) \
104 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
126472ab 105 if ((rp->rcb_flags & RAW_LADDR) &&
02122dcc 106 !equal(rp->rcb_laddr, rh->raw_dst))
126472ab
SL
107 continue;
108 if ((rp->rcb_flags & RAW_FADDR) &&
02122dcc 109 !equal(rp->rcb_faddr, rh->raw_src))
94a62155 110 continue;
94a62155
BJ
111 if (last) {
112 struct mbuf *n;
f832270b 113 if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
94a62155 114 goto nospace;
126472ab
SL
115 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
116 /* should notify about lost packet */
faad37c0
SL
117 m_freem(n);
118 goto nospace;
119 }
94a62155
BJ
120 sorwakeup(last);
121 }
122nospace:
126472ab 123 last = rp->rcb_socket;
94a62155 124 }
72e4f44e
SL
125 if (last) {
126 m = m_free(m); /* header */
127 if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
128 goto drop;
129 sorwakeup(last);
130 goto next;
131 }
8df9431e
BJ
132drop:
133 m_freem(m);
134 goto next;
135}
136
72e4f44e
SL
137raw_ctlinput(cmd, arg)
138 int cmd;
139 caddr_t arg;
140{
39674d5f
SL
141
142 if (cmd < 0 || cmd > PRC_NCMDS)
143 return;
72e4f44e
SL
144}
145
8df9431e 146/*ARGSUSED*/
14fa60f2 147raw_usrreq(so, req, m, nam, opt)
8df9431e
BJ
148 struct socket *so;
149 int req;
14fa60f2
BJ
150 struct mbuf *m, *nam;
151 struct socketopt *opt;
8df9431e 152{
94a62155
BJ
153 register struct rawcb *rp = sotorawcb(so);
154 int error = 0;
8df9431e 155
94a62155
BJ
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:
1e977657 167 if ((so->so_state & SS_PRIV) == 0)
72e4f44e 168 return (EACCES);
94a62155 169 if (rp)
1e977657 170 return (EINVAL);
14fa60f2 171 error = raw_attach(so);
94a62155
BJ
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:
126472ab 191 if (rp->rcb_flags & RAW_FADDR)
94a62155 192 return (EISCONN);
14fa60f2 193 raw_connaddr(rp, nam);
94a62155
BJ
194 soisconnected(so);
195 break;
196
197 case PRU_DISCONNECT:
126472ab 198 if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155
BJ
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:
14fa60f2 216 if (nam) {
126472ab 217 if (rp->rcb_flags & RAW_FADDR)
94a62155 218 return (EISCONN);
14fa60f2 219 raw_connaddr(rp, nam);
126472ab 220 } else if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155 221 return (ENOTCONN);
8a2f82db 222 error = (*so->so_proto->pr_output)(m, so);
14fa60f2 223 if (nam)
126472ab 224 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
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;
8df9431e 244
126472ab 245 case PRU_SOCKADDR:
14fa60f2
BJ
246 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, struct sockaddr *),
247 sizeof (struct sockaddr));
248 nam->m_len = sizeof (struct sockaddr);
126472ab
SL
249 break;
250
94a62155
BJ
251 default:
252 panic("raw_usrreq");
253 }
254 return (error);
8df9431e 255}