bsd.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <array>
  4. #include <memory>
  5. #include <utility>
  6. #include <vector>
  7. #include <fmt/format.h>
  8. #include "common/microprofile.h"
  9. #include "common/socket_types.h"
  10. #include "core/core.h"
  11. #include "core/hle/kernel/k_thread.h"
  12. #include "core/hle/service/ipc_helpers.h"
  13. #include "core/hle/service/sockets/bsd.h"
  14. #include "core/hle/service/sockets/sockets_translate.h"
  15. #include "core/internal_network/network.h"
  16. #include "core/internal_network/socket_proxy.h"
  17. #include "core/internal_network/sockets.h"
  18. #include "network/network.h"
  19. using Common::Expected;
  20. using Common::Unexpected;
  21. namespace Service::Sockets {
  22. namespace {
  23. bool IsConnectionBased(Type type) {
  24. switch (type) {
  25. case Type::STREAM:
  26. return true;
  27. case Type::DGRAM:
  28. return false;
  29. default:
  30. UNIMPLEMENTED_MSG("Unimplemented type={}", type);
  31. return false;
  32. }
  33. }
  34. } // Anonymous namespace
  35. void BSD::PollWork::Execute(BSD* bsd) {
  36. std::tie(ret, bsd_errno) = bsd->PollImpl(write_buffer, read_buffer, nfds, timeout);
  37. }
  38. void BSD::PollWork::Response(HLERequestContext& ctx) {
  39. if (write_buffer.size() > 0) {
  40. ctx.WriteBuffer(write_buffer);
  41. }
  42. IPC::ResponseBuilder rb{ctx, 4};
  43. rb.Push(ResultSuccess);
  44. rb.Push<s32>(ret);
  45. rb.PushEnum(bsd_errno);
  46. }
  47. void BSD::AcceptWork::Execute(BSD* bsd) {
  48. std::tie(ret, bsd_errno) = bsd->AcceptImpl(fd, write_buffer);
  49. }
  50. void BSD::AcceptWork::Response(HLERequestContext& ctx) {
  51. if (write_buffer.size() > 0) {
  52. ctx.WriteBuffer(write_buffer);
  53. }
  54. IPC::ResponseBuilder rb{ctx, 5};
  55. rb.Push(ResultSuccess);
  56. rb.Push<s32>(ret);
  57. rb.PushEnum(bsd_errno);
  58. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  59. }
  60. void BSD::ConnectWork::Execute(BSD* bsd) {
  61. bsd_errno = bsd->ConnectImpl(fd, addr);
  62. }
  63. void BSD::ConnectWork::Response(HLERequestContext& ctx) {
  64. IPC::ResponseBuilder rb{ctx, 4};
  65. rb.Push(ResultSuccess);
  66. rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
  67. rb.PushEnum(bsd_errno);
  68. }
  69. void BSD::RecvWork::Execute(BSD* bsd) {
  70. std::tie(ret, bsd_errno) = bsd->RecvImpl(fd, flags, message);
  71. }
  72. void BSD::RecvWork::Response(HLERequestContext& ctx) {
  73. ctx.WriteBuffer(message);
  74. IPC::ResponseBuilder rb{ctx, 4};
  75. rb.Push(ResultSuccess);
  76. rb.Push<s32>(ret);
  77. rb.PushEnum(bsd_errno);
  78. }
  79. void BSD::RecvFromWork::Execute(BSD* bsd) {
  80. std::tie(ret, bsd_errno) = bsd->RecvFromImpl(fd, flags, message, addr);
  81. }
  82. void BSD::RecvFromWork::Response(HLERequestContext& ctx) {
  83. ctx.WriteBuffer(message, 0);
  84. if (!addr.empty()) {
  85. ctx.WriteBuffer(addr, 1);
  86. }
  87. IPC::ResponseBuilder rb{ctx, 5};
  88. rb.Push(ResultSuccess);
  89. rb.Push<s32>(ret);
  90. rb.PushEnum(bsd_errno);
  91. rb.Push<u32>(static_cast<u32>(addr.size()));
  92. }
  93. void BSD::SendWork::Execute(BSD* bsd) {
  94. std::tie(ret, bsd_errno) = bsd->SendImpl(fd, flags, message);
  95. }
  96. void BSD::SendWork::Response(HLERequestContext& ctx) {
  97. IPC::ResponseBuilder rb{ctx, 4};
  98. rb.Push(ResultSuccess);
  99. rb.Push<s32>(ret);
  100. rb.PushEnum(bsd_errno);
  101. }
  102. void BSD::SendToWork::Execute(BSD* bsd) {
  103. std::tie(ret, bsd_errno) = bsd->SendToImpl(fd, flags, message, addr);
  104. }
  105. void BSD::SendToWork::Response(HLERequestContext& ctx) {
  106. IPC::ResponseBuilder rb{ctx, 4};
  107. rb.Push(ResultSuccess);
  108. rb.Push<s32>(ret);
  109. rb.PushEnum(bsd_errno);
  110. }
  111. void BSD::RegisterClient(HLERequestContext& ctx) {
  112. LOG_WARNING(Service, "(STUBBED) called");
  113. IPC::ResponseBuilder rb{ctx, 3};
  114. rb.Push(ResultSuccess);
  115. rb.Push<s32>(0); // bsd errno
  116. }
  117. void BSD::StartMonitoring(HLERequestContext& ctx) {
  118. LOG_WARNING(Service, "(STUBBED) called");
  119. IPC::ResponseBuilder rb{ctx, 2};
  120. rb.Push(ResultSuccess);
  121. }
  122. void BSD::Socket(HLERequestContext& ctx) {
  123. IPC::RequestParser rp{ctx};
  124. const u32 domain = rp.Pop<u32>();
  125. const u32 type = rp.Pop<u32>();
  126. const u32 protocol = rp.Pop<u32>();
  127. LOG_DEBUG(Service, "called. domain={} type={} protocol={}", domain, type, protocol);
  128. const auto [fd, bsd_errno] = SocketImpl(static_cast<Domain>(domain), static_cast<Type>(type),
  129. static_cast<Protocol>(protocol));
  130. IPC::ResponseBuilder rb{ctx, 4};
  131. rb.Push(ResultSuccess);
  132. rb.Push<s32>(fd);
  133. rb.PushEnum(bsd_errno);
  134. }
  135. void BSD::Select(HLERequestContext& ctx) {
  136. LOG_WARNING(Service, "(STUBBED) called");
  137. IPC::ResponseBuilder rb{ctx, 4};
  138. rb.Push(ResultSuccess);
  139. rb.Push<u32>(0); // ret
  140. rb.Push<u32>(0); // bsd errno
  141. }
  142. void BSD::Poll(HLERequestContext& ctx) {
  143. IPC::RequestParser rp{ctx};
  144. const s32 nfds = rp.Pop<s32>();
  145. const s32 timeout = rp.Pop<s32>();
  146. LOG_DEBUG(Service, "called. nfds={} timeout={}", nfds, timeout);
  147. ExecuteWork(ctx, PollWork{
  148. .nfds = nfds,
  149. .timeout = timeout,
  150. .read_buffer = ctx.ReadBuffer(),
  151. .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
  152. });
  153. }
  154. void BSD::Accept(HLERequestContext& ctx) {
  155. IPC::RequestParser rp{ctx};
  156. const s32 fd = rp.Pop<s32>();
  157. LOG_DEBUG(Service, "called. fd={}", fd);
  158. ExecuteWork(ctx, AcceptWork{
  159. .fd = fd,
  160. .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
  161. });
  162. }
  163. void BSD::Bind(HLERequestContext& ctx) {
  164. IPC::RequestParser rp{ctx};
  165. const s32 fd = rp.Pop<s32>();
  166. LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
  167. BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
  168. }
  169. void BSD::Connect(HLERequestContext& ctx) {
  170. IPC::RequestParser rp{ctx};
  171. const s32 fd = rp.Pop<s32>();
  172. LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
  173. ExecuteWork(ctx, ConnectWork{
  174. .fd = fd,
  175. .addr = ctx.ReadBuffer(),
  176. });
  177. }
  178. void BSD::GetPeerName(HLERequestContext& ctx) {
  179. IPC::RequestParser rp{ctx};
  180. const s32 fd = rp.Pop<s32>();
  181. LOG_DEBUG(Service, "called. fd={}", fd);
  182. std::vector<u8> write_buffer(ctx.GetWriteBufferSize());
  183. const Errno bsd_errno = GetPeerNameImpl(fd, write_buffer);
  184. ctx.WriteBuffer(write_buffer);
  185. IPC::ResponseBuilder rb{ctx, 5};
  186. rb.Push(ResultSuccess);
  187. rb.Push<s32>(bsd_errno != Errno::SUCCESS ? -1 : 0);
  188. rb.PushEnum(bsd_errno);
  189. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  190. }
  191. void BSD::GetSockName(HLERequestContext& ctx) {
  192. IPC::RequestParser rp{ctx};
  193. const s32 fd = rp.Pop<s32>();
  194. LOG_DEBUG(Service, "called. fd={}", fd);
  195. std::vector<u8> write_buffer(ctx.GetWriteBufferSize());
  196. const Errno bsd_errno = GetSockNameImpl(fd, write_buffer);
  197. ctx.WriteBuffer(write_buffer);
  198. IPC::ResponseBuilder rb{ctx, 5};
  199. rb.Push(ResultSuccess);
  200. rb.Push<s32>(bsd_errno != Errno::SUCCESS ? -1 : 0);
  201. rb.PushEnum(bsd_errno);
  202. rb.Push<u32>(static_cast<u32>(write_buffer.size()));
  203. }
  204. void BSD::GetSockOpt(HLERequestContext& ctx) {
  205. IPC::RequestParser rp{ctx};
  206. const s32 fd = rp.Pop<s32>();
  207. const u32 level = rp.Pop<u32>();
  208. const auto optname = static_cast<OptName>(rp.Pop<u32>());
  209. std::vector<u8> optval(ctx.GetWriteBufferSize());
  210. LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} len=0x{:x}", fd, level, optname,
  211. optval.size());
  212. const Errno err = GetSockOptImpl(fd, level, optname, optval);
  213. ctx.WriteBuffer(optval);
  214. IPC::ResponseBuilder rb{ctx, 5};
  215. rb.Push(ResultSuccess);
  216. rb.Push<s32>(err == Errno::SUCCESS ? 0 : -1);
  217. rb.PushEnum(err);
  218. rb.Push<u32>(static_cast<u32>(optval.size()));
  219. }
  220. void BSD::Listen(HLERequestContext& ctx) {
  221. IPC::RequestParser rp{ctx};
  222. const s32 fd = rp.Pop<s32>();
  223. const s32 backlog = rp.Pop<s32>();
  224. LOG_DEBUG(Service, "called. fd={} backlog={}", fd, backlog);
  225. BuildErrnoResponse(ctx, ListenImpl(fd, backlog));
  226. }
  227. void BSD::Fcntl(HLERequestContext& ctx) {
  228. IPC::RequestParser rp{ctx};
  229. const s32 fd = rp.Pop<s32>();
  230. const s32 cmd = rp.Pop<s32>();
  231. const s32 arg = rp.Pop<s32>();
  232. LOG_DEBUG(Service, "called. fd={} cmd={} arg={}", fd, cmd, arg);
  233. const auto [ret, bsd_errno] = FcntlImpl(fd, static_cast<FcntlCmd>(cmd), arg);
  234. IPC::ResponseBuilder rb{ctx, 4};
  235. rb.Push(ResultSuccess);
  236. rb.Push<s32>(ret);
  237. rb.PushEnum(bsd_errno);
  238. }
  239. void BSD::SetSockOpt(HLERequestContext& ctx) {
  240. IPC::RequestParser rp{ctx};
  241. const s32 fd = rp.Pop<s32>();
  242. const u32 level = rp.Pop<u32>();
  243. const OptName optname = static_cast<OptName>(rp.Pop<u32>());
  244. const auto buffer = ctx.ReadBuffer();
  245. const u8* optval = buffer.empty() ? nullptr : buffer.data();
  246. size_t optlen = buffer.size();
  247. std::array<u64, 2> values;
  248. if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
  249. std::memcpy(values.data(), buffer.data(), sizeof(values));
  250. optlen = sizeof(values);
  251. optval = reinterpret_cast<const u8*>(values.data());
  252. }
  253. LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
  254. static_cast<u32>(optname), optlen);
  255. BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval));
  256. }
  257. void BSD::Shutdown(HLERequestContext& ctx) {
  258. IPC::RequestParser rp{ctx};
  259. const s32 fd = rp.Pop<s32>();
  260. const s32 how = rp.Pop<s32>();
  261. LOG_DEBUG(Service, "called. fd={} how={}", fd, how);
  262. BuildErrnoResponse(ctx, ShutdownImpl(fd, how));
  263. }
  264. void BSD::Recv(HLERequestContext& ctx) {
  265. IPC::RequestParser rp{ctx};
  266. const s32 fd = rp.Pop<s32>();
  267. const u32 flags = rp.Pop<u32>();
  268. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize());
  269. ExecuteWork(ctx, RecvWork{
  270. .fd = fd,
  271. .flags = flags,
  272. .message = std::vector<u8>(ctx.GetWriteBufferSize()),
  273. });
  274. }
  275. void BSD::RecvFrom(HLERequestContext& ctx) {
  276. IPC::RequestParser rp{ctx};
  277. const s32 fd = rp.Pop<s32>();
  278. const u32 flags = rp.Pop<u32>();
  279. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags,
  280. ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1));
  281. ExecuteWork(ctx, RecvFromWork{
  282. .fd = fd,
  283. .flags = flags,
  284. .message = std::vector<u8>(ctx.GetWriteBufferSize(0)),
  285. .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)),
  286. });
  287. }
  288. void BSD::Send(HLERequestContext& ctx) {
  289. IPC::RequestParser rp{ctx};
  290. const s32 fd = rp.Pop<s32>();
  291. const u32 flags = rp.Pop<u32>();
  292. LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize());
  293. ExecuteWork(ctx, SendWork{
  294. .fd = fd,
  295. .flags = flags,
  296. .message = ctx.ReadBuffer(),
  297. });
  298. }
  299. void BSD::SendTo(HLERequestContext& ctx) {
  300. IPC::RequestParser rp{ctx};
  301. const s32 fd = rp.Pop<s32>();
  302. const u32 flags = rp.Pop<u32>();
  303. LOG_DEBUG(Service, "called. fd={} flags=0x{} len={} addrlen={}", fd, flags,
  304. ctx.GetReadBufferSize(0), ctx.GetReadBufferSize(1));
  305. ExecuteWork(ctx, SendToWork{
  306. .fd = fd,
  307. .flags = flags,
  308. .message = ctx.ReadBuffer(0),
  309. .addr = ctx.ReadBuffer(1),
  310. });
  311. }
  312. void BSD::Write(HLERequestContext& ctx) {
  313. IPC::RequestParser rp{ctx};
  314. const s32 fd = rp.Pop<s32>();
  315. LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetReadBufferSize());
  316. ExecuteWork(ctx, SendWork{
  317. .fd = fd,
  318. .flags = 0,
  319. .message = ctx.ReadBuffer(),
  320. });
  321. }
  322. void BSD::Read(HLERequestContext& ctx) {
  323. IPC::RequestParser rp{ctx};
  324. const s32 fd = rp.Pop<s32>();
  325. LOG_WARNING(Service, "(STUBBED) called. fd={} len={}", fd, ctx.GetWriteBufferSize());
  326. IPC::ResponseBuilder rb{ctx, 4};
  327. rb.Push(ResultSuccess);
  328. rb.Push<u32>(0); // ret
  329. rb.Push<u32>(0); // bsd errno
  330. }
  331. void BSD::Close(HLERequestContext& ctx) {
  332. IPC::RequestParser rp{ctx};
  333. const s32 fd = rp.Pop<s32>();
  334. LOG_DEBUG(Service, "called. fd={}", fd);
  335. BuildErrnoResponse(ctx, CloseImpl(fd));
  336. }
  337. void BSD::DuplicateSocket(HLERequestContext& ctx) {
  338. struct InputParameters {
  339. s32 fd;
  340. u64 reserved;
  341. };
  342. static_assert(sizeof(InputParameters) == 0x10);
  343. struct OutputParameters {
  344. s32 ret;
  345. Errno bsd_errno;
  346. };
  347. static_assert(sizeof(OutputParameters) == 0x8);
  348. IPC::RequestParser rp{ctx};
  349. auto input = rp.PopRaw<InputParameters>();
  350. Expected<s32, Errno> res = DuplicateSocketImpl(input.fd);
  351. IPC::ResponseBuilder rb{ctx, 4};
  352. rb.Push(ResultSuccess);
  353. rb.PushRaw(OutputParameters{
  354. .ret = res.value_or(0),
  355. .bsd_errno = res ? Errno::SUCCESS : res.error(),
  356. });
  357. }
  358. void BSD::EventFd(HLERequestContext& ctx) {
  359. IPC::RequestParser rp{ctx};
  360. const u64 initval = rp.Pop<u64>();
  361. const u32 flags = rp.Pop<u32>();
  362. LOG_WARNING(Service, "(STUBBED) called. initval={}, flags={}", initval, flags);
  363. BuildErrnoResponse(ctx, Errno::SUCCESS);
  364. }
  365. template <typename Work>
  366. void BSD::ExecuteWork(HLERequestContext& ctx, Work work) {
  367. work.Execute(this);
  368. work.Response(ctx);
  369. }
  370. std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) {
  371. if (type == Type::SEQPACKET) {
  372. UNIMPLEMENTED_MSG("SOCK_SEQPACKET errno management");
  373. } else if (type == Type::RAW && (domain != Domain::INET || protocol != Protocol::ICMP)) {
  374. UNIMPLEMENTED_MSG("SOCK_RAW errno management");
  375. }
  376. [[maybe_unused]] const bool unk_flag = (static_cast<u32>(type) & 0x20000000) != 0;
  377. UNIMPLEMENTED_IF_MSG(unk_flag, "Unknown flag in type");
  378. type = static_cast<Type>(static_cast<u32>(type) & ~0x20000000);
  379. const s32 fd = FindFreeFileDescriptorHandle();
  380. if (fd < 0) {
  381. LOG_ERROR(Service, "No more file descriptors available");
  382. return {-1, Errno::MFILE};
  383. }
  384. file_descriptors[fd] = FileDescriptor{};
  385. FileDescriptor& descriptor = *file_descriptors[fd];
  386. // ENONMEM might be thrown here
  387. LOG_INFO(Service, "New socket fd={}", fd);
  388. auto room_member = room_network.GetRoomMember().lock();
  389. if (room_member && room_member->IsConnected()) {
  390. descriptor.socket = std::make_shared<Network::ProxySocket>(room_network);
  391. } else {
  392. descriptor.socket = std::make_shared<Network::Socket>();
  393. }
  394. descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(protocol));
  395. descriptor.is_connection_based = IsConnectionBased(type);
  396. return {fd, Errno::SUCCESS};
  397. }
  398. std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
  399. s32 nfds, s32 timeout) {
  400. if (write_buffer.size() < nfds * sizeof(PollFD)) {
  401. return {-1, Errno::INVAL};
  402. }
  403. if (nfds == 0) {
  404. // When no entries are provided, -1 is returned with errno zero
  405. return {-1, Errno::SUCCESS};
  406. }
  407. const size_t length = std::min(read_buffer.size(), write_buffer.size());
  408. std::vector<PollFD> fds(nfds);
  409. std::memcpy(fds.data(), read_buffer.data(), length);
  410. if (timeout >= 0) {
  411. const s64 seconds = timeout / 1000;
  412. const u64 nanoseconds = 1'000'000 * (static_cast<u64>(timeout) % 1000);
  413. if (seconds < 0) {
  414. return {-1, Errno::INVAL};
  415. }
  416. if (nanoseconds > 999'999'999) {
  417. return {-1, Errno::INVAL};
  418. }
  419. } else if (timeout != -1) {
  420. return {-1, Errno::INVAL};
  421. }
  422. for (PollFD& pollfd : fds) {
  423. ASSERT(False(pollfd.revents));
  424. if (pollfd.fd > static_cast<s32>(MAX_FD) || pollfd.fd < 0) {
  425. LOG_ERROR(Service, "File descriptor handle={} is invalid", pollfd.fd);
  426. pollfd.revents = PollEvents{};
  427. return {0, Errno::SUCCESS};
  428. }
  429. const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
  430. if (!descriptor) {
  431. LOG_TRACE(Service, "File descriptor handle={} is not allocated", pollfd.fd);
  432. pollfd.revents = PollEvents::Nval;
  433. return {0, Errno::SUCCESS};
  434. }
  435. }
  436. std::vector<Network::PollFD> host_pollfds(fds.size());
  437. std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [this](PollFD pollfd) {
  438. Network::PollFD result;
  439. result.socket = file_descriptors[pollfd.fd]->socket.get();
  440. result.events = Translate(pollfd.events);
  441. result.revents = Network::PollEvents{};
  442. return result;
  443. });
  444. const auto result = Network::Poll(host_pollfds, timeout);
  445. const size_t num = host_pollfds.size();
  446. for (size_t i = 0; i < num; ++i) {
  447. fds[i].revents = Translate(host_pollfds[i].revents);
  448. }
  449. std::memcpy(write_buffer.data(), fds.data(), length);
  450. return Translate(result);
  451. }
  452. std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
  453. if (!IsFileDescriptorValid(fd)) {
  454. return {-1, Errno::BADF};
  455. }
  456. const s32 new_fd = FindFreeFileDescriptorHandle();
  457. if (new_fd < 0) {
  458. LOG_ERROR(Service, "No more file descriptors available");
  459. return {-1, Errno::MFILE};
  460. }
  461. FileDescriptor& descriptor = *file_descriptors[fd];
  462. auto [result, bsd_errno] = descriptor.socket->Accept();
  463. if (bsd_errno != Network::Errno::SUCCESS) {
  464. return {-1, Translate(bsd_errno)};
  465. }
  466. file_descriptors[new_fd] = FileDescriptor{};
  467. FileDescriptor& new_descriptor = *file_descriptors[new_fd];
  468. new_descriptor.socket = std::move(result.socket);
  469. new_descriptor.is_connection_based = descriptor.is_connection_based;
  470. const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
  471. const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size());
  472. std::memcpy(write_buffer.data(), &guest_addr_in, length);
  473. return {new_fd, Errno::SUCCESS};
  474. }
  475. Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
  476. if (!IsFileDescriptorValid(fd)) {
  477. return Errno::BADF;
  478. }
  479. ASSERT(addr.size() == sizeof(SockAddrIn));
  480. SockAddrIn addr_in;
  481. std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
  482. return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
  483. }
  484. Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
  485. if (!IsFileDescriptorValid(fd)) {
  486. return Errno::BADF;
  487. }
  488. UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
  489. SockAddrIn addr_in;
  490. std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
  491. return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
  492. }
  493. Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
  494. if (!IsFileDescriptorValid(fd)) {
  495. return Errno::BADF;
  496. }
  497. const auto [addr_in, bsd_errno] = file_descriptors[fd]->socket->GetPeerName();
  498. if (bsd_errno != Network::Errno::SUCCESS) {
  499. return Translate(bsd_errno);
  500. }
  501. const SockAddrIn guest_addrin = Translate(addr_in);
  502. ASSERT(write_buffer.size() >= sizeof(guest_addrin));
  503. write_buffer.resize(sizeof(guest_addrin));
  504. std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
  505. return Translate(bsd_errno);
  506. }
  507. Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
  508. if (!IsFileDescriptorValid(fd)) {
  509. return Errno::BADF;
  510. }
  511. const auto [addr_in, bsd_errno] = file_descriptors[fd]->socket->GetSockName();
  512. if (bsd_errno != Network::Errno::SUCCESS) {
  513. return Translate(bsd_errno);
  514. }
  515. const SockAddrIn guest_addrin = Translate(addr_in);
  516. ASSERT(write_buffer.size() >= sizeof(guest_addrin));
  517. write_buffer.resize(sizeof(guest_addrin));
  518. std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
  519. return Translate(bsd_errno);
  520. }
  521. Errno BSD::ListenImpl(s32 fd, s32 backlog) {
  522. if (!IsFileDescriptorValid(fd)) {
  523. return Errno::BADF;
  524. }
  525. return Translate(file_descriptors[fd]->socket->Listen(backlog));
  526. }
  527. std::pair<s32, Errno> BSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
  528. if (!IsFileDescriptorValid(fd)) {
  529. return {-1, Errno::BADF};
  530. }
  531. FileDescriptor& descriptor = *file_descriptors[fd];
  532. switch (cmd) {
  533. case FcntlCmd::GETFL:
  534. ASSERT(arg == 0);
  535. return {descriptor.flags, Errno::SUCCESS};
  536. case FcntlCmd::SETFL: {
  537. const bool enable = (arg & Network::FLAG_O_NONBLOCK) != 0;
  538. const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable));
  539. if (bsd_errno != Errno::SUCCESS) {
  540. return {-1, bsd_errno};
  541. }
  542. descriptor.flags = arg;
  543. return {0, Errno::SUCCESS};
  544. }
  545. default:
  546. UNIMPLEMENTED_MSG("Unimplemented cmd={}", cmd);
  547. return {-1, Errno::SUCCESS};
  548. }
  549. }
  550. Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval) {
  551. if (!IsFileDescriptorValid(fd)) {
  552. return Errno::BADF;
  553. }
  554. if (level != static_cast<u32>(SocketLevel::SOCKET)) {
  555. UNIMPLEMENTED_MSG("Unknown getsockopt level");
  556. return Errno::SUCCESS;
  557. }
  558. Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
  559. switch (optname) {
  560. case OptName::ERROR_: {
  561. auto [pending_err, getsockopt_err] = socket->GetPendingError();
  562. if (getsockopt_err == Network::Errno::SUCCESS) {
  563. Errno translated_pending_err = Translate(pending_err);
  564. ASSERT_OR_EXECUTE_MSG(
  565. optval.size() == sizeof(Errno), { return Errno::INVAL; },
  566. "Incorrect getsockopt option size");
  567. optval.resize(sizeof(Errno));
  568. memcpy(optval.data(), &translated_pending_err, sizeof(Errno));
  569. }
  570. return Translate(getsockopt_err);
  571. }
  572. default:
  573. UNIMPLEMENTED_MSG("Unimplemented optname={}", optname);
  574. return Errno::SUCCESS;
  575. }
  576. }
  577. Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) {
  578. if (!IsFileDescriptorValid(fd)) {
  579. return Errno::BADF;
  580. }
  581. if (level != static_cast<u32>(SocketLevel::SOCKET)) {
  582. UNIMPLEMENTED_MSG("Unknown setsockopt level");
  583. return Errno::SUCCESS;
  584. }
  585. Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
  586. if (optname == OptName::LINGER) {
  587. ASSERT(optlen == sizeof(Linger));
  588. Linger linger;
  589. std::memcpy(&linger, optval, sizeof(linger));
  590. ASSERT(linger.onoff == 0 || linger.onoff == 1);
  591. return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
  592. }
  593. ASSERT(optlen == sizeof(u32));
  594. u32 value;
  595. std::memcpy(&value, optval, sizeof(value));
  596. switch (optname) {
  597. case OptName::REUSEADDR:
  598. ASSERT(value == 0 || value == 1);
  599. return Translate(socket->SetReuseAddr(value != 0));
  600. case OptName::KEEPALIVE:
  601. ASSERT(value == 0 || value == 1);
  602. return Translate(socket->SetKeepAlive(value != 0));
  603. case OptName::BROADCAST:
  604. ASSERT(value == 0 || value == 1);
  605. return Translate(socket->SetBroadcast(value != 0));
  606. case OptName::SNDBUF:
  607. return Translate(socket->SetSndBuf(value));
  608. case OptName::RCVBUF:
  609. return Translate(socket->SetRcvBuf(value));
  610. case OptName::SNDTIMEO:
  611. return Translate(socket->SetSndTimeo(value));
  612. case OptName::RCVTIMEO:
  613. return Translate(socket->SetRcvTimeo(value));
  614. case OptName::NOSIGPIPE:
  615. LOG_WARNING(Service, "(STUBBED) setting NOSIGPIPE to {}", value);
  616. return Errno::SUCCESS;
  617. default:
  618. UNIMPLEMENTED_MSG("Unimplemented optname={}", optname);
  619. return Errno::SUCCESS;
  620. }
  621. }
  622. Errno BSD::ShutdownImpl(s32 fd, s32 how) {
  623. if (!IsFileDescriptorValid(fd)) {
  624. return Errno::BADF;
  625. }
  626. const Network::ShutdownHow host_how = Translate(static_cast<ShutdownHow>(how));
  627. return Translate(file_descriptors[fd]->socket->Shutdown(host_how));
  628. }
  629. std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message) {
  630. if (!IsFileDescriptorValid(fd)) {
  631. return {-1, Errno::BADF};
  632. }
  633. FileDescriptor& descriptor = *file_descriptors[fd];
  634. // Apply flags
  635. using Network::FLAG_MSG_DONTWAIT;
  636. using Network::FLAG_O_NONBLOCK;
  637. if ((flags & FLAG_MSG_DONTWAIT) != 0) {
  638. flags &= ~FLAG_MSG_DONTWAIT;
  639. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  640. descriptor.socket->SetNonBlock(true);
  641. }
  642. }
  643. const auto [ret, bsd_errno] = Translate(descriptor.socket->Recv(flags, message));
  644. // Restore original state
  645. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  646. descriptor.socket->SetNonBlock(false);
  647. }
  648. return {ret, bsd_errno};
  649. }
  650. std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
  651. std::vector<u8>& addr) {
  652. if (!IsFileDescriptorValid(fd)) {
  653. return {-1, Errno::BADF};
  654. }
  655. FileDescriptor& descriptor = *file_descriptors[fd];
  656. Network::SockAddrIn addr_in{};
  657. Network::SockAddrIn* p_addr_in = nullptr;
  658. if (descriptor.is_connection_based) {
  659. // Connection based file descriptors (e.g. TCP) zero addr
  660. addr.clear();
  661. } else {
  662. p_addr_in = &addr_in;
  663. }
  664. // Apply flags
  665. using Network::FLAG_MSG_DONTWAIT;
  666. using Network::FLAG_O_NONBLOCK;
  667. if ((flags & FLAG_MSG_DONTWAIT) != 0) {
  668. flags &= ~FLAG_MSG_DONTWAIT;
  669. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  670. descriptor.socket->SetNonBlock(true);
  671. }
  672. }
  673. const auto [ret, bsd_errno] = Translate(descriptor.socket->RecvFrom(flags, message, p_addr_in));
  674. // Restore original state
  675. if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
  676. descriptor.socket->SetNonBlock(false);
  677. }
  678. if (p_addr_in) {
  679. if (ret < 0) {
  680. addr.clear();
  681. } else {
  682. ASSERT(addr.size() == sizeof(SockAddrIn));
  683. const SockAddrIn result = Translate(addr_in);
  684. std::memcpy(addr.data(), &result, sizeof(result));
  685. }
  686. }
  687. return {ret, bsd_errno};
  688. }
  689. std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) {
  690. if (!IsFileDescriptorValid(fd)) {
  691. return {-1, Errno::BADF};
  692. }
  693. return Translate(file_descriptors[fd]->socket->Send(message, flags));
  694. }
  695. std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
  696. std::span<const u8> addr) {
  697. if (!IsFileDescriptorValid(fd)) {
  698. return {-1, Errno::BADF};
  699. }
  700. Network::SockAddrIn addr_in;
  701. Network::SockAddrIn* p_addr_in = nullptr;
  702. if (!addr.empty()) {
  703. ASSERT(addr.size() == sizeof(SockAddrIn));
  704. SockAddrIn guest_addr_in;
  705. std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
  706. addr_in = Translate(guest_addr_in);
  707. p_addr_in = &addr_in;
  708. }
  709. return Translate(file_descriptors[fd]->socket->SendTo(flags, message, p_addr_in));
  710. }
  711. Errno BSD::CloseImpl(s32 fd) {
  712. if (!IsFileDescriptorValid(fd)) {
  713. return Errno::BADF;
  714. }
  715. const Errno bsd_errno = Translate(file_descriptors[fd]->socket->Close());
  716. if (bsd_errno != Errno::SUCCESS) {
  717. return bsd_errno;
  718. }
  719. LOG_INFO(Service, "Close socket fd={}", fd);
  720. file_descriptors[fd].reset();
  721. return bsd_errno;
  722. }
  723. Expected<s32, Errno> BSD::DuplicateSocketImpl(s32 fd) {
  724. if (!IsFileDescriptorValid(fd)) {
  725. return Unexpected(Errno::BADF);
  726. }
  727. const s32 new_fd = FindFreeFileDescriptorHandle();
  728. if (new_fd < 0) {
  729. LOG_ERROR(Service, "No more file descriptors available");
  730. return Unexpected(Errno::MFILE);
  731. }
  732. file_descriptors[new_fd] = file_descriptors[fd];
  733. return new_fd;
  734. }
  735. std::optional<std::shared_ptr<Network::SocketBase>> BSD::GetSocket(s32 fd) {
  736. if (!IsFileDescriptorValid(fd)) {
  737. return std::nullopt;
  738. }
  739. return file_descriptors[fd]->socket;
  740. }
  741. s32 BSD::FindFreeFileDescriptorHandle() noexcept {
  742. for (s32 fd = 0; fd < static_cast<s32>(file_descriptors.size()); ++fd) {
  743. if (!file_descriptors[fd]) {
  744. return fd;
  745. }
  746. }
  747. return -1;
  748. }
  749. bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
  750. if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
  751. LOG_ERROR(Service, "Invalid file descriptor handle={}", fd);
  752. return false;
  753. }
  754. if (!file_descriptors[fd]) {
  755. LOG_ERROR(Service, "File descriptor handle={} is not allocated", fd);
  756. return false;
  757. }
  758. return true;
  759. }
  760. void BSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept {
  761. IPC::ResponseBuilder rb{ctx, 4};
  762. rb.Push(ResultSuccess);
  763. rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
  764. rb.PushEnum(bsd_errno);
  765. }
  766. void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
  767. for (auto& optional_descriptor : file_descriptors) {
  768. if (!optional_descriptor.has_value()) {
  769. continue;
  770. }
  771. FileDescriptor& descriptor = *optional_descriptor;
  772. descriptor.socket.get()->HandleProxyPacket(packet);
  773. }
  774. }
  775. BSD::BSD(Core::System& system_, const char* name)
  776. : ServiceFramework{system_, name}, room_network{system_.GetRoomNetwork()} {
  777. // clang-format off
  778. static const FunctionInfo functions[] = {
  779. {0, &BSD::RegisterClient, "RegisterClient"},
  780. {1, &BSD::StartMonitoring, "StartMonitoring"},
  781. {2, &BSD::Socket, "Socket"},
  782. {3, nullptr, "SocketExempt"},
  783. {4, nullptr, "Open"},
  784. {5, &BSD::Select, "Select"},
  785. {6, &BSD::Poll, "Poll"},
  786. {7, nullptr, "Sysctl"},
  787. {8, &BSD::Recv, "Recv"},
  788. {9, &BSD::RecvFrom, "RecvFrom"},
  789. {10, &BSD::Send, "Send"},
  790. {11, &BSD::SendTo, "SendTo"},
  791. {12, &BSD::Accept, "Accept"},
  792. {13, &BSD::Bind, "Bind"},
  793. {14, &BSD::Connect, "Connect"},
  794. {15, &BSD::GetPeerName, "GetPeerName"},
  795. {16, &BSD::GetSockName, "GetSockName"},
  796. {17, &BSD::GetSockOpt, "GetSockOpt"},
  797. {18, &BSD::Listen, "Listen"},
  798. {19, nullptr, "Ioctl"},
  799. {20, &BSD::Fcntl, "Fcntl"},
  800. {21, &BSD::SetSockOpt, "SetSockOpt"},
  801. {22, &BSD::Shutdown, "Shutdown"},
  802. {23, nullptr, "ShutdownAllSockets"},
  803. {24, &BSD::Write, "Write"},
  804. {25, &BSD::Read, "Read"},
  805. {26, &BSD::Close, "Close"},
  806. {27, &BSD::DuplicateSocket, "DuplicateSocket"},
  807. {28, nullptr, "GetResourceStatistics"},
  808. {29, nullptr, "RecvMMsg"},
  809. {30, nullptr, "SendMMsg"},
  810. {31, &BSD::EventFd, "EventFd"},
  811. {32, nullptr, "RegisterResourceStatisticsName"},
  812. {33, nullptr, "Initialize2"},
  813. };
  814. // clang-format on
  815. RegisterHandlers(functions);
  816. if (auto room_member = room_network.GetRoomMember().lock()) {
  817. proxy_packet_received = room_member->BindOnProxyPacketReceived(
  818. [this](const Network::ProxyPacket& packet) { OnProxyPacketReceived(packet); });
  819. } else {
  820. LOG_ERROR(Service, "Network isn't initialized");
  821. }
  822. }
  823. BSD::~BSD() {
  824. if (auto room_member = room_network.GetRoomMember().lock()) {
  825. room_member->Unbind(proxy_packet_received);
  826. }
  827. }
  828. std::unique_lock<std::mutex> BSD::LockService() {
  829. // Do not lock socket IClient instances.
  830. return {};
  831. }
  832. BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} {
  833. // clang-format off
  834. static const FunctionInfo functions[] = {
  835. {0, nullptr, "SetIfUp"},
  836. {1, nullptr, "SetIfUpWithEvent"},
  837. {2, nullptr, "CancelIf"},
  838. {3, nullptr, "SetIfDown"},
  839. {4, nullptr, "GetIfState"},
  840. {5, nullptr, "DhcpRenew"},
  841. {6, nullptr, "AddStaticArpEntry"},
  842. {7, nullptr, "RemoveArpEntry"},
  843. {8, nullptr, "LookupArpEntry"},
  844. {9, nullptr, "LookupArpEntry2"},
  845. {10, nullptr, "ClearArpEntries"},
  846. {11, nullptr, "ClearArpEntries2"},
  847. {12, nullptr, "PrintArpEntries"},
  848. {13, nullptr, "Unknown13"},
  849. {14, nullptr, "Unknown14"},
  850. {15, nullptr, "Unknown15"},
  851. };
  852. // clang-format on
  853. RegisterHandlers(functions);
  854. }
  855. BSDCFG::~BSDCFG() = default;
  856. } // namespace Service::Sockets