upgraded to the latest NetBSD version
[unix-history] / usr / src / sys / net / raw_usrreq.c
CommitLineData
cb1c44c2 1/*
c8dfc989
KB
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
cb1c44c2 4 *
dbf0c423 5 * %sccs.include.redist.c%
5b519e94 6 *
c8dfc989 7 * @(#)raw_usrreq.c 8.1 (Berkeley) %G%
cb1c44c2 8 */
8df9431e 9
5548a02f
KB
10#include <sys/param.h>
11#include <sys/mbuf.h>
12#include <sys/domain.h>
13#include <sys/protosw.h>
14#include <sys/socket.h>
15#include <sys/socketvar.h>
16#include <sys/errno.h>
f4d55810 17
5548a02f
KB
18#include <net/if.h>
19#include <net/route.h>
20#include <net/netisr.h>
21#include <net/raw_cb.h>
f4d55810 22
94a62155
BJ
23/*
24 * Initialize raw connection block q.
1e977657 25 */
38de5671 26void
94a62155
BJ
27raw_init()
28{
1e977657 29
94a62155
BJ
30 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
31}
8df9431e 32
b72a6efb
KS
33
34/*
35 * Raw protocol input routine. Find the socket
36 * associated with the packet(s) and move them over. If
37 * nothing exists for this packet, drop it.
38 */
8df9431e
BJ
39/*
40 * Raw protocol interface.
41 */
38de5671 42void
02122dcc 43raw_input(m0, proto, src, dst)
94a62155 44 struct mbuf *m0;
ad2ef60c 45 register struct sockproto *proto;
02122dcc 46 struct sockaddr *src, *dst;
8df9431e 47{
94a62155 48 register struct rawcb *rp;
b72a6efb 49 register struct mbuf *m = m0;
ad2ef60c 50 register int sockets = 0;
94a62155 51 struct socket *last;
8df9431e 52
94a62155
BJ
53 last = 0;
54 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
b72a6efb 55 if (rp->rcb_proto.sp_family != proto->sp_family)
94a62155 56 continue;
829f867e 57 if (rp->rcb_proto.sp_protocol &&
b72a6efb 58 rp->rcb_proto.sp_protocol != proto->sp_protocol)
126472ab 59 continue;
94a62155
BJ
60 /*
61 * We assume the lower level routines have
62 * placed the address in a canonical format
126472ab 63 * suitable for a structure comparison.
b72a6efb
KS
64 *
65 * Note that if the lengths are not the same
66 * the comparison will fail at the first byte.
94a62155 67 */
b72a6efb
KS
68#define equal(a1, a2) \
69 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
70 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
126472ab 71 continue;
b72a6efb 72 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
94a62155 73 continue;
94a62155
BJ
74 if (last) {
75 struct mbuf *n;
b72a6efb
KS
76 if (n = m_copy(m, 0, (int)M_COPYALL)) {
77 if (sbappendaddr(&last->so_rcv, src,
fa1454d3
MK
78 n, (struct mbuf *)0) == 0)
79 /* should notify about lost packet */
80 m_freem(n);
ad2ef60c 81 else {
fa1454d3 82 sorwakeup(last);
ad2ef60c
KS
83 sockets++;
84 }
faad37c0 85 }
94a62155 86 }
126472ab 87 last = rp->rcb_socket;
94a62155 88 }
72e4f44e 89 if (last) {
b72a6efb
KS
90 if (sbappendaddr(&last->so_rcv, src,
91 m, (struct mbuf *)0) == 0)
92 m_freem(m);
ad2ef60c 93 else {
fa1454d3 94 sorwakeup(last);
ad2ef60c
KS
95 sockets++;
96 }
fa1454d3
MK
97 } else
98 m_freem(m);
8df9431e
BJ
99}
100
a1edc12b 101/*ARGSUSED*/
38de5671 102void
72e4f44e
SL
103raw_ctlinput(cmd, arg)
104 int cmd;
8011f5df 105 struct sockaddr *arg;
72e4f44e 106{
39674d5f
SL
107
108 if (cmd < 0 || cmd > PRC_NCMDS)
109 return;
a1edc12b 110 /* INCOMPLETE */
72e4f44e
SL
111}
112
8df9431e 113/*ARGSUSED*/
38de5671 114int
93790f32 115raw_usrreq(so, req, m, nam, control)
8df9431e
BJ
116 struct socket *so;
117 int req;
93790f32 118 struct mbuf *m, *nam, *control;
8df9431e 119{
94a62155 120 register struct rawcb *rp = sotorawcb(so);
9e9695c7 121 register int error = 0;
b72a6efb 122 int len;
94a62155 123
6624ec0b
MK
124 if (req == PRU_CONTROL)
125 return (EOPNOTSUPP);
93790f32 126 if (control && control->m_len) {
9e9695c7
SL
127 error = EOPNOTSUPP;
128 goto release;
129 }
b72a6efb 130 if (rp == 0) {
9e9695c7
SL
131 error = EINVAL;
132 goto release;
133 }
94a62155
BJ
134 switch (req) {
135
136 /*
137 * Allocate a raw control block and fill in the
138 * necessary info to allow packets to be routed to
139 * the appropriate raw interface routine.
140 */
141 case PRU_ATTACH:
9e9695c7
SL
142 if ((so->so_state & SS_PRIV) == 0) {
143 error = EACCES;
4945768c 144 break;
9e9695c7 145 }
829f867e 146 error = raw_attach(so, (int)nam);
94a62155
BJ
147 break;
148
149 /*
150 * Destroy state just before socket deallocation.
151 * Flush data or not depending on the options.
152 */
153 case PRU_DETACH:
9e9695c7
SL
154 if (rp == 0) {
155 error = ENOTCONN;
4945768c 156 break;
9e9695c7 157 }
94a62155
BJ
158 raw_detach(rp);
159 break;
160
b72a6efb 161#ifdef notdef
94a62155
BJ
162 /*
163 * If a socket isn't bound to a single address,
164 * the raw input routine will hand it anything
165 * within that protocol family (assuming there's
166 * nothing else around it should go to).
167 */
168 case PRU_CONNECT:
b72a6efb 169 if (rp->rcb_faddr) {
9e9695c7 170 error = EISCONN;
4945768c 171 break;
9e9695c7 172 }
b72a6efb
KS
173 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
174 rp->rcb_faddr = mtod(nam, struct sockaddr *);
94a62155
BJ
175 soisconnected(so);
176 break;
177
9e9695c7 178 case PRU_BIND:
b72a6efb 179 if (rp->rcb_laddr) {
9e9695c7 180 error = EINVAL; /* XXX */
4945768c 181 break;
9e9695c7
SL
182 }
183 error = raw_bind(so, nam);
184 break;
b72a6efb
KS
185#endif
186
187 case PRU_CONNECT2:
188 error = EOPNOTSUPP;
189 goto release;
9e9695c7 190
94a62155 191 case PRU_DISCONNECT:
b72a6efb 192 if (rp->rcb_faddr == 0) {
9e9695c7 193 error = ENOTCONN;
4945768c 194 break;
9e9695c7 195 }
94a62155
BJ
196 raw_disconnect(rp);
197 soisdisconnected(so);
198 break;
199
200 /*
201 * Mark the connection as being incapable of further input.
202 */
203 case PRU_SHUTDOWN:
204 socantsendmore(so);
205 break;
206
207 /*
208 * Ship a packet out. The appropriate raw output
209 * routine handles any massaging necessary.
210 */
211 case PRU_SEND:
14fa60f2 212 if (nam) {
b72a6efb 213 if (rp->rcb_faddr) {
9e9695c7 214 error = EISCONN;
4945768c 215 break;
9e9695c7 216 }
b72a6efb
KS
217 rp->rcb_faddr = mtod(nam, struct sockaddr *);
218 } else if (rp->rcb_faddr == 0) {
9e9695c7 219 error = ENOTCONN;
4945768c 220 break;
9e9695c7 221 }
8a2f82db 222 error = (*so->so_proto->pr_output)(m, so);
9e9695c7 223 m = NULL;
14fa60f2 224 if (nam)
b72a6efb 225 rp->rcb_faddr = 0;
94a62155
BJ
226 break;
227
228 case PRU_ABORT:
229 raw_disconnect(rp);
230 sofree(so);
231 soisdisconnected(so);
232 break;
233
0f12c0aa
MK
234 case PRU_SENSE:
235 /*
236 * stat: don't bother with a blocksize.
237 */
238 return (0);
239
94a62155
BJ
240 /*
241 * Not supported.
242 */
799dcac1 243 case PRU_RCVOOB:
94a62155 244 case PRU_RCVD:
799dcac1
JB
245 return(EOPNOTSUPP);
246
1fe3d605 247 case PRU_LISTEN:
799dcac1 248 case PRU_ACCEPT:
94a62155
BJ
249 case PRU_SENDOOB:
250 error = EOPNOTSUPP;
251 break;
8df9431e 252
126472ab 253 case PRU_SOCKADDR:
b72a6efb
KS
254 if (rp->rcb_laddr == 0) {
255 error = EINVAL;
256 break;
257 }
258 len = rp->rcb_laddr->sa_len;
259 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
260 nam->m_len = len;
126472ab
SL
261 break;
262
a7343092 263 case PRU_PEERADDR:
b72a6efb
KS
264 if (rp->rcb_faddr == 0) {
265 error = ENOTCONN;
266 break;
267 }
268 len = rp->rcb_faddr->sa_len;
269 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
270 nam->m_len = len;
a7343092
SL
271 break;
272
94a62155
BJ
273 default:
274 panic("raw_usrreq");
275 }
9e9695c7
SL
276release:
277 if (m != NULL)
278 m_freem(m);
94a62155 279 return (error);
8df9431e 280}