2
0

pex-stun.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include <arpa/inet.h>
  2. #include <netinet/in.h>
  3. #include <netinet/ip.h>
  4. #include <netinet/udp.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <libubox/usock.h>
  8. #include "unetd.h"
  9. static inline int avl_stun_cmp(const void *k1, const void *k2, void *priv)
  10. {
  11. return memcmp(k1, k2, 12);
  12. }
  13. static bool has_connected_peer(struct network *net, bool pex)
  14. {
  15. struct network_peer *peer;
  16. vlist_for_each_element(&net->peers, peer, node) {
  17. if (pex && !peer->pex_port)
  18. continue;
  19. if (peer->state.connected || peer->indirect)
  20. return true;
  21. }
  22. return false;
  23. }
  24. void network_stun_server_add(struct network *net, const char *host)
  25. {
  26. struct network_stun *stun = &net->stun;
  27. struct network_stun_server *s;
  28. char *name_buf;
  29. s = calloc_a(sizeof(*s), &name_buf, strlen(host) + 1);
  30. s->pending_node.key = s->req.transaction;
  31. s->host = strcpy(name_buf, host);
  32. list_add_tail(&s->list, &stun->servers);
  33. }
  34. static void
  35. network_stun_close_socket(struct network *net)
  36. {
  37. struct network_host *local = net->net_config.local_host;
  38. struct network_stun *stun = &net->stun;
  39. if (!stun->wgport_disabled)
  40. return;
  41. D_NET(net, "close STUN socket");
  42. uloop_fd_delete(&stun->socket);
  43. close(stun->socket.fd);
  44. wg_init_local(net, &local->peer);
  45. stun->wgport_disabled = false;
  46. }
  47. static void
  48. network_stun_socket_cb(struct uloop_fd *fd, unsigned int events)
  49. {
  50. struct network_stun *stun = container_of(fd, struct network_stun, socket);
  51. struct network *net = container_of(stun, struct network, stun);
  52. char buf[1024];
  53. ssize_t len;
  54. while (1) {
  55. len = recv(fd->fd, buf, sizeof(buf), 0);
  56. if (len < 0) {
  57. if (errno == EAGAIN)
  58. break;
  59. if (errno == EINTR)
  60. continue;
  61. perror("recv");
  62. network_stun_close_socket(net);
  63. return;
  64. }
  65. if (!stun_msg_is_valid(buf, len))
  66. continue;
  67. network_stun_rx_packet(net, buf, len);
  68. }
  69. }
  70. static void
  71. network_stun_open_socket(struct network *net)
  72. {
  73. struct network_host *local = net->net_config.local_host;
  74. struct network_stun *stun = &net->stun;
  75. int fd;
  76. if (stun->wgport_disabled)
  77. return;
  78. D_NET(net, "open STUN socket");
  79. wg_init_local(net, NULL);
  80. fd = usock(USOCK_SERVER | USOCK_UDP | USOCK_IPV4ONLY | USOCK_NONBLOCK,
  81. NULL, usock_port(stun->port_local));
  82. if (fd < 0) {
  83. wg_init_local(net, &local->peer);
  84. return;
  85. }
  86. stun->socket.fd = fd;
  87. uloop_fd_add(&stun->socket, ULOOP_READ);
  88. stun->wgport_disabled = true;
  89. }
  90. static bool
  91. network_stun_query_next(struct network *net)
  92. {
  93. struct network_stun *stun = &net->stun;
  94. struct network_stun_server *s;
  95. char addrstr[INET6_ADDRSTRLEN];
  96. union network_endpoint ep;
  97. uint16_t res_port = 0;
  98. const void *msg;
  99. ssize_t ret;
  100. size_t len;
  101. s = list_first_entry(&stun->servers, struct network_stun_server, list);
  102. if (s->pending)
  103. return false;
  104. /* send next query */
  105. if (network_get_endpoint(&ep, AF_INET, s->host, 0, s->seq++) < 0) {
  106. D_NET(net, "lookup failed for STUN host %s", s->host);
  107. goto out;
  108. }
  109. if (ep.sa.sa_family != AF_INET || !ep.in.sin_port)
  110. goto out;
  111. if (!stun->wgport_disabled && stun->auth_port_ext)
  112. res_port = stun->auth_port_ext;
  113. D_NET(net, "Send STUN query to %s, res_port=%d, wg_disabled=%d",
  114. inet_ntop(ep.sa.sa_family, network_endpoint_addr(&ep, NULL),
  115. addrstr, sizeof(addrstr)), res_port, stun->wgport_disabled);
  116. msg = stun_msg_request_prepare(&s->req, &len, res_port);
  117. if (!msg)
  118. goto out;
  119. retry:
  120. s->req_auth_port = false;
  121. if (stun->wgport_disabled) {
  122. ret = sendto(stun->socket.fd, msg, len, 0, &ep.sa, sizeof(ep.in));
  123. } else if (!stun->auth_port_ext) {
  124. s->req_auth_port = true;
  125. ret = sendto(pex_socket(), msg, len, 0, &ep.sa, sizeof(ep.in));
  126. } else {
  127. struct {
  128. struct ip ip;
  129. struct udphdr udp;
  130. } packet_hdr = {};
  131. union network_addr local_addr = {};
  132. network_get_local_addr(&local_addr, &ep);
  133. packet_hdr.ip = (struct ip){
  134. .ip_hl = 5,
  135. .ip_v = 4,
  136. .ip_ttl = 64,
  137. .ip_p = IPPROTO_UDP,
  138. .ip_src = local_addr.in,
  139. .ip_dst = ep.in.sin_addr,
  140. };
  141. packet_hdr.udp = (struct udphdr){
  142. .uh_sport = htons(stun->port_local),
  143. .uh_dport = ep.in.sin_port,
  144. };
  145. ep.in.sin_port = 0;
  146. ret = sendto_rawudp(pex_raw_socket(AF_INET), &ep,
  147. &packet_hdr, sizeof(packet_hdr),
  148. msg, len);
  149. }
  150. if (ret < 0 && errno == EINTR)
  151. goto retry;
  152. out:
  153. avl_insert(&stun->pending, &s->pending_node);
  154. s->pending = true;
  155. if (!list_is_last(&s->list, &stun->servers))
  156. list_move_tail(&s->list, &stun->servers);
  157. return true;
  158. }
  159. static void
  160. network_stun_query_clear_pending(struct network *net)
  161. {
  162. struct network_stun *stun = &net->stun;
  163. struct network_stun_server *s;
  164. list_for_each_entry(s, &stun->servers, list) {
  165. if (!s->pending)
  166. continue;
  167. avl_delete(&stun->pending, &s->pending_node);
  168. s->pending = false;
  169. }
  170. }
  171. void network_stun_rx_packet(struct network *net, const void *data, size_t len)
  172. {
  173. struct network_stun *stun = &net->stun;
  174. const struct stun_msg_hdr *hdr = data;
  175. struct network_stun_server *s;
  176. s = avl_find_element(&stun->pending, hdr->transaction, s, pending_node);
  177. if (!s)
  178. return;
  179. if (!stun_msg_request_complete(&s->req, data, len))
  180. return;
  181. if (!s->req.port)
  182. return;
  183. network_stun_update_port(net, s->req_auth_port, s->req.port);
  184. if (s->req_auth_port)
  185. stun->state = STUN_STATE_STUN_QUERY_SEND;
  186. else
  187. stun->state = STUN_STATE_IDLE;
  188. network_stun_query_clear_pending(net);
  189. uloop_timeout_set(&stun->timer, 1);
  190. }
  191. static void
  192. network_stun_timer_cb(struct uloop_timeout *t)
  193. {
  194. struct network_stun *stun = container_of(t, struct network_stun, timer);
  195. struct network *net = container_of(stun, struct network, stun);
  196. unsigned int next = 0;
  197. restart:
  198. switch (stun->state) {
  199. case STUN_STATE_IDLE:
  200. network_stun_close_socket(net);
  201. next = 15 * 60 * 1000;
  202. stun->state = STUN_STATE_STUN_QUERY_SEND;
  203. D_NET(net, "STUN idle");
  204. break;
  205. case STUN_STATE_PEX_QUERY_WAIT:
  206. stun->state = STUN_STATE_STUN_QUERY_SEND;
  207. fallthrough;
  208. case STUN_STATE_STUN_QUERY_SEND:
  209. if (network_stun_query_next(net)) {
  210. next = 50;
  211. break;
  212. }
  213. stun->state = STUN_STATE_STUN_QUERY_WAIT;
  214. D_NET(net, "wait for STUN server responses");
  215. next = 1000;
  216. break;
  217. case STUN_STATE_STUN_QUERY_WAIT:
  218. D_NET(net, "timeout waiting for STUN server responses, retry=%d", stun->retry);
  219. network_stun_query_clear_pending(net);
  220. if (stun->retry > 0) {
  221. stun->retry--;
  222. stun->state = STUN_STATE_STUN_QUERY_SEND;
  223. goto restart;
  224. }
  225. if (!stun->port_ext && !stun->wgport_disabled) {
  226. network_stun_open_socket(net);
  227. stun->state = STUN_STATE_STUN_QUERY_SEND;
  228. stun->retry = 2;
  229. } else {
  230. stun->state = STUN_STATE_IDLE;
  231. }
  232. goto restart;
  233. }
  234. if (next)
  235. uloop_timeout_set(t, next);
  236. }
  237. void network_stun_update_port(struct network *net, bool auth, uint16_t val)
  238. {
  239. struct network_stun *stun = &net->stun;
  240. uint16_t *port = auth ? &stun->auth_port_ext : &stun->port_ext;
  241. D_NET(net, "Update external %s port: %d", auth ? "auth" : "data", val);
  242. *port = val;
  243. }
  244. void network_stun_start(struct network *net)
  245. {
  246. struct network_host *local = net->net_config.local_host;
  247. struct network_stun *stun = &net->stun;
  248. unsigned int next = 1;
  249. if (!local || list_empty(&stun->servers))
  250. return;
  251. if (local->peer.port != stun->port_local) {
  252. stun->port_ext = 0;
  253. stun->port_local = local->peer.port;
  254. }
  255. if (!stun->port_ext && has_connected_peer(net, true)) {
  256. D_NET(net, "wait for port information from PEX");
  257. stun->state = STUN_STATE_PEX_QUERY_WAIT;
  258. next = 60 * 1000;
  259. } else {
  260. if (!stun->port_ext && !has_connected_peer(net, false))
  261. network_stun_open_socket(net);
  262. stun->state = STUN_STATE_STUN_QUERY_SEND;
  263. stun->retry = 2;
  264. }
  265. uloop_timeout_set(&stun->timer, next);
  266. }
  267. void network_stun_init(struct network *net)
  268. {
  269. struct network_stun *stun = &net->stun;
  270. stun->socket.cb = network_stun_socket_cb;
  271. stun->timer.cb = network_stun_timer_cb;
  272. INIT_LIST_HEAD(&stun->servers);
  273. avl_init(&stun->pending, avl_stun_cmp, true, NULL);
  274. }
  275. void network_stun_free(struct network *net)
  276. {
  277. struct network_stun *stun = &net->stun;
  278. struct network_stun_server *s, *tmp;
  279. uloop_timeout_cancel(&stun->timer);
  280. network_stun_close_socket(net);
  281. avl_remove_all_elements(&stun->pending, s, pending_node, tmp)
  282. s->pending = false;
  283. list_for_each_entry_safe(s, tmp, &stun->servers, list) {
  284. list_del(&s->list);
  285. free(s);
  286. }
  287. }