More MP work.
[dragonfly.git] / sys / kern / sys_socket.c
1 /*
2  * Copyright (c) 1982, 1986, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)sys_socket.c        8.1 (Berkeley) 6/10/93
34  * $FreeBSD: src/sys/kern/sys_socket.c,v 1.28.2.2 2001/02/26 04:23:16 jlemon Exp $
35  * $DragonFly: src/sys/kern/sys_socket.c,v 1.10 2006/05/26 00:33:09 dillon Exp $
36  */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/file.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/socketops.h>
45 #include <sys/filio.h>                  /* XXX */
46 #include <sys/sockio.h>
47 #include <sys/stat.h>
48 #include <sys/uio.h>
49 #include <sys/filedesc.h>
50 #include <sys/ucred.h>
51
52 #include <net/if.h>
53 #include <net/route.h>
54
55 struct  fileops socketops = {
56         NULL,   /* port */
57         NULL,   /* clone */
58         soo_read, soo_write, soo_ioctl, soo_poll, sokqfilter,
59         soo_stat, soo_close, soo_shutdown
60 };
61
62 /*
63  * MPALMOSTSAFE - acquires mplock
64  */
65 int
66 soo_read(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
67 {
68         struct socket *so;
69         int error;
70
71         get_mplock();
72         so = (struct socket *)fp->f_data;
73         error = so_pru_soreceive(so, NULL, uio, NULL, NULL, NULL);
74         rel_mplock();
75         return (error);
76 }
77
78 /*
79  * MPALMOSTSAFE - acquires mplock
80  */
81 int
82 soo_write(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
83 {
84         struct socket *so;
85         int error;
86
87         get_mplock();
88         so = (struct socket *)fp->f_data;
89         error = so_pru_sosend(so, NULL, uio, NULL, NULL, 0, uio->uio_td);
90         rel_mplock();
91         return (error);
92 }
93
94 /*
95  * MPALMOSTSAFE - acquires mplock
96  */
97 int
98 soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct ucred *cred)
99 {
100         struct socket *so;
101         int error;
102
103         get_mplock();
104         so = (struct socket *)fp->f_data;
105
106         switch (cmd) {
107         case FIONBIO:
108                 if (*(int *)data)
109                         so->so_state |= SS_NBIO;
110                 else
111                         so->so_state &= ~SS_NBIO;
112                 error = 0;
113                 break;
114         case FIOASYNC:
115                 if (*(int *)data) {
116                         so->so_state |= SS_ASYNC;
117                         so->so_rcv.sb_flags |= SB_ASYNC;
118                         so->so_snd.sb_flags |= SB_ASYNC;
119                 } else {
120                         so->so_state &= ~SS_ASYNC;
121                         so->so_rcv.sb_flags &= ~SB_ASYNC;
122                         so->so_snd.sb_flags &= ~SB_ASYNC;
123                 }
124                 error = 0;
125                 break;
126         case FIONREAD:
127                 *(int *)data = so->so_rcv.sb_cc;
128                 error = 0;
129                 break;
130         case FIOSETOWN:
131                 error = fsetown(*(int *)data, &so->so_sigio);
132                 break;
133         case FIOGETOWN:
134                 *(int *)data = fgetown(so->so_sigio);
135                 error = 0;
136                 break;
137         case SIOCSPGRP:
138                 error = fsetown(-(*(int *)data), &so->so_sigio);
139                 break;
140         case SIOCGPGRP:
141                 *(int *)data = -fgetown(so->so_sigio);
142                 error = 0;
143                 break;
144         case SIOCATMARK:
145                 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
146                 error = 0;
147                 break;
148         default:
149                 /*
150                  * Interface/routing/protocol specific ioctls:
151                  * interface and routing ioctls should have a
152                  * different entry since a socket's unnecessary
153                  */
154                 if (IOCGROUP(cmd) == 'i')
155                         error = ifioctl(so, cmd, data, cred);
156                 else if (IOCGROUP(cmd) == 'r')
157                         error = rtioctl(cmd, data, cred);
158                 else
159                         error = so_pru_control(so, cmd, data, NULL);
160                 break;
161         }
162         rel_mplock();
163         return (error);
164 }
165
166 /*
167  * MPALMOSTSAFE - acquires mplock
168  */
169 int
170 soo_poll(struct file *fp, int events, struct ucred *cred)
171 {
172         struct socket *so;
173         int error;
174
175         get_mplock();
176         so = (struct socket *)fp->f_data;
177         error = so_pru_sopoll(so, events, cred);
178         rel_mplock();
179         return (error);
180 }
181
182 /*
183  * MPALMOSTSAFE - acquires mplock
184  */
185 int
186 soo_stat(struct file *fp, struct stat *ub, struct ucred *cred)
187 {
188         struct socket *so;
189         int error;
190
191         bzero((caddr_t)ub, sizeof (*ub));
192         ub->st_mode = S_IFSOCK;
193         get_mplock();
194         so = (struct socket *)fp->f_data;
195         /*
196          * If SS_CANTRCVMORE is set, but there's still data left in the
197          * receive buffer, the socket is still readable.
198          */
199         if ((so->so_state & SS_CANTRCVMORE) == 0 ||
200             so->so_rcv.sb_cc != 0)
201                 ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
202         if ((so->so_state & SS_CANTSENDMORE) == 0)
203                 ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
204         ub->st_size = so->so_rcv.sb_cc;
205         ub->st_uid = so->so_cred->cr_uid;
206         ub->st_gid = so->so_cred->cr_gid;
207         error = so_pru_sense(so, ub);
208         rel_mplock();
209         return (error);
210 }
211
212 /*
213  * MPALMOSTSAFE - acquires mplock
214  */
215 int
216 soo_close(struct file *fp)
217 {
218         int error;
219
220         get_mplock();
221         fp->f_ops = &badfileops;
222         if (fp->f_data)
223                 error = soclose((struct socket *)fp->f_data);
224         else
225                 error = 0;
226         fp->f_data = NULL;
227         rel_mplock();
228         return (error);
229 }
230
231 /*
232  * MPALMOSTSAFE - acquires mplock
233  */
234 int
235 soo_shutdown(struct file *fp, int how)
236 {
237         int error;
238
239         get_mplock();
240         if (fp->f_data)
241                 error = soshutdown((struct socket *)fp->f_data, how);
242         else
243                 error = 0;
244         rel_mplock();
245         return (error);
246 }
247