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