Line data Source code
1 : /* $OpenBSD: sys_socket.c,v 1.41 2018/08/20 16:00:22 mpi Exp $ */
2 : /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1982, 1986, 1990, 1993
6 : * The Regents of the University of California. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Neither the name of the University nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 : * SUCH DAMAGE.
31 : *
32 : * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
33 : */
34 :
35 : #include <sys/param.h>
36 : #include <sys/systm.h>
37 : #include <sys/file.h>
38 : #include <sys/proc.h>
39 : #include <sys/mbuf.h>
40 : #include <sys/protosw.h>
41 : #include <sys/socket.h>
42 : #include <sys/socketvar.h>
43 : #include <sys/ioctl.h>
44 : #include <sys/poll.h>
45 : #include <sys/stat.h>
46 : #include <sys/fcntl.h>
47 :
48 : #include <net/if.h>
49 : #include <net/route.h>
50 :
51 : struct fileops socketops = {
52 : .fo_read = soo_read,
53 : .fo_write = soo_write,
54 : .fo_ioctl = soo_ioctl,
55 : .fo_poll = soo_poll,
56 : .fo_kqfilter = soo_kqfilter,
57 : .fo_stat = soo_stat,
58 : .fo_close = soo_close
59 : };
60 :
61 : int
62 0 : soo_read(struct file *fp, struct uio *uio, int fflags)
63 : {
64 0 : struct socket *so = (struct socket *)fp->f_data;
65 0 : int flags = 0;
66 :
67 0 : if (fp->f_flag & FNONBLOCK)
68 0 : flags |= MSG_DONTWAIT;
69 :
70 0 : return (soreceive(so, NULL, uio, NULL, NULL, &flags, 0));
71 0 : }
72 :
73 : int
74 0 : soo_write(struct file *fp, struct uio *uio, int fflags)
75 : {
76 0 : struct socket *so = (struct socket *)fp->f_data;
77 : int flags = 0;
78 :
79 0 : if (fp->f_flag & FNONBLOCK)
80 0 : flags |= MSG_DONTWAIT;
81 :
82 0 : return (sosend(so, NULL, uio, NULL, NULL, flags));
83 : }
84 :
85 : int
86 0 : soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
87 : {
88 0 : struct socket *so = (struct socket *)fp->f_data;
89 : int s, error = 0;
90 :
91 0 : switch (cmd) {
92 :
93 : case FIONBIO:
94 : break;
95 :
96 : case FIOASYNC:
97 0 : s = solock(so);
98 0 : if (*(int *)data) {
99 0 : so->so_state |= SS_ASYNC;
100 0 : so->so_rcv.sb_flags |= SB_ASYNC;
101 0 : so->so_snd.sb_flags |= SB_ASYNC;
102 0 : } else {
103 0 : so->so_state &= ~SS_ASYNC;
104 0 : so->so_rcv.sb_flags &= ~SB_ASYNC;
105 0 : so->so_snd.sb_flags &= ~SB_ASYNC;
106 : }
107 0 : sounlock(so, s);
108 0 : break;
109 :
110 : case FIONREAD:
111 0 : *(int *)data = so->so_rcv.sb_datacc;
112 0 : break;
113 :
114 : case TIOCSPGRP:
115 : /* FALLTHROUGH */
116 : case SIOCSPGRP:
117 0 : so->so_pgid = *(int *)data;
118 0 : so->so_siguid = p->p_ucred->cr_ruid;
119 0 : so->so_sigeuid = p->p_ucred->cr_uid;
120 0 : break;
121 :
122 : case TIOCGPGRP:
123 0 : *(int *)data = -so->so_pgid;
124 0 : break;
125 :
126 : case SIOCGPGRP:
127 0 : *(int *)data = so->so_pgid;
128 0 : break;
129 :
130 : case SIOCATMARK:
131 0 : *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
132 0 : break;
133 :
134 : default:
135 : /*
136 : * Interface/routing/protocol specific ioctls:
137 : * interface and routing ioctls should have a
138 : * different entry since a socket's unnecessary
139 : */
140 0 : if (IOCGROUP(cmd) == 'i') {
141 0 : error = ifioctl(so, cmd, data, p);
142 0 : return (error);
143 : }
144 0 : if (IOCGROUP(cmd) == 'r')
145 0 : return (EOPNOTSUPP);
146 0 : error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
147 0 : (struct mbuf *)cmd, (struct mbuf *)data, NULL, p));
148 0 : break;
149 : }
150 :
151 0 : return (error);
152 0 : }
153 :
154 : int
155 0 : soo_poll(struct file *fp, int events, struct proc *p)
156 : {
157 0 : struct socket *so = fp->f_data;
158 : int revents = 0;
159 : int s;
160 :
161 0 : s = solock(so);
162 0 : if (events & (POLLIN | POLLRDNORM)) {
163 0 : if (soreadable(so))
164 0 : revents |= events & (POLLIN | POLLRDNORM);
165 : }
166 : /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
167 0 : if (so->so_state & SS_ISDISCONNECTED) {
168 0 : revents |= POLLHUP;
169 0 : } else if (events & (POLLOUT | POLLWRNORM)) {
170 0 : if (sowriteable(so))
171 0 : revents |= events & (POLLOUT | POLLWRNORM);
172 : }
173 0 : if (events & (POLLPRI | POLLRDBAND)) {
174 0 : if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
175 0 : revents |= events & (POLLPRI | POLLRDBAND);
176 : }
177 0 : if (revents == 0) {
178 0 : if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
179 0 : selrecord(p, &so->so_rcv.sb_sel);
180 0 : so->so_rcv.sb_flags |= SB_SEL;
181 0 : }
182 0 : if (events & (POLLOUT | POLLWRNORM)) {
183 0 : selrecord(p, &so->so_snd.sb_sel);
184 0 : so->so_snd.sb_flags |= SB_SEL;
185 0 : }
186 : }
187 0 : sounlock(so, s);
188 0 : return (revents);
189 : }
190 :
191 : int
192 0 : soo_stat(struct file *fp, struct stat *ub, struct proc *p)
193 : {
194 0 : struct socket *so = fp->f_data;
195 : int s;
196 :
197 0 : memset(ub, 0, sizeof (*ub));
198 0 : ub->st_mode = S_IFSOCK;
199 0 : s = solock(so);
200 0 : if ((so->so_state & SS_CANTRCVMORE) == 0 || so->so_rcv.sb_cc != 0)
201 0 : ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
202 0 : if ((so->so_state & SS_CANTSENDMORE) == 0)
203 0 : ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
204 0 : ub->st_uid = so->so_euid;
205 0 : ub->st_gid = so->so_egid;
206 0 : (void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
207 0 : (struct mbuf *)ub, NULL, NULL, p));
208 0 : sounlock(so, s);
209 0 : return (0);
210 : }
211 :
212 : int
213 0 : soo_close(struct file *fp, struct proc *p)
214 : {
215 : int flags, error = 0;
216 :
217 0 : if (fp->f_data) {
218 0 : flags = (fp->f_flag & FNONBLOCK) ? MSG_DONTWAIT : 0;
219 0 : error = soclose(fp->f_data, flags);
220 0 : }
221 0 : fp->f_data = 0;
222 0 : return (error);
223 : }
|