Fri Mar 6 03:35:00 2015 UTC ()
Return EINVAL if namelen isn't large enough to encompass the expected
members of sockaddr structures. i.e. sa_len and sa_family.

Discussed with and patch by christos@


(rtr)
diff -r1.173 -r1.174 src/sys/kern/uipc_syscalls.c

cvs diff -r1.173 -r1.174 src/sys/kern/uipc_syscalls.c (switch to unified diff)

--- src/sys/kern/uipc_syscalls.c 2014/09/05 09:20:59 1.173
+++ src/sys/kern/uipc_syscalls.c 2015/03/06 03:35:00 1.174
@@ -1,1497 +1,1503 @@ @@ -1,1497 +1,1503 @@
1/* $NetBSD: uipc_syscalls.c,v 1.173 2014/09/05 09:20:59 matt Exp $ */ 1/* $NetBSD: uipc_syscalls.c,v 1.174 2015/03/06 03:35:00 rtr Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1982, 1986, 1989, 1990, 1993 33 * Copyright (c) 1982, 1986, 1989, 1990, 1993
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors 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 45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission. 46 * without specific prior written permission.
47 * 47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95 60 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.173 2014/09/05 09:20:59 matt Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.174 2015/03/06 03:35:00 rtr Exp $");
65 65
66#include "opt_pipe.h" 66#include "opt_pipe.h"
67 67
68#include <sys/param.h> 68#include <sys/param.h>
69#include <sys/systm.h> 69#include <sys/systm.h>
70#include <sys/filedesc.h> 70#include <sys/filedesc.h>
71#include <sys/proc.h> 71#include <sys/proc.h>
72#include <sys/file.h> 72#include <sys/file.h>
73#include <sys/buf.h> 73#include <sys/buf.h>
74#define MBUFTYPES 74#define MBUFTYPES
75#include <sys/mbuf.h> 75#include <sys/mbuf.h>
76#include <sys/protosw.h> 76#include <sys/protosw.h>
77#include <sys/socket.h> 77#include <sys/socket.h>
78#include <sys/socketvar.h> 78#include <sys/socketvar.h>
79#include <sys/signalvar.h> 79#include <sys/signalvar.h>
80#include <sys/un.h> 80#include <sys/un.h>
81#include <sys/ktrace.h> 81#include <sys/ktrace.h>
82#include <sys/event.h> 82#include <sys/event.h>
83#include <sys/atomic.h> 83#include <sys/atomic.h>
84#include <sys/kauth.h> 84#include <sys/kauth.h>
85 85
86#include <sys/mount.h> 86#include <sys/mount.h>
87#include <sys/syscallargs.h> 87#include <sys/syscallargs.h>
88 88
89/* 89/*
90 * System call interface to the socket abstraction. 90 * System call interface to the socket abstraction.
91 */ 91 */
92extern const struct fileops socketops; 92extern const struct fileops socketops;
93 93
94int 94int
95sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, 95sys___socket30(struct lwp *l, const struct sys___socket30_args *uap,
96 register_t *retval) 96 register_t *retval)
97{ 97{
98 /* { 98 /* {
99 syscallarg(int) domain; 99 syscallarg(int) domain;
100 syscallarg(int) type; 100 syscallarg(int) type;
101 syscallarg(int) protocol; 101 syscallarg(int) protocol;
102 } */ 102 } */
103 int fd, error; 103 int fd, error;
104 104
105 error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type), 105 error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
106 SCARG(uap, protocol), &fd); 106 SCARG(uap, protocol), &fd);
107 if (error == 0) { 107 if (error == 0) {
108 *retval = fd; 108 *retval = fd;
109 } 109 }
110 return error; 110 return error;
111} 111}
112 112
113int 113int
114sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval) 114sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval)
115{ 115{
116 /* { 116 /* {
117 syscallarg(int) s; 117 syscallarg(int) s;
118 syscallarg(const struct sockaddr *) name; 118 syscallarg(const struct sockaddr *) name;
119 syscallarg(unsigned int) namelen; 119 syscallarg(unsigned int) namelen;
120 } */ 120 } */
121 struct mbuf *nam; 121 struct mbuf *nam;
122 int error; 122 int error;
123 123
124 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 124 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
125 MT_SONAME); 125 MT_SONAME);
126 if (error) 126 if (error)
127 return error; 127 return error;
128 128
129 return do_sys_bind(l, SCARG(uap, s), nam); 129 return do_sys_bind(l, SCARG(uap, s), nam);
130} 130}
131 131
132int 132int
133do_sys_bind(struct lwp *l, int fd, struct mbuf *nam) 133do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
134{ 134{
135 struct socket *so; 135 struct socket *so;
136 int error; 136 int error;
137 137
138 if ((error = fd_getsock(fd, &so)) != 0) { 138 if ((error = fd_getsock(fd, &so)) != 0) {
139 m_freem(nam); 139 m_freem(nam);
140 return (error); 140 return (error);
141 } 141 }
142 MCLAIM(nam, so->so_mowner); 142 MCLAIM(nam, so->so_mowner);
143 error = sobind(so, nam, l); 143 error = sobind(so, nam, l);
144 m_freem(nam); 144 m_freem(nam);
145 fd_putfile(fd); 145 fd_putfile(fd);
146 return error; 146 return error;
147} 147}
148 148
149int 149int
150sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval) 150sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
151{ 151{
152 /* { 152 /* {
153 syscallarg(int) s; 153 syscallarg(int) s;
154 syscallarg(int) backlog; 154 syscallarg(int) backlog;
155 } */ 155 } */
156 struct socket *so; 156 struct socket *so;
157 int error; 157 int error;
158 158
159 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) 159 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
160 return (error); 160 return (error);
161 error = solisten(so, SCARG(uap, backlog), l); 161 error = solisten(so, SCARG(uap, backlog), l);
162 fd_putfile(SCARG(uap, s)); 162 fd_putfile(SCARG(uap, s));
163 return error; 163 return error;
164} 164}
165 165
166int 166int
167do_sys_accept(struct lwp *l, int sock, struct mbuf **name, 167do_sys_accept(struct lwp *l, int sock, struct mbuf **name,
168 register_t *new_sock, const sigset_t *mask, int flags, int clrflags) 168 register_t *new_sock, const sigset_t *mask, int flags, int clrflags)
169{ 169{
170 file_t *fp, *fp2; 170 file_t *fp, *fp2;
171 struct mbuf *nam; 171 struct mbuf *nam;
172 int error, fd; 172 int error, fd;
173 struct socket *so, *so2; 173 struct socket *so, *so2;
174 short wakeup_state = 0; 174 short wakeup_state = 0;
175 175
176 if ((fp = fd_getfile(sock)) == NULL) 176 if ((fp = fd_getfile(sock)) == NULL)
177 return EBADF; 177 return EBADF;
178 if (fp->f_type != DTYPE_SOCKET) { 178 if (fp->f_type != DTYPE_SOCKET) {
179 fd_putfile(sock); 179 fd_putfile(sock);
180 return ENOTSOCK; 180 return ENOTSOCK;
181 } 181 }
182 if ((error = fd_allocfile(&fp2, &fd)) != 0) { 182 if ((error = fd_allocfile(&fp2, &fd)) != 0) {
183 fd_putfile(sock); 183 fd_putfile(sock);
184 return error; 184 return error;
185 } 185 }
186 nam = m_get(M_WAIT, MT_SONAME); 186 nam = m_get(M_WAIT, MT_SONAME);
187 *new_sock = fd; 187 *new_sock = fd;
188 so = fp->f_socket; 188 so = fp->f_socket;
189 solock(so); 189 solock(so);
190 190
191 if (__predict_false(mask)) 191 if (__predict_false(mask))
192 sigsuspendsetup(l, mask); 192 sigsuspendsetup(l, mask);
193 193
194 if (!(so->so_proto->pr_flags & PR_LISTEN)) { 194 if (!(so->so_proto->pr_flags & PR_LISTEN)) {
195 error = EOPNOTSUPP; 195 error = EOPNOTSUPP;
196 goto bad; 196 goto bad;
197 } 197 }
198 if ((so->so_options & SO_ACCEPTCONN) == 0) { 198 if ((so->so_options & SO_ACCEPTCONN) == 0) {
199 error = EINVAL; 199 error = EINVAL;
200 goto bad; 200 goto bad;
201 } 201 }
202 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 202 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
203 error = EWOULDBLOCK; 203 error = EWOULDBLOCK;
204 goto bad; 204 goto bad;
205 } 205 }
206 while (so->so_qlen == 0 && so->so_error == 0) { 206 while (so->so_qlen == 0 && so->so_error == 0) {
207 if (so->so_state & SS_CANTRCVMORE) { 207 if (so->so_state & SS_CANTRCVMORE) {
208 so->so_error = ECONNABORTED; 208 so->so_error = ECONNABORTED;
209 break; 209 break;
210 } 210 }
211 if (wakeup_state & SS_RESTARTSYS) { 211 if (wakeup_state & SS_RESTARTSYS) {
212 error = ERESTART; 212 error = ERESTART;
213 goto bad; 213 goto bad;
214 } 214 }
215 error = sowait(so, true, 0); 215 error = sowait(so, true, 0);
216 if (error) { 216 if (error) {
217 goto bad; 217 goto bad;
218 } 218 }
219 wakeup_state = so->so_state; 219 wakeup_state = so->so_state;
220 } 220 }
221 if (so->so_error) { 221 if (so->so_error) {
222 error = so->so_error; 222 error = so->so_error;
223 so->so_error = 0; 223 so->so_error = 0;
224 goto bad; 224 goto bad;
225 } 225 }
226 /* connection has been removed from the listen queue */ 226 /* connection has been removed from the listen queue */
227 KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT); 227 KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
228 so2 = TAILQ_FIRST(&so->so_q); 228 so2 = TAILQ_FIRST(&so->so_q);
229 if (soqremque(so2, 1) == 0) 229 if (soqremque(so2, 1) == 0)
230 panic("accept"); 230 panic("accept");
231 fp2->f_type = DTYPE_SOCKET; 231 fp2->f_type = DTYPE_SOCKET;
232 fp2->f_flag = (fp->f_flag & ~clrflags) | 232 fp2->f_flag = (fp->f_flag & ~clrflags) |
233 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)| 233 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
234 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0); 234 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
235 fp2->f_ops = &socketops; 235 fp2->f_ops = &socketops;
236 fp2->f_socket = so2; 236 fp2->f_socket = so2;
237 if (fp2->f_flag & FNONBLOCK) 237 if (fp2->f_flag & FNONBLOCK)
238 so2->so_state |= SS_NBIO; 238 so2->so_state |= SS_NBIO;
239 else 239 else
240 so2->so_state &= ~SS_NBIO; 240 so2->so_state &= ~SS_NBIO;
241 error = soaccept(so2, nam); 241 error = soaccept(so2, nam);
242 so2->so_cred = kauth_cred_dup(so->so_cred); 242 so2->so_cred = kauth_cred_dup(so->so_cred);
243 sounlock(so); 243 sounlock(so);
244 if (error) { 244 if (error) {
245 /* an error occurred, free the file descriptor and mbuf */ 245 /* an error occurred, free the file descriptor and mbuf */
246 m_freem(nam); 246 m_freem(nam);
247 mutex_enter(&fp2->f_lock); 247 mutex_enter(&fp2->f_lock);
248 fp2->f_count++; 248 fp2->f_count++;
249 mutex_exit(&fp2->f_lock); 249 mutex_exit(&fp2->f_lock);
250 closef(fp2); 250 closef(fp2);
251 fd_abort(curproc, NULL, fd); 251 fd_abort(curproc, NULL, fd);
252 } else { 252 } else {
253 fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0); 253 fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
254 fd_affix(curproc, fp2, fd); 254 fd_affix(curproc, fp2, fd);
255 *name = nam; 255 *name = nam;
256 } 256 }
257 fd_putfile(sock); 257 fd_putfile(sock);
258 if (__predict_false(mask)) 258 if (__predict_false(mask))
259 sigsuspendteardown(l); 259 sigsuspendteardown(l);
260 return error; 260 return error;
261 bad: 261 bad:
262 sounlock(so); 262 sounlock(so);
263 m_freem(nam); 263 m_freem(nam);
264 fd_putfile(sock); 264 fd_putfile(sock);
265 fd_abort(curproc, fp2, fd); 265 fd_abort(curproc, fp2, fd);
266 if (__predict_false(mask)) 266 if (__predict_false(mask))
267 sigsuspendteardown(l); 267 sigsuspendteardown(l);
268 return error; 268 return error;
269} 269}
270 270
271int 271int
272sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval) 272sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
273{ 273{
274 /* { 274 /* {
275 syscallarg(int) s; 275 syscallarg(int) s;
276 syscallarg(struct sockaddr *) name; 276 syscallarg(struct sockaddr *) name;
277 syscallarg(unsigned int *) anamelen; 277 syscallarg(unsigned int *) anamelen;
278 } */ 278 } */
279 int error, fd; 279 int error, fd;
280 struct mbuf *name; 280 struct mbuf *name;
281 281
282 error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0); 282 error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0);
283 if (error != 0) 283 if (error != 0)
284 return error; 284 return error;
285 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen), 285 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
286 MSG_LENUSRSPACE, name); 286 MSG_LENUSRSPACE, name);
287 if (name != NULL) 287 if (name != NULL)
288 m_free(name); 288 m_free(name);
289 if (error != 0) { 289 if (error != 0) {
290 fd = (int)*retval; 290 fd = (int)*retval;
291 if (fd_getfile(fd) != NULL) 291 if (fd_getfile(fd) != NULL)
292 (void)fd_close(fd); 292 (void)fd_close(fd);
293 } 293 }
294 return error; 294 return error;
295} 295}
296 296
297int 297int
298sys_paccept(struct lwp *l, const struct sys_paccept_args *uap, 298sys_paccept(struct lwp *l, const struct sys_paccept_args *uap,
299 register_t *retval) 299 register_t *retval)
300{ 300{
301 /* { 301 /* {
302 syscallarg(int) s; 302 syscallarg(int) s;
303 syscallarg(struct sockaddr *) name; 303 syscallarg(struct sockaddr *) name;
304 syscallarg(unsigned int *) anamelen; 304 syscallarg(unsigned int *) anamelen;
305 syscallarg(const sigset_t *) mask; 305 syscallarg(const sigset_t *) mask;
306 syscallarg(int) flags; 306 syscallarg(int) flags;
307 } */ 307 } */
308 int error, fd; 308 int error, fd;
309 struct mbuf *name; 309 struct mbuf *name;
310 sigset_t *mask, amask; 310 sigset_t *mask, amask;
311 311
312 if (SCARG(uap, mask) != NULL) { 312 if (SCARG(uap, mask) != NULL) {
313 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 313 error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
314 if (error) 314 if (error)
315 return error; 315 return error;
316 mask = &amask; 316 mask = &amask;
317 } else 317 } else
318 mask = NULL; 318 mask = NULL;
319 319
320 error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask, 320 error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask,
321 SCARG(uap, flags), FNONBLOCK); 321 SCARG(uap, flags), FNONBLOCK);
322 if (error != 0) 322 if (error != 0)
323 return error; 323 return error;
324 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen), 324 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
325 MSG_LENUSRSPACE, name); 325 MSG_LENUSRSPACE, name);
326 if (name != NULL) 326 if (name != NULL)
327 m_free(name); 327 m_free(name);
328 if (error != 0) { 328 if (error != 0) {
329 fd = (int)*retval; 329 fd = (int)*retval;
330 if (fd_getfile(fd) != NULL) 330 if (fd_getfile(fd) != NULL)
331 (void)fd_close(fd); 331 (void)fd_close(fd);
332 } 332 }
333 return error; 333 return error;
334} 334}
335 335
336int 336int
337sys_connect(struct lwp *l, const struct sys_connect_args *uap, 337sys_connect(struct lwp *l, const struct sys_connect_args *uap,
338 register_t *retval) 338 register_t *retval)
339{ 339{
340 /* { 340 /* {
341 syscallarg(int) s; 341 syscallarg(int) s;
342 syscallarg(const struct sockaddr *) name; 342 syscallarg(const struct sockaddr *) name;
343 syscallarg(unsigned int) namelen; 343 syscallarg(unsigned int) namelen;
344 } */ 344 } */
345 int error; 345 int error;
346 struct mbuf *nam; 346 struct mbuf *nam;
347 347
348 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 348 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
349 MT_SONAME); 349 MT_SONAME);
350 if (error) 350 if (error)
351 return error; 351 return error;
352 return do_sys_connect(l, SCARG(uap, s), nam); 352 return do_sys_connect(l, SCARG(uap, s), nam);
353} 353}
354 354
355int 355int
356do_sys_connect(struct lwp *l, int fd, struct mbuf *nam) 356do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
357{ 357{
358 struct socket *so; 358 struct socket *so;
359 int error; 359 int error;
360 int interrupted = 0; 360 int interrupted = 0;
361 361
362 if ((error = fd_getsock(fd, &so)) != 0) { 362 if ((error = fd_getsock(fd, &so)) != 0) {
363 m_freem(nam); 363 m_freem(nam);
364 return (error); 364 return (error);
365 } 365 }
366 solock(so); 366 solock(so);
367 MCLAIM(nam, so->so_mowner); 367 MCLAIM(nam, so->so_mowner);
368 if ((so->so_state & SS_ISCONNECTING) != 0) { 368 if ((so->so_state & SS_ISCONNECTING) != 0) {
369 error = EALREADY; 369 error = EALREADY;
370 goto out; 370 goto out;
371 } 371 }
372 372
373 error = soconnect(so, nam, l); 373 error = soconnect(so, nam, l);
374 if (error) 374 if (error)
375 goto bad; 375 goto bad;
376 if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) == 376 if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) ==
377 (SS_NBIO|SS_ISCONNECTING)) { 377 (SS_NBIO|SS_ISCONNECTING)) {
378 error = EINPROGRESS; 378 error = EINPROGRESS;
379 goto out; 379 goto out;
380 } 380 }
381 while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) { 381 while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
382 error = sowait(so, true, 0); 382 error = sowait(so, true, 0);
383 if (__predict_false((so->so_state & SS_ISABORTING) != 0)) { 383 if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
384 error = EPIPE; 384 error = EPIPE;
385 interrupted = 1; 385 interrupted = 1;
386 break; 386 break;
387 } 387 }
388 if (error) { 388 if (error) {
389 if (error == EINTR || error == ERESTART) 389 if (error == EINTR || error == ERESTART)
390 interrupted = 1; 390 interrupted = 1;
391 break; 391 break;
392 } 392 }
393 } 393 }
394 if (error == 0) { 394 if (error == 0) {
395 error = so->so_error; 395 error = so->so_error;
396 so->so_error = 0; 396 so->so_error = 0;
397 } 397 }
398 bad: 398 bad:
399 if (!interrupted) 399 if (!interrupted)
400 so->so_state &= ~SS_ISCONNECTING; 400 so->so_state &= ~SS_ISCONNECTING;
401 if (error == ERESTART) 401 if (error == ERESTART)
402 error = EINTR; 402 error = EINTR;
403 out: 403 out:
404 sounlock(so); 404 sounlock(so);
405 fd_putfile(fd); 405 fd_putfile(fd);
406 m_freem(nam); 406 m_freem(nam);
407 return error; 407 return error;
408} 408}
409 409
410static int 410static int
411makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type, 411makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
412 int domain, int proto, struct socket *soo) 412 int domain, int proto, struct socket *soo)
413{ 413{
414 struct socket *so; 414 struct socket *so;
415 int error; 415 int error;
416 416
417 if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) { 417 if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) {
418 return error; 418 return error;
419 } 419 }
420 if (flags & SOCK_NONBLOCK) { 420 if (flags & SOCK_NONBLOCK) {
421 so->so_state |= SS_NBIO; 421 so->so_state |= SS_NBIO;
422 } 422 }
423 423
424 if ((error = fd_allocfile(fp, fd)) != 0) { 424 if ((error = fd_allocfile(fp, fd)) != 0) {
425 soclose(so); 425 soclose(so);
426 return error; 426 return error;
427 } 427 }
428 fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0); 428 fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
429 (*fp)->f_flag = FREAD|FWRITE| 429 (*fp)->f_flag = FREAD|FWRITE|
430 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)| 430 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
431 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0); 431 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
432 (*fp)->f_type = DTYPE_SOCKET; 432 (*fp)->f_type = DTYPE_SOCKET;
433 (*fp)->f_ops = &socketops; 433 (*fp)->f_ops = &socketops;
434 (*fp)->f_socket = so; 434 (*fp)->f_socket = so;
435 return 0; 435 return 0;
436} 436}
437 437
438int 438int
439sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap, 439sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
440 register_t *retval) 440 register_t *retval)
441{ 441{
442 /* { 442 /* {
443 syscallarg(int) domain; 443 syscallarg(int) domain;
444 syscallarg(int) type; 444 syscallarg(int) type;
445 syscallarg(int) protocol; 445 syscallarg(int) protocol;
446 syscallarg(int *) rsv; 446 syscallarg(int *) rsv;
447 } */ 447 } */
448 file_t *fp1, *fp2; 448 file_t *fp1, *fp2;
449 struct socket *so1, *so2; 449 struct socket *so1, *so2;
450 int fd, error, sv[2]; 450 int fd, error, sv[2];
451 proc_t *p = curproc; 451 proc_t *p = curproc;
452 int flags = SCARG(uap, type) & SOCK_FLAGS_MASK; 452 int flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
453 int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK; 453 int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
454 int domain = SCARG(uap, domain); 454 int domain = SCARG(uap, domain);
455 int proto = SCARG(uap, protocol); 455 int proto = SCARG(uap, protocol);
456 456
457 error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL); 457 error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
458 if (error) 458 if (error)
459 return error; 459 return error;
460 so1 = fp1->f_socket; 460 so1 = fp1->f_socket;
461 sv[0] = fd; 461 sv[0] = fd;
462 462
463 error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1); 463 error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
464 if (error) 464 if (error)
465 goto out; 465 goto out;
466 so2 = fp2->f_socket; 466 so2 = fp2->f_socket;
467 sv[1] = fd; 467 sv[1] = fd;
468 468
469 solock(so1); 469 solock(so1);
470 error = soconnect2(so1, so2); 470 error = soconnect2(so1, so2);
471 if (error == 0 && type == SOCK_DGRAM) { 471 if (error == 0 && type == SOCK_DGRAM) {
472 /* 472 /*
473 * Datagram socket connection is asymmetric. 473 * Datagram socket connection is asymmetric.
474 */ 474 */
475 error = soconnect2(so2, so1); 475 error = soconnect2(so2, so1);
476 } 476 }
477 sounlock(so1); 477 sounlock(so1);
478 478
479 if (error == 0) 479 if (error == 0)
480 error = copyout(sv, SCARG(uap, rsv), sizeof(sv)); 480 error = copyout(sv, SCARG(uap, rsv), sizeof(sv));
481 if (error == 0) { 481 if (error == 0) {
482 fd_affix(p, fp2, sv[1]); 482 fd_affix(p, fp2, sv[1]);
483 fd_affix(p, fp1, sv[0]); 483 fd_affix(p, fp1, sv[0]);
484 return 0; 484 return 0;
485 } 485 }
486 fd_abort(p, fp2, sv[1]); 486 fd_abort(p, fp2, sv[1]);
487 (void)soclose(so2); 487 (void)soclose(so2);
488out: 488out:
489 fd_abort(p, fp1, sv[0]); 489 fd_abort(p, fp1, sv[0]);
490 (void)soclose(so1); 490 (void)soclose(so1);
491 return error; 491 return error;
492} 492}
493 493
494int 494int
495sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, 495sys_sendto(struct lwp *l, const struct sys_sendto_args *uap,
496 register_t *retval) 496 register_t *retval)
497{ 497{
498 /* { 498 /* {
499 syscallarg(int) s; 499 syscallarg(int) s;
500 syscallarg(const void *) buf; 500 syscallarg(const void *) buf;
501 syscallarg(size_t) len; 501 syscallarg(size_t) len;
502 syscallarg(int) flags; 502 syscallarg(int) flags;
503 syscallarg(const struct sockaddr *) to; 503 syscallarg(const struct sockaddr *) to;
504 syscallarg(unsigned int) tolen; 504 syscallarg(unsigned int) tolen;
505 } */ 505 } */
506 struct msghdr msg; 506 struct msghdr msg;
507 struct iovec aiov; 507 struct iovec aiov;
508 508
509 msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */ 509 msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
510 msg.msg_namelen = SCARG(uap, tolen); 510 msg.msg_namelen = SCARG(uap, tolen);
511 msg.msg_iov = &aiov; 511 msg.msg_iov = &aiov;
512 msg.msg_iovlen = 1; 512 msg.msg_iovlen = 1;
513 msg.msg_control = NULL; 513 msg.msg_control = NULL;
514 msg.msg_flags = 0; 514 msg.msg_flags = 0;
515 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */ 515 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
516 aiov.iov_len = SCARG(uap, len); 516 aiov.iov_len = SCARG(uap, len);
517 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 517 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
518} 518}
519 519
520int 520int
521sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, 521sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap,
522 register_t *retval) 522 register_t *retval)
523{ 523{
524 /* { 524 /* {
525 syscallarg(int) s; 525 syscallarg(int) s;
526 syscallarg(const struct msghdr *) msg; 526 syscallarg(const struct msghdr *) msg;
527 syscallarg(int) flags; 527 syscallarg(int) flags;
528 } */ 528 } */
529 struct msghdr msg; 529 struct msghdr msg;
530 int error; 530 int error;
531 531
532 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 532 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
533 if (error) 533 if (error)
534 return (error); 534 return (error);
535 535
536 msg.msg_flags = MSG_IOVUSRSPACE; 536 msg.msg_flags = MSG_IOVUSRSPACE;
537 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 537 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
538} 538}
539 539
540static int 540static int
541do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp, 541do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
542 struct msghdr *mp, int flags, register_t *retsize) 542 struct msghdr *mp, int flags, register_t *retsize)
543{ 543{
544 544
545 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL; 545 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
546 struct mbuf *to, *control; 546 struct mbuf *to, *control;
547 struct uio auio; 547 struct uio auio;
548 size_t len, iovsz; 548 size_t len, iovsz;
549 int i, error; 549 int i, error;
550 550
551 ktrkuser("msghdr", mp, sizeof *mp); 551 ktrkuser("msghdr", mp, sizeof *mp);
552 552
553 /* If the caller passed us stuff in mbufs, we must free them. */ 553 /* If the caller passed us stuff in mbufs, we must free them. */
554 to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL; 554 to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL;
555 control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL; 555 control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL;
556 iovsz = mp->msg_iovlen * sizeof(struct iovec); 556 iovsz = mp->msg_iovlen * sizeof(struct iovec);
557 557
558 if (mp->msg_flags & MSG_IOVUSRSPACE) { 558 if (mp->msg_flags & MSG_IOVUSRSPACE) {
559 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 559 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
560 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 560 if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
561 error = EMSGSIZE; 561 error = EMSGSIZE;
562 goto bad; 562 goto bad;
563 } 563 }
564 iov = kmem_alloc(iovsz, KM_SLEEP); 564 iov = kmem_alloc(iovsz, KM_SLEEP);
565 } 565 }
566 if (mp->msg_iovlen != 0) { 566 if (mp->msg_iovlen != 0) {
567 error = copyin(mp->msg_iov, iov, iovsz); 567 error = copyin(mp->msg_iov, iov, iovsz);
568 if (error) 568 if (error)
569 goto bad; 569 goto bad;
570 } 570 }
571 mp->msg_iov = iov; 571 mp->msg_iov = iov;
572 } 572 }
573 573
574 auio.uio_iov = mp->msg_iov; 574 auio.uio_iov = mp->msg_iov;
575 auio.uio_iovcnt = mp->msg_iovlen; 575 auio.uio_iovcnt = mp->msg_iovlen;
576 auio.uio_rw = UIO_WRITE; 576 auio.uio_rw = UIO_WRITE;
577 auio.uio_offset = 0; /* XXX */ 577 auio.uio_offset = 0; /* XXX */
578 auio.uio_resid = 0; 578 auio.uio_resid = 0;
579 KASSERT(l == curlwp); 579 KASSERT(l == curlwp);
580 auio.uio_vmspace = l->l_proc->p_vmspace; 580 auio.uio_vmspace = l->l_proc->p_vmspace;
581 581
582 for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) { 582 for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
583 /* 583 /*
584 * Writes return ssize_t because -1 is returned on error. 584 * Writes return ssize_t because -1 is returned on error.
585 * Therefore, we must restrict the length to SSIZE_MAX to 585 * Therefore, we must restrict the length to SSIZE_MAX to
586 * avoid garbage return values. 586 * avoid garbage return values.
587 */ 587 */
588 auio.uio_resid += tiov->iov_len; 588 auio.uio_resid += tiov->iov_len;
589 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 589 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
590 error = EINVAL; 590 error = EINVAL;
591 goto bad; 591 goto bad;
592 } 592 }
593 } 593 }
594 594
595 if (mp->msg_name && to == NULL) { 595 if (mp->msg_name && to == NULL) {
596 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 596 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
597 MT_SONAME); 597 MT_SONAME);
598 if (error) 598 if (error)
599 goto bad; 599 goto bad;
600 } 600 }
601 601
602 if (mp->msg_control) { 602 if (mp->msg_control) {
603 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 603 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
604 error = EINVAL; 604 error = EINVAL;
605 goto bad; 605 goto bad;
606 } 606 }
607 if (control == NULL) { 607 if (control == NULL) {
608 error = sockargs(&control, mp->msg_control, 608 error = sockargs(&control, mp->msg_control,
609 mp->msg_controllen, MT_CONTROL); 609 mp->msg_controllen, MT_CONTROL);
610 if (error) 610 if (error)
611 goto bad; 611 goto bad;
612 } 612 }
613 } 613 }
614 614
615 if (ktrpoint(KTR_GENIO) && iovsz > 0) { 615 if (ktrpoint(KTR_GENIO) && iovsz > 0) {
616 ktriov = kmem_alloc(iovsz, KM_SLEEP); 616 ktriov = kmem_alloc(iovsz, KM_SLEEP);
617 memcpy(ktriov, auio.uio_iov, iovsz); 617 memcpy(ktriov, auio.uio_iov, iovsz);
618 } 618 }
619 619
620 if (mp->msg_name) 620 if (mp->msg_name)
621 MCLAIM(to, so->so_mowner); 621 MCLAIM(to, so->so_mowner);
622 if (mp->msg_control) 622 if (mp->msg_control)
623 MCLAIM(control, so->so_mowner); 623 MCLAIM(control, so->so_mowner);
624 624
625 len = auio.uio_resid; 625 len = auio.uio_resid;
626 error = (*so->so_send)(so, to, &auio, NULL, control, flags, l); 626 error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
627 /* Protocol is responsible for freeing 'control' */ 627 /* Protocol is responsible for freeing 'control' */
628 control = NULL; 628 control = NULL;
629 629
630 if (error) { 630 if (error) {
631 if (auio.uio_resid != len && (error == ERESTART || 631 if (auio.uio_resid != len && (error == ERESTART ||
632 error == EINTR || error == EWOULDBLOCK)) 632 error == EINTR || error == EWOULDBLOCK))
633 error = 0; 633 error = 0;
634 if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 && 634 if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 &&
635 (flags & MSG_NOSIGNAL) == 0) { 635 (flags & MSG_NOSIGNAL) == 0) {
636 mutex_enter(proc_lock); 636 mutex_enter(proc_lock);
637 psignal(l->l_proc, SIGPIPE); 637 psignal(l->l_proc, SIGPIPE);
638 mutex_exit(proc_lock); 638 mutex_exit(proc_lock);
639 } 639 }
640 } 640 }
641 if (error == 0) 641 if (error == 0)
642 *retsize = len - auio.uio_resid; 642 *retsize = len - auio.uio_resid;
643 643
644bad: 644bad:
645 if (ktriov != NULL) { 645 if (ktriov != NULL) {
646 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error); 646 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
647 kmem_free(ktriov, iovsz); 647 kmem_free(ktriov, iovsz);
648 } 648 }
649 649
650 if (iov != aiov) 650 if (iov != aiov)
651 kmem_free(iov, iovsz); 651 kmem_free(iov, iovsz);
652 if (to) 652 if (to)
653 m_freem(to); 653 m_freem(to);
654 if (control) 654 if (control)
655 m_freem(control); 655 m_freem(control);
656 656
657 return error; 657 return error;
658} 658}
659 659
660int 660int
661do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, 661do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
662 register_t *retsize) 662 register_t *retsize)
663{ 663{
664 int error; 664 int error;
665 struct socket *so; 665 struct socket *so;
666 file_t *fp; 666 file_t *fp;
667 667
668 if ((error = fd_getsock1(s, &so, &fp)) != 0) 668 if ((error = fd_getsock1(s, &so, &fp)) != 0)
669 return error; 669 return error;
670 error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize); 670 error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize);
671 fd_putfile(s); 671 fd_putfile(s);
672 return error; 672 return error;
673} 673}
674 674
675int 675int
676sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, 676sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap,
677 register_t *retval) 677 register_t *retval)
678{ 678{
679 /* { 679 /* {
680 syscallarg(int) s; 680 syscallarg(int) s;
681 syscallarg(void *) buf; 681 syscallarg(void *) buf;
682 syscallarg(size_t) len; 682 syscallarg(size_t) len;
683 syscallarg(int) flags; 683 syscallarg(int) flags;
684 syscallarg(struct sockaddr *) from; 684 syscallarg(struct sockaddr *) from;
685 syscallarg(unsigned int *) fromlenaddr; 685 syscallarg(unsigned int *) fromlenaddr;
686 } */ 686 } */
687 struct msghdr msg; 687 struct msghdr msg;
688 struct iovec aiov; 688 struct iovec aiov;
689 int error; 689 int error;
690 struct mbuf *from; 690 struct mbuf *from;
691 691
692 msg.msg_name = NULL; 692 msg.msg_name = NULL;
693 msg.msg_iov = &aiov; 693 msg.msg_iov = &aiov;
694 msg.msg_iovlen = 1; 694 msg.msg_iovlen = 1;
695 aiov.iov_base = SCARG(uap, buf); 695 aiov.iov_base = SCARG(uap, buf);
696 aiov.iov_len = SCARG(uap, len); 696 aiov.iov_len = SCARG(uap, len);
697 msg.msg_control = NULL; 697 msg.msg_control = NULL;
698 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; 698 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
699 699
700 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); 700 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
701 if (error != 0) 701 if (error != 0)
702 return error; 702 return error;
703 703
704 error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr), 704 error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
705 MSG_LENUSRSPACE, from); 705 MSG_LENUSRSPACE, from);
706 if (from != NULL) 706 if (from != NULL)
707 m_free(from); 707 m_free(from);
708 return error; 708 return error;
709} 709}
710 710
711int 711int
712sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, 712sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap,
713 register_t *retval) 713 register_t *retval)
714{ 714{
715 /* { 715 /* {
716 syscallarg(int) s; 716 syscallarg(int) s;
717 syscallarg(struct msghdr *) msg; 717 syscallarg(struct msghdr *) msg;
718 syscallarg(int) flags; 718 syscallarg(int) flags;
719 } */ 719 } */
720 struct msghdr msg; 720 struct msghdr msg;
721 int error; 721 int error;
722 struct mbuf *from, *control; 722 struct mbuf *from, *control;
723 723
724 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 724 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
725 if (error) 725 if (error)
726 return error; 726 return error;
727 727
728 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 728 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
729 729
730 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, 730 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
731 msg.msg_control != NULL ? &control : NULL, retval); 731 msg.msg_control != NULL ? &control : NULL, retval);
732 if (error != 0) 732 if (error != 0)
733 return error; 733 return error;
734 734
735 if (msg.msg_control != NULL) 735 if (msg.msg_control != NULL)
736 error = copyout_msg_control(l, &msg, control); 736 error = copyout_msg_control(l, &msg, control);
737 737
738 if (error == 0) 738 if (error == 0)
739 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, 739 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
740 from); 740 from);
741 if (from != NULL) 741 if (from != NULL)
742 m_free(from); 742 m_free(from);
743 if (error == 0) { 743 if (error == 0) {
744 ktrkuser("msghdr", &msg, sizeof msg); 744 ktrkuser("msghdr", &msg, sizeof msg);
745 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 745 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
746 } 746 }
747 747
748 return error; 748 return error;
749} 749}
750 750
751int 751int
752sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap, 752sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap,
753 register_t *retval) 753 register_t *retval)
754{ 754{
755 /* { 755 /* {
756 syscallarg(int) s; 756 syscallarg(int) s;
757 syscallarg(struct mmsghdr *) mmsg; 757 syscallarg(struct mmsghdr *) mmsg;
758 syscallarg(unsigned int) vlen; 758 syscallarg(unsigned int) vlen;
759 syscallarg(unsigned int) flags; 759 syscallarg(unsigned int) flags;
760 } */ 760 } */
761 struct mmsghdr mmsg; 761 struct mmsghdr mmsg;
762 struct socket *so; 762 struct socket *so;
763 file_t *fp; 763 file_t *fp;
764 struct msghdr *msg = &mmsg.msg_hdr; 764 struct msghdr *msg = &mmsg.msg_hdr;
765 int error, s; 765 int error, s;
766 unsigned int vlen, flags, dg; 766 unsigned int vlen, flags, dg;
767 767
768 s = SCARG(uap, s); 768 s = SCARG(uap, s);
769 if ((error = fd_getsock1(s, &so, &fp)) != 0) 769 if ((error = fd_getsock1(s, &so, &fp)) != 0)
770 return error; 770 return error;
771 771
772 vlen = SCARG(uap, vlen); 772 vlen = SCARG(uap, vlen);
773 if (vlen > 1024) 773 if (vlen > 1024)
774 vlen = 1024; 774 vlen = 1024;
775 775
776 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 776 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
777 777
778 for (dg = 0; dg < vlen;) { 778 for (dg = 0; dg < vlen;) {
779 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); 779 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
780 if (error) 780 if (error)
781 break; 781 break;
782 782
783 msg->msg_flags = flags; 783 msg->msg_flags = flags;
784 784
785 error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval); 785 error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
786 if (error) 786 if (error)
787 break; 787 break;
788 788
789 ktrkuser("msghdr", msg, sizeof *msg); 789 ktrkuser("msghdr", msg, sizeof *msg);
790 mmsg.msg_len = *retval; 790 mmsg.msg_len = *retval;
791 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); 791 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
792 if (error) 792 if (error)
793 break; 793 break;
794 dg++; 794 dg++;
795 795
796 } 796 }
797 797
798 *retval = dg; 798 *retval = dg;
799 if (error) 799 if (error)
800 so->so_error = error; 800 so->so_error = error;
801 801
802 fd_putfile(s); 802 fd_putfile(s);
803 803
804 /* 804 /*
805 * If we succeeded at least once, return 0, hopefully so->so_error 805 * If we succeeded at least once, return 0, hopefully so->so_error
806 * will catch it next time. 806 * will catch it next time.
807 */ 807 */
808 if (dg) 808 if (dg)
809 return 0; 809 return 0;
810 return error; 810 return error;
811} 811}
812 812
813/* 813/*
814 * Adjust for a truncated SCM_RIGHTS control message. 814 * Adjust for a truncated SCM_RIGHTS control message.
815 * This means closing any file descriptors that aren't present 815 * This means closing any file descriptors that aren't present
816 * in the returned buffer. 816 * in the returned buffer.
817 * m is the mbuf holding the (already externalized) SCM_RIGHTS message. 817 * m is the mbuf holding the (already externalized) SCM_RIGHTS message.
818 */ 818 */
819static void 819static void
820free_rights(struct mbuf *m) 820free_rights(struct mbuf *m)
821{ 821{
822 struct cmsghdr *cm; 822 struct cmsghdr *cm;
823 int *fdv; 823 int *fdv;
824 unsigned int nfds, i; 824 unsigned int nfds, i;
825 825
826 KASSERT(sizeof(*cm) <= m->m_len); 826 KASSERT(sizeof(*cm) <= m->m_len);
827 cm = mtod(m, struct cmsghdr *); 827 cm = mtod(m, struct cmsghdr *);
828 828
829 KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len); 829 KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len);
830 KASSERT(cm->cmsg_len <= m->m_len); 830 KASSERT(cm->cmsg_len <= m->m_len);
831 nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int); 831 nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int);
832 fdv = (int *)CMSG_DATA(cm); 832 fdv = (int *)CMSG_DATA(cm);
833 833
834 for (i = 0; i < nfds; i++) 834 for (i = 0; i < nfds; i++)
835 if (fd_getfile(fdv[i]) != NULL) 835 if (fd_getfile(fdv[i]) != NULL)
836 (void)fd_close(fdv[i]); 836 (void)fd_close(fdv[i]);
837} 837}
838 838
839void 839void
840free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied) 840free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
841{ 841{
842 struct mbuf *next; 842 struct mbuf *next;
843 struct cmsghdr *cmsg; 843 struct cmsghdr *cmsg;
844 bool do_free_rights = false; 844 bool do_free_rights = false;
845 845
846 while (control != NULL) { 846 while (control != NULL) {
847 cmsg = mtod(control, struct cmsghdr *); 847 cmsg = mtod(control, struct cmsghdr *);
848 if (control == uncopied) 848 if (control == uncopied)
849 do_free_rights = true; 849 do_free_rights = true;
850 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET 850 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
851 && cmsg->cmsg_type == SCM_RIGHTS) 851 && cmsg->cmsg_type == SCM_RIGHTS)
852 free_rights(control); 852 free_rights(control);
853 next = control->m_next; 853 next = control->m_next;
854 m_free(control); 854 m_free(control);
855 control = next; 855 control = next;
856 } 856 }
857} 857}
858 858
859/* Copy socket control/CMSG data to user buffer, frees the mbuf */ 859/* Copy socket control/CMSG data to user buffer, frees the mbuf */
860int 860int
861copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) 861copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
862{ 862{
863 int i, len, error = 0; 863 int i, len, error = 0;
864 struct cmsghdr *cmsg; 864 struct cmsghdr *cmsg;
865 struct mbuf *m; 865 struct mbuf *m;
866 char *q; 866 char *q;
867 867
868 len = mp->msg_controllen; 868 len = mp->msg_controllen;
869 if (len <= 0 || control == 0) { 869 if (len <= 0 || control == 0) {
870 mp->msg_controllen = 0; 870 mp->msg_controllen = 0;
871 free_control_mbuf(l, control, control); 871 free_control_mbuf(l, control, control);
872 return 0; 872 return 0;
873 } 873 }
874 874
875 q = (char *)mp->msg_control; 875 q = (char *)mp->msg_control;
876 876
877 for (m = control; m != NULL; ) { 877 for (m = control; m != NULL; ) {
878 cmsg = mtod(m, struct cmsghdr *); 878 cmsg = mtod(m, struct cmsghdr *);
879 i = m->m_len; 879 i = m->m_len;
880 if (len < i) { 880 if (len < i) {
881 mp->msg_flags |= MSG_CTRUNC; 881 mp->msg_flags |= MSG_CTRUNC;
882 if (cmsg->cmsg_level == SOL_SOCKET 882 if (cmsg->cmsg_level == SOL_SOCKET
883 && cmsg->cmsg_type == SCM_RIGHTS) 883 && cmsg->cmsg_type == SCM_RIGHTS)
884 /* Do not truncate me ... */ 884 /* Do not truncate me ... */
885 break; 885 break;
886 i = len; 886 i = len;
887 } 887 }
888 error = copyout(mtod(m, void *), q, i); 888 error = copyout(mtod(m, void *), q, i);
889 ktrkuser("msgcontrol", mtod(m, void *), i); 889 ktrkuser("msgcontrol", mtod(m, void *), i);
890 if (error != 0) { 890 if (error != 0) {
891 /* We must free all the SCM_RIGHTS */ 891 /* We must free all the SCM_RIGHTS */
892 m = control; 892 m = control;
893 break; 893 break;
894 } 894 }
895 m = m->m_next; 895 m = m->m_next;
896 if (m) 896 if (m)
897 i = ALIGN(i); 897 i = ALIGN(i);
898 q += i; 898 q += i;
899 len -= i; 899 len -= i;
900 if (len <= 0) 900 if (len <= 0)
901 break; 901 break;
902 } 902 }
903 903
904 free_control_mbuf(l, control, m); 904 free_control_mbuf(l, control, m);
905 905
906 mp->msg_controllen = q - (char *)mp->msg_control; 906 mp->msg_controllen = q - (char *)mp->msg_control;
907 return error; 907 return error;
908} 908}
909 909
910static int 910static int
911do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp, 911do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
912 struct mbuf **from, struct mbuf **control, register_t *retsize) 912 struct mbuf **from, struct mbuf **control, register_t *retsize)
913{ 913{
914 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL; 914 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
915 struct uio auio; 915 struct uio auio;
916 size_t len, iovsz; 916 size_t len, iovsz;
917 int i, error; 917 int i, error;
918 918
919 ktrkuser("msghdr", mp, sizeof *mp); 919 ktrkuser("msghdr", mp, sizeof *mp);
920 920
921 *from = NULL; 921 *from = NULL;
922 if (control != NULL) 922 if (control != NULL)
923 *control = NULL; 923 *control = NULL;
924 924
925 iovsz = mp->msg_iovlen * sizeof(struct iovec); 925 iovsz = mp->msg_iovlen * sizeof(struct iovec);
926 926
927 if (mp->msg_flags & MSG_IOVUSRSPACE) { 927 if (mp->msg_flags & MSG_IOVUSRSPACE) {
928 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 928 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
929 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 929 if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
930 error = EMSGSIZE; 930 error = EMSGSIZE;
931 goto out; 931 goto out;
932 } 932 }
933 iov = kmem_alloc(iovsz, KM_SLEEP); 933 iov = kmem_alloc(iovsz, KM_SLEEP);
934 } 934 }
935 if (mp->msg_iovlen != 0) { 935 if (mp->msg_iovlen != 0) {
936 error = copyin(mp->msg_iov, iov, iovsz); 936 error = copyin(mp->msg_iov, iov, iovsz);
937 if (error) 937 if (error)
938 goto out; 938 goto out;
939 } 939 }
940 auio.uio_iov = iov; 940 auio.uio_iov = iov;
941 } else 941 } else
942 auio.uio_iov = mp->msg_iov; 942 auio.uio_iov = mp->msg_iov;
943 auio.uio_iovcnt = mp->msg_iovlen; 943 auio.uio_iovcnt = mp->msg_iovlen;
944 auio.uio_rw = UIO_READ; 944 auio.uio_rw = UIO_READ;
945 auio.uio_offset = 0; /* XXX */ 945 auio.uio_offset = 0; /* XXX */
946 auio.uio_resid = 0; 946 auio.uio_resid = 0;
947 KASSERT(l == curlwp); 947 KASSERT(l == curlwp);
948 auio.uio_vmspace = l->l_proc->p_vmspace; 948 auio.uio_vmspace = l->l_proc->p_vmspace;
949 949
950 tiov = auio.uio_iov; 950 tiov = auio.uio_iov;
951 for (i = 0; i < mp->msg_iovlen; i++, tiov++) { 951 for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
952 /* 952 /*
953 * Reads return ssize_t because -1 is returned on error. 953 * Reads return ssize_t because -1 is returned on error.
954 * Therefore we must restrict the length to SSIZE_MAX to 954 * Therefore we must restrict the length to SSIZE_MAX to
955 * avoid garbage return values. 955 * avoid garbage return values.
956 */ 956 */
957 auio.uio_resid += tiov->iov_len; 957 auio.uio_resid += tiov->iov_len;
958 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 958 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
959 error = EINVAL; 959 error = EINVAL;
960 goto out; 960 goto out;
961 } 961 }
962 } 962 }
963 963
964 if (ktrpoint(KTR_GENIO) && iovsz > 0) { 964 if (ktrpoint(KTR_GENIO) && iovsz > 0) {
965 ktriov = kmem_alloc(iovsz, KM_SLEEP); 965 ktriov = kmem_alloc(iovsz, KM_SLEEP);
966 memcpy(ktriov, auio.uio_iov, iovsz); 966 memcpy(ktriov, auio.uio_iov, iovsz);
967 } 967 }
968 968
969 len = auio.uio_resid; 969 len = auio.uio_resid;
970 mp->msg_flags &= MSG_USERFLAGS; 970 mp->msg_flags &= MSG_USERFLAGS;
971 error = (*so->so_receive)(so, from, &auio, NULL, control, 971 error = (*so->so_receive)(so, from, &auio, NULL, control,
972 &mp->msg_flags); 972 &mp->msg_flags);
973 len -= auio.uio_resid; 973 len -= auio.uio_resid;
974 *retsize = len; 974 *retsize = len;
975 if (error != 0 && len != 0 975 if (error != 0 && len != 0
976 && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) 976 && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
977 /* Some data transferred */ 977 /* Some data transferred */
978 error = 0; 978 error = 0;
979 979
980 if (ktriov != NULL) { 980 if (ktriov != NULL) {
981 ktrgeniov(s, UIO_READ, ktriov, len, error); 981 ktrgeniov(s, UIO_READ, ktriov, len, error);
982 kmem_free(ktriov, iovsz); 982 kmem_free(ktriov, iovsz);
983 } 983 }
984 984
985 if (error != 0) { 985 if (error != 0) {
986 m_freem(*from); 986 m_freem(*from);
987 *from = NULL; 987 *from = NULL;
988 if (control != NULL) { 988 if (control != NULL) {
989 free_control_mbuf(l, *control, *control); 989 free_control_mbuf(l, *control, *control);
990 *control = NULL; 990 *control = NULL;
991 } 991 }
992 } 992 }
993 out: 993 out:
994 if (iov != aiov) 994 if (iov != aiov)
995 kmem_free(iov, iovsz); 995 kmem_free(iov, iovsz);
996 return error; 996 return error;
997} 997}
998 998
999 999
1000int 1000int
1001do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, 1001do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
1002 struct mbuf **control, register_t *retsize) 1002 struct mbuf **control, register_t *retsize)
1003{ 1003{
1004 int error; 1004 int error;
1005 struct socket *so; 1005 struct socket *so;
1006 1006
1007 if ((error = fd_getsock(s, &so)) != 0) 1007 if ((error = fd_getsock(s, &so)) != 0)
1008 return error; 1008 return error;
1009 error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize); 1009 error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
1010 fd_putfile(s); 1010 fd_putfile(s);
1011 return error; 1011 return error;
1012} 1012}
1013 1013
1014int 1014int
1015sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap, 1015sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
1016 register_t *retval) 1016 register_t *retval)
1017{ 1017{
1018 /* { 1018 /* {
1019 syscallarg(int) s; 1019 syscallarg(int) s;
1020 syscallarg(struct mmsghdr *) mmsg; 1020 syscallarg(struct mmsghdr *) mmsg;
1021 syscallarg(unsigned int) vlen; 1021 syscallarg(unsigned int) vlen;
1022 syscallarg(unsigned int) flags; 1022 syscallarg(unsigned int) flags;
1023 syscallarg(struct timespec *) timeout; 1023 syscallarg(struct timespec *) timeout;
1024 } */ 1024 } */
1025 struct mmsghdr mmsg; 1025 struct mmsghdr mmsg;
1026 struct socket *so; 1026 struct socket *so;
1027 struct msghdr *msg = &mmsg.msg_hdr; 1027 struct msghdr *msg = &mmsg.msg_hdr;
1028 int error, s; 1028 int error, s;
1029 struct mbuf *from, *control; 1029 struct mbuf *from, *control;
1030 struct timespec ts, now; 1030 struct timespec ts, now;
1031 unsigned int vlen, flags, dg; 1031 unsigned int vlen, flags, dg;
1032 1032
1033 if (SCARG(uap, timeout)) { 1033 if (SCARG(uap, timeout)) {
1034 if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0) 1034 if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
1035 return error; 1035 return error;
1036 getnanotime(&now); 1036 getnanotime(&now);
1037 timespecadd(&now, &ts, &ts); 1037 timespecadd(&now, &ts, &ts);
1038 } 1038 }
1039 1039
1040 s = SCARG(uap, s); 1040 s = SCARG(uap, s);
1041 if ((error = fd_getsock(s, &so)) != 0) 1041 if ((error = fd_getsock(s, &so)) != 0)
1042 return error; 1042 return error;
1043 1043
1044 vlen = SCARG(uap, vlen); 1044 vlen = SCARG(uap, vlen);
1045 if (vlen > 1024) 1045 if (vlen > 1024)
1046 vlen = 1024; 1046 vlen = 1024;
1047 1047
1048 from = NULL; 1048 from = NULL;
1049 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 1049 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
1050 1050
1051 for (dg = 0; dg < vlen;) { 1051 for (dg = 0; dg < vlen;) {
1052 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); 1052 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
1053 if (error) 1053 if (error)
1054 break; 1054 break;
1055 1055
1056 msg->msg_flags = flags & ~MSG_WAITFORONE; 1056 msg->msg_flags = flags & ~MSG_WAITFORONE;
1057 1057
1058 if (from != NULL) { 1058 if (from != NULL) {
1059 m_free(from); 1059 m_free(from);
1060 from = NULL; 1060 from = NULL;
1061 } 1061 }
1062 1062
1063 error = do_sys_recvmsg_so(l, s, so, msg, &from, 1063 error = do_sys_recvmsg_so(l, s, so, msg, &from,
1064 msg->msg_control != NULL ? &control : NULL, retval); 1064 msg->msg_control != NULL ? &control : NULL, retval);
1065 if (error) { 1065 if (error) {
1066 if (error == EAGAIN && dg > 0) 1066 if (error == EAGAIN && dg > 0)
1067 error = 0; 1067 error = 0;
1068 break; 1068 break;
1069 } 1069 }
1070 1070
1071 if (msg->msg_control != NULL) 1071 if (msg->msg_control != NULL)
1072 error = copyout_msg_control(l, msg, control); 1072 error = copyout_msg_control(l, msg, control);
1073 if (error) 1073 if (error)
1074 break; 1074 break;
1075 1075
1076 error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0, 1076 error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
1077 from); 1077 from);
1078 if (error) 1078 if (error)
1079 break; 1079 break;
1080 1080
1081 ktrkuser("msghdr", msg, sizeof *msg); 1081 ktrkuser("msghdr", msg, sizeof *msg);
1082 mmsg.msg_len = *retval; 1082 mmsg.msg_len = *retval;
1083 1083
1084 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); 1084 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
1085 if (error) 1085 if (error)
1086 break; 1086 break;
1087 1087
1088 dg++; 1088 dg++;
1089 if (msg->msg_flags & MSG_OOB) 1089 if (msg->msg_flags & MSG_OOB)
1090 break; 1090 break;
1091 1091
1092 if (SCARG(uap, timeout)) { 1092 if (SCARG(uap, timeout)) {
1093 getnanotime(&now); 1093 getnanotime(&now);
1094 timespecsub(&now, &ts, &now); 1094 timespecsub(&now, &ts, &now);
1095 if (now.tv_sec > 0) 1095 if (now.tv_sec > 0)
1096 break; 1096 break;
1097 } 1097 }
1098 1098
1099 if (flags & MSG_WAITFORONE) 1099 if (flags & MSG_WAITFORONE)
1100 flags |= MSG_DONTWAIT; 1100 flags |= MSG_DONTWAIT;
1101 1101
1102 } 1102 }
1103 1103
1104 if (from != NULL) 1104 if (from != NULL)
1105 m_free(from); 1105 m_free(from);
1106 1106
1107 *retval = dg; 1107 *retval = dg;
1108 if (error) 1108 if (error)
1109 so->so_error = error; 1109 so->so_error = error;
1110 1110
1111 fd_putfile(s); 1111 fd_putfile(s);
1112 1112
1113 /* 1113 /*
1114 * If we succeeded at least once, return 0, hopefully so->so_error 1114 * If we succeeded at least once, return 0, hopefully so->so_error
1115 * will catch it next time. 1115 * will catch it next time.
1116 */ 1116 */
1117 if (dg) 1117 if (dg)
1118 return 0; 1118 return 0;
1119 1119
1120 return error; 1120 return error;
1121} 1121}
1122 1122
1123int 1123int
1124sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, 1124sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap,
1125 register_t *retval) 1125 register_t *retval)
1126{ 1126{
1127 /* { 1127 /* {
1128 syscallarg(int) s; 1128 syscallarg(int) s;
1129 syscallarg(int) how; 1129 syscallarg(int) how;
1130 } */ 1130 } */
1131 struct socket *so; 1131 struct socket *so;
1132 int error; 1132 int error;
1133 1133
1134 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) 1134 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1135 return error; 1135 return error;
1136 solock(so); 1136 solock(so);
1137 error = soshutdown(so, SCARG(uap, how)); 1137 error = soshutdown(so, SCARG(uap, how));
1138 sounlock(so); 1138 sounlock(so);
1139 fd_putfile(SCARG(uap, s)); 1139 fd_putfile(SCARG(uap, s));
1140 return error; 1140 return error;
1141} 1141}
1142 1142
1143int 1143int
1144sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, 1144sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap,
1145 register_t *retval) 1145 register_t *retval)
1146{ 1146{
1147 /* { 1147 /* {
1148 syscallarg(int) s; 1148 syscallarg(int) s;
1149 syscallarg(int) level; 1149 syscallarg(int) level;
1150 syscallarg(int) name; 1150 syscallarg(int) name;
1151 syscallarg(const void *) val; 1151 syscallarg(const void *) val;
1152 syscallarg(unsigned int) valsize; 1152 syscallarg(unsigned int) valsize;
1153 } */ 1153 } */
1154 struct sockopt sopt; 1154 struct sockopt sopt;
1155 struct socket *so; 1155 struct socket *so;
1156 file_t *fp; 1156 file_t *fp;
1157 int error; 1157 int error;
1158 unsigned int len; 1158 unsigned int len;
1159 1159
1160 len = SCARG(uap, valsize); 1160 len = SCARG(uap, valsize);
1161 if (len > 0 && SCARG(uap, val) == NULL) 1161 if (len > 0 && SCARG(uap, val) == NULL)
1162 return EINVAL; 1162 return EINVAL;
1163 1163
1164 if (len > MCLBYTES) 1164 if (len > MCLBYTES)
1165 return EINVAL; 1165 return EINVAL;
1166 1166
1167 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) 1167 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1168 return (error); 1168 return (error);
1169 1169
1170 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len); 1170 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
1171 1171
1172 if (len > 0) { 1172 if (len > 0) {
1173 error = copyin(SCARG(uap, val), sopt.sopt_data, len); 1173 error = copyin(SCARG(uap, val), sopt.sopt_data, len);
1174 if (error) 1174 if (error)
1175 goto out; 1175 goto out;
1176 } 1176 }
1177 1177
1178 error = sosetopt(so, &sopt); 1178 error = sosetopt(so, &sopt);
1179 if (so->so_options & SO_NOSIGPIPE) 1179 if (so->so_options & SO_NOSIGPIPE)
1180 atomic_or_uint(&fp->f_flag, FNOSIGPIPE); 1180 atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
1181 else 1181 else
1182 atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE); 1182 atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
1183 1183
1184 out: 1184 out:
1185 sockopt_destroy(&sopt); 1185 sockopt_destroy(&sopt);
1186 fd_putfile(SCARG(uap, s)); 1186 fd_putfile(SCARG(uap, s));
1187 return error; 1187 return error;
1188} 1188}
1189 1189
1190int 1190int
1191sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, 1191sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap,
1192 register_t *retval) 1192 register_t *retval)
1193{ 1193{
1194 /* { 1194 /* {
1195 syscallarg(int) s; 1195 syscallarg(int) s;
1196 syscallarg(int) level; 1196 syscallarg(int) level;
1197 syscallarg(int) name; 1197 syscallarg(int) name;
1198 syscallarg(void *) val; 1198 syscallarg(void *) val;
1199 syscallarg(unsigned int *) avalsize; 1199 syscallarg(unsigned int *) avalsize;
1200 } */ 1200 } */
1201 struct sockopt sopt; 1201 struct sockopt sopt;
1202 struct socket *so; 1202 struct socket *so;
1203 file_t *fp; 1203 file_t *fp;
1204 unsigned int valsize, len; 1204 unsigned int valsize, len;
1205 int error; 1205 int error;
1206 1206
1207 if (SCARG(uap, val) != NULL) { 1207 if (SCARG(uap, val) != NULL) {
1208 error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize)); 1208 error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
1209 if (error) 1209 if (error)
1210 return error; 1210 return error;
1211 } else 1211 } else
1212 valsize = 0; 1212 valsize = 0;
1213 1213
1214 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) 1214 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1215 return (error); 1215 return (error);
1216 1216
1217 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0); 1217 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
1218 1218
1219 if (fp->f_flag & FNOSIGPIPE) 1219 if (fp->f_flag & FNOSIGPIPE)
1220 so->so_options |= SO_NOSIGPIPE; 1220 so->so_options |= SO_NOSIGPIPE;
1221 else 1221 else
1222 so->so_options &= ~SO_NOSIGPIPE; 1222 so->so_options &= ~SO_NOSIGPIPE;
1223 error = sogetopt(so, &sopt); 1223 error = sogetopt(so, &sopt);
1224 if (error) 1224 if (error)
1225 goto out; 1225 goto out;
1226 1226
1227 if (valsize > 0) { 1227 if (valsize > 0) {
1228 len = min(valsize, sopt.sopt_size); 1228 len = min(valsize, sopt.sopt_size);
1229 error = copyout(sopt.sopt_data, SCARG(uap, val), len); 1229 error = copyout(sopt.sopt_data, SCARG(uap, val), len);
1230 if (error) 1230 if (error)
1231 goto out; 1231 goto out;
1232 1232
1233 error = copyout(&len, SCARG(uap, avalsize), sizeof(len)); 1233 error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
1234 if (error) 1234 if (error)
1235 goto out; 1235 goto out;
1236 } 1236 }
1237 1237
1238 out: 1238 out:
1239 sockopt_destroy(&sopt); 1239 sockopt_destroy(&sopt);
1240 fd_putfile(SCARG(uap, s)); 1240 fd_putfile(SCARG(uap, s));
1241 return error; 1241 return error;
1242} 1242}
1243 1243
1244#ifdef PIPE_SOCKETPAIR 1244#ifdef PIPE_SOCKETPAIR
1245 1245
1246int 1246int
1247pipe1(struct lwp *l, register_t *retval, int flags) 1247pipe1(struct lwp *l, register_t *retval, int flags)
1248{ 1248{
1249 file_t *rf, *wf; 1249 file_t *rf, *wf;
1250 struct socket *rso, *wso; 1250 struct socket *rso, *wso;
1251 int fd, error; 1251 int fd, error;
1252 proc_t *p; 1252 proc_t *p;
1253 1253
1254 if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE)) 1254 if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
1255 return EINVAL; 1255 return EINVAL;
1256 p = curproc; 1256 p = curproc;
1257 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0) 1257 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
1258 return error; 1258 return error;
1259 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0) 1259 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
1260 goto free1; 1260 goto free1;
1261 /* remember this socket pair implements a pipe */ 1261 /* remember this socket pair implements a pipe */
1262 wso->so_state |= SS_ISAPIPE; 1262 wso->so_state |= SS_ISAPIPE;
1263 rso->so_state |= SS_ISAPIPE; 1263 rso->so_state |= SS_ISAPIPE;
1264 if ((error = fd_allocfile(&rf, &fd)) != 0) 1264 if ((error = fd_allocfile(&rf, &fd)) != 0)
1265 goto free2; 1265 goto free2;
1266 retval[0] = fd; 1266 retval[0] = fd;
1267 rf->f_flag = FREAD | flags; 1267 rf->f_flag = FREAD | flags;
1268 rf->f_type = DTYPE_SOCKET; 1268 rf->f_type = DTYPE_SOCKET;
1269 rf->f_ops = &socketops; 1269 rf->f_ops = &socketops;
1270 rf->f_socket = rso; 1270 rf->f_socket = rso;
1271 if ((error = fd_allocfile(&wf, &fd)) != 0) 1271 if ((error = fd_allocfile(&wf, &fd)) != 0)
1272 goto free3; 1272 goto free3;
1273 wf->f_flag = FWRITE | flags; 1273 wf->f_flag = FWRITE | flags;
1274 wf->f_type = DTYPE_SOCKET; 1274 wf->f_type = DTYPE_SOCKET;
1275 wf->f_ops = &socketops; 1275 wf->f_ops = &socketops;
1276 wf->f_socket = wso; 1276 wf->f_socket = wso;
1277 retval[1] = fd; 1277 retval[1] = fd;
1278 solock(wso); 1278 solock(wso);
1279 error = unp_connect2(wso, rso); 1279 error = unp_connect2(wso, rso);
1280 sounlock(wso); 1280 sounlock(wso);
1281 if (error != 0) 1281 if (error != 0)
1282 goto free4; 1282 goto free4;
1283 fd_affix(p, wf, (int)retval[1]); 1283 fd_affix(p, wf, (int)retval[1]);
1284 fd_affix(p, rf, (int)retval[0]); 1284 fd_affix(p, rf, (int)retval[0]);
1285 return (0); 1285 return (0);
1286 free4: 1286 free4:
1287 fd_abort(p, wf, (int)retval[1]); 1287 fd_abort(p, wf, (int)retval[1]);
1288 free3: 1288 free3:
1289 fd_abort(p, rf, (int)retval[0]); 1289 fd_abort(p, rf, (int)retval[0]);
1290 free2: 1290 free2:
1291 (void)soclose(wso); 1291 (void)soclose(wso);
1292 free1: 1292 free1:
1293 (void)soclose(rso); 1293 (void)soclose(rso);
1294 return error; 1294 return error;
1295} 1295}
1296#endif /* PIPE_SOCKETPAIR */ 1296#endif /* PIPE_SOCKETPAIR */
1297 1297
1298/* 1298/*
1299 * Get peer socket name. 1299 * Get peer socket name.
1300 */ 1300 */
1301int 1301int
1302do_sys_getpeername(int fd, struct mbuf **nam) 1302do_sys_getpeername(int fd, struct mbuf **nam)
1303{ 1303{
1304 struct socket *so; 1304 struct socket *so;
1305 struct mbuf *m; 1305 struct mbuf *m;
1306 int error; 1306 int error;
1307 1307
1308 if ((error = fd_getsock(fd, &so)) != 0) 1308 if ((error = fd_getsock(fd, &so)) != 0)
1309 return error; 1309 return error;
1310 1310
1311 m = m_getclr(M_WAIT, MT_SONAME); 1311 m = m_getclr(M_WAIT, MT_SONAME);
1312 MCLAIM(m, so->so_mowner); 1312 MCLAIM(m, so->so_mowner);
1313 1313
1314 solock(so); 1314 solock(so);
1315 if ((so->so_state & SS_ISCONNECTED) == 0) 1315 if ((so->so_state & SS_ISCONNECTED) == 0)
1316 error = ENOTCONN; 1316 error = ENOTCONN;
1317 else { 1317 else {
1318 *nam = m; 1318 *nam = m;
1319 error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m); 1319 error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m);
1320 } 1320 }
1321 sounlock(so); 1321 sounlock(so);
1322 if (error != 0) 1322 if (error != 0)
1323 m_free(m); 1323 m_free(m);
1324 fd_putfile(fd); 1324 fd_putfile(fd);
1325 return error; 1325 return error;
1326} 1326}
1327 1327
1328/* 1328/*
1329 * Get local socket name. 1329 * Get local socket name.
1330 */ 1330 */
1331int 1331int
1332do_sys_getsockname(int fd, struct mbuf **nam) 1332do_sys_getsockname(int fd, struct mbuf **nam)
1333{ 1333{
1334 struct socket *so; 1334 struct socket *so;
1335 struct mbuf *m; 1335 struct mbuf *m;
1336 int error; 1336 int error;
1337 1337
1338 if ((error = fd_getsock(fd, &so)) != 0) 1338 if ((error = fd_getsock(fd, &so)) != 0)
1339 return error; 1339 return error;
1340 1340
1341 m = m_getclr(M_WAIT, MT_SONAME); 1341 m = m_getclr(M_WAIT, MT_SONAME);
1342 MCLAIM(m, so->so_mowner); 1342 MCLAIM(m, so->so_mowner);
1343 1343
1344 *nam = m; 1344 *nam = m;
1345 solock(so); 1345 solock(so);
1346 error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, m); 1346 error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, m);
1347 sounlock(so); 1347 sounlock(so);
1348 if (error != 0) 1348 if (error != 0)
1349 m_free(m); 1349 m_free(m);
1350 fd_putfile(fd); 1350 fd_putfile(fd);
1351 return error; 1351 return error;
1352} 1352}
1353 1353
1354int 1354int
1355copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags, 1355copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
1356 struct mbuf *addr) 1356 struct mbuf *addr)
1357{ 1357{
1358 int len; 1358 int len;
1359 int error; 1359 int error;
1360 1360
1361 if (asa == NULL) 1361 if (asa == NULL)
1362 /* Assume application not interested */ 1362 /* Assume application not interested */
1363 return 0; 1363 return 0;
1364 1364
1365 if (flags & MSG_LENUSRSPACE) { 1365 if (flags & MSG_LENUSRSPACE) {
1366 error = copyin(alen, &len, sizeof(len)); 1366 error = copyin(alen, &len, sizeof(len));
1367 if (error) 1367 if (error)
1368 return error; 1368 return error;
1369 } else 1369 } else
1370 len = *alen; 1370 len = *alen;
1371 if (len < 0) 1371 if (len < 0)
1372 return EINVAL; 1372 return EINVAL;
1373 1373
1374 if (addr == NULL) { 1374 if (addr == NULL) {
1375 len = 0; 1375 len = 0;
1376 error = 0; 1376 error = 0;
1377 } else { 1377 } else {
1378 if (len > addr->m_len) 1378 if (len > addr->m_len)
1379 len = addr->m_len; 1379 len = addr->m_len;
1380 /* Maybe this ought to copy a chain ? */ 1380 /* Maybe this ought to copy a chain ? */
1381 ktrkuser(mbuftypes[MT_SONAME], mtod(addr, void *), len); 1381 ktrkuser(mbuftypes[MT_SONAME], mtod(addr, void *), len);
1382 error = copyout(mtod(addr, void *), asa, len); 1382 error = copyout(mtod(addr, void *), asa, len);
1383 } 1383 }
1384 1384
1385 if (error == 0) { 1385 if (error == 0) {
1386 if (flags & MSG_LENUSRSPACE) 1386 if (flags & MSG_LENUSRSPACE)
1387 error = copyout(&len, alen, sizeof(len)); 1387 error = copyout(&len, alen, sizeof(len));
1388 else 1388 else
1389 *alen = len; 1389 *alen = len;
1390 } 1390 }
1391 1391
1392 return error; 1392 return error;
1393} 1393}
1394 1394
1395/* 1395/*
1396 * Get socket name. 1396 * Get socket name.
1397 */ 1397 */
1398int 1398int
1399sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, 1399sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap,
1400 register_t *retval) 1400 register_t *retval)
1401{ 1401{
1402 /* { 1402 /* {
1403 syscallarg(int) fdes; 1403 syscallarg(int) fdes;
1404 syscallarg(struct sockaddr *) asa; 1404 syscallarg(struct sockaddr *) asa;
1405 syscallarg(unsigned int *) alen; 1405 syscallarg(unsigned int *) alen;
1406 } */ 1406 } */
1407 struct mbuf *m; 1407 struct mbuf *m;
1408 int error; 1408 int error;
1409 1409
1410 error = do_sys_getsockname(SCARG(uap, fdes), &m); 1410 error = do_sys_getsockname(SCARG(uap, fdes), &m);
1411 if (error != 0) 1411 if (error != 0)
1412 return error; 1412 return error;
1413 1413
1414 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), 1414 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1415 MSG_LENUSRSPACE, m); 1415 MSG_LENUSRSPACE, m);
1416 if (m != NULL) 1416 if (m != NULL)
1417 m_free(m); 1417 m_free(m);
1418 return error; 1418 return error;
1419} 1419}
1420 1420
1421/* 1421/*
1422 * Get name of peer for connected socket. 1422 * Get name of peer for connected socket.
1423 */ 1423 */
1424int 1424int
1425sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, 1425sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap,
1426 register_t *retval) 1426 register_t *retval)
1427{ 1427{
1428 /* { 1428 /* {
1429 syscallarg(int) fdes; 1429 syscallarg(int) fdes;
1430 syscallarg(struct sockaddr *) asa; 1430 syscallarg(struct sockaddr *) asa;
1431 syscallarg(unsigned int *) alen; 1431 syscallarg(unsigned int *) alen;
1432 } */ 1432 } */
1433 struct mbuf *m; 1433 struct mbuf *m;
1434 int error; 1434 int error;
1435 1435
1436 error = do_sys_getpeername(SCARG(uap, fdes), &m); 1436 error = do_sys_getpeername(SCARG(uap, fdes), &m);
1437 if (error != 0) 1437 if (error != 0)
1438 return error; 1438 return error;
1439 1439
1440 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), 1440 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1441 MSG_LENUSRSPACE, m); 1441 MSG_LENUSRSPACE, m);
1442 if (m != NULL) 1442 if (m != NULL)
1443 m_free(m); 1443 m_free(m);
1444 return error; 1444 return error;
1445} 1445}
1446 1446
1447/* 1447/*
1448 * XXX In a perfect world, we wouldn't pass around socket control 1448 * XXX In a perfect world, we wouldn't pass around socket control
1449 * XXX arguments in mbufs, and this could go away. 1449 * XXX arguments in mbufs, and this could go away.
1450 */ 1450 */
1451int 1451int
1452sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type) 1452sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
1453{ 1453{
1454 struct sockaddr *sa; 1454 struct sockaddr *sa;
1455 struct mbuf *m; 1455 struct mbuf *m;
1456 int error; 1456 int error;
1457 1457
1458 /* 1458 /*
1459 * We can't allow socket names > UCHAR_MAX in length, since that 1459 * We can't allow socket names > UCHAR_MAX in length, since that
1460 * will overflow sa_len. Control data more than a page size in 1460 * will overflow sa_len. Control data more than a page size in
1461 * length is just too much. 1461 * length is just too much.
1462 */ 1462 */
1463 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE)) 1463 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1464 return EINVAL; 1464 return EINVAL;
1465 1465
 1466 /*
 1467 * length must greater than sizeof(sa_family) + sizeof(sa_len)
 1468 */
 1469 if (type == MT_SONAME && buflen <= 2)
 1470 return EINVAL;
 1471
1466 /* Allocate an mbuf to hold the arguments. */ 1472 /* Allocate an mbuf to hold the arguments. */
1467 m = m_get(M_WAIT, type); 1473 m = m_get(M_WAIT, type);
1468 /* can't claim. don't who to assign it to. */ 1474 /* can't claim. don't who to assign it to. */
1469 if (buflen > MLEN) { 1475 if (buflen > MLEN) {
1470 /* 1476 /*
1471 * Won't fit into a regular mbuf, so we allocate just 1477 * Won't fit into a regular mbuf, so we allocate just
1472 * enough external storage to hold the argument. 1478 * enough external storage to hold the argument.
1473 */ 1479 */
1474 MEXTMALLOC(m, buflen, M_WAITOK); 1480 MEXTMALLOC(m, buflen, M_WAITOK);
1475 } 1481 }
1476 m->m_len = buflen; 1482 m->m_len = buflen;
1477 error = copyin(bf, mtod(m, void *), buflen); 1483 error = copyin(bf, mtod(m, void *), buflen);
1478 if (error) { 1484 if (error) {
1479 (void)m_free(m); 1485 (void)m_free(m);
1480 return error; 1486 return error;
1481 } 1487 }
1482 ktrkuser(mbuftypes[type], mtod(m, void *), buflen); 1488 ktrkuser(mbuftypes[type], mtod(m, void *), buflen);
1483 *mp = m; 1489 *mp = m;
1484 if (type == MT_SONAME) { 1490 if (type == MT_SONAME) {
1485 sa = mtod(m, struct sockaddr *); 1491 sa = mtod(m, struct sockaddr *);
1486#if BYTE_ORDER != BIG_ENDIAN 1492#if BYTE_ORDER != BIG_ENDIAN
1487 /* 1493 /*
1488 * 4.3BSD compat thing - need to stay, since bind(2), 1494 * 4.3BSD compat thing - need to stay, since bind(2),
1489 * connect(2), sendto(2) were not versioned for COMPAT_43. 1495 * connect(2), sendto(2) were not versioned for COMPAT_43.
1490 */ 1496 */
1491 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1497 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1492 sa->sa_family = sa->sa_len; 1498 sa->sa_family = sa->sa_len;
1493#endif 1499#endif
1494 sa->sa_len = buflen; 1500 sa->sa_len = buflen;
1495 } 1501 }
1496 return 0; 1502 return 0;
1497} 1503}