missing setup of tape density and format
[unix-history] / usr / src / sys / net / raw_usrreq.c
... / ...
CommitLineData
1/* raw_usrreq.c 4.25 83/02/10 */
2
3#include "../h/param.h"
4#include "../h/mbuf.h"
5#include "../h/protosw.h"
6#include "../h/socket.h"
7#include "../h/socketvar.h"
8#include "../h/errno.h"
9
10#include "../net/if.h"
11#include "../net/netisr.h"
12#include "../net/raw_cb.h"
13
14#include "../vax/mtpr.h"
15
16/*
17 * Initialize raw connection block q.
18 */
19raw_init()
20{
21
22 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
23 rawintrq.ifq_maxlen = IFQ_MAXLEN;
24}
25
26/*
27 * Raw protocol interface.
28 */
29raw_input(m0, proto, src, dst)
30 struct mbuf *m0;
31 struct sockproto *proto;
32 struct sockaddr *src, *dst;
33{
34 register struct mbuf *m;
35 struct raw_header *rh;
36 int s;
37
38 /*
39 * Rip off an mbuf for a generic header.
40 */
41 m = m_get(M_DONTWAIT, MT_HEADER);
42 if (m == 0) {
43 m_freem(m0);
44 return;
45 }
46 m->m_next = m0;
47 m->m_len = sizeof(struct raw_header);
48 rh = mtod(m, struct raw_header *);
49 rh->raw_dst = *dst;
50 rh->raw_src = *src;
51 rh->raw_proto = *proto;
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 */
59 s = splimp();
60 if (IF_QFULL(&rawintrq))
61 m_freem(m);
62 else
63 IF_ENQUEUE(&rawintrq, m);
64 splx(s);
65 schednetisr(NETISR_RAW);
66}
67
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 */
74rawintr()
75{
76 int s;
77 struct mbuf *m;
78 register struct rawcb *rp;
79 register struct protosw *lproto;
80 register struct raw_header *rh;
81 struct socket *last;
82
83next:
84 s = splimp();
85 IF_DEQUEUE(&rawintrq, m);
86 splx(s);
87 if (m == 0)
88 return;
89 rh = mtod(m, struct raw_header *);
90 last = 0;
91 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
92 lproto = rp->rcb_socket->so_proto;
93 if (lproto->pr_family != rh->raw_proto.sp_family)
94 continue;
95 if (lproto->pr_protocol &&
96 lproto->pr_protocol != rh->raw_proto.sp_protocol)
97 continue;
98 /*
99 * We assume the lower level routines have
100 * placed the address in a canonical format
101 * suitable for a structure comparison.
102 */
103#define equal(a1, a2) \
104 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
105 if ((rp->rcb_flags & RAW_LADDR) &&
106 !equal(rp->rcb_laddr, rh->raw_dst))
107 continue;
108 if ((rp->rcb_flags & RAW_FADDR) &&
109 !equal(rp->rcb_faddr, rh->raw_src))
110 continue;
111 if (last) {
112 struct mbuf *n;
113 if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
114 goto nospace;
115 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
116 /* should notify about lost packet */
117 m_freem(n);
118 goto nospace;
119 }
120 sorwakeup(last);
121 }
122nospace:
123 last = rp->rcb_socket;
124 }
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 }
132drop:
133 m_freem(m);
134 goto next;
135}
136
137/*ARGSUSED*/
138raw_ctlinput(cmd, arg)
139 int cmd;
140 caddr_t arg;
141{
142
143 if (cmd < 0 || cmd > PRC_NCMDS)
144 return;
145 /* INCOMPLETE */
146}
147
148/*ARGSUSED*/
149raw_usrreq(so, req, m, nam)
150 struct socket *so;
151 int req;
152 struct mbuf *m, *nam;
153{
154 register struct rawcb *rp = sotorawcb(so);
155 int error = 0;
156
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:
168 if ((so->so_state & SS_PRIV) == 0)
169 return (EACCES);
170 if (rp)
171 return (EINVAL);
172 error = raw_attach(so);
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:
192 if (rp->rcb_flags & RAW_FADDR)
193 return (EISCONN);
194 raw_connaddr(rp, nam);
195 soisconnected(so);
196 break;
197
198 case PRU_DISCONNECT:
199 if ((rp->rcb_flags & RAW_FADDR) == 0)
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:
217 if (nam) {
218 if (rp->rcb_flags & RAW_FADDR)
219 return (EISCONN);
220 raw_connaddr(rp, nam);
221 } else if ((rp->rcb_flags & RAW_FADDR) == 0)
222 return (ENOTCONN);
223 error = (*so->so_proto->pr_output)(m, so);
224 if (nam)
225 rp->rcb_flags &= ~RAW_FADDR;
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;
245
246 case PRU_SOCKADDR:
247 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
248 sizeof (struct sockaddr));
249 nam->m_len = sizeof (struct sockaddr);
250 break;
251
252 default:
253 panic("raw_usrreq");
254 }
255 return (error);
256}