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