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 <cstddef>
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 static const int kDomain = AF_UNIX;
30 static const int kType = SOCK_STREAM;
31 
32 static bool SetSockAddr(llvm::StringRef name, const size_t name_offset,
33  sockaddr_un *saddr_un, socklen_t &saddr_un_len) {
34  if (name.size() + name_offset > sizeof(saddr_un->sun_path))
35  return false;
36 
37  memset(saddr_un, 0, sizeof(*saddr_un));
38  saddr_un->sun_family = kDomain;
39 
40  memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
41 
42  // For domain sockets we can use SUN_LEN in order to calculate size of
43  // sockaddr_un, but for abstract sockets we have to calculate size manually
44  // because of leading null symbol.
45  if (name_offset == 0)
46  saddr_un_len = SUN_LEN(saddr_un);
47  else
48  saddr_un_len =
49  offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
50 
51 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
52  saddr_un->sun_len = saddr_un_len;
53 #endif
54 
55  return true;
56 }
57 
58 DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit)
59  : Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {}
60 
62  bool child_processes_inherit)
63  : Socket(protocol, true, child_processes_inherit) {}
64 
66  const DomainSocket &listen_socket)
67  : Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd,
68  listen_socket.m_child_processes_inherit) {
69  m_socket = socket;
70 }
71 
72 Status DomainSocket::Connect(llvm::StringRef name) {
73  sockaddr_un saddr_un;
74  socklen_t saddr_un_len;
75  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
76  return Status("Failed to set socket address");
77 
78  Status error;
80  if (error.Fail())
81  return error;
82  if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
83  (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
85 
86  return error;
87 }
88 
89 Status DomainSocket::Listen(llvm::StringRef name, int backlog) {
90  sockaddr_un saddr_un;
91  socklen_t saddr_un_len;
92  if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
93  return Status("Failed to set socket address");
94 
95  DeleteSocketFile(name);
96 
97  Status error;
99  if (error.Fail())
100  return error;
101  if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==
102  0)
103  if (::listen(GetNativeSocket(), backlog) == 0)
104  return error;
105 
107  return error;
108 }
109 
111  Status error;
112  auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,
114  if (error.Success())
115  socket = new DomainSocket(conn_fd, *this);
116 
117  return error;
118 }
119 
120 size_t DomainSocket::GetNameOffset() const { return 0; }
121 
122 void DomainSocket::DeleteSocketFile(llvm::StringRef name) {
123  llvm::sys::fs::remove(name);
124 }
125 
128  return "";
129 
130  struct sockaddr_un saddr_un;
131  saddr_un.sun_family = AF_UNIX;
132  socklen_t sock_addr_len = sizeof(struct sockaddr_un);
133  if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) !=
134  0)
135  return "";
136 
137  if (sock_addr_len <= offsetof(struct sockaddr_un, sun_path))
138  return ""; // Unnamed domain socket
139 
140  llvm::StringRef name(saddr_un.sun_path + GetNameOffset(),
141  sock_addr_len - offsetof(struct sockaddr_un, sun_path) -
142  GetNameOffset());
143  name = name.rtrim('\0');
144 
145  return name.str();
146 }
147 
149  std::string name = GetSocketName();
150  if (name.empty())
151  return name;
152 
153  return llvm::formatv(
154  "{0}://{1}",
155  GetNameOffset() == 0 ? "unix-connect" : "unix-abstract-connect", name);
156 }
lldb_private::Socket::kInvalidSocketValue
static const NativeSocket kInvalidSocketValue
Definition: Socket.h:59
lldb_private::Socket::SetLastError
static void SetLastError(Status &error)
SetSockAddr
static bool SetSockAddr(llvm::StringRef name, const size_t name_offset, sockaddr_un *saddr_un, socklen_t &saddr_un_len)
Definition: DomainSocket.cpp:32
lldb_private::DomainSocket
Definition: DomainSocket.h:15
lldb_private::Socket::m_child_processes_inherit
bool m_child_processes_inherit
Definition: Socket.h:124
lldb_private::Socket::SocketProtocol
SocketProtocol
Definition: Socket.h:43
lldb_private::Socket
Definition: Socket.h:41
lldb_private::DomainSocket::GetRemoteConnectionURI
std::string GetRemoteConnectionURI() const override
Definition: DomainSocket.cpp:148
lldb_private::DomainSocket::GetNameOffset
virtual size_t GetNameOffset() const
Definition: DomainSocket.cpp:120
lldb_private::DomainSocket::GetSocketName
std::string GetSocketName() const
Definition: DomainSocket.cpp:126
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:72
lldb_private::Socket::m_socket
NativeSocket m_socket
Definition: Socket.h:123
lldb_private::DomainSocket::Accept
Status Accept(Socket *&socket) override
Definition: DomainSocket.cpp:110
lldb_private::Socket::GetNativeSocket
NativeSocket GetNativeSocket() const
Definition: Socket.h:90
kType
static const int kType
Definition: DomainSocket.cpp:30
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::NativeSocket
int NativeSocket
Definition: Socket.h:36
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)
kDomain
static const int kDomain
Definition: DomainSocket.cpp:29
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:89
lldb_private::DomainSocket::DeleteSocketFile
virtual void DeleteSocketFile(llvm::StringRef name)
Definition: DomainSocket.cpp:122
lldb
Definition: SBAddress.h:15
lldb_private::DomainSocket::DomainSocket
DomainSocket(bool should_close, bool child_processes_inherit)
Definition: DomainSocket.cpp:58