sys_socket.c revision 193332
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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: head/sys/kern/sys_socket.c 193332 2009-06-02 18:26:17Z rwatson $"); 34 35#include "opt_mac.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/file.h> 40#include <sys/filedesc.h> 41#include <sys/proc.h> 42#include <sys/protosw.h> 43#include <sys/sigio.h> 44#include <sys/signal.h> 45#include <sys/signalvar.h> 46#include <sys/socket.h> 47#include <sys/socketvar.h> 48#include <sys/filio.h> /* XXX */ 49#include <sys/sockio.h> 50#include <sys/stat.h> 51#include <sys/uio.h> 52#include <sys/ucred.h> 53#include <sys/vimage.h> 54 55#include <net/if.h> 56#include <net/route.h> 57 58#include <security/mac/mac_framework.h> 59 60struct fileops socketops = { 61 .fo_read = soo_read, 62 .fo_write = soo_write, 63 .fo_truncate = soo_truncate, 64 .fo_ioctl = soo_ioctl, 65 .fo_poll = soo_poll, 66 .fo_kqfilter = soo_kqfilter, 67 .fo_stat = soo_stat, 68 .fo_close = soo_close, 69 .fo_flags = DFLAG_PASSABLE 70}; 71 72/* ARGSUSED */ 73int 74soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred, 75 int flags, struct thread *td) 76{ 77 struct socket *so = fp->f_data; 78 int error; 79 80#ifdef MAC 81 error = mac_socket_check_receive(active_cred, so); 82 if (error) 83 return (error); 84#endif 85 CURVNET_SET(so->so_vnet); 86 error = soreceive(so, 0, uio, 0, 0, 0); 87 CURVNET_RESTORE(); 88 return (error); 89} 90 91/* ARGSUSED */ 92int 93soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred, 94 int flags, struct thread *td) 95{ 96 struct socket *so = fp->f_data; 97 int error; 98 99#ifdef MAC 100 error = mac_socket_check_send(active_cred, so); 101 if (error) 102 return (error); 103#endif 104 error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td); 105 if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) { 106 PROC_LOCK(uio->uio_td->td_proc); 107 psignal(uio->uio_td->td_proc, SIGPIPE); 108 PROC_UNLOCK(uio->uio_td->td_proc); 109 } 110 return (error); 111} 112 113int 114soo_truncate(struct file *fp, off_t length, struct ucred *active_cred, 115 struct thread *td) 116{ 117 118 return (EINVAL); 119} 120 121int 122soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred, 123 struct thread *td) 124{ 125 struct socket *so = fp->f_data; 126 int error = 0; 127 128 CURVNET_SET(so->so_vnet); 129 switch (cmd) { 130 case FIONBIO: 131 SOCK_LOCK(so); 132 if (*(int *)data) 133 so->so_state |= SS_NBIO; 134 else 135 so->so_state &= ~SS_NBIO; 136 SOCK_UNLOCK(so); 137 break; 138 139 case FIOASYNC: 140 /* 141 * XXXRW: This code separately acquires SOCK_LOCK(so) and 142 * SOCKBUF_LOCK(&so->so_rcv) even though they are the same 143 * mutex to avoid introducing the assumption that they are 144 * the same. 145 */ 146 if (*(int *)data) { 147 SOCK_LOCK(so); 148 so->so_state |= SS_ASYNC; 149 SOCK_UNLOCK(so); 150 SOCKBUF_LOCK(&so->so_rcv); 151 so->so_rcv.sb_flags |= SB_ASYNC; 152 SOCKBUF_UNLOCK(&so->so_rcv); 153 SOCKBUF_LOCK(&so->so_snd); 154 so->so_snd.sb_flags |= SB_ASYNC; 155 SOCKBUF_UNLOCK(&so->so_snd); 156 } else { 157 SOCK_LOCK(so); 158 so->so_state &= ~SS_ASYNC; 159 SOCK_UNLOCK(so); 160 SOCKBUF_LOCK(&so->so_rcv); 161 so->so_rcv.sb_flags &= ~SB_ASYNC; 162 SOCKBUF_UNLOCK(&so->so_rcv); 163 SOCKBUF_LOCK(&so->so_snd); 164 so->so_snd.sb_flags &= ~SB_ASYNC; 165 SOCKBUF_UNLOCK(&so->so_snd); 166 } 167 break; 168 169 case FIONREAD: 170 /* Unlocked read. */ 171 *(int *)data = so->so_rcv.sb_cc; 172 break; 173 174 case FIOSETOWN: 175 error = fsetown(*(int *)data, &so->so_sigio); 176 break; 177 178 case FIOGETOWN: 179 *(int *)data = fgetown(&so->so_sigio); 180 break; 181 182 case SIOCSPGRP: 183 error = fsetown(-(*(int *)data), &so->so_sigio); 184 break; 185 186 case SIOCGPGRP: 187 *(int *)data = -fgetown(&so->so_sigio); 188 break; 189 190 case SIOCATMARK: 191 /* Unlocked read. */ 192 *(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0; 193 break; 194 default: 195 /* 196 * Interface/routing/protocol specific ioctls: interface and 197 * routing ioctls should have a different entry since a 198 * socket is unnecessary. 199 */ 200 if (IOCGROUP(cmd) == 'i') 201 error = ifioctl(so, cmd, data, td); 202 else if (IOCGROUP(cmd) == 'r') 203 error = rtioctl_fib(cmd, data, so->so_fibnum); 204 else 205 error = ((*so->so_proto->pr_usrreqs->pru_control) 206 (so, cmd, data, 0, td)); 207 break; 208 } 209 CURVNET_RESTORE(); 210 return (error); 211} 212 213int 214soo_poll(struct file *fp, int events, struct ucred *active_cred, 215 struct thread *td) 216{ 217 struct socket *so = fp->f_data; 218#ifdef MAC 219 int error; 220 221 error = mac_socket_check_poll(active_cred, so); 222 if (error) 223 return (error); 224#endif 225 return (sopoll(so, events, fp->f_cred, td)); 226} 227 228int 229soo_stat(struct file *fp, struct stat *ub, struct ucred *active_cred, 230 struct thread *td) 231{ 232 struct socket *so = fp->f_data; 233#ifdef MAC 234 int error; 235#endif 236 237 bzero((caddr_t)ub, sizeof (*ub)); 238 ub->st_mode = S_IFSOCK; 239#ifdef MAC 240 error = mac_socket_check_stat(active_cred, so); 241 if (error) 242 return (error); 243#endif 244 /* 245 * If SBS_CANTRCVMORE is set, but there's still data left in the 246 * receive buffer, the socket is still readable. 247 */ 248 SOCKBUF_LOCK(&so->so_rcv); 249 if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0 || 250 so->so_rcv.sb_cc != 0) 251 ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH; 252 ub->st_size = so->so_rcv.sb_cc - so->so_rcv.sb_ctl; 253 SOCKBUF_UNLOCK(&so->so_rcv); 254 /* Unlocked read. */ 255 if ((so->so_snd.sb_state & SBS_CANTSENDMORE) == 0) 256 ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; 257 ub->st_uid = so->so_cred->cr_uid; 258 ub->st_gid = so->so_cred->cr_gid; 259 return (*so->so_proto->pr_usrreqs->pru_sense)(so, ub); 260} 261 262/* 263 * API socket close on file pointer. We call soclose() to close the socket 264 * (including initiating closing protocols). soclose() will sorele() the 265 * file reference but the actual socket will not go away until the socket's 266 * ref count hits 0. 267 */ 268/* ARGSUSED */ 269int 270soo_close(struct file *fp, struct thread *td) 271{ 272 int error = 0; 273 struct socket *so; 274 275 so = fp->f_data; 276 fp->f_ops = &badfileops; 277 fp->f_data = NULL; 278 279 if (so) 280 error = soclose(so); 281 return (error); 282} 283