xref: /netbsd-src/sys/kern/sys_socket.c (revision 313c6c94c424eed90c7b7e494aa83308a0a5d0ce)
1 /*	$NetBSD: sys_socket.c,v 1.61 2009/04/08 21:02:09 ad Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1982, 1986, 1990, 1993
34  *	The Regents of the University of California.  All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)sys_socket.c	8.3 (Berkeley) 2/14/95
61  */
62 
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: sys_socket.c,v 1.61 2009/04/08 21:02:09 ad Exp $");
65 
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/systm.h>
69 #include <sys/file.h>
70 #include <sys/mbuf.h>
71 #include <sys/protosw.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
74 #include <sys/ioctl.h>
75 #include <sys/stat.h>
76 #include <sys/poll.h>
77 #include <sys/proc.h>
78 #include <sys/kauth.h>
79 
80 #include <net/if.h>
81 #include <net/route.h>
82 
83 const struct fileops socketops = {
84 	.fo_read = soo_read,
85 	.fo_write = soo_write,
86 	.fo_ioctl = soo_ioctl,
87 	.fo_fcntl = soo_fcntl,
88 	.fo_poll = soo_poll,
89 	.fo_stat = soo_stat,
90 	.fo_close = soo_close,
91 	.fo_kqfilter = soo_kqfilter,
92 	.fo_drain = fnullop_drain, 	/* soo_drain, */
93 };
94 
95 /* ARGSUSED */
96 int
97 soo_read(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
98 	 int flags)
99 {
100 	struct socket *so = fp->f_data;
101 	int error;
102 
103 	error = (*so->so_receive)(so, (struct mbuf **)0,
104 	    uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0);
105 
106 	return error;
107 }
108 
109 /* ARGSUSED */
110 int
111 soo_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
112 	  int flags)
113 {
114 	struct socket *so = fp->f_data;
115 	int error;
116 
117 	error = (*so->so_send)(so, (struct mbuf *)0,
118 		uio, (struct mbuf *)0, (struct mbuf *)0, 0, curlwp);
119 
120 	return error;
121 }
122 
123 int
124 soo_ioctl(file_t *fp, u_long cmd, void *data)
125 {
126 	struct socket *so = fp->f_data;
127 	int error = 0;
128 
129 	switch (cmd) {
130 
131 	case FIONBIO:
132 		/* No reason to lock and this call is made very often. */
133 		so->so_nbio = *(int *)data;
134 		break;
135 
136 	case FIOASYNC:
137 		solock(so);
138 		if (*(int *)data) {
139 			so->so_state |= SS_ASYNC;
140 			so->so_rcv.sb_flags |= SB_ASYNC;
141 			so->so_snd.sb_flags |= SB_ASYNC;
142 		} else {
143 			so->so_state &= ~SS_ASYNC;
144 			so->so_rcv.sb_flags &= ~SB_ASYNC;
145 			so->so_snd.sb_flags &= ~SB_ASYNC;
146 		}
147 		sounlock(so);
148 		break;
149 
150 	case FIONREAD:
151 		*(int *)data = so->so_rcv.sb_cc;
152 		break;
153 
154 	case FIONWRITE:
155 		*(int *)data = so->so_snd.sb_cc;
156 		break;
157 
158 	case FIONSPACE:
159 		/*
160 		 * See the comment around sbspace()'s definition
161 		 * in sys/socketvar.h in face of counts about maximum
162 		 * to understand the following test. We detect overflow
163 		 * and return zero.
164 		 */
165 		solock(so);
166 		if ((so->so_snd.sb_hiwat < so->so_snd.sb_cc)
167 		    || (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
168 			*(int *)data = 0;
169 		else
170 			*(int *)data = sbspace(&so->so_snd);
171 		sounlock(so);
172 		break;
173 
174 	case SIOCSPGRP:
175 	case FIOSETOWN:
176 	case TIOCSPGRP:
177 		error = fsetown(&so->so_pgid, cmd, data);
178 		break;
179 
180 	case SIOCGPGRP:
181 	case FIOGETOWN:
182 	case TIOCGPGRP:
183 		error = fgetown(so->so_pgid, cmd, data);
184 		break;
185 
186 	case SIOCATMARK:
187 		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
188 		break;
189 
190 	default:
191 		/*
192 		 * Interface/routing/protocol specific ioctls:
193 		 * interface and routing ioctls should have a
194 		 * different entry since a socket's unnecessary
195 		 */
196 		KERNEL_LOCK(1, NULL);
197 		if (IOCGROUP(cmd) == 'i')
198 			error = ifioctl(so, cmd, data, curlwp);
199 		else if (IOCGROUP(cmd) == 'r')
200 			error = rtioctl(cmd, data, curlwp);
201 		else {
202 			error = (*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
203 			    (struct mbuf *)cmd, (struct mbuf *)data, NULL,
204 			     curlwp);
205 		}
206 		KERNEL_UNLOCK_ONE(NULL);
207 		break;
208 	}
209 
210 
211 	return error;
212 }
213 
214 int
215 soo_fcntl(file_t *fp, u_int cmd, void *data)
216 {
217 
218 	if (cmd == F_SETFL)
219 		return 0;
220 	else
221 		return EOPNOTSUPP;
222 }
223 
224 int
225 soo_poll(file_t *fp, int events)
226 {
227 
228 	return sopoll(fp->f_data, events);
229 }
230 
231 int
232 soo_stat(file_t *fp, struct stat *ub)
233 {
234 	struct socket *so = fp->f_data;
235 	int error;
236 
237 	memset((void *)ub, 0, sizeof(*ub));
238 	ub->st_mode = S_IFSOCK;
239 
240 	solock(so);
241 	error = (*so->so_proto->pr_usrreq)(so, PRU_SENSE,
242 	    (struct mbuf *)ub, (struct mbuf *)0, (struct mbuf *)0,
243 	    curlwp);
244 	sounlock(so);
245 
246 	return error;
247 }
248 
249 /* ARGSUSED */
250 int
251 soo_close(file_t *fp)
252 {
253 	int error = 0;
254 
255 	if (fp->f_data)
256 		error = soclose(fp->f_data);
257 	fp->f_data = 0;
258 
259 	return error;
260 }
261 
262 void
263 soo_drain(file_t *fp)
264 {
265 
266 	(void)sodrain(fp->f_data);
267 }
268