1/* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
|
34 * $Id: uipc_syscalls.c,v 1.25 1997/04/09 16:53:40 bde Exp $
|
34 * $Id: uipc_syscalls.c,v 1.26 1997/04/27 20:00:45 wollman Exp $ |
35 */ 36 37#include "opt_ktrace.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/sysproto.h> 42#include <sys/filedesc.h> 43#include <sys/proc.h> 44#include <sys/fcntl.h> 45#include <sys/file.h> 46#include <sys/buf.h> 47#include <sys/malloc.h> 48#include <sys/mbuf.h> 49#include <sys/protosw.h> 50#include <sys/stat.h> 51#include <sys/socket.h> 52#include <sys/socketvar.h> 53#include <sys/signalvar.h> 54#include <sys/un.h> 55#ifdef KTRACE 56#include <sys/ktrace.h> 57#endif 58 59extern int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags, 60 int *retsize)); 61extern int recvit __P((struct proc *p, int s, struct msghdr *mp, 62 caddr_t namelenp, int *retsize)); 63 64static int accept1 __P((struct proc *p, struct accept_args *uap, int *retval, 65 int compat)); 66static int getsockname1 __P((struct proc *p, struct getsockname_args *uap, 67 int *retval, int compat)); 68static int getpeername1 __P((struct proc *p, struct getpeername_args *uap, 69 int *retval, int compat)); 70 71/* 72 * System call interface to the socket abstraction. 73 */ 74#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 75#define COMPAT_OLDSOCK 76#endif 77 78extern struct fileops socketops; 79 80int 81socket(p, uap, retval) 82 struct proc *p; 83 register struct socket_args /* { 84 int domain; 85 int type; 86 int protocol; 87 } */ *uap; 88 int *retval; 89{ 90 struct filedesc *fdp = p->p_fd; 91 struct socket *so; 92 struct file *fp; 93 int fd, error; 94 95 error = falloc(p, &fp, &fd); 96 if (error) 97 return (error); 98 fp->f_flag = FREAD|FWRITE; 99 fp->f_type = DTYPE_SOCKET; 100 fp->f_ops = &socketops; 101 error = socreate(uap->domain, &so, uap->type, uap->protocol, p); 102 if (error) { 103 fdp->fd_ofiles[fd] = 0; 104 ffree(fp); 105 } else { 106 fp->f_data = (caddr_t)so; 107 *retval = fd; 108 } 109 return (error); 110} 111 112/* ARGSUSED */ 113int 114bind(p, uap, retval) 115 struct proc *p; 116 register struct bind_args /* { 117 int s; 118 caddr_t name; 119 int namelen; 120 } */ *uap; 121 int *retval; 122{ 123 struct file *fp;
|
124 struct mbuf *nam;
|
124 struct sockaddr *sa; |
125 int error; 126 127 error = getsock(p->p_fd, uap->s, &fp); 128 if (error) 129 return (error);
|
130 error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
|
130 error = getsockaddr(&sa, uap->name, uap->namelen); |
131 if (error) 132 return (error);
|
133 error = sobind((struct socket *)fp->f_data, nam, p);
134 m_freem(nam);
|
133 error = sobind((struct socket *)fp->f_data, sa, p); 134 FREE(sa, M_SONAME); |
135 return (error); 136} 137 138/* ARGSUSED */ 139int 140listen(p, uap, retval) 141 struct proc *p; 142 register struct listen_args /* { 143 int s; 144 int backlog; 145 } */ *uap; 146 int *retval; 147{ 148 struct file *fp; 149 int error; 150 151 error = getsock(p->p_fd, uap->s, &fp); 152 if (error) 153 return (error); 154 return (solisten((struct socket *)fp->f_data, uap->backlog, p)); 155} 156 157static int 158accept1(p, uap, retval, compat) 159 struct proc *p; 160 register struct accept_args /* { 161 int s; 162 caddr_t name; 163 int *anamelen; 164 } */ *uap; 165 int *retval; 166 int compat; 167{ 168 struct file *fp;
|
169 struct mbuf *nam;
|
169 struct sockaddr *sa; |
170 int namelen, error, s; 171 struct socket *head, *so; 172 short fflag; /* type must match fp->f_flag */ 173 174 if (uap->name) { 175 error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 176 sizeof (namelen)); 177 if(error) 178 return (error); 179 } 180 error = getsock(p->p_fd, uap->s, &fp); 181 if (error) 182 return (error); 183 s = splnet(); 184 head = (struct socket *)fp->f_data; 185 if ((head->so_options & SO_ACCEPTCONN) == 0) { 186 splx(s); 187 return (EINVAL); 188 } 189 if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) { 190 splx(s); 191 return (EWOULDBLOCK); 192 } 193 while (head->so_comp.tqh_first == NULL && head->so_error == 0) { 194 if (head->so_state & SS_CANTRCVMORE) { 195 head->so_error = ECONNABORTED; 196 break; 197 } 198 error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH, 199 "accept", 0); 200 if (error) { 201 splx(s); 202 return (error); 203 } 204 } 205 if (head->so_error) { 206 error = head->so_error; 207 head->so_error = 0; 208 splx(s); 209 return (error); 210 } 211 212 /* 213 * At this point we know that there is at least one connection 214 * ready to be accepted. Remove it from the queue prior to 215 * allocating the file descriptor for it since falloc() may 216 * block allowing another process to accept the connection 217 * instead. 218 */ 219 so = head->so_comp.tqh_first; 220 TAILQ_REMOVE(&head->so_comp, so, so_list); 221 head->so_qlen--; 222 223 fflag = fp->f_flag; 224 error = falloc(p, &fp, retval); 225 if (error) { 226 /* 227 * Probably ran out of file descriptors. Put the 228 * unaccepted connection back onto the queue and 229 * do another wakeup so some other process might 230 * have a chance at it. 231 */ 232 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list); 233 head->so_qlen++; 234 wakeup_one(&head->so_timeo); 235 splx(s); 236 return (error); 237 } 238 239 so->so_state &= ~SS_COMP; 240 so->so_head = NULL; 241 242 fp->f_type = DTYPE_SOCKET; 243 fp->f_flag = fflag; 244 fp->f_ops = &socketops; 245 fp->f_data = (caddr_t)so;
|
246 nam = m_get(M_WAIT, MT_SONAME);
247 (void) soaccept(so, nam);
|
246 sa = 0; 247 (void) soaccept(so, &sa); 248 if (sa == 0) { 249 namelen = 0; 250 if (uap->name) 251 goto gotnoname; 252 return 0; 253 } 254 if ((u_long)sa < 0xf0000000) { 255 panic("accept1 bad sa"); 256 } |
257 if (uap->name) { 258#ifdef COMPAT_OLDSOCK 259 if (compat)
|
251 mtod(nam, struct osockaddr *)->sa_family =
252 mtod(nam, struct sockaddr *)->sa_family;
|
260 ((struct osockaddr *)sa)->sa_family = 261 sa->sa_family; |
262#endif
|
254 if (namelen > nam->m_len)
255 namelen = nam->m_len;
256 /* SHOULD COPY OUT A CHAIN HERE */
257 error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
258 (u_int)namelen);
|
263 if (namelen > sa->sa_len) 264 namelen = sa->sa_len; 265 error = copyout(sa, (caddr_t)uap->name, (u_int)namelen); |
266 if (!error)
|
267gotnoname: |
268 error = copyout((caddr_t)&namelen, 269 (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); 270 }
|
263 m_freem(nam);
|
271 FREE(sa, M_SONAME); |
272 splx(s); 273 return (error); 274} 275 276int 277accept(p, uap, retval) 278 struct proc *p; 279 struct accept_args *uap; 280 int *retval; 281{ 282 283 return (accept1(p, uap, retval, 0)); 284} 285 286#ifdef COMPAT_OLDSOCK 287int 288oaccept(p, uap, retval) 289 struct proc *p; 290 struct accept_args *uap; 291 int *retval; 292{ 293 294 return (accept1(p, uap, retval, 1)); 295} 296#endif /* COMPAT_OLDSOCK */ 297 298/* ARGSUSED */ 299int 300connect(p, uap, retval) 301 struct proc *p; 302 register struct connect_args /* { 303 int s; 304 caddr_t name; 305 int namelen; 306 } */ *uap; 307 int *retval; 308{ 309 struct file *fp; 310 register struct socket *so;
|
303 struct mbuf *nam;
|
311 struct sockaddr *sa; |
312 int error, s; 313 314 error = getsock(p->p_fd, uap->s, &fp); 315 if (error) 316 return (error); 317 so = (struct socket *)fp->f_data; 318 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 319 return (EALREADY);
|
312 error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
|
320 error = getsockaddr(&sa, uap->name, uap->namelen); |
321 if (error) 322 return (error);
|
315 error = soconnect(so, nam, p);
|
323 error = soconnect(so, sa, p); |
324 if (error) 325 goto bad; 326 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
|
319 m_freem(nam);
|
327 FREE(sa, M_SONAME); |
328 return (EINPROGRESS); 329 } 330 s = splnet(); 331 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 332 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 333 "connec", 0); 334 if (error) 335 break; 336 } 337 if (error == 0) { 338 error = so->so_error; 339 so->so_error = 0; 340 } 341 splx(s); 342bad: 343 so->so_state &= ~SS_ISCONNECTING;
|
336 m_freem(nam);
|
344 FREE(sa, M_SONAME); |
345 if (error == ERESTART) 346 error = EINTR; 347 return (error); 348} 349 350int 351socketpair(p, uap, retval) 352 struct proc *p; 353 register struct socketpair_args /* { 354 int domain; 355 int type; 356 int protocol; 357 int *rsv; 358 } */ *uap; 359 int retval[]; 360{ 361 register struct filedesc *fdp = p->p_fd; 362 struct file *fp1, *fp2; 363 struct socket *so1, *so2; 364 int fd, error, sv[2]; 365 366 error = socreate(uap->domain, &so1, uap->type, uap->protocol, p); 367 if (error) 368 return (error); 369 error = socreate(uap->domain, &so2, uap->type, uap->protocol, p); 370 if (error) 371 goto free1; 372 error = falloc(p, &fp1, &fd); 373 if (error) 374 goto free2; 375 sv[0] = fd; 376 fp1->f_flag = FREAD|FWRITE; 377 fp1->f_type = DTYPE_SOCKET; 378 fp1->f_ops = &socketops; 379 fp1->f_data = (caddr_t)so1; 380 error = falloc(p, &fp2, &fd); 381 if (error) 382 goto free3; 383 fp2->f_flag = FREAD|FWRITE; 384 fp2->f_type = DTYPE_SOCKET; 385 fp2->f_ops = &socketops; 386 fp2->f_data = (caddr_t)so2; 387 sv[1] = fd; 388 error = soconnect2(so1, so2); 389 if (error) 390 goto free4; 391 if (uap->type == SOCK_DGRAM) { 392 /* 393 * Datagram socket connection is asymmetric. 394 */ 395 error = soconnect2(so2, so1); 396 if (error) 397 goto free4; 398 } 399 error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 400#if 0 /* old pipe(2) syscall compatability, unused these days */ 401 retval[0] = sv[0]; /* XXX ??? */ 402 retval[1] = sv[1]; /* XXX ??? */ 403#endif 404 return (error); 405free4: 406 ffree(fp2); 407 fdp->fd_ofiles[sv[1]] = 0; 408free3: 409 ffree(fp1); 410 fdp->fd_ofiles[sv[0]] = 0; 411free2: 412 (void)soclose(so2); 413free1: 414 (void)soclose(so1); 415 return (error); 416} 417 418int 419sendit(p, s, mp, flags, retsize) 420 register struct proc *p; 421 int s; 422 register struct msghdr *mp; 423 int flags, *retsize; 424{ 425 struct file *fp; 426 struct uio auio; 427 register struct iovec *iov; 428 register int i;
|
421 struct mbuf *to, *control;
|
429 struct mbuf *control; 430 struct sockaddr *to; |
431 int len, error; 432 struct socket *so; 433#ifdef KTRACE 434 struct iovec *ktriov = NULL; 435#endif 436 437 error = getsock(p->p_fd, s, &fp); 438 if (error) 439 return (error); 440 auio.uio_iov = mp->msg_iov; 441 auio.uio_iovcnt = mp->msg_iovlen; 442 auio.uio_segflg = UIO_USERSPACE; 443 auio.uio_rw = UIO_WRITE; 444 auio.uio_procp = p; 445 auio.uio_offset = 0; /* XXX */ 446 auio.uio_resid = 0; 447 iov = mp->msg_iov; 448 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 449 if ((auio.uio_resid += iov->iov_len) < 0) 450 return (EINVAL); 451 } 452 if (mp->msg_name) {
|
444 error = sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
|
453 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); |
454 if (error) 455 return (error); 456 } else 457 to = 0; 458 if (mp->msg_control) { 459 if (mp->msg_controllen < sizeof(struct cmsghdr) 460#ifdef COMPAT_OLDSOCK 461 && mp->msg_flags != MSG_COMPAT 462#endif 463 ) { 464 error = EINVAL; 465 goto bad; 466 } 467 error = sockargs(&control, mp->msg_control, 468 mp->msg_controllen, MT_CONTROL); 469 if (error) 470 goto bad; 471#ifdef COMPAT_OLDSOCK 472 if (mp->msg_flags == MSG_COMPAT) { 473 register struct cmsghdr *cm; 474 475 M_PREPEND(control, sizeof(*cm), M_WAIT); 476 if (control == 0) { 477 error = ENOBUFS; 478 goto bad; 479 } else { 480 cm = mtod(control, struct cmsghdr *); 481 cm->cmsg_len = control->m_len; 482 cm->cmsg_level = SOL_SOCKET; 483 cm->cmsg_type = SCM_RIGHTS; 484 } 485 } 486#endif 487 } else 488 control = 0; 489#ifdef KTRACE 490 if (KTRPOINT(p, KTR_GENIO)) { 491 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 492 493 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 494 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 495 } 496#endif 497 len = auio.uio_resid; 498 so = (struct socket *)fp->f_data; 499 error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
|
491 flags);
|
500 flags, p); |
501 if (error) { 502 if (auio.uio_resid != len && (error == ERESTART || 503 error == EINTR || error == EWOULDBLOCK)) 504 error = 0; 505 if (error == EPIPE) 506 psignal(p, SIGPIPE); 507 } 508 if (error == 0) 509 *retsize = len - auio.uio_resid; 510#ifdef KTRACE 511 if (ktriov != NULL) { 512 if (error == 0) 513 ktrgenio(p->p_tracep, s, UIO_WRITE, 514 ktriov, *retsize, error); 515 FREE(ktriov, M_TEMP); 516 } 517#endif 518bad: 519 if (to)
|
511 m_freem(to);
|
520 FREE(to, M_SONAME); |
521 return (error); 522} 523 524int 525sendto(p, uap, retval) 526 struct proc *p; 527 register struct sendto_args /* { 528 int s; 529 caddr_t buf; 530 size_t len; 531 int flags; 532 caddr_t to; 533 int tolen; 534 } */ *uap; 535 int *retval; 536{ 537 struct msghdr msg; 538 struct iovec aiov; 539 540 msg.msg_name = uap->to; 541 msg.msg_namelen = uap->tolen; 542 msg.msg_iov = &aiov; 543 msg.msg_iovlen = 1; 544 msg.msg_control = 0; 545#ifdef COMPAT_OLDSOCK 546 msg.msg_flags = 0; 547#endif 548 aiov.iov_base = uap->buf; 549 aiov.iov_len = uap->len; 550 return (sendit(p, uap->s, &msg, uap->flags, retval)); 551} 552 553#ifdef COMPAT_OLDSOCK 554int 555osend(p, uap, retval) 556 struct proc *p; 557 register struct osend_args /* { 558 int s; 559 caddr_t buf; 560 int len; 561 int flags; 562 } */ *uap; 563 int *retval; 564{ 565 struct msghdr msg; 566 struct iovec aiov; 567 568 msg.msg_name = 0; 569 msg.msg_namelen = 0; 570 msg.msg_iov = &aiov; 571 msg.msg_iovlen = 1; 572 aiov.iov_base = uap->buf; 573 aiov.iov_len = uap->len; 574 msg.msg_control = 0; 575 msg.msg_flags = 0; 576 return (sendit(p, uap->s, &msg, uap->flags, retval)); 577} 578 579int 580osendmsg(p, uap, retval) 581 struct proc *p; 582 register struct osendmsg_args /* { 583 int s; 584 caddr_t msg; 585 int flags; 586 } */ *uap; 587 int *retval; 588{ 589 struct msghdr msg; 590 struct iovec aiov[UIO_SMALLIOV], *iov; 591 int error; 592 593 error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 594 if (error) 595 return (error); 596 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 597 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 598 return (EMSGSIZE); 599 MALLOC(iov, struct iovec *, 600 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 601 M_WAITOK); 602 } else 603 iov = aiov; 604 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 605 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 606 if (error) 607 goto done; 608 msg.msg_flags = MSG_COMPAT; 609 msg.msg_iov = iov; 610 error = sendit(p, uap->s, &msg, uap->flags, retval); 611done: 612 if (iov != aiov) 613 FREE(iov, M_IOV); 614 return (error); 615} 616#endif 617 618int 619sendmsg(p, uap, retval) 620 struct proc *p; 621 register struct sendmsg_args /* { 622 int s; 623 caddr_t msg; 624 int flags; 625 } */ *uap; 626 int *retval; 627{ 628 struct msghdr msg; 629 struct iovec aiov[UIO_SMALLIOV], *iov; 630 int error; 631 632 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 633 if (error) 634 return (error); 635 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 636 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 637 return (EMSGSIZE); 638 MALLOC(iov, struct iovec *, 639 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 640 M_WAITOK); 641 } else 642 iov = aiov; 643 if (msg.msg_iovlen && 644 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 645 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 646 goto done; 647 msg.msg_iov = iov; 648#ifdef COMPAT_OLDSOCK 649 msg.msg_flags = 0; 650#endif 651 error = sendit(p, uap->s, &msg, uap->flags, retval); 652done: 653 if (iov != aiov) 654 FREE(iov, M_IOV); 655 return (error); 656} 657 658int 659recvit(p, s, mp, namelenp, retsize) 660 register struct proc *p; 661 int s; 662 register struct msghdr *mp; 663 caddr_t namelenp; 664 int *retsize; 665{ 666 struct file *fp; 667 struct uio auio; 668 register struct iovec *iov; 669 register int i; 670 int len, error;
|
662 struct mbuf *m, *from = 0, *control = 0;
|
671 struct mbuf *m, *control = 0; |
672 caddr_t ctlbuf; 673 struct socket *so;
|
674 struct sockaddr *fromsa = 0; |
675#ifdef KTRACE 676 struct iovec *ktriov = NULL; 677#endif 678 679 error = getsock(p->p_fd, s, &fp); 680 if (error) 681 return (error); 682 auio.uio_iov = mp->msg_iov; 683 auio.uio_iovcnt = mp->msg_iovlen; 684 auio.uio_segflg = UIO_USERSPACE; 685 auio.uio_rw = UIO_READ; 686 auio.uio_procp = p; 687 auio.uio_offset = 0; /* XXX */ 688 auio.uio_resid = 0; 689 iov = mp->msg_iov; 690 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 691 if ((auio.uio_resid += iov->iov_len) < 0) 692 return (EINVAL); 693 } 694#ifdef KTRACE 695 if (KTRPOINT(p, KTR_GENIO)) { 696 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 697 698 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 699 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 700 } 701#endif 702 len = auio.uio_resid; 703 so = (struct socket *)fp->f_data;
|
694 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &from, &auio,
|
704 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, |
705 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 706 &mp->msg_flags); 707 if (error) { 708 if (auio.uio_resid != len && (error == ERESTART || 709 error == EINTR || error == EWOULDBLOCK)) 710 error = 0; 711 } 712#ifdef KTRACE 713 if (ktriov != NULL) { 714 if (error == 0) 715 ktrgenio(p->p_tracep, s, UIO_READ, 716 ktriov, len - auio.uio_resid, error); 717 FREE(ktriov, M_TEMP); 718 } 719#endif 720 if (error) 721 goto out; 722 *retsize = len - auio.uio_resid; 723 if (mp->msg_name) { 724 len = mp->msg_namelen;
|
715 if (len <= 0 || from == 0)
|
725 if (len <= 0 || fromsa == 0) |
726 len = 0; 727 else { 728#ifdef COMPAT_OLDSOCK 729 if (mp->msg_flags & MSG_COMPAT)
|
720 mtod(from, struct osockaddr *)->sa_family =
721 mtod(from, struct sockaddr *)->sa_family;
|
730 ((struct osockaddr *)fromsa)->sa_family = 731 fromsa->sa_family; |
732#endif
|
723 if (len > from->m_len)
724 len = from->m_len;
725 /* else if len < from->m_len ??? */
726 error = copyout(mtod(from, caddr_t),
|
733#ifndef MIN 734#define MIN(a,b) ((a)>(b)?(b):(a)) 735#endif 736 len = MIN(len, fromsa->sa_len); 737 error = copyout(fromsa, |
738 (caddr_t)mp->msg_name, (unsigned)len); 739 if (error) 740 goto out; 741 } 742 mp->msg_namelen = len; 743 if (namelenp && 744 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 745#ifdef COMPAT_OLDSOCK 746 if (mp->msg_flags & MSG_COMPAT) 747 error = 0; /* old recvfrom didn't check */ 748 else 749#endif 750 goto out; 751 } 752 } 753 if (mp->msg_control) { 754#ifdef COMPAT_OLDSOCK 755 /* 756 * We assume that old recvmsg calls won't receive access 757 * rights and other control info, esp. as control info 758 * is always optional and those options didn't exist in 4.3. 759 * If we receive rights, trim the cmsghdr; anything else 760 * is tossed. 761 */ 762 if (control && mp->msg_flags & MSG_COMPAT) { 763 if (mtod(control, struct cmsghdr *)->cmsg_level != 764 SOL_SOCKET || 765 mtod(control, struct cmsghdr *)->cmsg_type != 766 SCM_RIGHTS) { 767 mp->msg_controllen = 0; 768 goto out; 769 } 770 control->m_len -= sizeof (struct cmsghdr); 771 control->m_data += sizeof (struct cmsghdr); 772 } 773#endif 774 len = mp->msg_controllen; 775 m = control; 776 mp->msg_controllen = 0; 777 ctlbuf = (caddr_t) mp->msg_control; 778 779 while (m && len > 0) { 780 unsigned int tocopy; 781 782 if (len >= m->m_len) 783 tocopy = m->m_len; 784 else { 785 mp->msg_flags |= MSG_CTRUNC; 786 tocopy = len; 787 } 788 789 if (error = copyout((caddr_t)mtod(m, caddr_t), 790 ctlbuf, tocopy)) 791 goto out; 792 793 ctlbuf += tocopy; 794 len -= tocopy; 795 m = m->m_next; 796 } 797 mp->msg_controllen = ctlbuf - mp->msg_control; 798 } 799out:
|
789 if (from)
790 m_freem(from);
|
800 if (fromsa) 801 FREE(fromsa, M_SONAME); |
802 if (control) 803 m_freem(control); 804 return (error); 805} 806 807int 808recvfrom(p, uap, retval) 809 struct proc *p; 810 register struct recvfrom_args /* { 811 int s; 812 caddr_t buf; 813 size_t len; 814 int flags; 815 caddr_t from; 816 int *fromlenaddr; 817 } */ *uap; 818 int *retval; 819{ 820 struct msghdr msg; 821 struct iovec aiov; 822 int error; 823 824 if (uap->fromlenaddr) { 825 error = copyin((caddr_t)uap->fromlenaddr, 826 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)); 827 if (error) 828 return (error); 829 } else 830 msg.msg_namelen = 0; 831 msg.msg_name = uap->from; 832 msg.msg_iov = &aiov; 833 msg.msg_iovlen = 1; 834 aiov.iov_base = uap->buf; 835 aiov.iov_len = uap->len; 836 msg.msg_control = 0; 837 msg.msg_flags = uap->flags; 838 return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval)); 839} 840 841#ifdef COMPAT_OLDSOCK 842int 843orecvfrom(p, uap, retval) 844 struct proc *p; 845 struct recvfrom_args *uap; 846 int *retval; 847{ 848 849 uap->flags |= MSG_COMPAT; 850 return (recvfrom(p, uap, retval)); 851} 852#endif 853 854 855#ifdef COMPAT_OLDSOCK 856int 857orecv(p, uap, retval) 858 struct proc *p; 859 register struct orecv_args /* { 860 int s; 861 caddr_t buf; 862 int len; 863 int flags; 864 } */ *uap; 865 int *retval; 866{ 867 struct msghdr msg; 868 struct iovec aiov; 869 870 msg.msg_name = 0; 871 msg.msg_namelen = 0; 872 msg.msg_iov = &aiov; 873 msg.msg_iovlen = 1; 874 aiov.iov_base = uap->buf; 875 aiov.iov_len = uap->len; 876 msg.msg_control = 0; 877 msg.msg_flags = uap->flags; 878 return (recvit(p, uap->s, &msg, (caddr_t)0, retval)); 879} 880 881/* 882 * Old recvmsg. This code takes advantage of the fact that the old msghdr 883 * overlays the new one, missing only the flags, and with the (old) access 884 * rights where the control fields are now. 885 */ 886int 887orecvmsg(p, uap, retval) 888 struct proc *p; 889 register struct orecvmsg_args /* { 890 int s; 891 struct omsghdr *msg; 892 int flags; 893 } */ *uap; 894 int *retval; 895{ 896 struct msghdr msg; 897 struct iovec aiov[UIO_SMALLIOV], *iov; 898 int error; 899 900 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 901 sizeof (struct omsghdr)); 902 if (error) 903 return (error); 904 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 905 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 906 return (EMSGSIZE); 907 MALLOC(iov, struct iovec *, 908 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 909 M_WAITOK); 910 } else 911 iov = aiov; 912 msg.msg_flags = uap->flags | MSG_COMPAT; 913 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 914 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 915 if (error) 916 goto done; 917 msg.msg_iov = iov; 918 error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval); 919 920 if (msg.msg_controllen && error == 0) 921 error = copyout((caddr_t)&msg.msg_controllen, 922 (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); 923done: 924 if (iov != aiov) 925 FREE(iov, M_IOV); 926 return (error); 927} 928#endif 929 930int 931recvmsg(p, uap, retval) 932 struct proc *p; 933 register struct recvmsg_args /* { 934 int s; 935 struct msghdr *msg; 936 int flags; 937 } */ *uap; 938 int *retval; 939{ 940 struct msghdr msg; 941 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 942 register int error; 943 944 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 945 if (error) 946 return (error); 947 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 948 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 949 return (EMSGSIZE); 950 MALLOC(iov, struct iovec *, 951 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 952 M_WAITOK); 953 } else 954 iov = aiov; 955#ifdef COMPAT_OLDSOCK 956 msg.msg_flags = uap->flags &~ MSG_COMPAT; 957#else 958 msg.msg_flags = uap->flags; 959#endif 960 uiov = msg.msg_iov; 961 msg.msg_iov = iov; 962 error = copyin((caddr_t)uiov, (caddr_t)iov, 963 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 964 if (error) 965 goto done; 966 error = recvit(p, uap->s, &msg, (caddr_t)0, retval); 967 if (!error) { 968 msg.msg_iov = uiov; 969 error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 970 } 971done: 972 if (iov != aiov) 973 FREE(iov, M_IOV); 974 return (error); 975} 976 977/* ARGSUSED */ 978int 979shutdown(p, uap, retval) 980 struct proc *p; 981 register struct shutdown_args /* { 982 int s; 983 int how; 984 } */ *uap; 985 int *retval; 986{ 987 struct file *fp; 988 int error; 989 990 error = getsock(p->p_fd, uap->s, &fp); 991 if (error) 992 return (error); 993 return (soshutdown((struct socket *)fp->f_data, uap->how)); 994} 995 996/* ARGSUSED */ 997int 998setsockopt(p, uap, retval) 999 struct proc *p; 1000 register struct setsockopt_args /* { 1001 int s; 1002 int level; 1003 int name; 1004 caddr_t val; 1005 int valsize; 1006 } */ *uap; 1007 int *retval; 1008{ 1009 struct file *fp; 1010 struct mbuf *m = NULL; 1011 int error; 1012 1013 error = getsock(p->p_fd, uap->s, &fp); 1014 if (error) 1015 return (error); 1016 if (uap->valsize > MLEN) 1017 return (EINVAL); 1018 if (uap->val) { 1019 m = m_get(M_WAIT, MT_SOOPTS); 1020 if (m == NULL) 1021 return (ENOBUFS); 1022 error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 1023 if (error) { 1024 (void) m_free(m); 1025 return (error); 1026 } 1027 m->m_len = uap->valsize; 1028 } 1029 return (sosetopt((struct socket *)fp->f_data, uap->level, 1030 uap->name, m, p)); 1031} 1032 1033/* ARGSUSED */ 1034int 1035getsockopt(p, uap, retval) 1036 struct proc *p; 1037 register struct getsockopt_args /* { 1038 int s; 1039 int level; 1040 int name; 1041 caddr_t val; 1042 int *avalsize; 1043 } */ *uap; 1044 int *retval; 1045{ 1046 struct file *fp; 1047 struct mbuf *m = NULL, *m0; 1048 int op, i, valsize, error; 1049 1050 error = getsock(p->p_fd, uap->s, &fp); 1051 if (error) 1052 return (error); 1053 if (uap->val) { 1054 error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 1055 sizeof (valsize)); 1056 if (error) 1057 return (error); 1058 } else 1059 valsize = 0; 1060 if ((error = sogetopt((struct socket *)fp->f_data, uap->level, 1061 uap->name, &m, p)) == 0 && uap->val && valsize && m != NULL) { 1062 op = 0; 1063 while (m && !error && op < valsize) { 1064 i = min(m->m_len, (valsize - op)); 1065 error = copyout(mtod(m, caddr_t), uap->val, (u_int)i); 1066 op += i; 1067 uap->val += i; 1068 m0 = m; 1069 MFREE(m0,m); 1070 } 1071 valsize = op; 1072 if (error == 0) 1073 error = copyout((caddr_t)&valsize, 1074 (caddr_t)uap->avalsize, sizeof (valsize)); 1075 } 1076 if (m != NULL) 1077 (void) m_free(m); 1078 return (error); 1079} 1080 1081/* 1082 * Get socket name. 1083 */ 1084/* ARGSUSED */ 1085static int 1086getsockname1(p, uap, retval, compat) 1087 struct proc *p; 1088 register struct getsockname_args /* { 1089 int fdes; 1090 caddr_t asa; 1091 int *alen; 1092 } */ *uap; 1093 int *retval; 1094 int compat; 1095{ 1096 struct file *fp; 1097 register struct socket *so;
|
1087 struct mbuf *m;
|
1098 struct sockaddr *sa; |
1099 int len, error; 1100 1101 error = getsock(p->p_fd, uap->fdes, &fp); 1102 if (error) 1103 return (error); 1104 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1105 if (error) 1106 return (error); 1107 so = (struct socket *)fp->f_data;
|
1097 m = m_getclr(M_WAIT, MT_SONAME);
1098 if (m == NULL)
1099 return (ENOBUFS);
1100 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m);
|
1108 sa = 0; 1109 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa); |
1110 if (error) 1111 goto bad;
|
1103 if (len > m->m_len)
1104 len = m->m_len;
|
1112 if (sa == 0) { 1113 len = 0; 1114 goto gotnothing; 1115 } 1116 1117 len = MIN(len, sa->sa_len); |
1118#ifdef COMPAT_OLDSOCK 1119 if (compat)
|
1107 mtod(m, struct osockaddr *)->sa_family =
1108 mtod(m, struct sockaddr *)->sa_family;
|
1120 ((struct osockaddr *)sa)->sa_family = sa->sa_family; |
1121#endif
|
1110 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
|
1122 error = copyout(sa, (caddr_t)uap->asa, (u_int)len); |
1123 if (error == 0)
|
1124gotnothing: |
1125 error = copyout((caddr_t)&len, (caddr_t)uap->alen, 1126 sizeof (len)); 1127bad:
|
1115 m_freem(m);
|
1128 if (sa) 1129 FREE(sa, M_SONAME); |
1130 return (error); 1131} 1132 1133int 1134getsockname(p, uap, retval) 1135 struct proc *p; 1136 struct getsockname_args *uap; 1137 int *retval; 1138{ 1139 1140 return (getsockname1(p, uap, retval, 0)); 1141} 1142 1143#ifdef COMPAT_OLDSOCK 1144int 1145ogetsockname(p, uap, retval) 1146 struct proc *p; 1147 struct getsockname_args *uap; 1148 int *retval; 1149{ 1150 1151 return (getsockname1(p, uap, retval, 1)); 1152} 1153#endif /* COMPAT_OLDSOCK */ 1154 1155/* 1156 * Get name of peer for connected socket. 1157 */ 1158/* ARGSUSED */ 1159static int 1160getpeername1(p, uap, retval, compat) 1161 struct proc *p; 1162 register struct getpeername_args /* { 1163 int fdes; 1164 caddr_t asa; 1165 int *alen; 1166 } */ *uap; 1167 int *retval; 1168 int compat; 1169{ 1170 struct file *fp; 1171 register struct socket *so;
|
1158 struct mbuf *m;
|
1172 struct sockaddr *sa; |
1173 int len, error; 1174 1175 error = getsock(p->p_fd, uap->fdes, &fp); 1176 if (error) 1177 return (error); 1178 so = (struct socket *)fp->f_data; 1179 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1180 return (ENOTCONN); 1181 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1182 if (error) 1183 return (error);
|
1170 m = m_getclr(M_WAIT, MT_SONAME);
1171 if (m == NULL)
1172 return (ENOBUFS);
1173 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m);
|
1184 sa = 0; 1185 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa); |
1186 if (error) 1187 goto bad;
|
1176 if (len > m->m_len)
1177 len = m->m_len;
|
1188 if (sa == 0) { 1189 len = 0; 1190 goto gotnothing; 1191 } 1192 len = MIN(len, sa->sa_len); |
1193#ifdef COMPAT_OLDSOCK 1194 if (compat)
|
1180 mtod(m, struct osockaddr *)->sa_family =
1181 mtod(m, struct sockaddr *)->sa_family;
|
1195 ((struct osockaddr *)sa)->sa_family = 1196 sa->sa_family; |
1197#endif
|
1183 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
|
1198 error = copyout(sa, (caddr_t)uap->asa, (u_int)len); |
1199 if (error) 1200 goto bad;
|
1201gotnothing: |
1202 error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1203bad:
|
1188 m_freem(m);
|
1204 if (sa) FREE(sa, M_SONAME); |
1205 return (error); 1206} 1207 1208int 1209getpeername(p, uap, retval) 1210 struct proc *p; 1211 struct getpeername_args *uap; 1212 int *retval; 1213{ 1214 1215 return (getpeername1(p, uap, retval, 0)); 1216} 1217 1218#ifdef COMPAT_OLDSOCK 1219int 1220ogetpeername(p, uap, retval) 1221 struct proc *p; 1222 struct ogetpeername_args *uap; 1223 int *retval; 1224{ 1225 1226 /* XXX uap should have type `getpeername_args *' to begin with. */ 1227 return (getpeername1(p, (struct getpeername_args *)uap, retval, 1)); 1228} 1229#endif /* COMPAT_OLDSOCK */ 1230 1231int 1232sockargs(mp, buf, buflen, type) 1233 struct mbuf **mp; 1234 caddr_t buf; 1235 int buflen, type; 1236{ 1237 register struct sockaddr *sa; 1238 register struct mbuf *m; 1239 int error; 1240 1241 if ((u_int)buflen > MLEN) { 1242#ifdef COMPAT_OLDSOCK 1243 if (type == MT_SONAME && (u_int)buflen <= 112) 1244 buflen = MLEN; /* unix domain compat. hack */ 1245 else 1246#endif 1247 return (EINVAL); 1248 } 1249 m = m_get(M_WAIT, type); 1250 if (m == NULL) 1251 return (ENOBUFS); 1252 m->m_len = buflen; 1253 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1254 if (error) 1255 (void) m_free(m); 1256 else { 1257 *mp = m; 1258 if (type == MT_SONAME) { 1259 sa = mtod(m, struct sockaddr *); 1260 1261#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1262 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1263 sa->sa_family = sa->sa_len; 1264#endif 1265 sa->sa_len = buflen; 1266 } 1267 } 1268 return (error); 1269} 1270 1271int
|
1272getsockaddr(namp, uaddr, len) 1273 struct sockaddr **namp; 1274 caddr_t uaddr; 1275 size_t len; 1276{ 1277 struct sockaddr *sa; 1278 int error; 1279 1280 if (len > SOCK_MAXADDRLEN) 1281 return ENAMETOOLONG; 1282 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK); 1283 error = copyin(uaddr, sa, len); 1284 if (error) { 1285 FREE(sa, M_SONAME); 1286 } else { 1287#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1288 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1289 sa->sa_family = sa->sa_len; 1290#endif 1291 sa->sa_len = len; 1292 *namp = sa; 1293 } 1294 return error; 1295} 1296 1297int |
1298getsock(fdp, fdes, fpp) 1299 struct filedesc *fdp; 1300 int fdes; 1301 struct file **fpp; 1302{ 1303 register struct file *fp; 1304 1305 if ((unsigned)fdes >= fdp->fd_nfiles || 1306 (fp = fdp->fd_ofiles[fdes]) == NULL) 1307 return (EBADF); 1308 if (fp->f_type != DTYPE_SOCKET) 1309 return (ENOTSOCK); 1310 *fpp = fp; 1311 return (0); 1312}
|