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