Нет описания https://github.com/Netsukuku/netsukuku
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  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. * Internal map code.
  20. */
  21. #include "includes.h"
  22. #include "ipv6-gmp.h"
  23. #include "map.h"
  24. #include "common.h"
  25. extern int errno;
  26. /*
  27. * pos_from_node: Position from node: It returns the position of the `node'
  28. * in the `map'.
  29. */
  30. int
  31. pos_from_node(map_node * node, map_node * map)
  32. {
  33. return ((char *) node - (char *) map) / sizeof(map_node);
  34. }
  35. /*
  36. * Node from position: it returns the node pointer calculated by the given
  37. * `pos' in the map.
  38. */
  39. map_node *
  40. node_from_pos(int pos, map_node * map)
  41. {
  42. return (map_node *) ((pos * sizeof(map_node)) + (char *) map);
  43. }
  44. /*
  45. * Position (of a struct in the map) to ip: Converts the node position
  46. * `map_pos' to its relative ip.
  47. */
  48. void
  49. postoip(u_int map_pos, inet_prefix ipstart, inet_prefix * ret)
  50. {
  51. ret->family = ipstart.family;
  52. if (ipstart.family == AF_INET) {
  53. ret->data[0] = map_pos + ipstart.data[0];
  54. ret->len = 4;
  55. } else {
  56. ret->len = 16;
  57. inet_copy_ipdata_raw(ret->data, &ipstart);
  58. sum_int(map_pos, ret->data);
  59. }
  60. ret->bits = ret->len * 8;
  61. }
  62. /*
  63. * Map (address) to ip: Converts an address of a struct in the map to the
  64. * corresponding ip.
  65. */
  66. void
  67. maptoip(uintptr_t mapstart, uintptr_t mapoff, inet_prefix ipstart,
  68. inet_prefix * ret)
  69. {
  70. int map_pos =
  71. pos_from_node((map_node *) mapoff, (map_node *) mapstart);
  72. postoip(map_pos, ipstart, ret);
  73. }
  74. /*
  75. * iptomap: Converts an ip to an address of a struct in the map and stores it
  76. * int `*ret'.
  77. */
  78. int
  79. iptomap(uintptr_t mapstart, inet_prefix ip, inet_prefix ipstart,
  80. map_node ** ret)
  81. {
  82. if (ip.family == AF_INET)
  83. *ret =
  84. (map_node
  85. *) (((ip.data[0] - ipstart.data[0]) * sizeof(map_node)) +
  86. mapstart);
  87. else {
  88. uint32_t h_ip[MAX_IP_INT], h_ipstart[MAX_IP_INT];
  89. memcpy(h_ip, ip.data, MAX_IP_SZ);
  90. memcpy(h_ipstart, ipstart.data, MAX_IP_SZ);
  91. /* h_ipstart=h_ip - h_ipstart */
  92. sub_128(h_ip, h_ipstart);
  93. /* The result is always < MAXGROUPNODE, so we can take for grant that
  94. * we have only one u_int*/
  95. *ret = (map_node *) (h_ipstart[0] * sizeof(map_node) + mapstart);
  96. }
  97. if (*ret > (map_node *) INTMAP_END(mapstart)
  98. || *ret < (map_node *) mapstart)
  99. /*Ok, this is an extern ip to our gnode. */
  100. return 1;
  101. return 0;
  102. }
  103. map_node *
  104. init_map(size_t len)
  105. {
  106. int i;
  107. map_node *map;
  108. if (!len)
  109. len = sizeof(map_node) * MAXGROUPNODE;
  110. map = (map_node *) xmalloc(len);
  111. setzero(map, len);
  112. for (i = 0; i < MAXGROUPNODE; i++)
  113. map[i].flags |= MAP_VOID;
  114. return map;
  115. }
  116. void
  117. free_map(map_node * map, size_t count)
  118. {
  119. int i, len;
  120. if (!count)
  121. count = MAXGROUPNODE;
  122. len = sizeof(map_node) * count;
  123. for (i = 0; i < count; i++) {
  124. if (map[i].links) {
  125. if (map[i].r_node)
  126. xfree(map[i].r_node);
  127. }
  128. }
  129. setzero(map, len);
  130. xfree(map);
  131. }
  132. map_rnode *
  133. rnode_insert(map_rnode * buf, size_t pos, map_rnode * new)
  134. {
  135. map_rnode *ptr = buf + pos;
  136. memcpy(ptr, new, sizeof(map_rnode));
  137. return ptr;
  138. }
  139. map_rnode *
  140. map_rnode_insert(map_node * node, size_t pos, map_rnode * new)
  141. {
  142. if (pos >= node->links)
  143. fatal("Error in %s: %d: Cannot insert map_rnode in %u position."
  144. " It goes beyond the buffer\n", ERROR_POS, pos);
  145. return rnode_insert(node->r_node, pos, new);
  146. }
  147. map_rnode *
  148. rnode_add(map_node * node, map_rnode * new)
  149. {
  150. node->links++;
  151. if (node->links == 1)
  152. node->r_node = xmalloc(sizeof(map_rnode));
  153. else
  154. node->r_node =
  155. xrealloc(node->r_node, node->links * sizeof(map_rnode));
  156. return map_rnode_insert(node, node->links - 1, new);
  157. }
  158. void
  159. rnode_swap(map_rnode * one, map_rnode * two)
  160. {
  161. map_rnode tmp;
  162. memcpy(&tmp, one, sizeof(map_rnode));
  163. memcpy(one, two, sizeof(map_rnode));
  164. memcpy(two, &tmp, sizeof(map_rnode));
  165. }
  166. void
  167. rnode_del(map_node * node, size_t pos)
  168. {
  169. if (pos >= node->links || node->links <= 0)
  170. fatal("Error in %s: %d: Cannot delete Map_rnode in %u position."
  171. " It goes beyond the buffer\n", ERROR_POS, pos);
  172. if (pos != node->links - 1)
  173. rnode_swap((map_rnode *) & node->r_node[pos],
  174. (map_rnode *) & node->r_node[(node->links - 1)]);
  175. node->links--;
  176. if (!node->links) {
  177. xfree(node->r_node);
  178. node->r_node = 0;
  179. } else
  180. node->r_node =
  181. xrealloc(node->r_node, node->links * sizeof(map_rnode));
  182. }
  183. /*
  184. * rnode_destroy
  185. *
  186. * Wipe out all the rnodes YEAHAHA ^_-
  187. */
  188. void
  189. rnode_destroy(map_node * node)
  190. {
  191. if (node->r_node && node->links)
  192. xfree(node->r_node);
  193. node->r_node = 0;
  194. node->links = 0;
  195. }
  196. /*
  197. * rnode_find
  198. *
  199. * It searches in the `node' a rnode which points to the node `n'.
  200. * It then returns the position of that rnode.
  201. * If the rnode is not found it returns -1;
  202. */
  203. int
  204. rnode_find(map_node * node, void *n)
  205. {
  206. int e;
  207. for (e = 0; e < node->links; e++)
  208. if (node->r_node[e].r_node == n)
  209. return e;
  210. return -1;
  211. }
  212. /*
  213. * map_node_del: It deletes a `node' from the `map'. Really it frees its rnodes
  214. * and set the node's flags to MAP_VOID.
  215. */
  216. void
  217. map_node_del(map_node * node)
  218. {
  219. rnode_destroy(node);
  220. setzero(node, sizeof(map_node));
  221. node->flags |= MAP_VOID;
  222. }
  223. void
  224. reset_int_map(map_node * map, int maxgroupnode)
  225. {
  226. int i;
  227. if (!maxgroupnode)
  228. maxgroupnode = MAXGROUPNODE;
  229. for (i = 0; i < maxgroupnode; i++)
  230. map_node_del(&map[i]);
  231. }
  232. /*
  233. * rnode_trtt_compar: It's used by rnode_trtt_order
  234. */
  235. int
  236. rnode_trtt_compar(const void *a, const void *b)
  237. {
  238. map_rnode *rnode_a = (map_rnode *) a, *rnode_b = (map_rnode *) b;
  239. if (rnode_a->trtt > rnode_b->trtt)
  240. return 1;
  241. else if (rnode_a->trtt == rnode_b->trtt)
  242. return 0;
  243. else
  244. return -1;
  245. }
  246. /*
  247. * rnode_trtt_order
  248. *
  249. * It qsorts the rnodes of a map_node comparing their trtt.
  250. * It is used by map_routes_order.
  251. */
  252. void
  253. rnode_trtt_order(map_node * node)
  254. {
  255. qsort(node->r_node, node->links, sizeof(map_rnode), rnode_trtt_compar);
  256. }
  257. /*
  258. * map_routes_order
  259. *
  260. * It orders all the r_node of each node using their trtt.
  261. */
  262. void
  263. map_routes_order(map_node * map)
  264. {
  265. int i;
  266. for (i = 0; i < MAXGROUPNODE; i++)
  267. rnode_trtt_order(&map[i]);
  268. }
  269. /*
  270. * get_route_trtt
  271. *
  272. * It returns the total round trip time (trtt) of `node' (in millisec) for the
  273. * `route'th route.
  274. */
  275. u_int
  276. get_route_trtt(map_node * node, u_short route)
  277. {
  278. if (route >= node->links || node->flags & MAP_VOID || node->links <= 0)
  279. return -1;
  280. if (node->flags & MAP_ME)
  281. return 0;
  282. return node->r_node[route].trtt;
  283. }
  284. /*
  285. * merge_maps:
  286. *
  287. * Given two maps it merges them selecting only the best routes.
  288. * In `base' map there will be the resulting map. The `new' map is the
  289. * second map. `base_root' points to the root_node present in the `base' map.
  290. * `new_root' points to the root_node of the `new' map.
  291. * It's assumed that `new_root' is a rnode of `base_root'.
  292. * Note that the `new' map is modified during the merging!
  293. */
  294. int
  295. merge_maps(map_node * base, map_node * new, map_node * base_root,
  296. map_node * new_root)
  297. {
  298. int i, e, x, count = 0, base_root_pos, ngpos;
  299. u_int base_trtt, new_trtt;
  300. map_node *new_root_in_base, *node_gw;
  301. base_root_pos = pos_from_node(base_root, base);
  302. new_root_in_base = &base[pos_from_node(new_root, new)];
  303. for (i = 0; i < MAXGROUPNODE; i++) {
  304. if (base[i].flags & MAP_ME || new[i].flags & MAP_ME ||
  305. new[i].flags & MAP_VOID)
  306. continue;
  307. for (e = 0; e < new[i].links; e++) {
  308. /*
  309. * We set in node_gw the gw that must be used to reach
  310. * the new[i] node, with the new_root_node as the
  311. * starting point; `node_gw' is a rnode of new_root_node.
  312. */
  313. node_gw = (map_node *) new[i].r_node[e].r_node;
  314. ngpos = pos_from_node(node_gw, new);
  315. if (ngpos == base_root_pos)
  316. /* We skip, cause the new_map it's using the
  317. * base_root node (me) as gw to reach new[i].
  318. */
  319. continue;
  320. /*
  321. * Now we change the r_nodes pointers of the new map to
  322. * let them point to the base map's nodes.
  323. */
  324. if (new[i].flags & MAP_RNODE) {
  325. /*
  326. * new[i] is a rnode of new_root node, so we
  327. * reach it trough new_root.
  328. */
  329. new[i].r_node[e].r_node = (int *) new_root_in_base;
  330. } else if (base[ngpos].flags & MAP_VOID || !base[ngpos].links) {
  331. /*
  332. * In the `base' map, `node_gw' is VOID.
  333. * We must use the new_root node as gw because
  334. * it is one of our rnode.
  335. */
  336. new[i].r_node[e].r_node = (int *) new_root_in_base;
  337. } else {
  338. /*
  339. * In this case the node_gw is already known in
  340. * the base map, so we change it to the gw used
  341. * to reach itself in the base map.
  342. */
  343. new[i].r_node[e].r_node = base[ngpos].r_node[0].r_node;
  344. }
  345. /*
  346. * new[i] has more routes than base[i]. Add them in
  347. * base[i].
  348. */
  349. if (e >= base[i].links) {
  350. rnode_add(&base[i], &new[i].r_node[e]);
  351. rnode_trtt_order(&base[i]);
  352. base[i].flags |= MAP_UPDATE;
  353. count++;
  354. continue;
  355. }
  356. /*
  357. * If the worst route in base[i] is better than the best
  358. * route in new[i], let's go ahead.
  359. */
  360. base_trtt = get_route_trtt(&base[i], base[i].links - 1);
  361. new_trtt = get_route_trtt(&new[i], e);
  362. if (base_trtt < new_trtt)
  363. continue;
  364. /*
  365. * Compare the each route of base[i] with
  366. * new[i].r_node[e]. The first route of base[i] which
  367. * is found to be worse than new[i].r_node[e] is
  368. * deleted and replaced with new[i].r_node[e] itself.
  369. */
  370. for (x = 0; x < base[i].links; x++) {
  371. base_trtt = get_route_trtt(&base[i], x);
  372. new_trtt = get_route_trtt(&new[i], e);
  373. if (base_trtt > new_trtt) {
  374. map_rnode_insert(&base[i], x, &new[i].r_node[e]);
  375. base[i].flags |= MAP_UPDATE;
  376. count++;
  377. break;
  378. }
  379. }
  380. }
  381. if (base[i].links)
  382. base[i].flags &= ~MAP_VOID;
  383. else
  384. map_node_del(&base[i]);
  385. }
  386. return count;
  387. }
  388. /*
  389. * mod_rnode_addr
  390. *
  391. * Modify_rnode_address
  392. */
  393. int
  394. mod_rnode_addr(map_rnode * rnode, int *map_start, int *new_start)
  395. {
  396. rnode->r_node =
  397. (int *) (((char *) rnode->r_node - (char *) map_start) +
  398. (char *) new_start);
  399. return 0;
  400. }
  401. /*
  402. * get_rnode_block
  403. *
  404. * It packs all the rnode structs of a node. The node->r_node pointer of the
  405. * map_rnode struct is changed to point to the position of the node in the map,
  406. * instead of the address. get_rnode_block returns the number
  407. * of rnode structs packed.
  408. * Note that the packed structs will be in network order.
  409. */
  410. int
  411. get_rnode_block(int *map, map_node * node, map_rnode * rblock, int rstart)
  412. {
  413. int e;
  414. char *p;
  415. for (e = 0; e < node->links; e++) {
  416. p = (char *) &rblock[e + rstart];
  417. memcpy(p, &node->r_node[e].r_node, sizeof(int *));
  418. p += sizeof(int *);
  419. memcpy(p, &node->r_node[e].trtt, sizeof(u_int));
  420. p += sizeof(u_int);
  421. mod_rnode_addr(&rblock[e + rstart], map, 0);
  422. ints_host_to_network(&rblock[e + rstart], map_rnode_iinfo);
  423. }
  424. return e;
  425. }
  426. /*
  427. * map_get_rblock
  428. *
  429. * It uses get_rnode_block to pack all the int_map's rnode.
  430. * `maxgroupnode' is the number of nodes present in the map.
  431. * `map' is the actual int_map, while `addr_map' is the address used by get_rnode_block
  432. * to change the rnodes' pointers (read get_rnode_block).
  433. * It returns a pointer to the start of the rnode block and stores in `count'
  434. * the number of rnode structs packed.
  435. * On error NULL is returned.
  436. */
  437. map_rnode *
  438. map_get_rblock(map_node * map, int *addr_map, int maxgroupnode, int *count)
  439. {
  440. int i, c = 0, tot = 0;
  441. map_rnode *rblock;
  442. *count = 0;
  443. for (i = 0; i < maxgroupnode; i++)
  444. tot += map[i].links;
  445. if (!tot)
  446. return 0;
  447. rblock = (map_rnode *) xmalloc(MAP_RNODE_PACK_SZ * tot);
  448. for (i = 0; i < maxgroupnode; i++)
  449. c += get_rnode_block((int *) addr_map, &map[i], rblock, c);
  450. *count = c;
  451. return rblock;
  452. }
  453. /*
  454. * store_rnode_block: Given a correct `node' it restores in it all the r_node structs
  455. * contained in the rnode_block. It returns the number of rnode structs restored.
  456. * Note that `rblock' will be modified during the restoration.
  457. */
  458. int
  459. store_rnode_block(int *map, map_node * node, map_rnode * rblock,
  460. int rstart)
  461. {
  462. int i;
  463. char *p;
  464. if (!node->links)
  465. return 0;
  466. node->r_node = xmalloc(MAP_RNODE_PACK_SZ * node->links);
  467. for (i = 0; i < node->links; i++) {
  468. p = (char *) &rblock[i + rstart];
  469. ints_network_to_host(p, map_rnode_iinfo);
  470. memcpy(&node->r_node[i].r_node, p, sizeof(int *));
  471. p += sizeof(int *);
  472. memcpy(&node->r_node[i].trtt, p, sizeof(u_int));
  473. p += sizeof(u_int);
  474. mod_rnode_addr(&node->r_node[i], 0, map);
  475. }
  476. return i;
  477. }
  478. /*
  479. * map_store_rblock: Given a correct int_map with `maxgroupnode' nodes,
  480. * it restores all the r_node structs in the `map' from the `rblock'
  481. * using store_rnode_block. `addr_map' is the address used to change
  482. * the rnodes' pointers (read store_rnode_block).
  483. */
  484. int
  485. map_store_rblock(map_node * map, int *addr_map, int maxgroupnode,
  486. map_rnode * rblock)
  487. {
  488. int i, c = 0;
  489. for (i = 0; i < maxgroupnode; i++)
  490. c += store_rnode_block(addr_map, &map[i], rblock, c);
  491. return c;
  492. }
  493. /*
  494. * verify_int_map_hdr: verifies the validity of an int_map_hdr struct.
  495. * If `imap_hdr' is invalid 1 will be returned.
  496. */
  497. int
  498. verify_int_map_hdr(struct int_map_hdr *imap_hdr, int maxgroupnode,
  499. int maxrnodeblock)
  500. {
  501. /* No map to care about */
  502. if (!imap_hdr->int_map_sz)
  503. return 0;
  504. if (imap_hdr->rblock_sz > maxrnodeblock ||
  505. imap_hdr->int_map_sz > maxgroupnode * MAP_NODE_PACK_SZ)
  506. return 1;
  507. return 0;
  508. }
  509. /*
  510. * pack_map_node: it packs the `node' struct and stores it in `pack'.
  511. * The packed struct will be in network order
  512. */
  513. void
  514. pack_map_node(map_node * node, char *pack)
  515. {
  516. char *buf;
  517. buf = pack;
  518. memcpy(buf, &node->flags, sizeof(u_short));
  519. buf += sizeof(u_short);
  520. memcpy(buf, &node->brdcast, sizeof(u_int));
  521. buf += sizeof(u_int);
  522. memcpy(buf, &node->links, sizeof(u_short));
  523. buf += sizeof(u_short);
  524. ints_host_to_network(pack, map_node_iinfo);
  525. }
  526. /*
  527. * unpack_map_node: it unpacks `pack', which contains a packed map_node struct.
  528. * The restored map_node struct will be written in `node'.
  529. * Note that `pack' will be modified during the restoration.
  530. */
  531. void
  532. unpack_map_node(map_node * node, char *pack)
  533. {
  534. char *buf;
  535. ints_network_to_host(pack, map_node_iinfo);
  536. buf = pack;
  537. memcpy(&node->flags, buf, sizeof(u_short));
  538. buf += sizeof(u_short);
  539. memcpy(&node->brdcast, buf, sizeof(u_int));
  540. buf += sizeof(u_int);
  541. memcpy(&node->links, buf, sizeof(u_short));
  542. buf += sizeof(u_short);
  543. node->r_node = 0;
  544. }
  545. /*
  546. * pack_map: It returns a pack of the int/bmap_map `map', which has
  547. * `maxgroupnode' nodes ready to be saved or sent. In `pack_sz' it
  548. * stores the size of the package. For info on `addr_map' please
  549. * read get_map_rblock().
  550. * The pack will be in network order.
  551. */
  552. char *
  553. pack_map(map_node * map, int *addr_map, int maxgroupnode,
  554. map_node * root_node, size_t * pack_sz)
  555. {
  556. struct int_map_hdr imap_hdr;
  557. map_rnode *rblock = 0;
  558. int count, i;
  559. char *package, *p;
  560. if (!addr_map)
  561. addr_map = (int *) map;
  562. setzero(&imap_hdr, sizeof(struct int_map_hdr));
  563. if (map) {
  564. /*rblock packing */
  565. rblock = map_get_rblock(map, addr_map, maxgroupnode, &count);
  566. /*Header creation */
  567. imap_hdr.root_node = root_node ? pos_from_node(root_node, map) : 0;
  568. imap_hdr.rblock_sz = count * MAP_RNODE_PACK_SZ;
  569. imap_hdr.int_map_sz = maxgroupnode * MAP_NODE_PACK_SZ;
  570. }
  571. /*Package creation */
  572. *pack_sz = INT_MAP_BLOCK_SZ(imap_hdr.int_map_sz, imap_hdr.rblock_sz);
  573. package = xmalloc(*pack_sz);
  574. memcpy(package, &imap_hdr, sizeof(struct int_map_hdr));
  575. ints_host_to_network(package, int_map_hdr_iinfo);
  576. p = package;
  577. if (imap_hdr.int_map_sz) {
  578. /* Pack the map_node strucs of the `map' */
  579. p += sizeof(struct int_map_hdr);
  580. for (i = 0; i < maxgroupnode; i++) {
  581. pack_map_node(&map[i], p);
  582. p += MAP_NODE_PACK_SZ;
  583. }
  584. }
  585. if (imap_hdr.rblock_sz) {
  586. memcpy(p, rblock, imap_hdr.rblock_sz);
  587. xfree(rblock);
  588. }
  589. return package;
  590. }
  591. /*
  592. * unpack_map: Given a valid int/bmap_map package (packed with pack_intmap), it
  593. * allocates a brand new int_map and restores in it the map and the rnodes.
  594. * It puts in `*new_root' the pointer to the root_node in the loaded map.
  595. * For info on `addr_map' please read map_store_rblock().
  596. * On success the a pointer to the new int_map is retuned, otherwise 0 will be
  597. * the fatal value.
  598. * Note: `pack' will be modified during the unpacking.
  599. */
  600. map_node *
  601. unpack_map(char *pack, int *addr_map, map_node ** new_root,
  602. int maxgroupnode, int maxrnodeblock)
  603. {
  604. map_node *map;
  605. struct int_map_hdr *imap_hdr = (struct int_map_hdr *) pack;
  606. map_rnode *rblock;
  607. int err, nodes, i;
  608. char *p;
  609. ints_network_to_host(imap_hdr, int_map_hdr_iinfo);
  610. if (verify_int_map_hdr(imap_hdr, maxgroupnode, maxrnodeblock)) {
  611. error("Malformed int/bmap_map_hdr. Aborting unpack_map().");
  612. return 0;
  613. }
  614. /*Extracting the map... */
  615. p = pack + sizeof(struct int_map_hdr);
  616. map = init_map(0);
  617. if (!imap_hdr->int_map_sz)
  618. return map;
  619. /* Restore in `map' the packed map_node struct */
  620. nodes = imap_hdr->int_map_sz / MAP_NODE_PACK_SZ;
  621. for (i = 0; i < nodes; i++) {
  622. unpack_map_node(&map[i], p);
  623. p += MAP_NODE_PACK_SZ;
  624. }
  625. /*Restoring the rnodes... */
  626. if (imap_hdr->rblock_sz) {
  627. /*Extracting the rnodes block and merging it to the map */
  628. rblock = (map_rnode *) p;
  629. if (!addr_map)
  630. addr_map = (int *) map;
  631. err = map_store_rblock(map, addr_map, nodes, rblock);
  632. if (err != imap_hdr->rblock_sz / MAP_RNODE_PACK_SZ) {
  633. error
  634. ("An error occurred while storing the rnodes block in the int/bnode_map");
  635. free_map(map, 0);
  636. return 0;
  637. }
  638. }
  639. if (new_root) {
  640. map[imap_hdr->root_node].flags |= MAP_ME;
  641. *new_root = &map[imap_hdr->root_node];
  642. }
  643. return map;
  644. }
  645. /*
  646. * * * save/load int_map * * *
  647. */
  648. int
  649. save_map(map_node * map, map_node * root_node, char *file)
  650. {
  651. FILE *fd;
  652. size_t pack_sz;
  653. char *pack;
  654. /*Pack! */
  655. pack = pack_map(map, 0, MAXGROUPNODE, root_node, &pack_sz);
  656. if (!pack_sz || !pack)
  657. return 0;
  658. if ((fd = fopen(file, "w")) == NULL) {
  659. error("Cannot save the int_map in %s: %s", file, strerror(errno));
  660. return -1;
  661. }
  662. /*Write! */
  663. fwrite(pack, pack_sz, 1, fd);
  664. xfree(pack);
  665. fclose(fd);
  666. return 0;
  667. }
  668. /*
  669. * load_map: It loads the internal_map from `file'.
  670. * It returns the start of the map and if `new_root' is not NULL, it
  671. * puts in `*new_root' the pointer to the root_node in the loaded map.
  672. * On error it returns NULL.
  673. */
  674. map_node *
  675. load_map(char *file, map_node ** new_root)
  676. {
  677. map_node *map = 0;
  678. FILE *fd;
  679. struct int_map_hdr imap_hdr;
  680. char *pack = 0;
  681. size_t pack_sz;
  682. if ((fd = fopen(file, "r")) == NULL) {
  683. error("Cannot load the map from %s: %s", file, strerror(errno));
  684. return 0;
  685. }
  686. if (!fread(&imap_hdr, sizeof(struct int_map_hdr), 1, fd))
  687. goto finish;
  688. ints_network_to_host(&imap_hdr, int_map_hdr_iinfo);
  689. if (!imap_hdr.int_map_sz)
  690. goto finish;
  691. if (verify_int_map_hdr(&imap_hdr, MAXGROUPNODE, MAXRNODEBLOCK_PACK_SZ))
  692. goto finish;
  693. rewind(fd);
  694. pack_sz = INT_MAP_BLOCK_SZ(imap_hdr.int_map_sz, imap_hdr.rblock_sz);
  695. pack = xmalloc(pack_sz);
  696. if (!fread(pack, pack_sz, 1, fd))
  697. goto finish;
  698. map =
  699. unpack_map(pack, 0, new_root, MAXGROUPNODE, MAXRNODEBLOCK_PACK_SZ);
  700. finish:
  701. if (pack)
  702. xfree(pack);
  703. fclose(fd);
  704. if (!map)
  705. error("Malformed map file. Aborting load_map().");
  706. return map;
  707. }