sys_socket.c revision 110908
1214501Srpaulo/*
2214501Srpaulo * Copyright (c) 1982, 1986, 1990, 1993
3214501Srpaulo *	The Regents of the University of California.  All rights reserved.
4214501Srpaulo *
5214501Srpaulo * Redistribution and use in source and binary forms, with or without
6214501Srpaulo * modification, are permitted provided that the following conditions
7214501Srpaulo * are met:
8214501Srpaulo * 1. Redistributions of source code must retain the above copyright
9214501Srpaulo *    notice, this list of conditions and the following disclaimer.
10214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
11214501Srpaulo *    notice, this list of conditions and the following disclaimer in the
12214501Srpaulo *    documentation and/or other materials provided with the distribution.
13214501Srpaulo * 3. All advertising materials mentioning features or use of this software
14214501Srpaulo *    must display the following acknowledgement:
15214501Srpaulo *	This product includes software developed by the University of
16214501Srpaulo *	California, Berkeley and its contributors.
17214501Srpaulo * 4. Neither the name of the University nor the names of its contributors
18214501Srpaulo *    may be used to endorse or promote products derived from this software
19214501Srpaulo *    without specific prior written permission.
20214501Srpaulo *
21214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22214501Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24214501Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25214501Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26214501Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27214501Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29214501Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30214501Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31214501Srpaulo * SUCH DAMAGE.
32214501Srpaulo *
33214501Srpaulo *	@(#)sys_socket.c	8.1 (Berkeley) 6/10/93
34214501Srpaulo * $FreeBSD: head/sys/kern/sys_socket.c 110908 2003-02-15 06:04:55Z alfred $
35214501Srpaulo */
36214501Srpaulo
37214501Srpaulo#include "opt_mac.h"
38214501Srpaulo
39214501Srpaulo#include <sys/param.h>
40214501Srpaulo#include <sys/systm.h>
41214501Srpaulo#include <sys/file.h>
42214501Srpaulo#include <sys/filedesc.h>
43214501Srpaulo#include <sys/mac.h>
44214501Srpaulo#include <sys/protosw.h>
45214501Srpaulo#include <sys/sigio.h>
46214501Srpaulo#include <sys/socket.h>
47214501Srpaulo#include <sys/socketvar.h>
48214501Srpaulo#include <sys/filio.h>			/* XXX */
49214501Srpaulo#include <sys/sockio.h>
50214501Srpaulo#include <sys/stat.h>
51214501Srpaulo#include <sys/uio.h>
52214501Srpaulo#include <sys/filedesc.h>
53214501Srpaulo#include <sys/ucred.h>
54214501Srpaulo
55214501Srpaulo#include <net/if.h>
56214501Srpaulo#include <net/route.h>
57214501Srpaulo
58214501Srpaulostruct	fileops socketops = {
59214501Srpaulo	soo_read, soo_write, soo_ioctl, soo_poll, soo_kqfilter,
60214501Srpaulo	soo_stat, soo_close, DFLAG_PASSABLE
61214501Srpaulo};
62214501Srpaulo
63214501Srpaulo/* ARGSUSED */
64214501Srpauloint
65214501Srpaulosoo_read(fp, uio, active_cred, flags, td)
66214501Srpaulo	struct file *fp;
67214501Srpaulo	struct uio *uio;
68214501Srpaulo	struct ucred *active_cred;
69214501Srpaulo	struct thread *td;
70214501Srpaulo	int flags;
71214501Srpaulo{
72214501Srpaulo	struct socket *so = fp->f_data;
73214501Srpaulo	int error;
74214501Srpaulo
75214501Srpaulo	mtx_lock(&Giant);
76214501Srpaulo#ifdef MAC
77214501Srpaulo	error = mac_check_socket_receive(active_cred, so);
78214501Srpaulo	if (error) {
79214501Srpaulo		mtx_unlock(&Giant);
80214501Srpaulo		return (error);
81214501Srpaulo	}
82214501Srpaulo#endif
83214501Srpaulo	error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0);
84214501Srpaulo	mtx_unlock(&Giant);
85214501Srpaulo	return (error);
86214501Srpaulo}
87214501Srpaulo
88214501Srpaulo/* ARGSUSED */
89214501Srpauloint
90214501Srpaulosoo_write(fp, uio, active_cred, flags, td)
91214501Srpaulo	struct file *fp;
92214501Srpaulo	struct uio *uio;
93214501Srpaulo	struct ucred *active_cred;
94214501Srpaulo	struct thread *td;
95214501Srpaulo	int flags;
96214501Srpaulo{
97214501Srpaulo	struct socket *so = fp->f_data;
98214501Srpaulo	int error;
99214501Srpaulo
100214501Srpaulo	mtx_lock(&Giant);
101214501Srpaulo#ifdef MAC
102214501Srpaulo	error = mac_check_socket_send(active_cred, so);
103214501Srpaulo	if (error) {
104214501Srpaulo		mtx_unlock(&Giant);
105214501Srpaulo		return (error);
106214501Srpaulo	}
107214501Srpaulo#endif
108214501Srpaulo	error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0,
109214501Srpaulo						    uio->uio_td);
110214501Srpaulo	mtx_unlock(&Giant);
111214501Srpaulo	return (error);
112214501Srpaulo}
113214501Srpaulo
114214501Srpauloint
115214501Srpaulosoo_ioctl(fp, cmd, data, active_cred, td)
116214501Srpaulo	struct file *fp;
117214501Srpaulo	u_long cmd;
118214501Srpaulo	void *data;
119214501Srpaulo	struct ucred *active_cred;
120214501Srpaulo	struct thread *td;
121214501Srpaulo{
122214501Srpaulo	register struct socket *so = fp->f_data;
123214501Srpaulo
124214501Srpaulo	switch (cmd) {
125214501Srpaulo
126214501Srpaulo	case FIONBIO:
127214501Srpaulo		if (*(int *)data)
128214501Srpaulo			so->so_state |= SS_NBIO;
129214501Srpaulo		else
130214501Srpaulo			so->so_state &= ~SS_NBIO;
131214501Srpaulo		return (0);
132214501Srpaulo
133214501Srpaulo	case FIOASYNC:
134214501Srpaulo		if (*(int *)data) {
135214501Srpaulo			so->so_state |= SS_ASYNC;
136214501Srpaulo			so->so_rcv.sb_flags |= SB_ASYNC;
137214501Srpaulo			so->so_snd.sb_flags |= SB_ASYNC;
138214501Srpaulo		} else {
139214501Srpaulo			so->so_state &= ~SS_ASYNC;
140214501Srpaulo			so->so_rcv.sb_flags &= ~SB_ASYNC;
141214501Srpaulo			so->so_snd.sb_flags &= ~SB_ASYNC;
142214501Srpaulo		}
143214501Srpaulo		return (0);
144214501Srpaulo
145214501Srpaulo	case FIONREAD:
146214501Srpaulo		*(int *)data = so->so_rcv.sb_cc;
147214501Srpaulo		return (0);
148214501Srpaulo
149214501Srpaulo	case FIOSETOWN:
150214501Srpaulo		return (fsetown(*(int *)data, &so->so_sigio));
151214501Srpaulo
152214501Srpaulo	case FIOGETOWN:
153214501Srpaulo		*(int *)data = fgetown(&so->so_sigio);
154214501Srpaulo		return (0);
155214501Srpaulo
156214501Srpaulo	case SIOCSPGRP:
157214501Srpaulo		return (fsetown(-(*(int *)data), &so->so_sigio));
158214501Srpaulo
159214501Srpaulo	case SIOCGPGRP:
160214501Srpaulo		*(int *)data = -fgetown(&so->so_sigio);
161214501Srpaulo		return (0);
162214501Srpaulo
163214501Srpaulo	case SIOCATMARK:
164214501Srpaulo		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
165214501Srpaulo		return (0);
166214501Srpaulo	}
167214501Srpaulo	/*
168214501Srpaulo	 * Interface/routing/protocol specific ioctls:
169214501Srpaulo	 * interface and routing ioctls should have a
170214501Srpaulo	 * different entry since a socket's unnecessary
171214501Srpaulo	 */
172214501Srpaulo	if (IOCGROUP(cmd) == 'i')
173214501Srpaulo		return (ifioctl(so, cmd, data, td));
174214501Srpaulo	if (IOCGROUP(cmd) == 'r')
175214501Srpaulo		return (rtioctl(cmd, data));
176214501Srpaulo	return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, td));
177214501Srpaulo}
178214501Srpaulo
179214501Srpauloint
180214501Srpaulosoo_poll(fp, events, active_cred, td)
181214501Srpaulo	struct file *fp;
182214501Srpaulo	int events;
183214501Srpaulo	struct ucred *active_cred;
184214501Srpaulo	struct thread *td;
185214501Srpaulo{
186214501Srpaulo	struct socket *so = fp->f_data;
187214501Srpaulo	return so->so_proto->pr_usrreqs->pru_sopoll(so, events,
188214501Srpaulo	    fp->f_cred, td);
189214501Srpaulo}
190214501Srpaulo
191214501Srpauloint
192214501Srpaulosoo_stat(fp, ub, active_cred, td)
193214501Srpaulo	struct file *fp;
194214501Srpaulo	struct stat *ub;
195214501Srpaulo	struct ucred *active_cred;
196214501Srpaulo	struct thread *td;
197214501Srpaulo{
198214501Srpaulo	struct socket *so = fp->f_data;
199214501Srpaulo
200214501Srpaulo	bzero((caddr_t)ub, sizeof (*ub));
201214501Srpaulo	ub->st_mode = S_IFSOCK;
202214501Srpaulo	/*
203214501Srpaulo	 * If SS_CANTRCVMORE is set, but there's still data left in the
204214501Srpaulo	 * receive buffer, the socket is still readable.
205214501Srpaulo	 */
206214501Srpaulo	if ((so->so_state & SS_CANTRCVMORE) == 0 ||
207214501Srpaulo	    so->so_rcv.sb_cc != 0)
208214501Srpaulo		ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
209214501Srpaulo	if ((so->so_state & SS_CANTSENDMORE) == 0)
210214501Srpaulo		ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
211214501Srpaulo	ub->st_size = so->so_rcv.sb_cc - so->so_rcv.sb_ctl;
212214501Srpaulo	ub->st_uid = so->so_cred->cr_uid;
213214501Srpaulo	ub->st_gid = so->so_cred->cr_gid;
214214501Srpaulo	return ((*so->so_proto->pr_usrreqs->pru_sense)(so, ub));
215214501Srpaulo}
216214501Srpaulo
217214501Srpaulo/*
218214501Srpaulo * API socket close on file pointer.  We call soclose() to close the
219214501Srpaulo * socket (including initiating closing protocols).  soclose() will
220214501Srpaulo * sorele() the file reference but the actual socket will not go away
221214501Srpaulo * until the socket's ref count hits 0.
222214501Srpaulo */
223214501Srpaulo/* ARGSUSED */
224214501Srpauloint
225214501Srpaulosoo_close(fp, td)
226214501Srpaulo	struct file *fp;
227214501Srpaulo	struct thread *td;
228214501Srpaulo{
229214501Srpaulo	int error = 0;
230214501Srpaulo	struct socket *so;
231214501Srpaulo
232214501Srpaulo	so = fp->f_data;
233214501Srpaulo	fp->f_ops = &badfileops;
234214501Srpaulo	fp->f_data = NULL;
235
236	if (so)
237		error = soclose(so);
238	return (error);
239}
240