You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.5 KiB

  1. #include <iostream>
  2. #include "nginx-util.hpp"
  3. #ifndef NO_SSL
  4. #include "nginx-ssl-util.hpp"
  5. #endif
  6. void create_lan_listen()
  7. {
  8. std::string listen = "# This file is re-created if Nginx starts or"
  9. " a LAN address changes.\n";
  10. std::string listen_default = listen;
  11. std::string ssl_listen = listen;
  12. std::string ssl_listen_default = listen;
  13. auto add_listen = [&listen, &listen_default
  14. #ifndef NO_SSL
  15. ,&ssl_listen, &ssl_listen_default
  16. #endif
  17. ]
  18. (const std::string &pre, const std::string &ip, const std::string &suf)
  19. -> void
  20. {
  21. if (ip.empty()) { return; }
  22. const std::string val = pre + ip + suf;
  23. listen += "\tlisten " + val + ":80;\n";
  24. listen_default += "\tlisten " + val + ":80 default_server;\n";
  25. #ifndef NO_SSL
  26. ssl_listen += "\tlisten " + val + ":443 ssl;\n";
  27. ssl_listen_default += "\tlisten " + val + ":443 ssl default_server;\n";
  28. #endif
  29. };
  30. #ifndef NO_UBUS
  31. try {
  32. auto loopback_status=ubus::call("network.interface.loopback", "status");
  33. for (auto ip : loopback_status.filter("ipv4-address", "", "address")) {
  34. add_listen("", static_cast<const char *>(blobmsg_data(ip)), "");
  35. }
  36. for (auto ip : loopback_status.filter("ipv6-address", "", "address")) {
  37. add_listen("[", static_cast<const char *>(blobmsg_data(ip)), "]");
  38. }
  39. } catch (const std::runtime_error &) { /* do nothing about it */ }
  40. try {
  41. auto lan_status = ubus::call("network.interface.lan", "status");
  42. for (auto ip : lan_status.filter("ipv4-address", "", "address")) {
  43. add_listen("", static_cast<const char *>(blobmsg_data(ip)), "");
  44. }
  45. for (auto ip : lan_status.filter("ipv6-address", "", "address")) {
  46. add_listen("[", static_cast<const char *>(blobmsg_data(ip)), "]");
  47. }
  48. for (auto ip : lan_status.filter("ipv6-prefix-assignment", "",
  49. "local-address", "address"))
  50. {
  51. add_listen("[", static_cast<const char *>(blobmsg_data(ip)), "]");
  52. }
  53. } catch (const std::runtime_error &) { /* do nothing about it */ }
  54. #else
  55. add_listen("", "127.0.0.1", "");
  56. #endif
  57. write_file(LAN_LISTEN, listen);
  58. write_file(LAN_LISTEN_DEFAULT, listen_default);
  59. #ifndef NO_SSL
  60. write_file(LAN_SSL_LISTEN, ssl_listen);
  61. write_file(LAN_SSL_LISTEN_DEFAULT, ssl_listen_default);
  62. #endif
  63. }
  64. void init_lan()
  65. {
  66. std::exception_ptr ex;
  67. #ifndef NO_SSL
  68. auto thrd = std::thread([]{ //&ex
  69. try { add_ssl_if_needed(std::string{LAN_NAME}); }
  70. catch (...) {
  71. std::cerr<<"init_lan notice: no server named "<<LAN_NAME<<std::endl;
  72. // not: ex = std::current_exception();
  73. }
  74. });
  75. #endif
  76. try { create_lan_listen(); }
  77. catch (...) {
  78. std::cerr<<"init_lan error: cannot create LAN listen files"<<std::endl;
  79. ex = std::current_exception();
  80. }
  81. #ifndef NO_SSL
  82. thrd.join();
  83. #endif
  84. if (ex) { std::rethrow_exception(ex); }
  85. }
  86. void get_env()
  87. {
  88. std::cout<<"NGINX_CONF="<<"'"<<NGINX_CONF<<"'"<<std::endl;
  89. std::cout<<"CONF_DIR="<<"'"<<CONF_DIR<<"'"<<std::endl;
  90. std::cout<<"LAN_NAME="<<"'"<<LAN_NAME<<"'"<<std::endl;
  91. std::cout<<"LAN_LISTEN="<<"'"<<LAN_LISTEN<<"'"<<std::endl;
  92. #ifndef NO_SSL
  93. std::cout<<"LAN_SSL_LISTEN="<<"'"<<LAN_SSL_LISTEN<<"'"<<std::endl;
  94. std::cout<<"SSL_SESSION_CACHE_ARG="<<"'"<<SSL_SESSION_CACHE_ARG(LAN_NAME)<<
  95. "'"<<std::endl;
  96. std::cout<<"SSL_SESSION_TIMEOUT_ARG="<<"'"<<SSL_SESSION_TIMEOUT_ARG<<"'\n";
  97. std::cout<<"ADD_SSL_FCT="<<"'"<<ADD_SSL_FCT<<"'"<<std::endl;
  98. #endif
  99. }
  100. auto main(int argc, char * argv[]) -> int
  101. {
  102. // TODO(pst): use std::span when available:
  103. auto args = std::basic_string_view<char *>{argv, static_cast<size_t>(argc)};
  104. auto cmds = std::array{
  105. std::array<std::string_view, 2>{"init_lan", ""},
  106. std::array<std::string_view, 2>{"get_env", ""},
  107. #ifndef NO_SSL
  108. std::array<std::string_view, 2>{ADD_SSL_FCT, " server_name" },
  109. std::array<std::string_view, 2>{"del_ssl", " server_name" },
  110. #endif
  111. };
  112. try {
  113. if (argc==2 && args[1]==cmds[0][0]) { init_lan(); }
  114. else if (argc==2 && args[1]==cmds[1][0]) { get_env(); }
  115. #ifndef NO_SSL
  116. else if (argc==3 && args[1]==cmds[2][0])
  117. { add_ssl_if_needed(std::string{args[2]});}
  118. else if (argc==3 && args[1]==cmds[3][0])
  119. { del_ssl(std::string{args[2]}); }
  120. else if (argc==2 && args[1]==cmds[3][0])
  121. { del_ssl(std::string{LAN_NAME}); }
  122. #endif
  123. else {
  124. std::cerr<<"Tool for creating Nginx configuration files (";
  125. #ifdef VERSION
  126. std::cerr<<"version "<<VERSION<<" ";
  127. #endif
  128. std::cerr<<"with ";
  129. #ifndef NO_UBUS
  130. std::cerr<<"ubus, ";
  131. #endif
  132. #ifndef NO_SSL
  133. std::cerr<<"libopenssl, ";
  134. #ifdef NO_PCRE
  135. std::cerr<<"std::regex, ";
  136. #else
  137. std::cerr<<"PCRE, ";
  138. #endif
  139. #endif
  140. std::cerr<<"pthread and libstdcpp)."<<std::endl;
  141. auto usage = std::string{"usage: "} + *argv + " [";
  142. for (auto cmd : cmds) {
  143. usage += std::string{cmd[0]};
  144. usage += std::string{cmd[1]} + "|";
  145. }
  146. usage[usage.size()-1] = ']';
  147. std::cerr<<usage<<std::endl;
  148. throw std::runtime_error("main error: argument not recognized");
  149. }
  150. return 0;
  151. }
  152. catch (const std::exception & e) { std::cerr<<e.what()<<std::endl; }
  153. catch (...) { perror("main error"); }
  154. return 1;
  155. }