// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/posix/unix_domain_socket_linux.h"

#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>

#include <vector>

#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"

#if !defined(__native_client_nonsfi__)
#include <sys/uio.h>
#endif

const size_t UnixDomainSocket::kMaxFileDescriptors = 16;

#if !defined(__native_client_nonsfi__)
// Creates a connected pair of UNIX-domain SOCK_SEQPACKET sockets, and passes
// ownership of the newly allocated file descriptors to |one| and |two|.
// Returns true on success.
static bool CreateSocketPair(base::ScopedFD* one, base::ScopedFD* two) {
  int raw_socks[2];
  if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks) == -1)
    return false;
  one->reset(raw_socks[0]);
  two->reset(raw_socks[1]);
  return true;
}

// static
bool UnixDomainSocket::EnableReceiveProcessId(int fd) {
  const int enable = 1;
  return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0;
}
#endif  // !defined(__native_client_nonsfi__)

// static
bool UnixDomainSocket::SendMsg(int fd,
                               const void* buf,
                               size_t length,
                               const std::vector<int>& fds) {
  struct msghdr msg = {};
  struct iovec iov = { const_cast<void*>(buf), length };
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  char* control_buffer = NULL;
  if (fds.size()) {
    const unsigned control_len = CMSG_SPACE(sizeof(int) * fds.size());
    control_buffer = new char[control_len];

    struct cmsghdr* cmsg;
    msg.msg_control = control_buffer;
    msg.msg_controllen = control_len;
    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
    memcpy(CMSG_DATA(cmsg), &fds[0], sizeof(int) * fds.size());
    msg.msg_controllen = cmsg->cmsg_len;
  }

  // Avoid a SIGPIPE if the other end breaks the connection.
  // Due to a bug in the Linux kernel (net/unix/af_unix.c) MSG_NOSIGNAL isn't
  // regarded for SOCK_SEQPACKET in the AF_UNIX domain, but it is mandated by
  // POSIX.
  const int flags = MSG_NOSIGNAL;
  const ssize_t r = HANDLE_EINTR(sendmsg(fd, &msg, flags));
  const bool ret = static_cast<ssize_t>(length) == r;
  delete[] control_buffer;
  return ret;
}

// static
ssize_t UnixDomainSocket::RecvMsg(int fd,
                                  void* buf,
                                  size_t length,
                                  ScopedVector<base::ScopedFD>* fds) {
  return UnixDomainSocket::RecvMsgWithPid(fd, buf, length, fds, NULL);
}

// static
ssize_t UnixDomainSocket::RecvMsgWithPid(int fd,
                                         void* buf,
                                         size_t length,
                                         ScopedVector<base::ScopedFD>* fds,
                                         base::ProcessId* pid) {
  return UnixDomainSocket::RecvMsgWithFlags(fd, buf, length, 0, fds, pid);
}

// static
ssize_t UnixDomainSocket::RecvMsgWithFlags(int fd,
                                           void* buf,
                                           size_t length,
                                           int flags,
                                           ScopedVector<base::ScopedFD>* fds,
                                           base::ProcessId* out_pid) {
  fds->clear();

  struct msghdr msg = {};
  struct iovec iov = { buf, length };
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  const size_t kControlBufferSize =
      CMSG_SPACE(sizeof(int) * kMaxFileDescriptors)
#if !defined(__native_client_nonsfi__)
      // The PNaCl toolchain for Non-SFI binary build does not support ucred.
      + CMSG_SPACE(sizeof(struct ucred))
#endif
      ;
  char control_buffer[kControlBufferSize];
  msg.msg_control = control_buffer;
  msg.msg_controllen = sizeof(control_buffer);

  const ssize_t r = HANDLE_EINTR(recvmsg(fd, &msg, flags));
  if (r == -1)
    return -1;

  int* wire_fds = NULL;
  unsigned wire_fds_len = 0;
  base::ProcessId pid = -1;

  if (msg.msg_controllen > 0) {
    struct cmsghdr* cmsg;
    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
      const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
      if (cmsg->cmsg_level == SOL_SOCKET &&
          cmsg->cmsg_type == SCM_RIGHTS) {
        DCHECK(payload_len % sizeof(int) == 0);
        DCHECK(wire_fds == NULL);
        wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
        wire_fds_len = payload_len / sizeof(int);
      }
#if !defined(__native_client_nonsfi__)
      // The PNaCl toolchain for Non-SFI binary build does not support
      // SCM_CREDENTIALS.
      if (cmsg->cmsg_level == SOL_SOCKET &&
          cmsg->cmsg_type == SCM_CREDENTIALS) {
        DCHECK(payload_len == sizeof(struct ucred));
        DCHECK(pid == -1);
        pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid;
      }
#endif
    }
  }

#if !defined(__native_client_nonsfi__)
  // The PNaCl toolchain for Non-SFI binary build does not support
  // MSG_TRUNC or MSG_CTRUNC.
  if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
    for (unsigned i = 0; i < wire_fds_len; ++i)
      close(wire_fds[i]);
    errno = EMSGSIZE;
    return -1;
  }
#endif

  if (wire_fds) {
    for (unsigned i = 0; i < wire_fds_len; ++i)
      fds->push_back(new base::ScopedFD(wire_fds[i]));
  }

  if (out_pid) {
    // |pid| will legitimately be -1 if we read EOF, so only DCHECK if we
    // actually received a message.  Unfortunately, Linux allows sending zero
    // length messages, which are indistinguishable from EOF, so this check
    // has false negatives.
    if (r > 0 || msg.msg_controllen > 0)
      DCHECK_GE(pid, 0);

    *out_pid = pid;
  }

  return r;
}

#if !defined(__native_client_nonsfi__)
// static
ssize_t UnixDomainSocket::SendRecvMsg(int fd,
                                      uint8_t* reply,
                                      unsigned max_reply_len,
                                      int* result_fd,
                                      const Pickle& request) {
  return UnixDomainSocket::SendRecvMsgWithFlags(fd, reply, max_reply_len,
                                                0,  /* recvmsg_flags */
                                                result_fd, request);
}

// static
ssize_t UnixDomainSocket::SendRecvMsgWithFlags(int fd,
                                               uint8_t* reply,
                                               unsigned max_reply_len,
                                               int recvmsg_flags,
                                               int* result_fd,
                                               const Pickle& request) {
  // This socketpair is only used for the IPC and is cleaned up before
  // returning.
  base::ScopedFD recv_sock, send_sock;
  if (!CreateSocketPair(&recv_sock, &send_sock))
    return -1;

  {
    std::vector<int> send_fds;
    send_fds.push_back(send_sock.get());
    if (!SendMsg(fd, request.data(), request.size(), send_fds))
      return -1;
  }

  // Close the sending end of the socket right away so that if our peer closes
  // it before sending a response (e.g., from exiting), RecvMsgWithFlags() will
  // return EOF instead of hanging.
  send_sock.reset();

  ScopedVector<base::ScopedFD> recv_fds;
  // When porting to OSX keep in mind it doesn't support MSG_NOSIGNAL, so the
  // sender might get a SIGPIPE.
  const ssize_t reply_len = RecvMsgWithFlags(
      recv_sock.get(), reply, max_reply_len, recvmsg_flags, &recv_fds, NULL);
  recv_sock.reset();
  if (reply_len == -1)
    return -1;

  // If we received more file descriptors than caller expected, then we treat
  // that as an error.
  if (recv_fds.size() > (result_fd != NULL ? 1 : 0)) {
    NOTREACHED();
    return -1;
  }

  if (result_fd)
    *result_fd = recv_fds.empty() ? -1 : recv_fds[0]->release();

  return reply_len;
}
#endif  // !defined(__native_client_nonsfi__)
