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.

route.c 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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. * route.c:
  20. * Routing table management code.
  21. */
  22. #include "includes.h"
  23. #include "common.h"
  24. #include "libnetlink.h"
  25. #include "inet.h"
  26. #include "krnl_route.h"
  27. #include "request.h"
  28. #include "endianness.h"
  29. #include "pkts.h"
  30. #include "bmap.h"
  31. #include "qspn.h"
  32. #include "radar.h"
  33. #include "netsukuku.h"
  34. #include "route.h"
  35. int get_gw_gnode_recurse(map_node *, map_gnode **, map_bnode **, u_int *,
  36. map_gnode *, map_gnode *, map_node *, u_char,
  37. u_char, void **, int, int);
  38. /*
  39. * get_gw_bnode_recurse: this function is part of get_gw_gnode_recurse().
  40. * The explanation of it's way of working is inside the get_gw_gnode()
  41. * function.
  42. */
  43. int
  44. get_gw_bnode_recurse(map_node * int_map, map_gnode ** ext_map,
  45. map_bnode ** bnode_map, u_int * bmap_nodes,
  46. map_gnode * find_gnode, map_gnode * gnode_gw,
  47. map_node * node_gw, u_char gnode_level,
  48. u_char gw_level, void **gateways, int gateways_nmembs,
  49. int single_gw)
  50. {
  51. map_gnode *gnode = 0;
  52. map_node *node, *root_node;
  53. ext_rnode_cache *erc;
  54. int i, bpos;
  55. i = gnode_level;
  56. if (i == gw_level) {
  57. /* Gateway found */
  58. gateways[0] = (void *) node_gw;
  59. return 0;
  60. } else if (!i)
  61. return -1;
  62. /* Find the bnode which borders on the `node_gw' gnode */
  63. bpos =
  64. map_find_bnode_rnode(bnode_map[i - 1], bmap_nodes[i - 1],
  65. (void *) node_gw);
  66. if (bpos == -1) {
  67. /*debug(DBG_INSANE, "get_gw: l=%d, node_gw=%x not found in bmap lvl %d",
  68. i, node_gw, i-1); */
  69. return -1;
  70. }
  71. if (!(i - 1))
  72. node = node_from_pos(bnode_map[i - 1][bpos].bnode_ptr, int_map);
  73. else {
  74. gnode = gnode_from_pos(bnode_map[i - 1][bpos].bnode_ptr,
  75. ext_map[_EL(i - 1)]);
  76. node = &gnode->g;
  77. /* If we are a bnode and the `gnode', the found bnode, is us,
  78. * let's check if we have `gnode_gw' in our external rnode
  79. * cache. If we have, the gw has been found */
  80. qspn_set_map_vars(i - 1, 0, &root_node, 0, 0);
  81. if (me.cur_node->flags & MAP_BNODE &&
  82. gnode == (map_gnode *) root_node) {
  83. /* debug(DBG_INSANE, "get_gw: bmap searching ernode for gnode 0x%x",node_gw); */
  84. erc = erc_find_gnode(me.cur_erc, gnode_gw, i);
  85. if (erc) {
  86. gateways[0] = (void *) erc->e;
  87. return 0;
  88. }
  89. }
  90. }
  91. /* debug(DBG_INSANE, "get_gw: bmap found = %x", node); */
  92. /* Descend in the lower level */
  93. if ((--i) >= gw_level)
  94. return get_gw_gnode_recurse(int_map, ext_map, bnode_map,
  95. bmap_nodes, find_gnode, gnode, node, i,
  96. gw_level, gateways, gateways_nmembs,
  97. single_gw);
  98. return -1;
  99. }
  100. /*
  101. * get_gw_gnode_recurse: recursive part of the get_gw_gnode function (see
  102. * below).
  103. * `gateways' is the array of pointers. which point to the found gateway
  104. * nodes.
  105. * `gateways_nmembs' is the number of members of the `gateways' array.
  106. */
  107. int
  108. get_gw_gnode_recurse(map_node * int_map, map_gnode ** ext_map,
  109. map_bnode ** bnode_map, u_int * bmap_nodes,
  110. map_gnode * find_gnode, map_gnode * gnode,
  111. map_node * node, u_char gnode_level, u_char gw_level,
  112. void **gateways, int gateways_nmembs, int single_gw)
  113. {
  114. map_gnode *gnode_gw = 0;
  115. map_node *node_gw;
  116. int i, pos, routes, sub_routes, e, ret;
  117. /*debug(DBG_INSANE, "get_gw: find_gnode=%x", find_gnode); */
  118. i = gnode_level;
  119. if (node->flags & MAP_RNODE) {
  120. /*
  121. * If `node' is an our rnode, then the gateway to reach it is
  122. * itself, so we set the `gnode_gw' to `node' in order to find
  123. * in the lower level a bnode which borders on `node'
  124. */
  125. gnode_gw = (void *) node;
  126. node_gw = (map_node *) gnode_gw;
  127. /*debug(DBG_INSANE, "get_gw: l=%d, node & MAP_RNODE. node_gw=node=%x",
  128. i, node); */
  129. } else if (node->flags & MAP_ME) {
  130. /*
  131. * If `node' is an our gnode. we reset the gnode_gw to
  132. * `find_gnode', in this way, in the lower level we'll find a
  133. * bnode which borders on `find_gnode'.
  134. */
  135. gnode_gw = (void *) find_gnode;
  136. node_gw = (map_node *) gnode_gw;
  137. /*debug(DBG_INSANE, "get_gw: l=%d, node & MAP_ME. find_gnode: %x",
  138. i, find_gnode); */
  139. } else {
  140. if (!node->links || (i && !gnode))
  141. /* That's no good */
  142. return -1;
  143. if (single_gw) {
  144. /* only one route is needed, do not fork */
  145. routes = 1;
  146. sub_routes = 1;
  147. } else {
  148. /* `routes': how many different links we must consider */
  149. routes = sub_gw_links[FAMILY_LVLS - i - 1];
  150. routes = routes > node->links ? node->links : routes;
  151. /* How many routes there are in each of the `routes'# links */
  152. sub_routes = gateways_nmembs / routes;
  153. }
  154. int old_pos[routes];
  155. memset(old_pos, -1, sizeof(int) * routes);
  156. ret = 0;
  157. for (e = 0; e < routes; e++) {
  158. /* Choose a random link, which was not chosen before */
  159. while (find_int
  160. ((pos =
  161. rand_range(0, node->links - 1)), old_pos, routes));
  162. old_pos[e] = pos;
  163. if (!i) {
  164. node_gw = (void *) node->r_node[pos].r_node;
  165. } else {
  166. gnode_gw = (map_gnode *) gnode->g.r_node[pos].r_node;
  167. node_gw = (void *) gnode_gw;
  168. }
  169. if (node_gw->flags & MAP_RNODE)
  170. find_gnode = (map_gnode *) node_gw;
  171. /*debug(DBG_INSANE, "get_gw: l=%d, e %d node_gw=rnode[%d].r_node=%x,"
  172. " find_gnode=%x", i, e, pos, node_gw, find_gnode); */
  173. ret +=
  174. get_gw_bnode_recurse(int_map, ext_map, bnode_map,
  175. bmap_nodes, find_gnode, gnode_gw,
  176. node_gw, i, gw_level,
  177. &gateways[e * sub_routes], sub_routes,
  178. single_gw);
  179. }
  180. return ret;
  181. }
  182. return get_gw_bnode_recurse(int_map, ext_map, bnode_map, bmap_nodes,
  183. find_gnode, gnode_gw, node_gw, i, gw_level,
  184. gateways, gateways_nmembs, single_gw);
  185. }
  186. /*
  187. * get_gw_gnode: It finds the MAX_MULTIPATH_ROUTES best gateway present in the
  188. * map of level `gw_level'. These gateways are the nodes to be used as gateway
  189. * to reach, from the `gw_level' level, the `find_gnode' gnode at the
  190. * `gnode_level' level.
  191. * If not a single gateway is found, NULL is returned, otherwise an array of
  192. * pointers to the gateway nodes is returned, the array has
  193. * MAX_MULTIPATH_ROUTES+1 nmembs. Some member of the array can be NULL, ignore
  194. * them. Remember to xfree the array of pointers!
  195. * If `single_gw' is not 0, only one gateway will be returned.
  196. */
  197. void **
  198. get_gw_gnode(map_node * int_map, map_gnode ** ext_map,
  199. map_bnode ** bnode_map, u_int * bmap_nodes,
  200. map_gnode * find_gnode, u_char gnode_level,
  201. u_char gw_level, int single_gw)
  202. {
  203. map_gnode *gnode;
  204. map_node *node;
  205. void **gateways = 0;
  206. int ret;
  207. if (!gnode_level || gw_level > gnode_level)
  208. goto error;
  209. gateways = xzalloc(sizeof(void *) * MAX_MULTIPATH_ROUTES + 1);
  210. /*
  211. * In order to find the gateway at level `gw_level', which will be
  212. * used to reach the `find_gnode' gnode at level `gnode_level',
  213. * firstly we find the gnode, at level `gnode_level' that can be used
  214. * as a gateway to reach `find_gnode', then we go down of one level
  215. * and we search the gateway that can be used to reach the border node
  216. * which borders to the previously found gateway. The same procedure
  217. * is done until we arrive at the desired `gw_level' level.
  218. *
  219. * Sadly this procedure can give us only one route to reach the
  220. * `find_gnode' gnode, in fact, there can be, at each level, multiple
  221. * gateways to reach the same gnode (or bnode). For this reason, at
  222. * each level, we must first fork at each found gateway and then we
  223. * can descend in the lower level. In this way each forked child will
  224. * try to find the gateway to reach the bnode which borders on the
  225. * parent gateway.
  226. * Each found gateway, which belongs to the `gw_level' is added to the
  227. * `gateways' array, but here comes another problem: if in each level
  228. * we find the maximum number of available gateways, there will be a
  229. * total of MAX_MULTIPATH_ROUTES^(gnode_level-gw_level) routes.
  230. * We can return only MAX_MULTIPATH_ROUTES routes, so we restrict the
  231. * number of forks per level. Each level has its forks number, which
  232. * is already stored in the `sub_gw_links' array. (For more info on
  233. * that array, read route.h).
  234. * That's all.
  235. *
  236. * To implement all that mess we use three functions, in this way:
  237. *
  238. * get_gw_gnode() is only the starting function. It sets
  239. * gnode=find_gnode and launches get_gw_gnode_recurse(gnode), which
  240. * finds the gateway to reach the given `gnode'. It then forks for
  241. * each gateway found and launches get_gw_bnode_recurse(gateway) which
  242. * searches, in the lower level, the bnode which borders on `gateway'.
  243. * Then get_gw_bnode_recurse() sets gnode to the found gateway and
  244. * launches again get_gw_gnode(gnode). The loop continues until the
  245. * `gw_level' is reached.
  246. *
  247. * Wow, that was a long explanation ;)
  248. */
  249. gnode = find_gnode;
  250. node = &gnode->g;
  251. /* The gateway to reach me is myself. */
  252. if (node->flags & MAP_ME) {
  253. gateways[0] = (void *) node;
  254. return gateways;
  255. }
  256. ret = get_gw_gnode_recurse(int_map, ext_map, bnode_map, bmap_nodes,
  257. find_gnode, gnode, node, gnode_level,
  258. gw_level, gateways, MAX_MULTIPATH_ROUTES,
  259. single_gw);
  260. if (ret < 0)
  261. goto error;
  262. return gateways;
  263. error:
  264. if (gateways)
  265. xfree(gateways);
  266. return 0;
  267. }
  268. /*
  269. * get_gw_ips: It's a wrapper to get_gw_gnode() that converts the found
  270. * gateways to IPs.
  271. * `gw_ip' is the array of inet_prefix structs where the converted IPs will be
  272. * stored. It must have MAX_MULTIPATH_ROUTES members.
  273. * If `single_gw' is not null, only the best gateway will be converted and it
  274. * is assumed that `gw_ip' has only 1 member.
  275. * The number of IPs stored in `gw_ip' is returned.
  276. * The pointer to the gateways node pointers are copied in the `gw_gnodes'
  277. * array, (if not null), which must have at least MAX_MULTIPATH_ROUTES members.
  278. * On error -1 is returned.
  279. */
  280. int
  281. get_gw_ips(map_node * int_map, map_gnode ** ext_map,
  282. map_bnode ** bnode_map, u_int * bmap_nodes,
  283. quadro_group * cur_quadg,
  284. map_gnode * find_gnode, u_char gnode_level,
  285. u_char gw_level, inet_prefix * gw_ip, map_node ** gw_nodes,
  286. int single_gw)
  287. {
  288. ext_rnode *e_rnode = 0;
  289. map_node **gw_node = 0;
  290. int i, e, gw_ip_members;
  291. gw_ip_members = single_gw ? 1 : MAX_MULTIPATH_ROUTES;
  292. setzero(gw_ip, sizeof(inet_prefix) * gw_ip_members);
  293. gw_node =
  294. (map_node **) get_gw_gnode(int_map, ext_map, bnode_map, bmap_nodes,
  295. find_gnode, gnode_level, gw_level,
  296. single_gw);
  297. if (!gw_node)
  298. return -1;
  299. for (i = 0, e = 0; i < MAX_MULTIPATH_ROUTES; i++) {
  300. if (!gw_node[i])
  301. continue;
  302. if (gw_node[i]->flags & MAP_ERNODE) {
  303. e_rnode = (ext_rnode *) gw_node[i];
  304. inet_copy(&gw_ip[e], &e_rnode->quadg.ipstart[gw_level]);
  305. } else
  306. maptoip((uintptr_t) int_map, (uintptr_t) gw_node[i],
  307. cur_quadg->ipstart[1], &gw_ip[e]);
  308. if (gw_nodes)
  309. gw_nodes[e] = gw_node[i];
  310. e++;
  311. }
  312. xfree(gw_node);
  313. return e ? e : -1;
  314. }
  315. /*
  316. * find_rnode_dev_and_retry
  317. *
  318. * Searches with rnl_get_dev() the rnode_list which points to `node'.
  319. * If it is not found it waits the next radar_scan. If it is not found again
  320. * NULL is returned, otherwise the devices list of the related rnode_list
  321. * struct is returned.
  322. */
  323. interface **
  324. find_rnode_dev_and_retry(map_node * node)
  325. {
  326. int retries;
  327. interface **devs = 0;
  328. for (retries = 0; !(devs = rnl_get_dev(rlist, node)) && !retries;
  329. retries++)
  330. radar_wait_new_scan();
  331. return devs;
  332. }
  333. /*
  334. * rt_build_nexthop_gw: returns an array of nexthop structs, which has a
  335. * maximum of `maxhops' members. The nexthop are all gateway which can be used
  336. * to reach `node' or `gnode'.
  337. * The array is xmallocateed.
  338. * On error NULL is returned.
  339. */
  340. struct nexthop *
  341. rt_build_nexthop_gw(map_node * node, map_gnode * gnode, int level,
  342. int maxhops)
  343. {
  344. map_node *tmp_node;
  345. struct nexthop *nh = 0;
  346. interface **devs;
  347. int n, i, ips, routes;
  348. if (!level) {
  349. nh = xmalloc(sizeof(struct nexthop) * (node->links + 1));
  350. setzero(nh, sizeof(struct nexthop) * (node->links + 1));
  351. for (i = 0, n = 0; i < node->links; i++) {
  352. tmp_node = (map_node *) node->r_node[i].r_node;
  353. maptoip((uintptr_t) me.int_map, (uintptr_t) tmp_node,
  354. me.cur_quadg.ipstart[1], &nh[n].gw);
  355. inet_htonl(nh[n].gw.data, nh[n].gw.family);
  356. if (!(devs = find_rnode_dev_and_retry(tmp_node)))
  357. continue;
  358. nh[n].dev = devs[0]->dev_name;
  359. nh[n].hops = node->links - i; /* multipath weigth */
  360. n++;
  361. if (maxhops && n >= maxhops)
  362. break;
  363. }
  364. nh[n].dev = 0;
  365. } else if (level) {
  366. inet_prefix gnode_gws[MAX_MULTIPATH_ROUTES];
  367. map_node *gw_nodes[MAX_MULTIPATH_ROUTES];
  368. routes = get_gw_ips(me.int_map, me.ext_map, me.bnode_map,
  369. me.bmap_nodes, &me.cur_quadg,
  370. gnode, level, 0, gnode_gws, gw_nodes, 0);
  371. if (routes < 0)
  372. goto finish;
  373. nh = xmalloc(sizeof(struct nexthop) * (routes + 1));
  374. setzero(nh, sizeof(struct nexthop) * (routes + 1));
  375. for (ips = 0, n = 0; ips < routes; ips++) {
  376. inet_copy(&nh[n].gw, &gnode_gws[ips]);
  377. inet_htonl(nh[n].gw.data, nh[n].gw.family);
  378. if (!(devs = find_rnode_dev_and_retry(gw_nodes[ips])))
  379. continue;
  380. nh[n].dev = devs[0]->dev_name;
  381. nh[n].hops = routes - ips; /* multipath weigth */
  382. n++;
  383. if (maxhops && n >= maxhops)
  384. break;
  385. }
  386. nh[n].dev = 0;
  387. }
  388. finish:
  389. return nh;
  390. }
  391. struct nexthop *
  392. rt_build_nexthop_voidgw(void *void_gw, interface ** oifs)
  393. {
  394. map_node *gw_node = 0;
  395. ext_rnode *e_rnode = 0;
  396. struct nexthop *nh;
  397. int dev_n, i;
  398. if (void_gw)
  399. gw_node = (map_node *) void_gw;
  400. if (!oifs && !(oifs = find_rnode_dev_and_retry(gw_node)))
  401. /* It wasn't found any suitable dev */
  402. return 0;
  403. for (dev_n = 0; oifs[dev_n]; dev_n++);
  404. nh = xmalloc(sizeof(struct nexthop) * (dev_n + 1));
  405. setzero(nh, sizeof(struct nexthop) * (dev_n + 1));
  406. if (gw_node->flags & MAP_ERNODE) {
  407. e_rnode = (ext_rnode *) gw_node;
  408. inet_copy(&nh[0].gw, &e_rnode->quadg.ipstart[0]);
  409. } else
  410. maptoip((uintptr_t) me.int_map, (uintptr_t) gw_node,
  411. me.cur_quadg.ipstart[1], &nh[0].gw);
  412. inet_htonl(nh[0].gw.data, nh[0].gw.family);
  413. nh[0].dev = oifs[0]->dev_name;
  414. nh[0].hops = 1;
  415. for (i = 1; i < dev_n; i++) {
  416. memcpy(&nh[i], &nh[0], sizeof(struct nexthop));
  417. nh[i].dev = oifs[i]->dev_name;
  418. nh[i].hops = 1;
  419. }
  420. nh[i].dev = 0;
  421. return nh;
  422. }
  423. /*
  424. * rt_update_node
  425. *
  426. * It adds/replaces or removes a route from the kernel's
  427. * table, if the node's flag is found, respectively, to be set to
  428. * MAP_UPDATE or set to MAP_VOID. When a route is deleted only the destination
  429. * arguments are required (i.e `void_gw', `oif' are not needed).
  430. *
  431. * The destination of the route can be given with `dst_ip', `dst_node' or
  432. * `dst_quadg'.
  433. *
  434. * If `dst_ip' is not null, the given inet_prefix struct is used, it's also
  435. * used the `dst_node' to retrieve the flags.
  436. * If the destination of the route is a node which belongs to the level 0, the
  437. * same node must be passed in the `dst_node' argument.
  438. *
  439. * If `level' is > 0 and `dst_quadg' is not null, then it updates the gnode
  440. * which is inside the `dst_quadg' struct: dst_quadg->gnode[_EL(level)]. The
  441. * quadro_group struct must be complete and refer to the groups of the
  442. * given gnode.
  443. *
  444. * If `level' is > 0 and `dst_quadg' is null, it's assumed that the gnode is passed
  445. * in `dst_node' and that the quadro_group for that gnode is me.cur_quadg.
  446. *
  447. * If `void_gw' is not null, it is used as the only gw to reach the destination
  448. * node, otherwise the gw will be calculated.
  449. * `oifs', if not null, will be used in conjuction with `void_gw' as the output
  450. * interfaces to be used in the route. `oifs' is an array of pointers of
  451. * maximum MAX_INTERFACES# members.
  452. */
  453. void
  454. rt_update_node(inet_prefix * dst_ip, void *dst_node,
  455. quadro_group * dst_quadg, void *void_gw, interface ** oifs,
  456. u_char level)
  457. {
  458. map_node *node = 0;
  459. map_gnode *gnode = 0;
  460. struct nexthop *nh = 0;
  461. inet_prefix to;
  462. int node_pos = 0, route_scope = 0;
  463. #ifdef DEBUG
  464. #define MAX_GW_IP_STR_SIZE (MAX_MULTIPATH_ROUTES*((INET6_ADDRSTRLEN+1)+IFNAMSIZ)+1)
  465. int n;
  466. char *to_ip = 0, gw_ip[MAX_GW_IP_STR_SIZE] = "";
  467. #else
  468. const char *to_ip = 0;
  469. #endif
  470. node = (map_node *) dst_node;
  471. gnode = (map_gnode *) dst_node;
  472. /*
  473. * Deduce the destination's ip
  474. */
  475. if (dst_ip)
  476. inet_copy(&to, dst_ip);
  477. else if (level) {
  478. if (!dst_quadg) {
  479. dst_quadg = &me.cur_quadg;
  480. node_pos = pos_from_gnode(gnode, me.ext_map[_EL(level)]);
  481. } else {
  482. gnode = dst_quadg->gnode[_EL(level)];
  483. node_pos = dst_quadg->gid[level];
  484. }
  485. node = &gnode->g;
  486. gnodetoip(dst_quadg, node_pos, level, &to);
  487. } else {
  488. node_pos = pos_from_node(node, me.int_map);
  489. maptoip((uintptr_t) me.int_map, (uintptr_t) node,
  490. me.cur_quadg.ipstart[1], &to);
  491. }
  492. #ifdef DEBUG
  493. to_ip = xstrdup(inet_to_str(to));
  494. #else
  495. to_ip = inet_to_str(to);
  496. #endif
  497. inet_htonl(to.data, to.family);
  498. if (node->flags & MAP_VOID)
  499. /* We have only to delete the route, skip to do_update */
  500. goto do_update;
  501. /*
  502. * If `node' it's a rnode of level 0, do nothing! It is already
  503. * directly connected to me. (If void_gw is not null, skip this check).
  504. */
  505. if (node->flags & MAP_RNODE && !level && !void_gw)
  506. goto finish;
  507. /* Dumb you, we don't need the route to reach ourself */
  508. if (node->flags & MAP_ME)
  509. goto finish;
  510. /*
  511. * Now, get the gateway to reach the destination.
  512. */
  513. if (void_gw)
  514. nh = rt_build_nexthop_voidgw(void_gw, oifs);
  515. else
  516. nh = rt_build_nexthop_gw(node, gnode, level, MAX_MULTIPATH_ROUTES);
  517. if (!nh) {
  518. debug(DBG_NORMAL, "Cannot get the gateway for "
  519. "the (g)node: %d of level: %d, ip:"
  520. "%s", node_pos, level, to_ip);
  521. goto finish;
  522. }
  523. do_update:
  524. #ifdef DEBUG
  525. for (n = 0; nh && nh[n].dev; n++) {
  526. strcat(gw_ip, inet_to_str(nh[n].gw));
  527. strcat(gw_ip, ":");
  528. strcat(gw_ip, nh[n].dev);
  529. if (nh[n + 1].dev)
  530. strcat(gw_ip, ",");
  531. }
  532. if (node->flags & MAP_VOID)
  533. strcpy(gw_ip, "deleted");
  534. debug(DBG_INSANE,
  535. "rt_update_node: to " PURPLE("%s/%d") " via " RED("%s"), to_ip,
  536. to.bits, gw_ip);
  537. #endif
  538. if (node->flags & MAP_RNODE && !level)
  539. /* The dst node is a node directly linked to us */
  540. route_scope = RT_SCOPE_LINK;
  541. if (node->flags & MAP_VOID) {
  542. /* Ok, let's delete it */
  543. if (route_del(RTN_UNICAST, 0, 0, &to, 0, 0, 0))
  544. error("WARNING: Cannot delete the route entry for the"
  545. "%snode %d lvl %d!", !level ? " " : " g",
  546. node_pos, level);
  547. } else if (route_replace(0, route_scope, 0, &to, nh, 0, 0))
  548. error("WARNING: Cannot update the route entry for the"
  549. "%snode %d lvl %d", !level ? " " : " g", node_pos, level);
  550. finish:
  551. #ifdef DEBUG
  552. if (to_ip)
  553. xfree(to_ip);
  554. #endif
  555. if (nh)
  556. xfree(nh);
  557. }
  558. /*
  559. * rt_rnodes_update
  560. *
  561. * It updates all the node which are rnodes of the root_node
  562. * of all the maps. If `check_update_flag' is non zero, the rnode will be
  563. * updated only if it has the MAP_UPDATE flag set.
  564. */
  565. void
  566. rt_rnodes_update(int check_update_flag)
  567. {
  568. u_short i, level;
  569. ext_rnode *e_rnode;
  570. map_node *root_node, *node, *rnode;
  571. map_gnode *gnode;
  572. interface **out_devs;
  573. /* Internal map */
  574. root_node = me.cur_node;
  575. for (i = 0; i < root_node->links; i++) {
  576. rnode = (map_node *) root_node->r_node[i].r_node;
  577. out_devs = rnl_get_dev(rlist, rnode);
  578. if (check_update_flag && !(rnode->flags & MAP_UPDATE))
  579. /* nothing to do for this rnode */
  580. continue;
  581. if (rnode->flags & MAP_ERNODE) {
  582. e_rnode = (ext_rnode *) rnode;
  583. rt_update_node(&e_rnode->quadg.ipstart[0], rnode, 0,
  584. me.cur_node, out_devs, /*level */ 0);
  585. rnode->flags &= ~MAP_UPDATE;
  586. for (level = 1; level < e_rnode->quadg.levels; level++) {
  587. if (!(gnode = e_rnode->quadg.gnode[_EL(level)]))
  588. continue;
  589. node = &gnode->g;
  590. rt_update_node(0, 0, &e_rnode->quadg,
  591. rnode, out_devs, level);
  592. node->flags &= ~MAP_UPDATE;
  593. }
  594. } else {
  595. rt_update_node(0, rnode, 0, me.cur_node, out_devs, /*level */
  596. 0);
  597. rnode->flags &= ~MAP_UPDATE;
  598. }
  599. }
  600. /*
  601. * Shall we activate it?
  602. * route_flush_cache(my_family);
  603. */
  604. }
  605. /*
  606. * rt_full_update
  607. *
  608. * It updates _ALL_ the possible routes it can get from _ALL_ the maps.
  609. * If `check_update_flag' is not 0, it will update only the routes of the
  610. * nodes with the MAP_UPDATE flag set. Note that the MAP_VOID nodes aren't
  611. * considered.
  612. */
  613. void
  614. rt_full_update(int check_update_flag)
  615. {
  616. u_short i, l;
  617. /* Update ext_maps */
  618. for (l = me.cur_quadg.levels - 1; l >= 1; l--)
  619. for (i = 0; i < MAXGROUPNODE; i++) {
  620. if (me.ext_map[_EL(l)][i].g.flags & MAP_VOID ||
  621. me.ext_map[_EL(l)][i].flags & GMAP_VOID ||
  622. me.ext_map[_EL(l)][i].g.flags & MAP_ME)
  623. continue;
  624. if (check_update_flag &&
  625. !(me.ext_map[_EL(l)][i].g.flags & MAP_UPDATE))
  626. continue;
  627. rt_update_node(0, &me.ext_map[_EL(l)][i].g, 0, 0, 0, l);
  628. me.ext_map[_EL(l)][i].g.flags &= ~MAP_UPDATE;
  629. }
  630. /* Update int_map */
  631. for (i = 0, l = 0; i < MAXGROUPNODE; i++) {
  632. if (me.int_map[i].flags & MAP_VOID || me.int_map[i].flags & MAP_ME)
  633. continue;
  634. if (check_update_flag && !((me.int_map[i].flags & MAP_UPDATE)))
  635. continue;
  636. rt_update_node(0, &me.int_map[i], 0, 0, 0, l);
  637. me.int_map[i].flags &= ~MAP_UPDATE;
  638. }
  639. route_flush_cache(my_family);
  640. }
  641. /*
  642. * rt_get_default_gw
  643. *
  644. * It stores in `gw' the IP address of the current default gw, and in
  645. * `dev_name' its utilised net interface. If the default gw doesn't exist
  646. * `gw' and `dev_name' are set to 0.
  647. * If an error occurred a number < 0 is returned.
  648. * `dev_name' must be of IFNAMSIZ# bytes.
  649. */
  650. int
  651. rt_get_default_gw(inet_prefix * gw, char *dev_name)
  652. {
  653. inet_prefix default_gw;
  654. inet_setip_anyaddr(&default_gw, my_family);
  655. default_gw.len = default_gw.bits = 0;
  656. return route_get_exact_prefix_dst(default_gw, gw, dev_name);
  657. }
  658. int
  659. rt_exec_gw(char *dev, inet_prefix to, inet_prefix gw,
  660. int (*route_function) (ROUTE_CMD_VARS), u_char table)
  661. {
  662. struct nexthop nh[2], *neho;
  663. if (to.len)
  664. inet_htonl(to.data, to.family);
  665. if (gw.len) {
  666. setzero(nh, sizeof(struct nexthop) * 2);
  667. inet_copy(&nh[0].gw, &gw);
  668. inet_htonl(nh[0].gw.data, nh[0].gw.family);
  669. nh[0].dev = dev;
  670. nh[1].dev = 0;
  671. neho = nh;
  672. } else
  673. neho = 0;
  674. return route_function(0, 0, 0, &to, neho, dev, table);
  675. }
  676. int
  677. rt_add_gw(char *dev, inet_prefix to, inet_prefix gw, u_char table)
  678. {
  679. return rt_exec_gw(dev, to, gw, route_add, table);
  680. }
  681. int
  682. rt_del_gw(char *dev, inet_prefix to, inet_prefix gw, u_char table)
  683. {
  684. return rt_exec_gw(dev, to, gw, route_del, table);
  685. }
  686. int
  687. rt_change_gw(char *dev, inet_prefix to, inet_prefix gw, u_char table)
  688. {
  689. return rt_exec_gw(dev, to, gw, route_change, table);
  690. }
  691. int
  692. rt_replace_gw(char *dev, inet_prefix to, inet_prefix gw, u_char table)
  693. {
  694. return rt_exec_gw(dev, to, gw, route_replace, table);
  695. }
  696. int
  697. rt_replace_def_gw(char *dev, inet_prefix gw, u_char table)
  698. {
  699. inet_prefix to;
  700. if (inet_setip_anyaddr(&to, my_family)) {
  701. error("rt_replace_def_gw(): Cannot use INADRR_ANY for the %d "
  702. "family", to.family);
  703. return -1;
  704. }
  705. to.len = to.bits = 0;
  706. return rt_replace_gw(dev, to, gw, table);
  707. }
  708. int
  709. rt_delete_def_gw(u_char table)
  710. {
  711. inet_prefix to;
  712. if (inet_setip_anyaddr(&to, my_family)) {
  713. error("rt_delete_def_gw(): Cannot use INADRR_ANY for the %d "
  714. "family", to.family);
  715. return -1;
  716. }
  717. to.len = to.bits = 0;
  718. return route_del(0, 0, 0, &to, 0, 0, table);
  719. }
  720. /*
  721. * rt_del_loopback_net:
  722. * We remove the loopback net, leaving only the 127.0.0.1 ip for loopback.
  723. * ip route del local 127.0.0.0/8 proto kernel scope host src 127.0.0.1
  724. * ip route del broadcast 127.255.255.255 proto kernel scope link src 127.0.0.1
  725. * ip route del broadcast 127.0.0.0 proto kernel scope link src 127.0.0.1
  726. */
  727. int
  728. rt_del_loopback_net(void)
  729. {
  730. inet_prefix to;
  731. char lo_dev[] = "lo";
  732. u_int idata[MAX_IP_INT];
  733. setzero(idata, MAX_IP_SZ);
  734. if (my_family != AF_INET)
  735. return 0;
  736. /*
  737. * ip route del broadcast 127.0.0.0 proto kernel scope link \
  738. * src 127.0.0.1
  739. */
  740. idata[0] = LOOPBACK_NET;
  741. inet_setip(&to, idata, my_family);
  742. route_del(RTN_BROADCAST, 0, 0, &to, 0, 0, RT_TABLE_LOCAL);
  743. /*
  744. * ip route del local 127.0.0.0/8 proto kernel scope host \
  745. * src 127.0.0.1
  746. */
  747. to.bits = 8;
  748. route_del(RTN_LOCAL, 0, 0, &to, 0, lo_dev, RT_TABLE_LOCAL);
  749. /*
  750. * ip route del broadcast 127.255.255.255 proto kernel scope link \
  751. * src 127.0.0.1
  752. */
  753. idata[0] = LOOPBACK_BCAST;
  754. inet_setip(&to, idata, my_family);
  755. route_del(RTN_BROADCAST, 0, 0, &to, 0, lo_dev, RT_TABLE_LOCAL);
  756. return 0;
  757. }
  758. /*
  759. * rt_append_subnet_src:
  760. * it appends the subnet relative to a `src' IP and its device in the routing
  761. * table, f.e. when you do "ifconfig eth0 10.2.3.1 up" the kernel
  762. * automatically adds this route:
  763. * 10.0.0.0/8 dev eth0 proto kernel scope link src 10.2.3.1
  764. * In this case `src'="10.2.3.1" and `dev'="eth0"
  765. */
  766. int
  767. rt_append_subnet_src(inet_prefix * src, char *dev)
  768. {
  769. inet_prefix to, src_htonl;
  770. if (src->family == AF_INET6)
  771. fatal(ERROR_MSG "Family not supported", ERROR_POS);
  772. inet_copy(&src_htonl, src);
  773. inet_htonl(src_htonl.data, src->family);
  774. setzero(&to, sizeof(inet_prefix));
  775. to.family = src->family;
  776. to.len = src->len;
  777. if (((NTK_PRIVATE_B(src_htonl.data[0])) ||
  778. (NTK_PRIVATE_C(src_htonl.data[0])))) {
  779. to.bits = 16;
  780. to.data[0] = htonl((src->data[0] & 0xffff0000));
  781. } else {
  782. to.bits = 8;
  783. to.data[0] = htonl((src->data[0] & 0xff000000));
  784. }
  785. return route_append(0, RT_SCOPE_LINK, &src_htonl, &to, 0, dev, 0);
  786. }