| 483 | } |
| 484 | |
| 485 | int |
| 486 | kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) |
| 487 | { |
| 488 | struct socket *so; |
| 489 | struct file *fp; |
| 490 | int error, interrupted = 0; |
| 491 | |
| 492 | #ifdef CAPABILITY_MODE |
| 493 | if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD)) |
| 494 | return (ECAPMODE); |
| 495 | #endif |
| 496 | |
| 497 | AUDIT_ARG_FD(fd); |
| 498 | AUDIT_ARG_SOCKADDR(td, dirfd, sa); |
| 499 | error = getsock_cap(td, fd, &cap_connect_rights, |
| 500 | &fp, NULL, NULL); |
| 501 | if (error != 0) |
| 502 | return (error); |
| 503 | so = fp->f_data; |
| 504 | if (so->so_state & SS_ISCONNECTING) { |
| 505 | error = EALREADY; |
| 506 | goto done1; |
| 507 | } |
| 508 | #ifdef KTRACE |
| 509 | if (KTRPOINT(td, KTR_STRUCT)) |
| 510 | ktrsockaddr(sa); |
| 511 | #endif |
| 512 | #ifdef MAC |
| 513 | error = mac_socket_check_connect(td->td_ucred, so, sa); |
| 514 | if (error != 0) |
| 515 | goto bad; |
| 516 | #endif |
| 517 | if (dirfd == AT_FDCWD) |
| 518 | error = soconnect(so, sa, td); |
| 519 | else |
| 520 | error = soconnectat(dirfd, so, sa, td); |
| 521 | if (error != 0) |
| 522 | goto bad; |
| 523 | if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { |
| 524 | error = EINPROGRESS; |
| 525 | goto done1; |
| 526 | } |
| 527 | SOCK_LOCK(so); |
| 528 | while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { |
| 529 | error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH, |
| 530 | "connec", 0); |
| 531 | if (error != 0) { |
| 532 | if (error == EINTR || error == ERESTART) |
| 533 | interrupted = 1; |
| 534 | break; |
| 535 | } |
| 536 | } |
| 537 | if (error == 0) { |
| 538 | error = so->so_error; |
| 539 | so->so_error = 0; |
| 540 | } |
| 541 | SOCK_UNLOCK(so); |
| 542 | bad: |
no test coverage detected