protocol_edge.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. protocol_edge.c -- handle the meta-protocol, edges
  3. Copyright (C) 1999-2005 Ivo Timmermans,
  4. 2000-2016 Guus Sliepen <guus@tinc-vpn.org>
  5. 2009 Michael Tokarev <mjt@corpit.ru>
  6. This program 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 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with this program; if not, write to the Free Software Foundation, Inc.,
  16. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #include "system.h"
  19. #include "avl_tree.h"
  20. #include "conf.h"
  21. #include "connection.h"
  22. #include "edge.h"
  23. #include "graph.h"
  24. #include "logger.h"
  25. #include "meta.h"
  26. #include "net.h"
  27. #include "netutl.h"
  28. #include "node.h"
  29. #include "protocol.h"
  30. #include "utils.h"
  31. #include "xalloc.h"
  32. bool send_add_edge(connection_t *c, const edge_t *e) {
  33. bool x;
  34. char *address, *port;
  35. sockaddr2str(&e->address, &address, &port);
  36. x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
  37. e->from->name, e->to->name, address, port,
  38. e->options, e->weight);
  39. free(address);
  40. free(port);
  41. return x;
  42. }
  43. bool add_edge_h(connection_t *c) {
  44. edge_t *e;
  45. node_t *from, *to;
  46. char from_name[MAX_STRING_SIZE];
  47. char to_name[MAX_STRING_SIZE];
  48. char to_address[MAX_STRING_SIZE];
  49. char to_port[MAX_STRING_SIZE];
  50. sockaddr_t address;
  51. uint32_t options;
  52. int weight;
  53. if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d",
  54. from_name, to_name, to_address, to_port, &options, &weight) != 6) {
  55. logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name,
  56. c->hostname);
  57. return false;
  58. }
  59. /* Check if names are valid */
  60. if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) {
  61. logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name,
  62. c->hostname, "invalid name");
  63. return false;
  64. }
  65. if(seen_request(c->buffer)) {
  66. return true;
  67. }
  68. /* Lookup nodes */
  69. from = lookup_node(from_name);
  70. to = lookup_node(to_name);
  71. if(tunnelserver &&
  72. from != myself && from != c->node &&
  73. to != myself && to != c->node) {
  74. /* ignore indirect edge registrations for tunnelserver */
  75. ifdebug(PROTOCOL) logger(LOG_WARNING,
  76. "Ignoring indirect %s from %s (%s)",
  77. "ADD_EDGE", c->name, c->hostname);
  78. return true;
  79. }
  80. if(!from) {
  81. from = new_node();
  82. from->name = xstrdup(from_name);
  83. node_add(from);
  84. }
  85. if(!to) {
  86. to = new_node();
  87. to->name = xstrdup(to_name);
  88. node_add(to);
  89. }
  90. /* Convert addresses */
  91. address = str2sockaddr(to_address, to_port);
  92. /* Check if edge already exists */
  93. e = lookup_edge(from, to);
  94. if(e) {
  95. if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
  96. if(from == myself) {
  97. ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
  98. "ADD_EDGE", c->name, c->hostname);
  99. send_add_edge(c, e);
  100. return true;
  101. } else {
  102. ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
  103. "ADD_EDGE", c->name, c->hostname);
  104. e->options = options;
  105. if(sockaddrcmp(&e->address, &address)) {
  106. sockaddrfree(&e->address);
  107. e->address = address;
  108. }
  109. if(e->weight != weight) {
  110. avl_node_t *node = avl_unlink(edge_weight_tree, e);
  111. e->weight = weight;
  112. avl_insert_node(edge_weight_tree, node);
  113. }
  114. goto done;
  115. }
  116. } else {
  117. return true;
  118. }
  119. } else if(from == myself) {
  120. ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
  121. "ADD_EDGE", c->name, c->hostname);
  122. contradicting_add_edge++;
  123. e = new_edge();
  124. e->from = from;
  125. e->to = to;
  126. send_del_edge(c, e);
  127. free_edge(e);
  128. return true;
  129. }
  130. e = new_edge();
  131. e->from = from;
  132. e->to = to;
  133. e->address = address;
  134. e->options = options;
  135. e->weight = weight;
  136. edge_add(e);
  137. done:
  138. /* Tell the rest about the new edge */
  139. if(!tunnelserver) {
  140. forward_request(c);
  141. }
  142. /* Run MST before or after we tell the rest? */
  143. graph();
  144. return true;
  145. }
  146. bool send_del_edge(connection_t *c, const edge_t *e) {
  147. return send_request(c, "%d %x %s %s", DEL_EDGE, rand(),
  148. e->from->name, e->to->name);
  149. }
  150. bool del_edge_h(connection_t *c) {
  151. edge_t *e;
  152. char from_name[MAX_STRING_SIZE];
  153. char to_name[MAX_STRING_SIZE];
  154. node_t *from, *to;
  155. if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) {
  156. logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name,
  157. c->hostname);
  158. return false;
  159. }
  160. /* Check if names are valid */
  161. if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) {
  162. logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name,
  163. c->hostname, "invalid name");
  164. return false;
  165. }
  166. if(seen_request(c->buffer)) {
  167. return true;
  168. }
  169. /* Lookup nodes */
  170. from = lookup_node(from_name);
  171. to = lookup_node(to_name);
  172. if(tunnelserver &&
  173. from != myself && from != c->node &&
  174. to != myself && to != c->node) {
  175. /* ignore indirect edge registrations for tunnelserver */
  176. ifdebug(PROTOCOL) logger(LOG_WARNING,
  177. "Ignoring indirect %s from %s (%s)",
  178. "DEL_EDGE", c->name, c->hostname);
  179. return true;
  180. }
  181. if(!from) {
  182. ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree",
  183. "DEL_EDGE", c->name, c->hostname);
  184. return true;
  185. }
  186. if(!to) {
  187. ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree",
  188. "DEL_EDGE", c->name, c->hostname);
  189. return true;
  190. }
  191. /* Check if edge exists */
  192. e = lookup_edge(from, to);
  193. if(!e) {
  194. ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree",
  195. "DEL_EDGE", c->name, c->hostname);
  196. return true;
  197. }
  198. if(e->from == myself) {
  199. ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself",
  200. "DEL_EDGE", c->name, c->hostname);
  201. contradicting_del_edge++;
  202. send_add_edge(c, e); /* Send back a correction */
  203. return true;
  204. }
  205. /* Tell the rest about the deleted edge */
  206. if(!tunnelserver) {
  207. forward_request(c);
  208. }
  209. /* Delete the edge */
  210. edge_del(e);
  211. /* Run MST before or after we tell the rest? */
  212. graph();
  213. /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
  214. if(!to->status.reachable) {
  215. e = lookup_edge(to, myself);
  216. if(e) {
  217. if(!tunnelserver) {
  218. send_del_edge(everyone, e);
  219. }
  220. edge_del(e);
  221. }
  222. }
  223. return true;
  224. }