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 27namespace net { 28namespace deprecated { 29 30namespace { 31 32int 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 63scoped_ptr<UnixDomainListenSocket> 64UnixDomainListenSocket::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 83scoped_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 92scoped_ptr<UnixDomainListenSocket> 93UnixDomainListenSocket::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 103UnixDomainListenSocket::UnixDomainListenSocket( 104 SocketDescriptor s, 105 StreamListenSocket::Delegate* del, 106 const AuthCallback& auth_callback) 107 : StreamListenSocket(s, del), 108 auth_callback_(auth_callback) {} 109 110UnixDomainListenSocket::~UnixDomainListenSocket() {} 111 112void 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 130UnixDomainListenSocketFactory::UnixDomainListenSocketFactory( 131 const std::string& path, 132 const UnixDomainListenSocket::AuthCallback& auth_callback) 133 : path_(path), 134 auth_callback_(auth_callback) {} 135 136UnixDomainListenSocketFactory::~UnixDomainListenSocketFactory() {} 137 138scoped_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 146UnixDomainListenSocketWithAbstractNamespaceFactory:: 147UnixDomainListenSocketWithAbstractNamespaceFactory( 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 154UnixDomainListenSocketWithAbstractNamespaceFactory:: 155~UnixDomainListenSocketWithAbstractNamespaceFactory() {} 156 157scoped_ptr<StreamListenSocket> 158UnixDomainListenSocketWithAbstractNamespaceFactory::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