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.

rehook.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * --
  19. * rehook.c:
  20. * This code manages the rehook of gnodes, the challenges that must be solved
  21. * and generated in order to prove the number of nodes present in a gnode.
  22. */
  23. #include "includes.h"
  24. #include "common.h"
  25. #include "hash.h"
  26. #include "llist.c"
  27. #include "libnetlink.h"
  28. #include "ll_map.h"
  29. #include "inet.h"
  30. #include "if.h"
  31. #include "krnl_route.h"
  32. #include "endianness.h"
  33. #include "bmap.h"
  34. #include "route.h"
  35. #include "iptunnel.h"
  36. #include "request.h"
  37. #include "pkts.h"
  38. #include "tracer.h"
  39. #include "qspn.h"
  40. #include "andna.h"
  41. #include "hook.h"
  42. #include "rehook.h"
  43. #include "radar.h"
  44. #include "netsukuku.h"
  45. #include "common.h"
  46. /*
  47. * rehook_argv: argv for the new_rehook_thread thread
  48. */
  49. struct rehook_argv {
  50. int gid;
  51. map_gnode *gnode;
  52. int level;
  53. int gnode_count;
  54. };
  55. pthread_attr_t new_rehook_thread_attr;
  56. void
  57. rehook_init(void)
  58. {
  59. total_rehooks = 0;
  60. last_instance_rehook = 0;
  61. rehook_mutex = 0;
  62. pthread_attr_init(&new_rehook_thread_attr);
  63. pthread_attr_setdetachstate(&new_rehook_thread_attr,
  64. PTHREAD_CREATE_DETACHED);
  65. }
  66. /*
  67. * rehook_compute_new_gnode: computes the IP which shall be used to create a
  68. * new gnode if the we cannot rehook to any gnode.
  69. * The computed ip is stored in `new_ip'.
  70. * `old_ip' is the IP we used before the rehook was launched.
  71. */
  72. void
  73. rehook_compute_new_gnode(inet_prefix * old_ip, inet_prefix * new_ip,
  74. int hook_level)
  75. {
  76. quadro_group qg;
  77. int hash_gid;
  78. iptoquadg(*old_ip, me.ext_map, &qg, QUADG_GID);
  79. /*
  80. * Hash our gids starting from the `hook_level' level,
  81. * then xor the bytes of the hash merging them in a single byte.
  82. */
  83. hash_gid = fnv_32_buf(&qg.gid[hook_level],
  84. (FAMILY_LVLS - hook_level), FNV1_32_INIT);
  85. qg.gid[hook_level] = xor_int(hash_gid);
  86. /* Be sure to choose VOID gnodes */
  87. void_gids(&qg, hook_level, me.ext_map, me.int_map);
  88. /* Save the new ip in `new_ip' */
  89. gidtoipstart(qg.gid, FAMILY_LVLS, FAMILY_LVLS, my_family, new_ip);
  90. }
  91. int
  92. send_challenge(int gnode, int level, int gnode_count)
  93. {
  94. /* TODO ^_^ */
  95. return 0;
  96. }
  97. /*
  98. * update_rehook_time: updates the rehook_time counter. If the limits are
  99. * reached -1 is returned and nothing is changed, otherwise 0 is the returned
  100. * value. (See rehook.h for more info on the limits).
  101. */
  102. int
  103. update_rehook_time(int level)
  104. {
  105. time_t cur_t, sec_elapsed;
  106. cur_t = time(0);
  107. sec_elapsed = (cur_t - last_instance_rehook);
  108. if (total_rehooks && sec_elapsed > REHOOK_INSTANCE_TIME(level)) {
  109. /*
  110. * REHOOK_INSTANCE_TIME expired: we cannot take anymore rehooks
  111. * in this instance.
  112. */
  113. if (sec_elapsed > REHOOK_WAIT_TIME(level))
  114. /* REHOOK_WAIT_TIME expired: a new instance begins */
  115. total_rehooks = 0;
  116. else
  117. return -1;
  118. }
  119. if (total_rehooks > REHOOK_PER_INSTANCE)
  120. /* Too many rehooks in this instance */
  121. return -1;
  122. if (!total_rehooks)
  123. last_instance_rehook = cur_t;
  124. total_rehooks++;
  125. return 0;
  126. }
  127. /*
  128. * wait_new_rnode: it waits until we have a rnode, which belongs to
  129. * `rargv->gnode' or to `rk_gnode_ip'.
  130. */
  131. void
  132. wait_new_rnode(struct rehook_argv *rargv)
  133. {
  134. ext_rnode_cache *erc;
  135. int gid_a[MAX_LEVELS], gid_b[MAX_LEVELS];
  136. int e = 0, i, retries;
  137. debug(DBG_NOISE,
  138. "wait_new_rnode: waiting the %d rnode %d lvl appearance",
  139. rargv->gid, rargv->level);
  140. memcpy(&gid_a, me.cur_quadg.gid, sizeof(me.cur_quadg.gid));
  141. gid_a[rargv->level] = rargv->gid;
  142. iptogids(&rk_gnode_ip, gid_b, me.cur_quadg.levels);
  143. retries = QSPN_WAIT_ROUND_LVL(rargv->level) / MAX_RADAR_WAIT + 1;
  144. for (i = 0; i < retries; i++) {
  145. e = 0;
  146. erc = me.cur_erc;
  147. list_for(erc) {
  148. if (!gids_cmp(erc->e->quadg.gid, gid_a, rargv->level,
  149. me.cur_quadg.levels)) {
  150. e = 1;
  151. break;
  152. }
  153. if (!gids_cmp(erc->e->quadg.gid, gid_b, rargv->level,
  154. me.cur_quadg.levels)) {
  155. e = 1;
  156. break;
  157. }
  158. }
  159. if (e) {
  160. debug(DBG_NOISE, "wait_new_rnode: %d rnode %d "
  161. "lvl found", rargv->gid, rargv->level);
  162. return;
  163. }
  164. radar_wait_new_scan();
  165. }
  166. debug(DBG_NORMAL,
  167. "wait_new_rnode: not found! Anyway, trying to rehook");
  168. }
  169. /*
  170. * new_rehook_thread: a thread for each rehook() is necessary because the
  171. * rehook has to run without stopping the calling thread.
  172. */
  173. void *
  174. new_rehook_thread(void *r)
  175. {
  176. struct rehook_argv *rargv = (struct rehook_argv *) r;
  177. ext_rnode_cache *erc;
  178. map_node *root_node;
  179. map_gnode *gnode;
  180. int i;
  181. /*
  182. * Send a new challenge if `CHALLENGE_THRESHOLD' was exceeded
  183. */
  184. if (rargv->level && rargv->gnode_count >= CHALLENGE_THRESHOLD)
  185. if (send_challenge(rargv->gid, rargv->level, rargv->gnode_count))
  186. /* Challenge failed, do not rehook */
  187. goto finish;
  188. /* Store in `rk_gnode_ip' our new gnode ip to be used when the rehook
  189. * fails, just in case */
  190. rehook_compute_new_gnode(&me.cur_ip, &rk_gnode_ip, rargv->level);
  191. #if 0
  192. /* Before rehooking, at least one qspn_round has to be completed */
  193. while (!me.cur_qspn_id[rargv->level])
  194. usleep(505050);
  195. #endif
  196. /* Wait the radar_daemon, we need it up & running */
  197. while (!radar_daemon_ctl)
  198. usleep(505050);
  199. if (rargv->gid != me.cur_quadg.gid[rargv->level])
  200. wait_new_rnode(rargv);
  201. /*
  202. * Rehook now
  203. */
  204. rehook(rargv->gnode, rargv->level);
  205. if (rargv->level) {
  206. /* Mark all the gnodes we border on as HOOKED, in this way
  207. * we won't try to rehook each time */
  208. erc = me.cur_erc;
  209. list_for(erc) {
  210. if (!erc->e)
  211. continue;
  212. if (erc->e->quadg.gnode[_EL(rargv->level)])
  213. erc->e->quadg.gnode[_EL(rargv->level)]->flags |=
  214. GMAP_HGNODE;
  215. }
  216. /* Mark also rargv->gnode */
  217. rargv->gnode->flags |= GMAP_HGNODE;
  218. /* Mark all the gnodes which are rnodes of our gnode of the
  219. * `rargv->level' level. */
  220. root_node = &me.cur_quadg.gnode[_EL(rargv->level)]->g;
  221. for (i = 0; i < root_node->links; i++) {
  222. gnode = (map_gnode *) root_node->r_node[i].r_node;
  223. gnode->g.flags |= GMAP_HGNODE;
  224. }
  225. }
  226. finish:
  227. xfree(rargv);
  228. rehook_mutex = 0;
  229. return 0;
  230. }
  231. /*
  232. * new_rehook: takes in exam the `gnode' composed by `gnode_count'# nodes, which
  233. * is at level `level' and which has a gnode id equal to `gid'.
  234. * When `level' is 0, `gnode' is a node and gnode_count isn't considered.
  235. */
  236. void
  237. new_rehook(map_gnode * gnode, int gid, int level, int gnode_count)
  238. {
  239. struct rehook_argv *rargv;
  240. pthread_t thread;
  241. if (restricted_mode && level == me.cur_quadg.levels - 1 &&
  242. gid != me.cur_quadg.gid[level])
  243. /* We are in restricted mode. The `gnode' is too restricted.
  244. * Our restricted class isn't the same of `gnode', therefore
  245. * do nothing. The restricted class are immutable. */
  246. return;
  247. if (!level && gid != me.cur_quadg.gid[level])
  248. /* We rehook at level 0 only if we have the same gid of
  249. * another node, so in this case we don't have to rehook */
  250. return;
  251. else if (level) {
  252. if (gnode_count < qspn_gnode_count[_EL(level)])
  253. /* We have more nodes, we don't have to rehook! */
  254. return;
  255. else if (gnode_count == qspn_gnode_count[_EL(level)] &&
  256. gid < me.cur_quadg.gid[level])
  257. /* We have the same number of nodes, but `gid' is
  258. * smaller than our gnode id, so it must rehook,
  259. * not us */
  260. return;
  261. else if (gnode_count == qspn_gnode_count[_EL(level)] &&
  262. gid == me.cur_quadg.gid[level] &&
  263. gnode->g.flags & MAP_RNODE)
  264. /* If `gnode' has our same gid and it is our rnode,
  265. * it's alright. */
  266. return;
  267. }
  268. if (gid == me.cur_quadg.gid[level]) {
  269. /*
  270. * There is a (g)node which has our same gid, hence we rehook
  271. * to our gnode of the higher level (hopefully we get a new
  272. * gid).
  273. */
  274. if (level + 1 < me.cur_quadg.levels)
  275. level++;
  276. gid = me.cur_quadg.gid[level];
  277. gnode = me.cur_quadg.gnode[_EL(level)];
  278. } else if (level && gnode->flags & GMAP_HGNODE)
  279. /* `gnode' is marked as HOOKED, return. */
  280. return;
  281. debug(DBG_NORMAL,
  282. "new_rehook: me.gid %d, gnode %d, level %d, gnode_count %d, "
  283. "qspn_gcount %d, our rnode: %d", me.cur_quadg.gid[level], gid,
  284. level, gnode_count, qspn_gnode_count[_EL(level)],
  285. gnode->g.flags & MAP_RNODE);
  286. /*
  287. * Update the rehook time and let's see if we can take this new rehook
  288. */
  289. if (update_rehook_time(level)) {
  290. debug(DBG_SOFT, "new_rehook: we have to wait before accepting "
  291. "another rehook");
  292. return;
  293. }
  294. if (rehook_mutex)
  295. return;
  296. rehook_mutex = 1;
  297. rargv = xmalloc(sizeof(struct rehook_argv));
  298. rargv->gid = gid;
  299. rargv->gnode = gnode;
  300. rargv->level = level;
  301. rargv->gnode_count = gnode_count;
  302. pthread_create(&thread, &new_rehook_thread_attr, new_rehook_thread,
  303. (void *) rargv);
  304. }
  305. /*
  306. * rehook: resets all the global variables set during the last hook/rehook,
  307. * and launches the netsukuku_hook() again. All the previous map will be lost
  308. * if not saved, the IP will also change.
  309. * During the rehook, the radar_daemon and andna_maintain_hnames_active() are
  310. * stopped.
  311. * After the rehook, the andna_hook will be launched and the stopped daemon
  312. * reactivated.
  313. */
  314. int
  315. rehook(map_gnode * hook_gnode, int hook_level)
  316. {
  317. int ret = 0;
  318. /* Stop the radar_daemon */
  319. radar_daemon_ctl = 0;
  320. /* Wait the end of the current radar */
  321. radar_wait_new_scan();
  322. /* Mark ourself as hooking, this will stop
  323. * andna_maintain_hnames_active() daemon too. */
  324. me.cur_node->flags |= MAP_HNODE;
  325. /*
  326. * Reset the rnode list and external rnode list
  327. */
  328. rnl_reset(&rlist, &rlist_counter);
  329. e_rnode_free(&me.cur_erc, &me.cur_erc_counter);
  330. if (restricted_mode) {
  331. /*
  332. * Delete all the tunnels, and reset all the structs used by
  333. * igs.c
  334. */
  335. del_all_tunnel_ifs(0, 0, 0, NTK_TUNL_PREFIX);
  336. reset_igw_nexthop(multigw_nh);
  337. reset_igws(me.igws, me.igws_counter, me.cur_quadg.levels);
  338. reset_igw_rules();
  339. free_my_igws(&me.my_igws);
  340. }
  341. /* Andna reset */
  342. if (!server_opt.disable_andna) {
  343. andna_cache_destroy();
  344. counter_c_destroy();
  345. rh_cache_flush();
  346. }
  347. /* Clear the uptime */
  348. me.uptime = time(0);
  349. /*
  350. * * * REHOOK! * * *
  351. */
  352. netsukuku_hook(hook_gnode, hook_level);
  353. /* Restart the radar daemon */
  354. radar_daemon_ctl = 1;
  355. if (!server_opt.disable_andna) {
  356. /* Rehook in ANDNA and update our hostnames */
  357. andna_hook(0);
  358. andna_update_hnames(0);
  359. }
  360. return ret;
  361. }