main.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #define _GNU_SOURCE
  6. #include <unistd.h>
  7. #include <arpa/inet.h>
  8. #include <libubox/uloop.h>
  9. #include <libubox/blobmsg_json.h>
  10. #include "unetd.h"
  11. struct cmdline_network {
  12. struct cmdline_network *next;
  13. char *data;
  14. };
  15. static struct cmdline_network *cmd_nets;
  16. static const char *hosts_file;
  17. const char *mssfix_path = UNETD_MSS_BPF_PATH;
  18. const char *data_dir = UNETD_DATA_DIR;
  19. int global_pex_port = UNETD_GLOBAL_PEX_PORT;
  20. bool debug;
  21. static void
  22. network_write_hosts(struct network *net, FILE *f)
  23. {
  24. struct network_host *host;
  25. char ip[INET6_ADDRSTRLEN];
  26. if (!net->net_config.local_host)
  27. return;
  28. avl_for_each_element(&net->hosts, host, node) {
  29. inet_ntop(AF_INET6, &host->peer.local_addr, ip, sizeof(ip));
  30. fprintf(f, "%s\t%s%s%s\n", ip, network_host_name(host),
  31. net->config.domain ? "." : "",
  32. net->config.domain ? net->config.domain : "");
  33. }
  34. }
  35. void unetd_write_hosts(void)
  36. {
  37. struct network *net;
  38. char *tmpfile = NULL;
  39. FILE *f;
  40. int fd;
  41. if (!hosts_file)
  42. return;
  43. if (asprintf(&tmpfile, "%s.XXXXXXXX", hosts_file) < 0)
  44. return;
  45. fd = mkstemp(tmpfile);
  46. if (fd < 0) {
  47. perror("mkstemp");
  48. goto out;
  49. }
  50. chmod(tmpfile, 0644);
  51. f = fdopen(fd, "w");
  52. if (!f) {
  53. close(fd);
  54. goto out;
  55. }
  56. avl_for_each_element(&networks, net, node)
  57. network_write_hosts(net, f);
  58. fclose(f);
  59. if (rename(tmpfile, hosts_file))
  60. unlink(tmpfile);
  61. out:
  62. free(tmpfile);
  63. }
  64. static void add_networks(void)
  65. {
  66. struct cmdline_network *net;
  67. static struct blob_buf b;
  68. struct blob_attr *name;
  69. for (net = cmd_nets; net; net = net->next) {
  70. blob_buf_init(&b, 0);
  71. if (!blobmsg_add_json_from_string(&b, net->data))
  72. continue;
  73. blobmsg_parse(&network_policy[NETWORK_ATTR_NAME], 1, &name,
  74. blobmsg_data(b.head), blobmsg_len(b.head));
  75. if (!name)
  76. continue;
  77. unetd_network_add(blobmsg_get_string(name), b.head);
  78. }
  79. blob_buf_free(&b);
  80. }
  81. int main(int argc, char **argv)
  82. {
  83. struct cmdline_network *net;
  84. const char *unix_socket = NULL;
  85. int ch;
  86. while ((ch = getopt(argc, argv, "D:dh:u:M:N:P:")) != -1) {
  87. switch (ch) {
  88. case 'D':
  89. data_dir = optarg;
  90. break;
  91. case 'd':
  92. debug = true;
  93. break;
  94. case 'h':
  95. hosts_file = optarg;
  96. break;
  97. case 'N':
  98. net = calloc(1, sizeof(*net));
  99. net->next = cmd_nets;
  100. net->data = optarg;
  101. cmd_nets = net;
  102. break;
  103. case 'M':
  104. mssfix_path = optarg;
  105. break;
  106. case 'P':
  107. global_pex_port = atoi(optarg);
  108. break;
  109. case 'u':
  110. unix_socket = optarg;
  111. break;
  112. }
  113. }
  114. uloop_init();
  115. unetd_ubus_init();
  116. unetd_write_hosts();
  117. global_pex_open(unix_socket);
  118. add_networks();
  119. uloop_run();
  120. pex_close();
  121. network_free_all();
  122. uloop_done();
  123. return 0;
  124. }