bsd.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include <fmt/format.h>
  10. #include "common/microprofile.h"
  11. #include "common/thread.h"
  12. #include "core/hle/ipc_helpers.h"
  13. #include "core/hle/kernel/thread.h"
  14. #include "core/hle/service/sockets/bsd.h"
  15. #include "core/hle/service/sockets/sockets_translate.h"
  16. #include "core/network/network.h"
  17. #include "core/network/sockets.h"
  18. namespace Service::Sockets {
  19. namespace {
  20. bool IsConnectionBased(Type type) {
  21. switch (type) {
  22. case Type::STREAM:
  23. return true;
  24. case Type::DGRAM:
  25. return false;
  26. default:
  27. UNIMPLEMENTED_MSG("Unimplemented type={}", static_cast<int>(type));
  28. return false;
  29. }
  30. }
  31. } // Anonymous namespace
  32. void BSD::PollWork::Execute(BSD* bsd) {
  33. std::tie(ret, bsd_errno) = bsd->PollImpl(write_buffer, read_buffer, nfds, timeout);
  34. }
  35. void BSD::PollWork::Response(Kernel::HLERequestContext& ctx) {
  36. ctx.WriteBuffer(write_buffer);
  37. IPC::ResponseBuilder rb{ctx, 4};
  38. rb.Push(RESULT_SUCCESS);
  39. rb.Push<s32>(ret);
  40. rb.PushEnum(bsd_errno);
  41. }
  42. void BSD::AcceptWork::Execute(BSD* bsd) {
  43. std::tie(ret, bsd_errno) = bsd->AcceptImpl(fd, write_buffer);
  44. }
  45. void BSD::AcceptWork::Response(Kernel::HLERequestContext& ctx) {
  46. ctx.WriteBuffer(write_buffer);
  47. IPC::ResponseBuilder rb{ctx, 5};
  48. rb.Push(RESULT_SUCCESS);
  49. rb.Push<s32>(ret);
  50. rb.PushEnum(bsd_errno);
  51. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  52. }
  53. void BSD::ConnectWork::Execute(BSD* bsd) {
  54. bsd_errno = bsd->ConnectImpl(fd, addr);
  55. }
  56. void BSD::ConnectWork::Response(Kernel::HLERequestContext& ctx) {
  57. IPC::ResponseBuilder rb{ctx, 4};
  58. rb.Push(RESULT_SUCCESS);
  59. rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
  60. rb.PushEnum(bsd_errno);
  61. }
  62. void BSD::RecvWork::Execute(BSD* bsd) {
  63. std::tie(ret, bsd_errno) = bsd->RecvImpl(fd, flags, message);
  64. }
  65. void BSD::RecvWork::Response(Kernel::HLERequestContext& ctx) {
  66. ctx.WriteBuffer(message);
  67. IPC::ResponseBuilder rb{ctx, 4};
  68. rb.Push(RESULT_SUCCESS);
  69. rb.Push<s32>(ret);
  70. rb.PushEnum(bsd_errno);
  71. }
  72. void BSD::RecvFromWork::Execute(BSD* bsd) {
  73. std::tie(ret, bsd_errno) = bsd->RecvFromImpl(fd, flags, message, addr);
  74. }
  75. void BSD::RecvFromWork::Response(Kernel::HLERequestContext& ctx) {
  76. ctx.WriteBuffer(message, 0);
  77. if (!addr.empty()) {
  78. ctx.WriteBuffer(addr, 1);
  79. }
  80. IPC::ResponseBuilder rb{ctx, 5};
  81. rb.Push(RESULT_SUCCESS);
  82. rb.Push<s32>(ret);
  83. rb.PushEnum(bsd_errno);
  84. rb.Push<u32>(static_cast<u32>(addr.size()));
  85. }
  86. void BSD::SendWork::Execute(BSD* bsd) {
  87. std::tie(ret, bsd_errno) = bsd->SendImpl(fd, flags, message);
  88. }
  89. void BSD::SendWork::Response(Kernel::HLERequestContext& ctx) {
  90. IPC::ResponseBuilder rb{ctx, 4};
  91. rb.Push(RESULT_SUCCESS);
  92. rb.Push<s32>(ret);
  93. rb.PushEnum(bsd_errno);
  94. }
  95. void BSD::SendToWork::Execute(BSD* bsd) {
  96. std::tie(ret, bsd_errno) = bsd->SendToImpl(fd, flags, message, addr);
  97. }
  98. void BSD::SendToWork::Response(Kernel::HLERequestContext& ctx) {
  99. IPC::ResponseBuilder rb{ctx, 4};
  100. rb.Push(RESULT_SUCCESS);
  101. rb.Push<s32>(ret);
  102. rb.PushEnum(bsd_errno);
  103. }
  104. void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
  105. LOG_WARNING(Service, "(STUBBED) called");
  106. IPC::ResponseBuilder rb{ctx, 3};
  107. rb.Push(RESULT_SUCCESS);
  108. rb.Push<s32>(0); // bsd errno
  109. }
  110. void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) {
  111. LOG_WARNING(Service, "(STUBBED) called");
  112. IPC::ResponseBuilder rb{ctx, 2};
  113. rb.Push(RESULT_SUCCESS);
  114. }
  115. void BSD::Socket(Kernel::HLERequestContext& ctx) {
  116. IPC::RequestParser rp{ctx};
  117. const u32 domain = rp.Pop<u32>();
  118. const u32 type = rp.Pop<u32>();
  119. const u32 protocol = rp.Pop<u32>();
  120. LOG_DEBUG(Service, "called. domain={} type={} protocol={}", domain, type, protocol);
  121. const auto [fd, bsd_errno] = SocketImpl(static_cast<Domain>(domain), static_cast<Type>(type),
  122. static_cast<Protocol>(protocol));
  123. IPC::ResponseBuilder rb{ctx, 4};
  124. rb.Push(RESULT_SUCCESS);
  125. rb.Push<s32>(fd);
  126. rb.PushEnum(bsd_errno);
  127. }
  128. void BSD::Select(Kernel::HLERequestContext& ctx) {
  129. LOG_WARNING(Service, "(STUBBED) called");
  130. IPC::ResponseBuilder rb{ctx, 4};
  131. rb.Push(RESULT_SUCCESS);
  132. rb.Push<u32>(0); // ret
  133. rb.Push<u32>(0); // bsd errno
  134. }
  135. void BSD::Poll(Kernel::HLERequestContext& ctx) {
  136. IPC::RequestParser rp{ctx};
  137. const s32 nfds = rp.Pop<s32>();
  138. const s32 timeout = rp.Pop<s32>();
  139. LOG_DEBUG(Service, "called. nfds={} timeout={}", nfds, timeout);
  140. ExecuteWork(ctx, "BSD:Poll", timeout != 0,
  141. PollWork{
  142. .nfds = nfds,
  143. .timeout = timeout,
  144. .read_buffer = ctx.ReadBuffer(),
  145. .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
  146. });
  147. }
  148. void BSD::Accept(Kernel::HLERequestContext& ctx) {
  149. IPC::RequestParser rp{ctx};
  150. const s32 fd = rp.Pop<s32>();
  151. LOG_DEBUG(Service, "called. fd={}", fd);
  152. ExecuteWork(ctx, "BSD:Accept", IsBlockingSocket(fd),
  153. AcceptWork{
  154. .fd = fd,
  155. .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
  156. });
  157. }
  158. void BSD::Bind(Kernel::HLERequestContext& ctx) {
  159. IPC::RequestParser rp{ctx};
  160. const s32 fd = rp.Pop<s32>();
  161. LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
  162. BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
  163. }
  164. void BSD::Connect(Kernel::HLERequestContext& ctx) {
  165. IPC::RequestParser rp{ctx};
  166. const s32 fd = rp.Pop<s32>();
  167. LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
  168. ExecuteWork(ctx, "BSD:Connect", IsBlockingSocket(fd),
  169. ConnectWork{
  170. .fd = fd,
  171. .addr = ctx.ReadBuffer(),
  172. });
  173. }
  174. void BSD::GetPeerName(Kernel::HLERequestContext& ctx) {
  175. IPC::RequestParser rp{ctx};
  176. const s32 fd = rp.Pop<s32>();
  177. LOG_DEBUG(Service, "called. fd={}", fd);
  178. std::vector<u8> write_buffer(ctx.GetWriteBufferSize());
  179. const Errno bsd_errno = GetPeerNameImpl(fd, write_buffer);
  180. ctx.WriteBuffer(write_buffer);
  181. IPC::ResponseBuilder rb{ctx, 5};
  182. rb.Push(RESULT_SUCCESS);
  183. rb.Push<s32>(bsd_errno != Errno::SUCCESS ? -1 : 0);
  184. rb.PushEnum(bsd_errno);
  185. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  186. }
  187. void BSD::GetSockName(Kernel::HLERequestContext& ctx) {
  188. IPC::RequestParser rp{ctx};
  189. const s32 fd = rp.Pop<s32>();
  190. LOG_DEBUG(Service, "called. fd={}", fd);
  191. std::vector<u8> write_buffer(ctx.GetWriteBufferSize());
  192. const Errno bsd_errno = GetSockNameImpl(fd, write_buffer);
  193. ctx.WriteBuffer(write_buffer);
  194. IPC::ResponseBuilder rb{ctx, 5};
  195. rb.Push(RESULT_SUCCESS);
  196. rb.Push<s32>(bsd_errno != Errno::SUCCESS ? -1 : 0);
  197. rb.PushEnum(bsd_errno);
  198. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  199. }
  200. void BSD::Listen(Kernel::HLERequestContext& ctx) {
  201. IPC::RequestParser rp{ctx};
  202. const s32 fd = rp.Pop<s32>();
  203. const s32 backlog = rp.Pop<s32>();
  204. LOG_DEBUG(Service, "called. fd={} backlog={}", fd, backlog);
  205. BuildErrnoResponse(ctx, ListenImpl(fd, backlog));
  206. }
  207. void BSD::Fcntl(Kernel::HLERequestContext& ctx) {
  208. IPC::RequestParser rp{ctx};
  209. const s32 fd = rp.Pop<s32>();
  210. const s32 cmd = rp.Pop<s32>();
  211. const s32 arg = rp.Pop<s32>();
  212. LOG_DEBUG(Service, "called. fd={} cmd={} arg={}", fd, cmd, arg);
  213. const auto [ret, bsd_errno] = FcntlImpl(fd, static_cast<FcntlCmd>(cmd), arg);
  214. IPC::ResponseBuilder rb{ctx, 4};
  215. rb.Push(RESULT_SUCCESS);
  216. rb.Push<s32>(ret);
  217. rb.PushEnum(bsd_errno);
  218. }
  219. void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) {
  220. IPC::RequestParser rp{ctx};
  221. const s32 fd = rp.Pop<s32>();
  222. const u32 level = rp.Pop<u32>();
  223. const OptName optname = static_cast<OptName>(rp.Pop<u32>());
  224. const std::vector<u8> buffer = ctx.ReadBuffer();
  225. const u8* optval = buffer.empty() ? nullptr : buffer.data();
  226. size_t optlen = buffer.size();
  227. std::array<u64, 2> values;
  228. if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
  229. std::memcpy(values.data(), buffer.data(), sizeof(values));
  230. optlen = sizeof(values);
  231. optval = reinterpret_cast<const u8*>(values.data());
  232. }
  233. LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
  234. static_cast<u32>(optname), optlen);
  235. BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval));
  236. }
  237. void BSD::Shutdown(Kernel::HLERequestContext& ctx) {
  238. IPC::RequestParser rp{ctx};
  239. const s32 fd = rp.Pop<s32>();
  240. const s32 how = rp.Pop<s32>();
  241. LOG_DEBUG(Service, "called. fd={} how={}", fd, how);
  242. BuildErrnoResponse(ctx, ShutdownImpl(fd, how));
  243. }
  244. void BSD::Recv(Kernel::HLERequestContext& ctx) {
  245. IPC::RequestParser rp{ctx};
  246. const s32 fd = rp.Pop<s32>();
  247. const u32 flags = rp.Pop<u32>();
  248. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize());
  249. ExecuteWork(ctx, "BSD:Recv", IsBlockingSocket(fd),
  250. RecvWork{
  251. .fd = fd,
  252. .flags = flags,
  253. .message = std::vector<u8>(ctx.GetWriteBufferSize()),
  254. });
  255. }
  256. void BSD::RecvFrom(Kernel::HLERequestContext& ctx) {
  257. IPC::RequestParser rp{ctx};
  258. const s32 fd = rp.Pop<s32>();
  259. const u32 flags = rp.Pop<u32>();
  260. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags,
  261. ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1));
  262. ExecuteWork(ctx, "BSD:RecvFrom", IsBlockingSocket(fd),
  263. RecvFromWork{
  264. .fd = fd,
  265. .flags = flags,
  266. .message = std::vector<u8>(ctx.GetWriteBufferSize(0)),
  267. .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)),
  268. });
  269. }
  270. void BSD::Send(Kernel::HLERequestContext& ctx) {
  271. IPC::RequestParser rp{ctx};
  272. const s32 fd = rp.Pop<s32>();
  273. const u32 flags = rp.Pop<u32>();
  274. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize());
  275. ExecuteWork(ctx, "BSD:Send", IsBlockingSocket(fd),
  276. SendWork{
  277. .fd = fd,
  278. .flags = flags,
  279. .message = ctx.ReadBuffer(),
  280. });
  281. }
  282. void BSD::SendTo(Kernel::HLERequestContext& ctx) {
  283. IPC::RequestParser rp{ctx};
  284. const s32 fd = rp.Pop<s32>();
  285. const u32 flags = rp.Pop<u32>();
  286. LOG_DEBUG(Service, "called. fd={} flags=0x{} len={} addrlen={}", fd, flags,
  287. ctx.GetReadBufferSize(0), ctx.GetReadBufferSize(1));
  288. ExecuteWork(ctx, "BSD:SendTo", IsBlockingSocket(fd),
  289. SendToWork{
  290. .fd = fd,
  291. .flags = flags,
  292. .message = ctx.ReadBuffer(0),
  293. .addr = ctx.ReadBuffer(1),
  294. });
  295. }
  296. void BSD::Write(Kernel::HLERequestContext& ctx) {
  297. IPC::RequestParser rp{ctx};
  298. const s32 fd = rp.Pop<s32>();
  299. LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetReadBufferSize());
  300. ExecuteWork(ctx, "BSD:Write", IsBlockingSocket(fd),
  301. SendWork{
  302. .fd = fd,
  303. .flags = 0,
  304. .message = ctx.ReadBuffer(),
  305. });
  306. }
  307. void BSD::Close(Kernel::HLERequestContext& ctx) {
  308. IPC::RequestParser rp{ctx};
  309. const s32 fd = rp.Pop<s32>();
  310. LOG_DEBUG(Service, "called. fd={}", fd);
  311. BuildErrnoResponse(ctx, CloseImpl(fd));
  312. }
  313. template <typename Work>
  314. void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason,
  315. bool is_blocking, Work work) {
  316. if (!is_blocking) {
  317. work.Execute(this);
  318. work.Response(ctx);
  319. return;
  320. }
  321. // Signal a dummy response to make IPC validation happy
  322. // This will be overwritten by the SleepClientThread callback
  323. work.Response(ctx);
  324. auto worker = worker_pool.CaptureWorker();
  325. ctx.SleepClientThread(std::string(sleep_reason), std::numeric_limits<u64>::max(),
  326. worker->Callback<Work>(), worker->KernelEvent());
  327. worker->SendWork(std::move(work));
  328. }
  329. std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) {
  330. if (type == Type::SEQPACKET) {
  331. UNIMPLEMENTED_MSG("SOCK_SEQPACKET errno management");
  332. } else if (type == Type::RAW && (domain != Domain::INET || protocol != Protocol::ICMP)) {
  333. UNIMPLEMENTED_MSG("SOCK_RAW errno management");
  334. }
  335. [[maybe_unused]] const bool unk_flag = (static_cast<u32>(type) & 0x20000000) != 0;
  336. UNIMPLEMENTED_IF_MSG(unk_flag, "Unknown flag in type");
  337. type = static_cast<Type>(static_cast<u32>(type) & ~0x20000000);
  338. const s32 fd = FindFreeFileDescriptorHandle();
  339. if (fd < 0) {
  340. LOG_ERROR(Service, "No more file descriptors available");
  341. return {-1, Errno::MFILE};
  342. }
  343. FileDescriptor& descriptor = file_descriptors[fd].emplace();
  344. // ENONMEM might be thrown here
  345. LOG_INFO(Service, "New socket fd={}", fd);
  346. descriptor.socket = std::make_unique<Network::Socket>();
  347. descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(type, protocol));
  348. descriptor.is_connection_based = IsConnectionBased(type);
  349. return {fd, Errno::SUCCESS};
  350. }
  351. std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer,
  352. s32 nfds, s32 timeout) {
  353. if (write_buffer.size() < nfds * sizeof(PollFD)) {
  354. return {-1, Errno::INVAL};
  355. }
  356. if (nfds == 0) {
  357. // When no entries are provided, -1 is returned with errno zero
  358. return {-1, Errno::SUCCESS};
  359. }
  360. const size_t length = std::min(read_buffer.size(), write_buffer.size());
  361. std::vector<PollFD> fds(nfds);
  362. std::memcpy(fds.data(), read_buffer.data(), length);
  363. if (timeout >= 0) {
  364. const s64 seconds = timeout / 1000;
  365. const u64 nanoseconds = 1'000'000 * (static_cast<u64>(timeout) % 1000);
  366. if (seconds < 0) {
  367. return {-1, Errno::INVAL};
  368. }
  369. if (nanoseconds > 999'999'999) {
  370. return {-1, Errno::INVAL};
  371. }
  372. } else if (timeout != -1) {
  373. return {-1, Errno::INVAL};
  374. }
  375. for (PollFD& pollfd : fds) {
  376. ASSERT(pollfd.revents == 0);
  377. if (pollfd.fd > static_cast<s32>(MAX_FD) || pollfd.fd < 0) {
  378. LOG_ERROR(Service, "File descriptor handle={} is invalid", pollfd.fd);
  379. pollfd.revents = 0;
  380. return {0, Errno::SUCCESS};
  381. }
  382. std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
  383. if (!descriptor) {
  384. LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd);
  385. pollfd.revents = POLL_NVAL;
  386. return {0, Errno::SUCCESS};
  387. }
  388. }
  389. std::vector<Network::PollFD> host_pollfds(fds.size());
  390. std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [this](PollFD pollfd) {
  391. Network::PollFD result;
  392. result.socket = file_descriptors[pollfd.fd]->socket.get();
  393. result.events = TranslatePollEventsToHost(pollfd.events);
  394. result.revents = 0;
  395. return result;
  396. });
  397. const auto result = Network::Poll(host_pollfds, timeout);
  398. const size_t num = host_pollfds.size();
  399. for (size_t i = 0; i < num; ++i) {
  400. fds[i].revents = TranslatePollEventsToGuest(host_pollfds[i].revents);
  401. }
  402. std::memcpy(write_buffer.data(), fds.data(), length);
  403. return Translate(result);
  404. }
  405. std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
  406. if (!IsFileDescriptorValid(fd)) {
  407. return {-1, Errno::BADF};
  408. }
  409. const s32 new_fd = FindFreeFileDescriptorHandle();
  410. if (new_fd < 0) {
  411. LOG_ERROR(Service, "No more file descriptors available");
  412. return {-1, Errno::MFILE};
  413. }
  414. FileDescriptor& descriptor = *file_descriptors[fd];
  415. auto [result, bsd_errno] = descriptor.socket->Accept();
  416. if (bsd_errno != Network::Errno::SUCCESS) {
  417. return {-1, Translate(bsd_errno)};
  418. }
  419. FileDescriptor& new_descriptor = file_descriptors[new_fd].emplace();
  420. new_descriptor.socket = std::move(result.socket);
  421. new_descriptor.is_connection_based = descriptor.is_connection_based;
  422. ASSERT(write_buffer.size() == sizeof(SockAddrIn));
  423. const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
  424. std::memcpy(write_buffer.data(), &guest_addr_in, sizeof(guest_addr_in));
  425. return {new_fd, Errno::SUCCESS};
  426. }
  427. Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) {
  428. if (!IsFileDescriptorValid(fd)) {
  429. return Errno::BADF;
  430. }
  431. ASSERT(addr.size() == sizeof(SockAddrIn));
  432. SockAddrIn addr_in;
  433. std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
  434. return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
  435. }
  436. Errno BSD::ConnectImpl(s32 fd, const std::vector<u8>& addr) {
  437. if (!IsFileDescriptorValid(fd)) {
  438. return Errno::BADF;
  439. }
  440. UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
  441. SockAddrIn addr_in;
  442. std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
  443. return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
  444. }
  445. Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
  446. if (!IsFileDescriptorValid(fd)) {
  447. return Errno::BADF;
  448. }
  449. const auto [addr_in, bsd_errno] = file_descriptors[fd]->socket->GetPeerName();
  450. if (bsd_errno != Network::Errno::SUCCESS) {
  451. return Translate(bsd_errno);
  452. }
  453. const SockAddrIn guest_addrin = Translate(addr_in);
  454. ASSERT(write_buffer.size() == sizeof(guest_addrin));
  455. std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
  456. return Translate(bsd_errno);
  457. }
  458. Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
  459. if (!IsFileDescriptorValid(fd)) {
  460. return Errno::BADF;
  461. }
  462. const auto [addr_in, bsd_errno] = file_descriptors[fd]->socket->GetSockName();
  463. if (bsd_errno != Network::Errno::SUCCESS) {
  464. return Translate(bsd_errno);
  465. }
  466. const SockAddrIn guest_addrin = Translate(addr_in);
  467. ASSERT(write_buffer.size() == sizeof(guest_addrin));
  468. std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
  469. return Translate(bsd_errno);
  470. }
  471. Errno BSD::ListenImpl(s32 fd, s32 backlog) {
  472. if (!IsFileDescriptorValid(fd)) {
  473. return Errno::BADF;
  474. }
  475. return Translate(file_descriptors[fd]->socket->Listen(backlog));
  476. }
  477. std::pair<s32, Errno> BSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
  478. if (!IsFileDescriptorValid(fd)) {
  479. return {-1, Errno::BADF};
  480. }
  481. FileDescriptor& descriptor = *file_descriptors[fd];
  482. switch (cmd) {
  483. case FcntlCmd::GETFL:
  484. ASSERT(arg == 0);
  485. return {descriptor.flags, Errno::SUCCESS};
  486. case FcntlCmd::SETFL: {
  487. const bool enable = (arg & FLAG_O_NONBLOCK) != 0;
  488. const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable));
  489. if (bsd_errno != Errno::SUCCESS) {
  490. return {-1, bsd_errno};
  491. }
  492. descriptor.flags = arg;
  493. return {0, Errno::SUCCESS};
  494. }
  495. default:
  496. UNIMPLEMENTED_MSG("Unimplemented cmd={}", static_cast<int>(cmd));
  497. return {-1, Errno::SUCCESS};
  498. }
  499. }
  500. Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) {
  501. UNIMPLEMENTED_IF(level != 0xffff); // SOL_SOCKET
  502. if (!IsFileDescriptorValid(fd)) {
  503. return Errno::BADF;
  504. }
  505. Network::Socket* const socket = file_descriptors[fd]->socket.get();
  506. if (optname == OptName::LINGER) {
  507. ASSERT(optlen == sizeof(Linger));
  508. Linger linger;
  509. std::memcpy(&linger, optval, sizeof(linger));
  510. ASSERT(linger.onoff == 0 || linger.onoff == 1);
  511. return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
  512. }
  513. ASSERT(optlen == sizeof(u32));
  514. u32 value;
  515. std::memcpy(&value, optval, sizeof(value));
  516. switch (optname) {
  517. case OptName::REUSEADDR:
  518. ASSERT(value == 0 || value == 1);
  519. return Translate(socket->SetReuseAddr(value != 0));
  520. case OptName::BROADCAST:
  521. ASSERT(value == 0 || value == 1);
  522. return Translate(socket->SetBroadcast(value != 0));
  523. case OptName::SNDBUF:
  524. return Translate(socket->SetSndBuf(value));
  525. case OptName::RCVBUF:
  526. return Translate(socket->SetRcvBuf(value));
  527. case OptName::SNDTIMEO:
  528. return Translate(socket->SetSndTimeo(value));
  529. case OptName::RCVTIMEO:
  530. return Translate(socket->SetRcvTimeo(value));
  531. default:
  532. UNIMPLEMENTED_MSG("Unimplemented optname={}", static_cast<int>(optname));
  533. return Errno::SUCCESS;
  534. }
  535. }
  536. Errno BSD::ShutdownImpl(s32 fd, s32 how) {
  537. if (!IsFileDescriptorValid(fd)) {
  538. return Errno::BADF;
  539. }
  540. const Network::ShutdownHow host_how = Translate(static_cast<ShutdownHow>(how));
  541. return Translate(file_descriptors[fd]->socket->Shutdown(host_how));
  542. }
  543. std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message) {
  544. if (!IsFileDescriptorValid(fd)) {
  545. return {-1, Errno::BADF};
  546. }
  547. return Translate(file_descriptors[fd]->socket->Recv(flags, message));
  548. }
  549. std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
  550. std::vector<u8>& addr) {
  551. if (!IsFileDescriptorValid(fd)) {
  552. return {-1, Errno::BADF};
  553. }
  554. FileDescriptor& descriptor = *file_descriptors[fd];
  555. Network::SockAddrIn addr_in{};
  556. Network::SockAddrIn* p_addr_in = nullptr;
  557. if (descriptor.is_connection_based) {
  558. // Connection based file descriptors (e.g. TCP) zero addr
  559. addr.clear();
  560. } else {
  561. p_addr_in = &addr_in;
  562. }
  563. // Apply flags
  564. if ((flags & FLAG_MSG_DONTWAIT) != 0) {
  565. flags &= ~FLAG_MSG_DONTWAIT;
  566. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  567. descriptor.socket->SetNonBlock(true);
  568. }
  569. }
  570. const auto [ret, bsd_errno] = Translate(descriptor.socket->RecvFrom(flags, message, p_addr_in));
  571. // Restore original state
  572. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  573. descriptor.socket->SetNonBlock(false);
  574. }
  575. if (p_addr_in) {
  576. if (ret < 0) {
  577. addr.clear();
  578. } else {
  579. ASSERT(addr.size() == sizeof(SockAddrIn));
  580. const SockAddrIn result = Translate(addr_in);
  581. std::memcpy(addr.data(), &result, sizeof(result));
  582. }
  583. }
  584. return {ret, bsd_errno};
  585. }
  586. std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, const std::vector<u8>& message) {
  587. if (!IsFileDescriptorValid(fd)) {
  588. return {-1, Errno::BADF};
  589. }
  590. return Translate(file_descriptors[fd]->socket->Send(message, flags));
  591. }
  592. std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message,
  593. const std::vector<u8>& addr) {
  594. if (!IsFileDescriptorValid(fd)) {
  595. return {-1, Errno::BADF};
  596. }
  597. Network::SockAddrIn addr_in;
  598. Network::SockAddrIn* p_addr_in = nullptr;
  599. if (!addr.empty()) {
  600. ASSERT(addr.size() == sizeof(SockAddrIn));
  601. SockAddrIn guest_addr_in;
  602. std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
  603. addr_in = Translate(guest_addr_in);
  604. p_addr_in = &addr_in;
  605. }
  606. return Translate(file_descriptors[fd]->socket->SendTo(flags, message, p_addr_in));
  607. }
  608. Errno BSD::CloseImpl(s32 fd) {
  609. if (!IsFileDescriptorValid(fd)) {
  610. return Errno::BADF;
  611. }
  612. const Errno bsd_errno = Translate(file_descriptors[fd]->socket->Close());
  613. if (bsd_errno != Errno::SUCCESS) {
  614. return bsd_errno;
  615. }
  616. LOG_INFO(Service, "Close socket fd={}", fd);
  617. file_descriptors[fd].reset();
  618. return bsd_errno;
  619. }
  620. s32 BSD::FindFreeFileDescriptorHandle() noexcept {
  621. for (s32 fd = 0; fd < static_cast<s32>(file_descriptors.size()); ++fd) {
  622. if (!file_descriptors[fd]) {
  623. return fd;
  624. }
  625. }
  626. return -1;
  627. }
  628. bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
  629. if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
  630. LOG_ERROR(Service, "Invalid file descriptor handle={}", fd);
  631. return false;
  632. }
  633. if (!file_descriptors[fd]) {
  634. LOG_ERROR(Service, "File descriptor handle={} is not allocated", fd);
  635. return false;
  636. }
  637. return true;
  638. }
  639. bool BSD::IsBlockingSocket(s32 fd) const noexcept {
  640. // Inform invalid sockets as non-blocking
  641. // This way we avoid using a worker thread as it will fail without blocking host
  642. if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
  643. return false;
  644. }
  645. if (!file_descriptors[fd]) {
  646. return false;
  647. }
  648. return (file_descriptors[fd]->flags & FLAG_O_NONBLOCK) != 0;
  649. }
  650. void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept {
  651. IPC::ResponseBuilder rb{ctx, 4};
  652. rb.Push(RESULT_SUCCESS);
  653. rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
  654. rb.PushEnum(bsd_errno);
  655. }
  656. BSD::BSD(Core::System& system, const char* name)
  657. : ServiceFramework(name), worker_pool{system, this} {
  658. // clang-format off
  659. static const FunctionInfo functions[] = {
  660. {0, &BSD::RegisterClient, "RegisterClient"},
  661. {1, &BSD::StartMonitoring, "StartMonitoring"},
  662. {2, &BSD::Socket, "Socket"},
  663. {3, nullptr, "SocketExempt"},
  664. {4, nullptr, "Open"},
  665. {5, &BSD::Select, "Select"},
  666. {6, &BSD::Poll, "Poll"},
  667. {7, nullptr, "Sysctl"},
  668. {8, &BSD::Recv, "Recv"},
  669. {9, &BSD::RecvFrom, "RecvFrom"},
  670. {10, &BSD::Send, "Send"},
  671. {11, &BSD::SendTo, "SendTo"},
  672. {12, &BSD::Accept, "Accept"},
  673. {13, &BSD::Bind, "Bind"},
  674. {14, &BSD::Connect, "Connect"},
  675. {15, &BSD::GetPeerName, "GetPeerName"},
  676. {16, &BSD::GetSockName, "GetSockName"},
  677. {17, nullptr, "GetSockOpt"},
  678. {18, &BSD::Listen, "Listen"},
  679. {19, nullptr, "Ioctl"},
  680. {20, &BSD::Fcntl, "Fcntl"},
  681. {21, &BSD::SetSockOpt, "SetSockOpt"},
  682. {22, &BSD::Shutdown, "Shutdown"},
  683. {23, nullptr, "ShutdownAllSockets"},
  684. {24, &BSD::Write, "Write"},
  685. {25, nullptr, "Read"},
  686. {26, &BSD::Close, "Close"},
  687. {27, nullptr, "DuplicateSocket"},
  688. {28, nullptr, "GetResourceStatistics"},
  689. {29, nullptr, "RecvMMsg"},
  690. {30, nullptr, "SendMMsg"},
  691. {31, nullptr, "EventFd"},
  692. {32, nullptr, "RegisterResourceStatisticsName"},
  693. {33, nullptr, "Initialize2"},
  694. };
  695. // clang-format on
  696. RegisterHandlers(functions);
  697. }
  698. BSD::~BSD() = default;
  699. BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
  700. // clang-format off
  701. static const FunctionInfo functions[] = {
  702. {0, nullptr, "SetIfUp"},
  703. {1, nullptr, "SetIfUpWithEvent"},
  704. {2, nullptr, "CancelIf"},
  705. {3, nullptr, "SetIfDown"},
  706. {4, nullptr, "GetIfState"},
  707. {5, nullptr, "DhcpRenew"},
  708. {6, nullptr, "AddStaticArpEntry"},
  709. {7, nullptr, "RemoveArpEntry"},
  710. {8, nullptr, "LookupArpEntry"},
  711. {9, nullptr, "LookupArpEntry2"},
  712. {10, nullptr, "ClearArpEntries"},
  713. {11, nullptr, "ClearArpEntries2"},
  714. {12, nullptr, "PrintArpEntries"},
  715. };
  716. // clang-format on
  717. RegisterHandlers(functions);
  718. }
  719. BSDCFG::~BSDCFG() = default;
  720. } // namespace Service::Sockets