tnet_dns_resolvconf.rl 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (C) 2010-2015 Mamadou DIOP.
  3. *
  4. * This file is part of Open Source Doubango Framework.
  5. *
  6. * DOUBANGO is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * DOUBANGO is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with DOUBANGO.
  18. *
  19. */
  20. /**@file tnet_dns_resolvconf.c
  21. * @brief Parser for "/etc/resolv.conf" file to retrive DNS servers.
  22. */
  23. #include "tnet_dns_resolvconf.h"
  24. #include "tnet_utils.h"
  25. #include "dns/tnet_dns.h"
  26. #include "tsk_string.h"
  27. #include "tsk_memory.h"
  28. #include "tsk_ragel_state.h"
  29. #include "tsk_debug.h"
  30. #include <string.h>
  31. /* === Ragel state machine === */
  32. %%{
  33. machine tdns_machine_resolvconf;
  34. action tag{
  35. tag_start = p;
  36. }
  37. action add_dns{
  38. int len = (int)(p - tag_start);
  39. if(len && len<=sizeof(ip)){
  40. tnet_address_t *address;
  41. memset(ip, '\0', sizeof(ip));
  42. memcpy(ip, tag_start, len);
  43. TSK_DEBUG_INFO("Adding DNS server = %s:%d", ip, TNET_DNS_SERVER_PORT_DEFAULT);
  44. address = tnet_address_create(ip);
  45. address->family = tnet_get_family(ip, TNET_DNS_SERVER_PORT_DEFAULT);
  46. address->dnsserver = 1;
  47. tsk_list_push_ascending_data(servers, (void**)&address);
  48. }
  49. }
  50. SP = " ";
  51. LF = "\n";
  52. CR = "\r";
  53. CRLF = CR LF;
  54. ENDL = (LF | CR | CRLF);
  55. o_name = any+;
  56. o_value = any+;
  57. COMMENT = SP*<: ("#" | ";") any*;
  58. OPTION_ANY = SP*<: o_name :>SP+<: o_value :>SP*;
  59. OPTION_DNS = SP*<: "nameserver"i :>SP+<: o_value>tag %add_dns :>SP*;
  60. LINE = (OPTION_DNS)@100 | (OPTION_ANY)@0 | (COMMENT)@50;
  61. main := ((LINE :>ENDL) | ENDL)* %3 any* %2;
  62. }%%
  63. /** Gets list of DNS servers from a conf file.
  64. * @param path Path of the conf file from which to retrieve the DNS servers.
  65. * should be @a "/etc/resolv.conf". You can adjust the value by modifying @ref TNET_RESOLV_CONF_PATH.<br>
  66. * If you are using <b>Android</b> and the resolv.conf file is missing, then run the following line in a command window: <br>
  67. * <i>ln -s /private/var/run/resolv.conf /etc/resolv.conf</i><br> If this fails, then try to manually add the file.
  68. * @retval List of DNS servers.
  69. */
  70. tnet_addresses_L_t * tnet_dns_resolvconf_parse(const char* path)
  71. {
  72. tnet_addresses_L_t* servers = tsk_null;
  73. tnet_ip_t ip;
  74. const char* fullpath = path;
  75. const char* tag_start = tsk_null;
  76. FILE* fd;
  77. char* buf = tsk_null;
  78. // Ragel
  79. int cs = 0;
  80. const char *p;
  81. const char *pe;
  82. const char *eof;
  83. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  84. %%write data;
  85. TSK_RAGEL_DISABLE_WARNINGS_END()
  86. (void)(eof);
  87. (void)(tdns_machine_resolvconf_first_final);
  88. (void)(tdns_machine_resolvconf_error);
  89. (void)(tdns_machine_resolvconf_en_main);
  90. if(tsk_strnullORempty(fullpath)){
  91. fullpath = TNET_RESOLV_CONF_PATH;
  92. }
  93. /* Open the file and read all data */
  94. if((fd = fopen(fullpath, "r"))){
  95. long len;
  96. fseek(fd, 0L, SEEK_END);
  97. len = ftell(fd);
  98. fseek(fd, 0L, SEEK_SET);
  99. if (!(buf = (char*)tsk_calloc(len + 1, 1))) {
  100. TSK_DEBUG_ERROR("Failed to allocate buffer with size = %ld", (len + 1));
  101. goto bail;
  102. }
  103. fread(buf, 1, len, fd);
  104. p = &buf[0];
  105. pe = p + len + 1/*hack*/;
  106. eof = pe;
  107. fclose(fd);
  108. buf[len] = '\n'; // hack to have perfect lines
  109. servers = tsk_list_create();
  110. }
  111. else {
  112. #if ANDROID || defined(__APPLE__) /* TARGET_OS_IPHONE not defined for bsd libraries */
  113. TSK_DEBUG_INFO("Failed to open [%s]. But don't panic, we have detected that you are using Google Android/iOS Systems.\n"
  114. "You should look at the Progammer's Guide for more information.\n If you are not using DNS functions, don't worry about this warning.",
  115. fullpath);
  116. #else
  117. TSK_DEBUG_ERROR("Failed to open %s.", fullpath);
  118. #endif
  119. goto bail;
  120. }
  121. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  122. %%write init;
  123. %%write exec;
  124. TSK_RAGEL_DISABLE_WARNINGS_END()
  125. if (cs < %%{ write first_final; }%% ) {
  126. TSK_DEBUG_ERROR("Failed to parse %s.", fullpath);
  127. TSK_OBJECT_SAFE_FREE(servers);
  128. }
  129. bail:
  130. TSK_FREE(buf);
  131. return servers;
  132. }