lint
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
f4d55810 1/* raw_usrreq.c 4.25 83/02/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"
f4d55810
SL
8#include "../h/errno.h"
9
8df9431e 10#include "../net/if.h"
14fa60f2 11#include "../net/netisr.h"
94a62155 12#include "../net/raw_cb.h"
f4d55810
SL
13
14#include "../vax/mtpr.h"
94a62155
BJ
15
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 */
cce93e4b 41 m = m_get(M_DONTWAIT, MT_HEADER);
94a62155
BJ
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
a1edc12b 137/*ARGSUSED*/
72e4f44e
SL
138raw_ctlinput(cmd, arg)
139 int cmd;
140 caddr_t arg;
141{
39674d5f
SL
142
143 if (cmd < 0 || cmd > PRC_NCMDS)
144 return;
a1edc12b 145 /* INCOMPLETE */
72e4f44e
SL
146}
147
8df9431e 148/*ARGSUSED*/
c20f7455 149raw_usrreq(so, req, m, nam)
8df9431e
BJ
150 struct socket *so;
151 int req;
14fa60f2 152 struct mbuf *m, *nam;
8df9431e 153{
94a62155
BJ
154 register struct rawcb *rp = sotorawcb(so);
155 int error = 0;
8df9431e 156
94a62155
BJ
157 if (rp == 0 && req != PRU_ATTACH)
158 return (EINVAL);
159
160 switch (req) {
161
162 /*
163 * Allocate a raw control block and fill in the
164 * necessary info to allow packets to be routed to
165 * the appropriate raw interface routine.
166 */
167 case PRU_ATTACH:
1e977657 168 if ((so->so_state & SS_PRIV) == 0)
72e4f44e 169 return (EACCES);
94a62155 170 if (rp)
1e977657 171 return (EINVAL);
14fa60f2 172 error = raw_attach(so);
94a62155
BJ
173 break;
174
175 /*
176 * Destroy state just before socket deallocation.
177 * Flush data or not depending on the options.
178 */
179 case PRU_DETACH:
180 if (rp == 0)
181 return (ENOTCONN);
182 raw_detach(rp);
183 break;
184
185 /*
186 * If a socket isn't bound to a single address,
187 * the raw input routine will hand it anything
188 * within that protocol family (assuming there's
189 * nothing else around it should go to).
190 */
191 case PRU_CONNECT:
126472ab 192 if (rp->rcb_flags & RAW_FADDR)
94a62155 193 return (EISCONN);
14fa60f2 194 raw_connaddr(rp, nam);
94a62155
BJ
195 soisconnected(so);
196 break;
197
198 case PRU_DISCONNECT:
126472ab 199 if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155
BJ
200 return (ENOTCONN);
201 raw_disconnect(rp);
202 soisdisconnected(so);
203 break;
204
205 /*
206 * Mark the connection as being incapable of further input.
207 */
208 case PRU_SHUTDOWN:
209 socantsendmore(so);
210 break;
211
212 /*
213 * Ship a packet out. The appropriate raw output
214 * routine handles any massaging necessary.
215 */
216 case PRU_SEND:
14fa60f2 217 if (nam) {
126472ab 218 if (rp->rcb_flags & RAW_FADDR)
94a62155 219 return (EISCONN);
14fa60f2 220 raw_connaddr(rp, nam);
126472ab 221 } else if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155 222 return (ENOTCONN);
8a2f82db 223 error = (*so->so_proto->pr_output)(m, so);
14fa60f2 224 if (nam)
126472ab 225 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
226 break;
227
228 case PRU_ABORT:
229 raw_disconnect(rp);
230 sofree(so);
231 soisdisconnected(so);
232 break;
233
234 /*
235 * Not supported.
236 */
237 case PRU_ACCEPT:
238 case PRU_RCVD:
239 case PRU_CONTROL:
240 case PRU_SENSE:
241 case PRU_RCVOOB:
242 case PRU_SENDOOB:
243 error = EOPNOTSUPP;
244 break;
8df9431e 245
126472ab 246 case PRU_SOCKADDR:
ac76a23d 247 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
14fa60f2
BJ
248 sizeof (struct sockaddr));
249 nam->m_len = sizeof (struct sockaddr);
126472ab
SL
250 break;
251
94a62155
BJ
252 default:
253 panic("raw_usrreq");
254 }
255 return (error);
8df9431e 256}