LLDB  mainline
DomainSocket.cpp
Go to the documentation of this file.
1 //===-- DomainSocket.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "llvm/Support/Errno.h"
12 #include "llvm/Support/FileSystem.h"
13 
14 #include <stddef.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 #ifdef __ANDROID__
22 // Android does not have SUN_LEN
23 #ifndef SUN_LEN
24 #define SUN_LEN(ptr) \
25  (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))
26 #endif
27 #endif // #ifdef __ANDROID__
28 
29 namespace {
30 
31 const int kDomain = AF_UNIX;
32 const int kType = SOCK_STREAM;
33 
34 bool SetSockAddr(llvm::StringRef name, const size_t name_offset,
35  sockaddr_un *saddr_un, socklen_t &saddr_un_len) {
36  if (name.size() + name_offset > sizeof(saddr_un->sun_path))
37  return false;
38 
39  memset(saddr_un, 0, sizeof(*saddr_un));
40  saddr_un->sun_family = kDomain;
41 
42  memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
43 
44  // For domain sockets we can use SUN_LEN in order to calculate size of
45  // sockaddr_un, but for abstract sockets we have to calculate size manually
46  // because of leading null symbol.
47  if (name_offset == 0)
48  saddr_un_len = SUN_LEN(saddr_un);
49  else
50  saddr_un_len =
51  offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
52 
53 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
54  saddr_un->sun_len = saddr_un_len;
55 #endif
56 
57  return true;
58 }
59 } // namespace
60 
61 DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit)
62  : Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {}
63 
65  bool child_processes_inherit)
66  : Socket(protocol, true, child_processes_inherit) {}
67 
69  const DomainSocket &listen_socket)
70  : Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd,
71  listen_socket.m_child_processes_inherit) {
72  m_socket = socket;
73 }
74 
75 Status DomainSocket::Connect(llvm::StringRef name) {
76  sockaddr_un saddr_un;
77  socklen_t saddr_un_len;
78  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
79  return Status("Failed to set socket address");
80 
81  Status error;
83  if (error.Fail())
84  return error;
85  if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
86  (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
88 
89  return error;
90 }
91 
92 Status DomainSocket::Listen(llvm::StringRef name, int backlog) {
93  sockaddr_un saddr_un;
94  socklen_t saddr_un_len;
95  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
96  return Status("Failed to set socket address");
97 
98  DeleteSocketFile(name);
99 
100  Status error;
101  m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
102  if (error.Fail())
103  return error;
104  if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==
105  0)
106  if (::listen(GetNativeSocket(), backlog) == 0)
107  return error;
108 
110  return error;
111 }
112 
114  Status error;
115  auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,
117  if (error.Success())
118  socket = new DomainSocket(conn_fd, *this);
119 
120  return error;
121 }
122 
123 size_t DomainSocket::GetNameOffset() const { return 0; }
124 
125 void DomainSocket::DeleteSocketFile(llvm::StringRef name) {
126  llvm::sys::fs::remove(name);
127 }
128 
130  if (m_socket != kInvalidSocketValue) {
131  struct sockaddr_un saddr_un;
132  saddr_un.sun_family = AF_UNIX;
133  socklen_t sock_addr_len = sizeof(struct sockaddr_un);
134  if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) ==
135  0) {
136  std::string name(saddr_un.sun_path + GetNameOffset(),
137  sock_addr_len -
138  offsetof(struct sockaddr_un, sun_path) -
139  GetNameOffset());
140  if (name.back() == '\0') name.pop_back();
141  return name;
142  }
143  }
144  return "";
145 }
146 
148  if (m_socket != kInvalidSocketValue) {
149  return std::string(llvm::formatv(
150  "{0}://{1}",
151  GetNameOffset() == 0 ? "unix-connect" : "unix-abstract-connect",
152  GetSocketName()));
153  }
154  return "";
155 }
lldb_private::Socket::kInvalidSocketValue
static const NativeSocket kInvalidSocketValue
Definition: Socket.h:51
lldb_private::Socket::SetLastError
static void SetLastError(Status &error)
lldb_private::DomainSocket
Definition: DomainSocket.h:15
lldb_private::Socket::m_child_processes_inherit
bool m_child_processes_inherit
Definition: Socket.h:129
lldb_private::Socket::SocketProtocol
SocketProtocol
Definition: Socket.h:44
lldb_private::Socket
Definition: Socket.h:42
lldb_private::DomainSocket::GetRemoteConnectionURI
std::string GetRemoteConnectionURI() const override
Definition: DomainSocket.cpp:147
lldb_private::DomainSocket::GetNameOffset
virtual size_t GetNameOffset() const
Definition: DomainSocket.cpp:123
lldb_private::DomainSocket::GetSocketName
std::string GetSocketName() const
Definition: DomainSocket.cpp:129
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::DomainSocket::Connect
Status Connect(llvm::StringRef name) override
Definition: DomainSocket.cpp:75
lldb_private::Socket::m_socket
NativeSocket m_socket
Definition: Socket.h:128
lldb_private::DomainSocket::Accept
Status Accept(Socket *&socket) override
Definition: DomainSocket.cpp:113
lldb_private::Socket::GetNativeSocket
NativeSocket GetNativeSocket() const
Definition: Socket.h:94
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::NativeSocket
int NativeSocket
Definition: Socket.h:37
lldb_private::Status
Definition: Status.h:44
lldb_private::Socket::CreateSocket
static NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit, Status &error)
lldb_private::Socket::AcceptSocket
static NativeSocket AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit, Status &error)
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
DomainSocket.h
lldb_private::DomainSocket::Listen
Status Listen(llvm::StringRef name, int backlog) override
Definition: DomainSocket.cpp:92
lldb_private::DomainSocket::DeleteSocketFile
virtual void DeleteSocketFile(llvm::StringRef name)
Definition: DomainSocket.cpp:125
lldb
Definition: SBAddress.h:15
lldb_private::DomainSocket::DomainSocket
DomainSocket(bool should_close, bool child_processes_inherit)
Definition: DomainSocket.cpp:61