Home | History | Annotate | Download | only in socket
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/unix_domain_listen_socket_posix.h"
      6 
      7 #include <errno.h>
      8 #include <sys/socket.h>
      9 #include <sys/stat.h>
     10 #include <sys/types.h>
     11 #include <sys/un.h>
     12 #include <unistd.h>
     13 
     14 #include <cstring>
     15 #include <string>
     16 
     17 #include "base/bind.h"
     18 #include "base/callback.h"
     19 #include "base/posix/eintr_wrapper.h"
     20 #include "base/threading/platform_thread.h"
     21 #include "build/build_config.h"
     22 #include "net/base/net_errors.h"
     23 #include "net/base/net_util.h"
     24 #include "net/socket/socket_descriptor.h"
     25 #include "net/socket/unix_domain_client_socket_posix.h"
     26 
     27 namespace net {
     28 namespace deprecated {
     29 
     30 namespace {
     31 
     32 int CreateAndBind(const std::string& socket_path,
     33                   bool use_abstract_namespace,
     34                   SocketDescriptor* socket_fd) {
     35   DCHECK(socket_fd);
     36 
     37   SockaddrStorage address;
     38   if (!UnixDomainClientSocket::FillAddress(socket_path,
     39                                            use_abstract_namespace,
     40                                            &address)) {
     41     return ERR_ADDRESS_INVALID;
     42   }
     43 
     44   SocketDescriptor fd = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
     45   if (fd == kInvalidSocket)
     46     return errno ? MapSystemError(errno) : ERR_UNEXPECTED;
     47 
     48   if (bind(fd, address.addr, address.addr_len) < 0) {
     49     int rv = MapSystemError(errno);
     50     close(fd);
     51     PLOG(ERROR) << "Could not bind unix domain socket to " << socket_path
     52                 << (use_abstract_namespace ? " (with abstract namespace)" : "");
     53     return rv;
     54   }
     55 
     56   *socket_fd = fd;
     57   return OK;
     58 }
     59 
     60 }  // namespace
     61 
     62 // static
     63 scoped_ptr<UnixDomainListenSocket>
     64 UnixDomainListenSocket::CreateAndListenInternal(
     65     const std::string& path,
     66     const std::string& fallback_path,
     67     StreamListenSocket::Delegate* del,
     68     const AuthCallback& auth_callback,
     69     bool use_abstract_namespace) {
     70   SocketDescriptor socket_fd = kInvalidSocket;
     71   int rv = CreateAndBind(path, use_abstract_namespace, &socket_fd);
     72   if (rv != OK && !fallback_path.empty())
     73     rv = CreateAndBind(fallback_path, use_abstract_namespace, &socket_fd);
     74   if (rv != OK)
     75     return scoped_ptr<UnixDomainListenSocket>();
     76   scoped_ptr<UnixDomainListenSocket> sock(
     77       new UnixDomainListenSocket(socket_fd, del, auth_callback));
     78   sock->Listen();
     79   return sock.Pass();
     80 }
     81 
     82 // static
     83 scoped_ptr<UnixDomainListenSocket> UnixDomainListenSocket::CreateAndListen(
     84     const std::string& path,
     85     StreamListenSocket::Delegate* del,
     86     const AuthCallback& auth_callback) {
     87   return CreateAndListenInternal(path, "", del, auth_callback, false);
     88 }
     89 
     90 #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
     91 // static
     92 scoped_ptr<UnixDomainListenSocket>
     93 UnixDomainListenSocket::CreateAndListenWithAbstractNamespace(
     94     const std::string& path,
     95     const std::string& fallback_path,
     96     StreamListenSocket::Delegate* del,
     97     const AuthCallback& auth_callback) {
     98   return
     99       CreateAndListenInternal(path, fallback_path, del, auth_callback, true);
    100 }
    101 #endif
    102 
    103 UnixDomainListenSocket::UnixDomainListenSocket(
    104     SocketDescriptor s,
    105     StreamListenSocket::Delegate* del,
    106     const AuthCallback& auth_callback)
    107     : StreamListenSocket(s, del),
    108       auth_callback_(auth_callback) {}
    109 
    110 UnixDomainListenSocket::~UnixDomainListenSocket() {}
    111 
    112 void UnixDomainListenSocket::Accept() {
    113   SocketDescriptor conn = StreamListenSocket::AcceptSocket();
    114   if (conn == kInvalidSocket)
    115     return;
    116   UnixDomainServerSocket::Credentials credentials;
    117   if (!UnixDomainServerSocket::GetPeerCredentials(conn, &credentials) ||
    118       !auth_callback_.Run(credentials)) {
    119     if (IGNORE_EINTR(close(conn)) < 0)
    120       LOG(ERROR) << "close() error";
    121     return;
    122   }
    123   scoped_ptr<UnixDomainListenSocket> sock(
    124       new UnixDomainListenSocket(conn, socket_delegate_, auth_callback_));
    125   // It's up to the delegate to AddRef if it wants to keep it around.
    126   sock->WatchSocket(WAITING_READ);
    127   socket_delegate_->DidAccept(this, sock.PassAs<StreamListenSocket>());
    128 }
    129 
    130 UnixDomainListenSocketFactory::UnixDomainListenSocketFactory(
    131     const std::string& path,
    132     const UnixDomainListenSocket::AuthCallback& auth_callback)
    133     : path_(path),
    134       auth_callback_(auth_callback) {}
    135 
    136 UnixDomainListenSocketFactory::~UnixDomainListenSocketFactory() {}
    137 
    138 scoped_ptr<StreamListenSocket> UnixDomainListenSocketFactory::CreateAndListen(
    139     StreamListenSocket::Delegate* delegate) const {
    140   return UnixDomainListenSocket::CreateAndListen(
    141       path_, delegate, auth_callback_).PassAs<StreamListenSocket>();
    142 }
    143 
    144 #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
    145 
    146 UnixDomainListenSocketWithAbstractNamespaceFactory::
    147 UnixDomainListenSocketWithAbstractNamespaceFactory(
    148     const std::string& path,
    149     const std::string& fallback_path,
    150     const UnixDomainListenSocket::AuthCallback& auth_callback)
    151     : UnixDomainListenSocketFactory(path, auth_callback),
    152       fallback_path_(fallback_path) {}
    153 
    154 UnixDomainListenSocketWithAbstractNamespaceFactory::
    155 ~UnixDomainListenSocketWithAbstractNamespaceFactory() {}
    156 
    157 scoped_ptr<StreamListenSocket>
    158 UnixDomainListenSocketWithAbstractNamespaceFactory::CreateAndListen(
    159     StreamListenSocket::Delegate* delegate) const {
    160   return UnixDomainListenSocket::CreateAndListenWithAbstractNamespace(
    161              path_, fallback_path_, delegate, auth_callback_)
    162          .PassAs<StreamListenSocket>();
    163 }
    164 
    165 #endif
    166 
    167 }  // namespace deprecated
    168 }  // namespace net
    169