netdb.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Assertions.h>
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/ByteString.h>
  9. #include <AK/ScopeGuard.h>
  10. #include <Kernel/Net/IPv4.h>
  11. #include <arpa/inet.h>
  12. #include <errno.h>
  13. #include <netdb.h>
  14. #include <netinet/in.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. extern "C" {
  19. #ifdef NO_TLS
  20. int h_errno;
  21. #else
  22. __thread int h_errno;
  23. #endif
  24. static hostent __gethostbyname_buffer;
  25. static in_addr_t __gethostbyname_address;
  26. static in_addr_t* __gethostbyname_address_list_buffer[2];
  27. static char* __gethostbyname_alias_list_buffer[1];
  28. static hostent __gethostbyaddr_buffer;
  29. static in_addr_t* __gethostbyaddr_address_list_buffer[2];
  30. static char* __gethostbyaddr_alias_list_buffer[1];
  31. // IPCCompiler depends on LibC. Because of this, it cannot be compiled
  32. // before LibC is. However, the lookup magic can only be obtained from the
  33. // endpoint itself if IPCCompiler has compiled the IPC file, so this creates
  34. // a chicken-and-egg situation. Because of this, the LookupServer endpoint magic
  35. // is hardcoded here.
  36. // Keep the name synchronized with LookupServer/LookupServer.ipc.
  37. static constexpr u32 lookup_server_endpoint_magic = "LookupServer"sv.hash();
  38. // Get service entry buffers and file information for the getservent() family of functions.
  39. static FILE* services_file = nullptr;
  40. static char const* services_path = "/etc/services";
  41. struct ServiceFileLine {
  42. String name;
  43. String protocol;
  44. int port;
  45. Vector<ByteBuffer> aliases;
  46. };
  47. static ErrorOr<Optional<ServiceFileLine>> parse_service_file_line(char const* line, ssize_t read);
  48. static servent __getserv_buffer;
  49. static ByteString __getserv_name_buffer;
  50. static ByteString __getserv_protocol_buffer;
  51. static int __getserv_port_buffer;
  52. static Vector<ByteBuffer> __getserv_alias_list_buffer;
  53. static Vector<char*> __getserv_alias_list;
  54. static bool keep_service_file_open = false;
  55. static ssize_t service_file_offset = 0;
  56. // Get protocol entry buffers and file information for the getprotent() family of functions.
  57. static FILE* protocols_file = nullptr;
  58. static char const* protocols_path = "/etc/protocols";
  59. static bool fill_getproto_buffers(char const* line, ssize_t read);
  60. static protoent __getproto_buffer;
  61. static ByteString __getproto_name_buffer;
  62. static Vector<ByteBuffer> __getproto_alias_list_buffer;
  63. static Vector<char*> __getproto_alias_list;
  64. static int __getproto_protocol_buffer;
  65. static bool keep_protocols_file_open = false;
  66. static ssize_t protocol_file_offset = 0;
  67. static int connect_to_lookup_server()
  68. {
  69. int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
  70. if (fd < 0) {
  71. perror("socket");
  72. return -1;
  73. }
  74. sockaddr_un address {
  75. AF_LOCAL,
  76. "/tmp/portal/lookup"
  77. };
  78. if (connect(fd, (sockaddr const*)&address, sizeof(address)) < 0) {
  79. perror("connect_to_lookup_server");
  80. close(fd);
  81. return -1;
  82. }
  83. return fd;
  84. }
  85. static ByteString gethostbyname_name_buffer;
  86. hostent* gethostbyname(char const* name)
  87. {
  88. struct hostent ret = {};
  89. struct hostent* result = nullptr;
  90. size_t buffer_size = 1024;
  91. char* buffer = nullptr;
  92. auto free_buffer_on_exit = ScopeGuard([buffer] {
  93. if (buffer != nullptr)
  94. free(buffer);
  95. });
  96. while (true) {
  97. buffer = (char*)realloc(buffer, buffer_size);
  98. if (buffer == nullptr) {
  99. // NOTE: Since gethostbyname usually can't fail because of memory,
  100. // it has no way of representing OOM or allocation failure.
  101. // NO_RECOVERY is the next best thing.
  102. h_errno = NO_RECOVERY;
  103. return NULL;
  104. }
  105. int rc = gethostbyname_r(name, &ret, buffer, buffer_size, &result, &h_errno);
  106. if (rc == ERANGE) {
  107. buffer_size *= 2;
  108. continue;
  109. }
  110. if (rc < 0)
  111. return nullptr;
  112. break;
  113. }
  114. gethostbyname_name_buffer = name;
  115. __gethostbyname_buffer.h_name = const_cast<char*>(gethostbyname_name_buffer.characters());
  116. __gethostbyname_alias_list_buffer[0] = nullptr;
  117. __gethostbyname_buffer.h_aliases = __gethostbyname_alias_list_buffer;
  118. __gethostbyname_buffer.h_addrtype = AF_INET;
  119. memcpy(&__gethostbyname_address, result->h_addr_list[0], sizeof(in_addr_t));
  120. __gethostbyname_address_list_buffer[0] = &__gethostbyname_address;
  121. __gethostbyname_address_list_buffer[1] = nullptr;
  122. __gethostbyname_buffer.h_addr_list = (char**)__gethostbyname_address_list_buffer;
  123. __gethostbyname_buffer.h_length = result->h_length;
  124. return &__gethostbyname_buffer;
  125. }
  126. int gethostbyname_r(char const* __restrict name, struct hostent* __restrict ret, char* buffer, size_t buffer_size, struct hostent** __restrict result, int* __restrict h_errnop)
  127. {
  128. *h_errnop = 0;
  129. *result = nullptr;
  130. size_t buffer_offset = 0;
  131. memset(buffer, 0, buffer_size);
  132. auto add_string_to_buffer = [&](char const* data) -> Optional<char*> {
  133. size_t data_lenth = strlen(data);
  134. if (buffer_offset + data_lenth + 1 >= buffer_size)
  135. return {};
  136. auto* buffer_beginning = buffer + buffer_offset;
  137. memcpy(buffer + buffer_offset, data, data_lenth);
  138. buffer_offset += data_lenth;
  139. buffer[buffer_offset++] = '\0';
  140. buffer_offset += 8 - (buffer_offset % 8);
  141. return buffer_beginning;
  142. };
  143. auto add_data_to_buffer = [&](void const* data, size_t size, size_t count = 1) -> Optional<void*> {
  144. auto bytes = size * count;
  145. if (buffer_offset + bytes >= buffer_size)
  146. return {};
  147. auto* buffer_beginning = buffer + buffer_offset;
  148. memcpy(buffer + buffer_offset, data, bytes);
  149. buffer_offset += bytes;
  150. buffer_offset += 8 - (buffer_offset % 8);
  151. return buffer_beginning;
  152. };
  153. auto add_ptr_to_buffer = [&](void* ptr) -> Optional<void*> {
  154. return add_data_to_buffer(&ptr, sizeof(ptr));
  155. };
  156. auto populate_ret = [&](char const* name, in_addr_t address) -> int {
  157. auto h_name = add_string_to_buffer(name);
  158. if (!h_name.has_value())
  159. return ERANGE;
  160. ret->h_name = static_cast<char*>(h_name.value());
  161. auto null_list_item = add_ptr_to_buffer(nullptr);
  162. if (!null_list_item.has_value())
  163. return ERANGE;
  164. ret->h_aliases = static_cast<char**>(null_list_item.value());
  165. auto address_item = add_data_to_buffer(&address, sizeof(address));
  166. if (!address_item.has_value())
  167. return ERANGE;
  168. auto address_list = add_ptr_to_buffer(address_item.value());
  169. if (!address_list.has_value())
  170. return ERANGE;
  171. if (!add_ptr_to_buffer(nullptr).has_value())
  172. return ERANGE;
  173. ret->h_addr_list = static_cast<char**>(address_list.value());
  174. ret->h_addrtype = AF_INET;
  175. ret->h_length = 4;
  176. *result = ret;
  177. return 0;
  178. };
  179. auto ipv4_address = IPv4Address::from_string({ name, strlen(name) });
  180. if (ipv4_address.has_value()) {
  181. return populate_ret(ipv4_address.value().to_byte_string().characters(), ipv4_address.value().to_in_addr_t());
  182. }
  183. int fd = connect_to_lookup_server();
  184. if (fd < 0) {
  185. *h_errnop = TRY_AGAIN;
  186. return -TRY_AGAIN;
  187. }
  188. auto close_fd_on_exit = ScopeGuard([fd] {
  189. close(fd);
  190. });
  191. auto name_length = strlen(name);
  192. VERIFY(name_length <= NumericLimits<i32>::max());
  193. struct [[gnu::packed]] {
  194. u32 message_size;
  195. u32 endpoint_magic;
  196. i32 message_id;
  197. u32 name_length;
  198. } request_header = {
  199. (u32)(sizeof(request_header) - sizeof(request_header.message_size) + name_length),
  200. lookup_server_endpoint_magic,
  201. 1,
  202. static_cast<u32>(name_length),
  203. };
  204. if (auto nsent = write(fd, &request_header, sizeof(request_header)); nsent < 0) {
  205. *h_errnop = TRY_AGAIN;
  206. return -TRY_AGAIN;
  207. } else if (nsent != sizeof(request_header)) {
  208. *h_errnop = NO_RECOVERY;
  209. return -NO_RECOVERY;
  210. }
  211. if (auto nsent = write(fd, name, name_length); nsent < 0) {
  212. *h_errnop = TRY_AGAIN;
  213. return -TRY_AGAIN;
  214. } else if (static_cast<size_t>(nsent) != name_length) {
  215. *h_errnop = NO_RECOVERY;
  216. return -NO_RECOVERY;
  217. }
  218. struct [[gnu::packed]] {
  219. u32 message_size;
  220. u32 endpoint_magic;
  221. i32 message_id;
  222. i32 code;
  223. u32 addresses_count;
  224. } response_header;
  225. if (auto nreceived = read(fd, &response_header, sizeof(response_header)); nreceived < 0) {
  226. *h_errnop = TRY_AGAIN;
  227. return -TRY_AGAIN;
  228. } else if (nreceived != sizeof(response_header)) {
  229. *h_errnop = NO_RECOVERY;
  230. return -NO_RECOVERY;
  231. }
  232. if (response_header.endpoint_magic != lookup_server_endpoint_magic || response_header.message_id != 2) {
  233. *h_errnop = NO_RECOVERY;
  234. return -NO_RECOVERY;
  235. }
  236. if (response_header.code != 0) {
  237. *h_errnop = NO_RECOVERY;
  238. return -NO_RECOVERY;
  239. }
  240. if (response_header.addresses_count == 0) {
  241. *h_errnop = HOST_NOT_FOUND;
  242. return -HOST_NOT_FOUND;
  243. }
  244. i32 response_length;
  245. if (auto nreceived = read(fd, &response_length, sizeof(response_length)); nreceived < 0) {
  246. *h_errnop = TRY_AGAIN;
  247. return -TRY_AGAIN;
  248. } else if (nreceived != sizeof(response_length)
  249. || response_length != sizeof(in_addr_t)) {
  250. *h_errnop = NO_RECOVERY;
  251. return -NO_RECOVERY;
  252. }
  253. in_addr_t address;
  254. if (auto nreceived = read(fd, &address, response_length); nreceived < 0) {
  255. *h_errnop = TRY_AGAIN;
  256. return -TRY_AGAIN;
  257. } else if (nreceived != response_length) {
  258. *h_errnop = NO_RECOVERY;
  259. return -NO_RECOVERY;
  260. }
  261. return populate_ret(name, address);
  262. }
  263. static ByteString gethostbyaddr_name_buffer;
  264. hostent* gethostbyaddr(void const* addr, socklen_t addr_size, int type)
  265. {
  266. h_errno = 0;
  267. if (type != AF_INET) {
  268. errno = EAFNOSUPPORT;
  269. return nullptr;
  270. }
  271. if (addr_size < sizeof(in_addr)) {
  272. errno = EINVAL;
  273. return nullptr;
  274. }
  275. int fd = connect_to_lookup_server();
  276. if (fd < 0) {
  277. h_errno = TRY_AGAIN;
  278. return nullptr;
  279. }
  280. auto close_fd_on_exit = ScopeGuard([fd] {
  281. close(fd);
  282. });
  283. in_addr_t const& in_addr = ((const struct in_addr*)addr)->s_addr;
  284. struct [[gnu::packed]] {
  285. u32 message_size;
  286. u32 endpoint_magic;
  287. i32 message_id;
  288. i32 address_length;
  289. } request_header = {
  290. sizeof(request_header) - sizeof(request_header.message_size) + sizeof(in_addr),
  291. lookup_server_endpoint_magic,
  292. 3,
  293. sizeof(in_addr),
  294. };
  295. if (auto nsent = write(fd, &request_header, sizeof(request_header)); nsent < 0) {
  296. h_errno = TRY_AGAIN;
  297. return nullptr;
  298. } else if (nsent != sizeof(request_header)) {
  299. h_errno = NO_RECOVERY;
  300. return nullptr;
  301. }
  302. if (auto nsent = write(fd, &in_addr, sizeof(in_addr)); nsent < 0) {
  303. h_errno = TRY_AGAIN;
  304. return nullptr;
  305. } else if (nsent != sizeof(in_addr)) {
  306. h_errno = TRY_AGAIN;
  307. return nullptr;
  308. }
  309. struct [[gnu::packed]] {
  310. u32 message_size;
  311. u32 endpoint_magic;
  312. i32 message_id;
  313. i32 code;
  314. u32 name_length;
  315. } response_header;
  316. if (auto nreceived = read(fd, &response_header, sizeof(response_header)); nreceived < 0) {
  317. h_errno = TRY_AGAIN;
  318. return nullptr;
  319. } else if (nreceived != sizeof(response_header)) {
  320. h_errno = NO_RECOVERY;
  321. return nullptr;
  322. }
  323. if (response_header.endpoint_magic != lookup_server_endpoint_magic
  324. || response_header.message_id != 4
  325. || response_header.code != 0) {
  326. h_errno = NO_RECOVERY;
  327. return nullptr;
  328. }
  329. char* buffer;
  330. auto string_impl = StringImpl::create_uninitialized(response_header.name_length, buffer);
  331. if (auto nreceived = read(fd, buffer, response_header.name_length); nreceived < 0) {
  332. h_errno = TRY_AGAIN;
  333. return nullptr;
  334. } else if (static_cast<u32>(nreceived) != response_header.name_length) {
  335. h_errno = NO_RECOVERY;
  336. return nullptr;
  337. }
  338. gethostbyaddr_name_buffer = move(string_impl);
  339. __gethostbyaddr_buffer.h_name = buffer;
  340. __gethostbyaddr_alias_list_buffer[0] = nullptr;
  341. __gethostbyaddr_buffer.h_aliases = __gethostbyaddr_alias_list_buffer;
  342. __gethostbyaddr_buffer.h_addrtype = AF_INET;
  343. // FIXME: Should we populate the hostent's address list here with a sockaddr_in for the provided host?
  344. __gethostbyaddr_address_list_buffer[0] = nullptr;
  345. __gethostbyaddr_buffer.h_addr_list = (char**)__gethostbyaddr_address_list_buffer;
  346. __gethostbyaddr_buffer.h_length = 4;
  347. return &__gethostbyaddr_buffer;
  348. }
  349. struct servent* getservent()
  350. {
  351. // If the services file is not open, attempt to open it and return null if it fails.
  352. if (!services_file) {
  353. services_file = fopen(services_path, "r");
  354. if (!services_file) {
  355. perror("error opening services file");
  356. return nullptr;
  357. }
  358. }
  359. if (fseek(services_file, service_file_offset, SEEK_SET) != 0) {
  360. perror("error seeking file");
  361. fclose(services_file);
  362. return nullptr;
  363. }
  364. char* line = nullptr;
  365. size_t len = 0;
  366. ssize_t read;
  367. auto free_line_on_exit = ScopeGuard([line] {
  368. if (line) {
  369. free(line);
  370. }
  371. });
  372. Optional<ServiceFileLine> service_file_line = {};
  373. // Read lines from services file until an actual service name is found.
  374. do {
  375. read = getline(&line, &len, services_file);
  376. service_file_offset += read;
  377. auto service_file_line_or_error = parse_service_file_line(line, read);
  378. if (service_file_line_or_error.is_error())
  379. return nullptr;
  380. service_file_line = service_file_line_or_error.release_value();
  381. if (service_file_line.has_value())
  382. break;
  383. } while (read != -1);
  384. if (read == -1) {
  385. fclose(services_file);
  386. services_file = nullptr;
  387. service_file_offset = 0;
  388. return nullptr;
  389. }
  390. if (!service_file_line.has_value())
  391. return nullptr;
  392. servent* service_entry = nullptr;
  393. __getserv_name_buffer = service_file_line.value().name.to_byte_string();
  394. __getserv_port_buffer = service_file_line.value().port;
  395. __getserv_protocol_buffer = service_file_line.value().protocol.to_byte_string();
  396. __getserv_alias_list_buffer = service_file_line.value().aliases;
  397. __getserv_buffer.s_name = const_cast<char*>(__getserv_name_buffer.characters());
  398. __getserv_buffer.s_port = htons(__getserv_port_buffer);
  399. __getserv_buffer.s_proto = const_cast<char*>(__getserv_protocol_buffer.characters());
  400. __getserv_alias_list.clear_with_capacity();
  401. __getserv_alias_list.ensure_capacity(__getserv_alias_list_buffer.size() + 1);
  402. for (auto& alias : __getserv_alias_list_buffer)
  403. __getserv_alias_list.unchecked_append(reinterpret_cast<char*>(alias.data()));
  404. __getserv_alias_list.unchecked_append(nullptr);
  405. __getserv_buffer.s_aliases = __getserv_alias_list.data();
  406. service_entry = &__getserv_buffer;
  407. if (!keep_service_file_open) {
  408. endservent();
  409. }
  410. return service_entry;
  411. }
  412. struct servent* getservbyname(char const* name, char const* protocol)
  413. {
  414. if (name == nullptr)
  415. return nullptr;
  416. bool previous_file_open_setting = keep_service_file_open;
  417. setservent(1);
  418. struct servent* current_service = nullptr;
  419. auto service_file_handler = ScopeGuard([previous_file_open_setting] {
  420. if (!previous_file_open_setting) {
  421. endservent();
  422. }
  423. });
  424. while (true) {
  425. current_service = getservent();
  426. if (current_service == nullptr)
  427. break;
  428. else if (!protocol && strcmp(current_service->s_name, name) == 0)
  429. break;
  430. else if (strcmp(current_service->s_name, name) == 0 && strcmp(current_service->s_proto, protocol) == 0)
  431. break;
  432. }
  433. return current_service;
  434. }
  435. struct servent* getservbyport(int port, char const* protocol)
  436. {
  437. bool previous_file_open_setting = keep_service_file_open;
  438. setservent(1);
  439. struct servent* current_service = nullptr;
  440. auto service_file_handler = ScopeGuard([previous_file_open_setting] {
  441. if (!previous_file_open_setting) {
  442. endservent();
  443. }
  444. });
  445. while (true) {
  446. current_service = getservent();
  447. if (current_service == nullptr)
  448. break;
  449. else if (!protocol && current_service->s_port == port)
  450. break;
  451. else if (current_service->s_port == port && (strcmp(current_service->s_proto, protocol) == 0))
  452. break;
  453. }
  454. return current_service;
  455. }
  456. void setservent(int stay_open)
  457. {
  458. if (!services_file) {
  459. services_file = fopen(services_path, "r");
  460. if (!services_file) {
  461. perror("error opening services file");
  462. return;
  463. }
  464. }
  465. rewind(services_file);
  466. keep_service_file_open = stay_open;
  467. service_file_offset = 0;
  468. }
  469. void endservent()
  470. {
  471. if (!services_file) {
  472. return;
  473. }
  474. fclose(services_file);
  475. services_file = nullptr;
  476. }
  477. static ErrorOr<Optional<ServiceFileLine>> parse_service_file_line(char const* line, ssize_t read)
  478. {
  479. // If the line isn't a service (eg. empty or a comment)
  480. if (read <= 0 || line[0] < 65 || line[0] > 122)
  481. return { Optional<ServiceFileLine> {} };
  482. auto split_line = StringView(line, read).replace(" "sv, "\t"sv, ReplaceMode::All).split('\t');
  483. if (split_line.size() < 2)
  484. return Error::from_string_view("malformed service file"sv);
  485. auto name = TRY(String::from_byte_string(split_line[0]));
  486. auto port_protocol = TRY(String::from_byte_string(split_line[1]));
  487. auto port_protocol_split = TRY(port_protocol.split('/'));
  488. if (port_protocol_split.size() < 2)
  489. return Error::from_string_view("malformed service file"sv);
  490. auto port = port_protocol_split[0].to_number<int>();
  491. if (!port.has_value())
  492. return Error::from_string_view("port isn't a number"sv);
  493. // Remove whitespace at the end of the protocol
  494. auto protocol = TRY(port_protocol_split[1].replace(" "sv, ""sv, ReplaceMode::All));
  495. protocol = TRY(protocol.replace("\t"sv, ""sv, ReplaceMode::All));
  496. protocol = TRY(protocol.replace("\n"sv, ""sv, ReplaceMode::All));
  497. Vector<ByteBuffer> aliases;
  498. // If there are aliases for the service, we will fill the aliases list
  499. if (split_line.size() > 2 && !split_line[2].starts_with('#')) {
  500. for (size_t i = 2; i < split_line.size(); i++) {
  501. if (split_line[i].starts_with('#')) {
  502. break;
  503. }
  504. auto alias = split_line[i].to_byte_buffer();
  505. if (alias.try_append("\0", sizeof(char)).is_error())
  506. return Error::from_string_view("Failed to add null-byte to service alias"sv);
  507. aliases.append(move(alias));
  508. }
  509. }
  510. return ServiceFileLine {
  511. name, protocol, port.value(), aliases
  512. };
  513. }
  514. struct protoent* getprotoent()
  515. {
  516. // If protocols file isn't open, attempt to open and return null on failure.
  517. if (!protocols_file) {
  518. protocols_file = fopen(protocols_path, "r");
  519. if (!protocols_file) {
  520. perror("error opening protocols file");
  521. return nullptr;
  522. }
  523. }
  524. if (fseek(protocols_file, protocol_file_offset, SEEK_SET) != 0) {
  525. perror("error seeking protocols file");
  526. fclose(protocols_file);
  527. return nullptr;
  528. }
  529. char* line = nullptr;
  530. size_t len = 0;
  531. ssize_t read;
  532. auto free_line_on_exit = ScopeGuard([line] {
  533. if (line) {
  534. free(line);
  535. }
  536. });
  537. do {
  538. read = getline(&line, &len, protocols_file);
  539. protocol_file_offset += read;
  540. if (read > 0 && (line[0] >= 65 && line[0] <= 122)) {
  541. break;
  542. }
  543. } while (read != -1);
  544. if (read == -1) {
  545. fclose(protocols_file);
  546. protocols_file = nullptr;
  547. protocol_file_offset = 0;
  548. return nullptr;
  549. }
  550. struct protoent* protocol_entry = nullptr;
  551. if (!fill_getproto_buffers(line, read))
  552. return nullptr;
  553. __getproto_buffer.p_name = const_cast<char*>(__getproto_name_buffer.characters());
  554. __getproto_buffer.p_proto = __getproto_protocol_buffer;
  555. __getproto_alias_list.clear_with_capacity();
  556. __getproto_alias_list.ensure_capacity(__getproto_alias_list_buffer.size() + 1);
  557. for (auto& alias : __getproto_alias_list_buffer)
  558. __getproto_alias_list.unchecked_append(reinterpret_cast<char*>(alias.data()));
  559. __getserv_alias_list.unchecked_append(nullptr);
  560. __getproto_buffer.p_aliases = __getproto_alias_list.data();
  561. protocol_entry = &__getproto_buffer;
  562. if (!keep_protocols_file_open)
  563. endprotoent();
  564. return protocol_entry;
  565. }
  566. struct protoent* getprotobyname(char const* name)
  567. {
  568. bool previous_file_open_setting = keep_protocols_file_open;
  569. setprotoent(1);
  570. struct protoent* current_protocol = nullptr;
  571. auto protocol_file_handler = ScopeGuard([previous_file_open_setting] {
  572. if (!previous_file_open_setting) {
  573. endprotoent();
  574. }
  575. });
  576. while (true) {
  577. current_protocol = getprotoent();
  578. if (current_protocol == nullptr)
  579. break;
  580. else if (strcmp(current_protocol->p_name, name) == 0)
  581. break;
  582. }
  583. return current_protocol;
  584. }
  585. struct protoent* getprotobynumber(int proto)
  586. {
  587. bool previous_file_open_setting = keep_protocols_file_open;
  588. setprotoent(1);
  589. struct protoent* current_protocol = nullptr;
  590. auto protocol_file_handler = ScopeGuard([previous_file_open_setting] {
  591. if (!previous_file_open_setting) {
  592. endprotoent();
  593. }
  594. });
  595. while (true) {
  596. current_protocol = getprotoent();
  597. if (current_protocol == nullptr)
  598. break;
  599. else if (current_protocol->p_proto == proto)
  600. break;
  601. }
  602. return current_protocol;
  603. }
  604. void setprotoent(int stay_open)
  605. {
  606. if (!protocols_file) {
  607. protocols_file = fopen(protocols_path, "r");
  608. if (!protocols_file) {
  609. perror("setprotoent(): error opening protocols file");
  610. return;
  611. }
  612. }
  613. rewind(protocols_file);
  614. keep_protocols_file_open = stay_open;
  615. protocol_file_offset = 0;
  616. }
  617. void endprotoent()
  618. {
  619. if (!protocols_file) {
  620. return;
  621. }
  622. fclose(protocols_file);
  623. protocols_file = nullptr;
  624. }
  625. static bool fill_getproto_buffers(char const* line, ssize_t read)
  626. {
  627. ByteString string_line = ByteString(line, read);
  628. auto split_line = string_line.replace(" "sv, "\t"sv, ReplaceMode::All).split('\t');
  629. // This indicates an incorrect file format. Protocols file entries should
  630. // always have at least a name and a protocol.
  631. if (split_line.size() < 2) {
  632. warnln("getprotoent(): malformed protocols file");
  633. return false;
  634. }
  635. __getproto_name_buffer = split_line[0];
  636. auto number = split_line[1].to_number<int>();
  637. if (!number.has_value())
  638. return false;
  639. __getproto_protocol_buffer = number.value();
  640. __getproto_alias_list_buffer.clear();
  641. // If there are aliases for the protocol, we will fill the alias list buffer.
  642. if (split_line.size() > 2 && !split_line[2].starts_with('#')) {
  643. for (size_t i = 2; i < split_line.size(); i++) {
  644. if (split_line[i].starts_with('#'))
  645. break;
  646. auto alias = split_line[i].to_byte_buffer();
  647. if (alias.try_append("\0", sizeof(char)).is_error())
  648. return false;
  649. __getproto_alias_list_buffer.append(move(alias));
  650. }
  651. }
  652. return true;
  653. }
  654. int getaddrinfo(char const* __restrict node, char const* __restrict service, const struct addrinfo* __restrict hints, struct addrinfo** __restrict res)
  655. {
  656. *res = nullptr;
  657. if (hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
  658. return EAI_FAMILY;
  659. if (!node) {
  660. if (hints && hints->ai_flags & AI_PASSIVE)
  661. node = "0.0.0.0";
  662. else
  663. node = "127.0.0.1";
  664. }
  665. size_t buffer_size = 1024;
  666. char* buffer = nullptr;
  667. int gethostbyname_errno = 0;
  668. struct hostent ret = {};
  669. struct hostent* host_ent = nullptr;
  670. while (true) {
  671. buffer = (char*)realloc(buffer, buffer_size);
  672. if (buffer == nullptr)
  673. return EAI_MEMORY;
  674. int rc = gethostbyname_r(node, &ret, buffer, buffer_size, &host_ent, &gethostbyname_errno);
  675. if (rc == ERANGE) {
  676. buffer_size *= 2;
  677. continue;
  678. }
  679. if (!host_ent)
  680. return EAI_FAIL;
  681. break;
  682. }
  683. char const* proto = nullptr;
  684. if (hints && hints->ai_socktype) {
  685. switch (hints->ai_socktype) {
  686. case SOCK_STREAM:
  687. proto = "tcp";
  688. break;
  689. case SOCK_DGRAM:
  690. proto = "udp";
  691. break;
  692. default:
  693. return EAI_SOCKTYPE;
  694. }
  695. }
  696. long port;
  697. int socktype;
  698. Optional<ServiceFileLine> service_file_line = {};
  699. if ((!hints || (hints->ai_flags & AI_NUMERICSERV) == 0) && service) {
  700. services_file = fopen(services_path, "r");
  701. if (!services_file) {
  702. return EAI_FAIL;
  703. }
  704. auto close_services_file_handler = ScopeGuard([&] {
  705. fclose(services_file);
  706. });
  707. char* line = nullptr;
  708. size_t length = 0;
  709. ssize_t read;
  710. while (true) {
  711. do {
  712. read = getline(&line, &length, services_file);
  713. auto service_file_line_or_error = parse_service_file_line(line, read);
  714. if (service_file_line_or_error.is_error())
  715. return EAI_SYSTEM;
  716. service_file_line = service_file_line_or_error.release_value();
  717. if (service_file_line.has_value())
  718. break;
  719. } while (read != -1);
  720. if (read == -1 || !service_file_line.has_value())
  721. break;
  722. if (service_file_line.value().name != service)
  723. continue;
  724. if (service_file_line.value().protocol != proto)
  725. continue;
  726. break;
  727. }
  728. }
  729. if (!service_file_line.has_value()) {
  730. if (service) {
  731. char* end;
  732. port = htons(strtol(service, &end, 10));
  733. if (*end)
  734. return EAI_FAIL;
  735. } else {
  736. port = htons(0);
  737. }
  738. if (hints && hints->ai_socktype != 0)
  739. socktype = hints->ai_socktype;
  740. else
  741. socktype = SOCK_STREAM;
  742. } else {
  743. port = service_file_line.value().port;
  744. socktype = service_file_line.value().protocol == "tcp" ? SOCK_STREAM : SOCK_DGRAM;
  745. }
  746. addrinfo* first_info = nullptr;
  747. addrinfo* prev_info = nullptr;
  748. for (int host_index = 0; host_ent->h_addr_list[host_index]; host_index++) {
  749. sockaddr_in* sin = new sockaddr_in;
  750. sin->sin_family = AF_INET;
  751. sin->sin_port = port;
  752. memcpy(&sin->sin_addr.s_addr, host_ent->h_addr_list[host_index], host_ent->h_length);
  753. addrinfo* info = new addrinfo;
  754. info->ai_flags = 0;
  755. info->ai_family = AF_INET;
  756. info->ai_socktype = socktype;
  757. info->ai_protocol = PF_INET;
  758. info->ai_addrlen = sizeof(*sin);
  759. info->ai_addr = reinterpret_cast<sockaddr*>(sin);
  760. if (hints && hints->ai_flags & AI_CANONNAME)
  761. info->ai_canonname = strdup(host_ent->h_name);
  762. else
  763. info->ai_canonname = nullptr;
  764. info->ai_next = nullptr;
  765. if (!first_info)
  766. first_info = info;
  767. if (prev_info)
  768. prev_info->ai_next = info;
  769. prev_info = info;
  770. }
  771. if (first_info) {
  772. *res = first_info;
  773. return 0;
  774. } else
  775. return EAI_NONAME;
  776. }
  777. void freeaddrinfo(struct addrinfo* res)
  778. {
  779. if (res) {
  780. delete reinterpret_cast<sockaddr_in*>(res->ai_addr);
  781. free(res->ai_canonname);
  782. freeaddrinfo(res->ai_next);
  783. delete res;
  784. }
  785. }
  786. char const* gai_strerror(int errcode)
  787. {
  788. switch (errcode) {
  789. case EAI_ADDRFAMILY:
  790. return "no address for this address family available";
  791. case EAI_AGAIN:
  792. return "name server returned temporary failure";
  793. case EAI_BADFLAGS:
  794. return "invalid flags";
  795. case EAI_FAIL:
  796. return "name server returned permanent failure";
  797. case EAI_FAMILY:
  798. return "unsupported address family";
  799. case EAI_MEMORY:
  800. return "out of memory";
  801. case EAI_NODATA:
  802. return "no address available";
  803. case EAI_NONAME:
  804. return "node or service is not known";
  805. case EAI_SERVICE:
  806. return "service not available";
  807. case EAI_SOCKTYPE:
  808. return "unsupported socket type";
  809. case EAI_SYSTEM:
  810. return "system error";
  811. case EAI_OVERFLOW:
  812. return "buffer too small";
  813. default:
  814. return "invalid error code";
  815. }
  816. }
  817. int getnameinfo(const struct sockaddr* __restrict addr, socklen_t addrlen, char* __restrict host, socklen_t hostlen, char* __restrict serv, socklen_t servlen, int flags)
  818. {
  819. if (addr->sa_family != AF_INET || addrlen < sizeof(sockaddr_in))
  820. return EAI_FAMILY;
  821. sockaddr_in const* sin = reinterpret_cast<sockaddr_in const*>(addr);
  822. if (host && hostlen > 0) {
  823. if (flags != 0)
  824. dbgln("getnameinfo flags are not implemented: {:#x}", flags);
  825. if (!inet_ntop(AF_INET, &sin->sin_addr, host, hostlen)) {
  826. if (errno == ENOSPC)
  827. return EAI_OVERFLOW;
  828. else
  829. return EAI_SYSTEM;
  830. }
  831. }
  832. if (serv && servlen > 0) {
  833. if (snprintf(serv, servlen, "%d", (int)ntohs(sin->sin_port)) > (int)servlen)
  834. return EAI_OVERFLOW;
  835. }
  836. return 0;
  837. }
  838. void herror(char const* s)
  839. {
  840. dbgln("herror(): {}: {}", s, hstrerror(h_errno));
  841. warnln("{}: {}", s, hstrerror(h_errno));
  842. }
  843. char const* hstrerror(int err)
  844. {
  845. switch (err) {
  846. case HOST_NOT_FOUND:
  847. return "The specified host is unknown.";
  848. case NO_DATA:
  849. return "The requested name is valid but does not have an IP address.";
  850. case NO_RECOVERY:
  851. return "A nonrecoverable name server error occurred.";
  852. case TRY_AGAIN:
  853. return "A temporary error occurred on an authoritative name server. Try again later.";
  854. default:
  855. return "Unknown error.";
  856. }
  857. }
  858. }