date and time created 83/02/10 21:57:52 by sam
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
c20f7455 1/* raw_usrreq.c 4.24 83/01/13 */
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"
a1edc12b 8#include "../vax/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
BJ
13
14/*
15 * Initialize raw connection block q.
1e977657 16 */
94a62155
BJ
17raw_init()
18{
1e977657 19
94a62155 20 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
1e977657 21 rawintrq.ifq_maxlen = IFQ_MAXLEN;
94a62155 22}
8df9431e
BJ
23
24/*
25 * Raw protocol interface.
26 */
02122dcc 27raw_input(m0, proto, src, dst)
94a62155 28 struct mbuf *m0;
126472ab 29 struct sockproto *proto;
02122dcc 30 struct sockaddr *src, *dst;
8df9431e 31{
94a62155
BJ
32 register struct mbuf *m;
33 struct raw_header *rh;
8df9431e
BJ
34 int s;
35
94a62155
BJ
36 /*
37 * Rip off an mbuf for a generic header.
38 */
cce93e4b 39 m = m_get(M_DONTWAIT, MT_HEADER);
94a62155
BJ
40 if (m == 0) {
41 m_freem(m0);
42 return;
43 }
44 m->m_next = m0;
94a62155
BJ
45 m->m_len = sizeof(struct raw_header);
46 rh = mtod(m, struct raw_header *);
126472ab
SL
47 rh->raw_dst = *dst;
48 rh->raw_src = *src;
49 rh->raw_proto = *proto;
94a62155
BJ
50
51 /*
52 * Header now contains enough info to decide
53 * which socket to place packet in (if any).
54 * Queue it up for the raw protocol process
55 * running at software interrupt level.
56 */
8df9431e 57 s = splimp();
1e977657
BJ
58 if (IF_QFULL(&rawintrq))
59 m_freem(m);
60 else
61 IF_ENQUEUE(&rawintrq, m);
8df9431e 62 splx(s);
9c8692e9 63 schednetisr(NETISR_RAW);
8df9431e
BJ
64}
65
94a62155
BJ
66/*
67 * Raw protocol input routine. Process packets entered
68 * into the queue at interrupt time. Find the socket
69 * associated with the packet(s) and move them over. If
70 * nothing exists for this packet, drop it.
71 */
8df9431e
BJ
72rawintr()
73{
74 int s;
75 struct mbuf *m;
94a62155 76 register struct rawcb *rp;
126472ab 77 register struct protosw *lproto;
02122dcc 78 register struct raw_header *rh;
94a62155 79 struct socket *last;
8df9431e 80
8df9431e
BJ
81next:
82 s = splimp();
8df9431e
BJ
83 IF_DEQUEUE(&rawintrq, m);
84 splx(s);
85 if (m == 0)
86 return;
126472ab 87 rh = mtod(m, struct raw_header *);
94a62155
BJ
88 last = 0;
89 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
126472ab
SL
90 lproto = rp->rcb_socket->so_proto;
91 if (lproto->pr_family != rh->raw_proto.sp_family)
94a62155 92 continue;
126472ab
SL
93 if (lproto->pr_protocol &&
94 lproto->pr_protocol != rh->raw_proto.sp_protocol)
95 continue;
94a62155
BJ
96 /*
97 * We assume the lower level routines have
98 * placed the address in a canonical format
126472ab 99 * suitable for a structure comparison.
94a62155 100 */
02122dcc
SL
101#define equal(a1, a2) \
102 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
126472ab 103 if ((rp->rcb_flags & RAW_LADDR) &&
02122dcc 104 !equal(rp->rcb_laddr, rh->raw_dst))
126472ab
SL
105 continue;
106 if ((rp->rcb_flags & RAW_FADDR) &&
02122dcc 107 !equal(rp->rcb_faddr, rh->raw_src))
94a62155 108 continue;
94a62155
BJ
109 if (last) {
110 struct mbuf *n;
f832270b 111 if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
94a62155 112 goto nospace;
126472ab
SL
113 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
114 /* should notify about lost packet */
faad37c0
SL
115 m_freem(n);
116 goto nospace;
117 }
94a62155
BJ
118 sorwakeup(last);
119 }
120nospace:
126472ab 121 last = rp->rcb_socket;
94a62155 122 }
72e4f44e
SL
123 if (last) {
124 m = m_free(m); /* header */
125 if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
126 goto drop;
127 sorwakeup(last);
128 goto next;
129 }
8df9431e
BJ
130drop:
131 m_freem(m);
132 goto next;
133}
134
a1edc12b 135/*ARGSUSED*/
72e4f44e
SL
136raw_ctlinput(cmd, arg)
137 int cmd;
138 caddr_t arg;
139{
39674d5f
SL
140
141 if (cmd < 0 || cmd > PRC_NCMDS)
142 return;
a1edc12b 143 /* INCOMPLETE */
72e4f44e
SL
144}
145
8df9431e 146/*ARGSUSED*/
c20f7455 147raw_usrreq(so, req, m, nam)
8df9431e
BJ
148 struct socket *so;
149 int req;
14fa60f2 150 struct mbuf *m, *nam;
8df9431e 151{
94a62155
BJ
152 register struct rawcb *rp = sotorawcb(so);
153 int error = 0;
8df9431e 154
94a62155
BJ
155 if (rp == 0 && req != PRU_ATTACH)
156 return (EINVAL);
157
158 switch (req) {
159
160 /*
161 * Allocate a raw control block and fill in the
162 * necessary info to allow packets to be routed to
163 * the appropriate raw interface routine.
164 */
165 case PRU_ATTACH:
1e977657 166 if ((so->so_state & SS_PRIV) == 0)
72e4f44e 167 return (EACCES);
94a62155 168 if (rp)
1e977657 169 return (EINVAL);
14fa60f2 170 error = raw_attach(so);
94a62155
BJ
171 break;
172
173 /*
174 * Destroy state just before socket deallocation.
175 * Flush data or not depending on the options.
176 */
177 case PRU_DETACH:
178 if (rp == 0)
179 return (ENOTCONN);
180 raw_detach(rp);
181 break;
182
183 /*
184 * If a socket isn't bound to a single address,
185 * the raw input routine will hand it anything
186 * within that protocol family (assuming there's
187 * nothing else around it should go to).
188 */
189 case PRU_CONNECT:
126472ab 190 if (rp->rcb_flags & RAW_FADDR)
94a62155 191 return (EISCONN);
14fa60f2 192 raw_connaddr(rp, nam);
94a62155
BJ
193 soisconnected(so);
194 break;
195
196 case PRU_DISCONNECT:
126472ab 197 if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155
BJ
198 return (ENOTCONN);
199 raw_disconnect(rp);
200 soisdisconnected(so);
201 break;
202
203 /*
204 * Mark the connection as being incapable of further input.
205 */
206 case PRU_SHUTDOWN:
207 socantsendmore(so);
208 break;
209
210 /*
211 * Ship a packet out. The appropriate raw output
212 * routine handles any massaging necessary.
213 */
214 case PRU_SEND:
14fa60f2 215 if (nam) {
126472ab 216 if (rp->rcb_flags & RAW_FADDR)
94a62155 217 return (EISCONN);
14fa60f2 218 raw_connaddr(rp, nam);
126472ab 219 } else if ((rp->rcb_flags & RAW_FADDR) == 0)
94a62155 220 return (ENOTCONN);
8a2f82db 221 error = (*so->so_proto->pr_output)(m, so);
14fa60f2 222 if (nam)
126472ab 223 rp->rcb_flags &= ~RAW_FADDR;
94a62155
BJ
224 break;
225
226 case PRU_ABORT:
227 raw_disconnect(rp);
228 sofree(so);
229 soisdisconnected(so);
230 break;
231
232 /*
233 * Not supported.
234 */
235 case PRU_ACCEPT:
236 case PRU_RCVD:
237 case PRU_CONTROL:
238 case PRU_SENSE:
239 case PRU_RCVOOB:
240 case PRU_SENDOOB:
241 error = EOPNOTSUPP;
242 break;
8df9431e 243
126472ab 244 case PRU_SOCKADDR:
ac76a23d 245 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
14fa60f2
BJ
246 sizeof (struct sockaddr));
247 nam->m_len = sizeof (struct sockaddr);
126472ab
SL
248 break;
249
94a62155
BJ
250 default:
251 panic("raw_usrreq");
252 }
253 return (error);
8df9431e 254}