]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/net/raw_usrreq.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / net / raw_usrreq.c
1 /*-
2  * Copyright (c) 1980, 1986, 1993
3  *      The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      @(#)raw_usrreq.c        8.1 (Berkeley) 6/10/93
31  * $FreeBSD$
32  */
33
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/mutex.h>
40 #include <sys/priv.h>
41 #include <sys/protosw.h>
42 #include <sys/signalvar.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/sx.h>
46 #include <sys/systm.h>
47
48 #include <net/raw_cb.h>
49
50 MTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
51
52 /*
53  * Initialize raw connection block q.
54  */
55 void
56 raw_init(void)
57 {
58
59         LIST_INIT(&rawcb_list);
60 }
61
62 /*
63  * Raw protocol input routine.  Find the socket associated with the packet(s)
64  * and move them over.  If nothing exists for this packet, drop it.
65  */
66 /*
67  * Raw protocol interface.
68  */
69 void
70 raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
71 {
72         struct rawcb *rp;
73         struct mbuf *m = m0;
74         struct socket *last;
75
76         last = 0;
77         mtx_lock(&rawcb_mtx);
78         LIST_FOREACH(rp, &rawcb_list, list) {
79                 if (rp->rcb_proto.sp_family != proto->sp_family)
80                         continue;
81                 if (rp->rcb_proto.sp_protocol  &&
82                     rp->rcb_proto.sp_protocol != proto->sp_protocol)
83                         continue;
84                 if (last) {
85                         struct mbuf *n;
86                         n = m_copy(m, 0, (int)M_COPYALL);
87                         if (n) {
88                                 if (sbappendaddr(&last->so_rcv, src,
89                                     n, (struct mbuf *)0) == 0)
90                                         /* should notify about lost packet */
91                                         m_freem(n);
92                                 else
93                                         sorwakeup(last);
94                         }
95                 }
96                 last = rp->rcb_socket;
97         }
98         if (last) {
99                 if (sbappendaddr(&last->so_rcv, src,
100                     m, (struct mbuf *)0) == 0)
101                         m_freem(m);
102                 else
103                         sorwakeup(last);
104         } else
105                 m_freem(m);
106         mtx_unlock(&rawcb_mtx);
107 }
108
109 /*ARGSUSED*/
110 void
111 raw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
112 {
113
114         if (cmd < 0 || cmd >= PRC_NCMDS)
115                 return;
116         /* INCOMPLETE */
117 }
118
119 static void
120 raw_uabort(struct socket *so)
121 {
122
123         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
124
125         soisdisconnected(so);
126 }
127
128 static void
129 raw_uclose(struct socket *so)
130 {
131
132         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
133
134         soisdisconnected(so);
135 }
136
137 /* pru_accept is EOPNOTSUPP */
138
139 static int
140 raw_uattach(struct socket *so, int proto, struct thread *td)
141 {
142         int error;
143
144         /*
145          * Implementors of raw sockets will already have allocated the PCB,
146          * so it must be non-NULL here.
147          */
148         KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
149
150         if (td != NULL) {
151                 error = priv_check(td, PRIV_NET_RAW);
152                 if (error)
153                         return (error);
154         }
155         return (raw_attach(so, proto));
156 }
157
158 static int
159 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
160 {
161
162         return (EINVAL);
163 }
164
165 static int
166 raw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
167 {
168
169         return (EINVAL);
170 }
171
172 /* pru_connect2 is EOPNOTSUPP */
173 /* pru_control is EOPNOTSUPP */
174
175 static void
176 raw_udetach(struct socket *so)
177 {
178         struct rawcb *rp = sotorawcb(so);
179
180         KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
181
182         raw_detach(rp);
183 }
184
185 static int
186 raw_udisconnect(struct socket *so)
187 {
188
189         KASSERT(sotorawcb(so) != NULL, ("raw_udisconnect: rp == NULL"));
190
191         return (ENOTCONN);
192 }
193
194 /* pru_listen is EOPNOTSUPP */
195
196 static int
197 raw_upeeraddr(struct socket *so, struct sockaddr **nam)
198 {
199
200         KASSERT(sotorawcb(so) != NULL, ("raw_upeeraddr: rp == NULL"));
201
202         return (ENOTCONN);
203 }
204
205 /* pru_rcvd is EOPNOTSUPP */
206 /* pru_rcvoob is EOPNOTSUPP */
207
208 static int
209 raw_usend(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
210     struct mbuf *control, struct thread *td)
211 {
212
213         KASSERT(sotorawcb(so) != NULL, ("raw_usend: rp == NULL"));
214
215         if ((flags & PRUS_OOB) || (control && control->m_len)) {
216                 /* XXXRW: Should control also be freed here? */
217                 if (m != NULL)
218                         m_freem(m);
219                 return (EOPNOTSUPP);
220         }
221
222         /*
223          * For historical (bad?) reasons, we effectively ignore the address
224          * argument to sendto(2).  Perhaps we should return an error instead?
225          */
226         return ((*so->so_proto->pr_output)(m, so));
227 }
228
229 /* pru_sense is null */
230
231 static int
232 raw_ushutdown(struct socket *so)
233 {
234
235         KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
236
237         socantsendmore(so);
238         return (0);
239 }
240
241 static int
242 raw_usockaddr(struct socket *so, struct sockaddr **nam)
243 {
244
245         KASSERT(sotorawcb(so) != NULL, ("raw_usockaddr: rp == NULL"));
246
247         return (EINVAL);
248 }
249
250 struct pr_usrreqs raw_usrreqs = {
251         .pru_abort =            raw_uabort,
252         .pru_attach =           raw_uattach,
253         .pru_bind =             raw_ubind,
254         .pru_connect =          raw_uconnect,
255         .pru_detach =           raw_udetach, 
256         .pru_disconnect =       raw_udisconnect,
257         .pru_peeraddr =         raw_upeeraddr,
258         .pru_send =             raw_usend,
259         .pru_shutdown =         raw_ushutdown,
260         .pru_sockaddr =         raw_usockaddr,
261         .pru_close =            raw_uclose,
262 };