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.

gmap.c 36KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570
  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. #include "includes.h"
  19. #include "inet.h"
  20. #include "endianness.h"
  21. #include "map.h"
  22. #include "gmap.h"
  23. #include "bmap.h"
  24. #include "common.h"
  25. /*
  26. * get_groups
  27. *
  28. * It returns how many groups there are in the given level.
  29. */
  30. int
  31. get_groups(int max_levels, int lvl)
  32. {
  33. return lvl == max_levels ? 1 : MAXGROUPNODE;
  34. }
  35. /*
  36. * is_group_invalid
  37. *
  38. * returns 1 if the `gid' of level `lvl' is invalid and
  39. * cannot be used in a regular IP.
  40. */
  41. int
  42. is_group_invalid(int *gids, int gid, int lvl, int family)
  43. {
  44. if (family == AF_INET) {
  45. if (lvl == GET_LEVELS(family) - 1) {
  46. if (!gid) /* ZERONET */
  47. return 1;
  48. if (gid >= 224 && gid <= 255)
  49. /* MULTICAST and BADCLASS */
  50. return 1;
  51. if (gid == 127) /* LOOPBACK */
  52. return 1;
  53. if (gid == 192 && gids[lvl - 1] == 168)
  54. /* 192.168.x.x is private, we cannot use IP of
  55. * that range */
  56. return 1;
  57. if ((gid == 172
  58. && (gids[lvl - 1] >= 16 || gids[lvl - 1] <= 31))
  59. && !restricted_mode)
  60. /* We aren't in restricted mode, so
  61. * 172.16.0.0-172.31.255.255 is a private
  62. * class */
  63. return 1;
  64. if (restricted_mode &&
  65. ((restricted_class == RESTRICTED_10 && gid != 10) ||
  66. (restricted_class == RESTRICTED_172 &&
  67. !(gid == 172 && (gids[lvl - 1] >= 16 ||
  68. gids[lvl - 1] <= 31))
  69. )
  70. )
  71. )
  72. /* We are in restricted mode, thus this IP is
  73. * invalid because it isn't in the 10.x.x.x or
  74. * 172.(16-31).x.x format */
  75. return 1;
  76. } else if (lvl == GET_LEVELS(family) - 2) {
  77. if (gid == 168 && gids[lvl + 1] == 192)
  78. /* 192.168.x.x */
  79. return 1;
  80. if (((gid >= 16 || gid <= 31) && gids[lvl + 1] == 172) &&
  81. !restricted_mode)
  82. /* 172.16.0.0-172.31.255.255 */
  83. return 1;
  84. }
  85. } else if (family == AF_INET6) {
  86. /* TODO: nothing ? */
  87. return 0;
  88. }
  89. return 0;
  90. }
  91. /*
  92. * pos_from_gnode
  93. * Position from gnode
  94. *
  95. * It returns the position of the `gnode' in the `map'
  96. */
  97. int
  98. pos_from_gnode(map_gnode * gnode, map_gnode * map)
  99. {
  100. return (int) (((char *) gnode - (char *) map) / sizeof(map_gnode));
  101. }
  102. /*
  103. * Gnode from position
  104. *
  105. * it returns the fnode pointer calculated by the given `pos' in the map
  106. */
  107. map_gnode *
  108. gnode_from_pos(int pos, map_gnode * map)
  109. {
  110. return (map_gnode *) ((pos * sizeof(map_gnode)) + (char *) map);
  111. }
  112. /*
  113. * rnodetoip
  114. *
  115. * converts the node `maprnode', which is a rnode of the root_node,
  116. * to the relative ip.
  117. */
  118. void
  119. rnodetoip(uintptr_t mapstart, uintptr_t maprnode, inet_prefix ipstart,
  120. inet_prefix * ret)
  121. {
  122. ext_rnode *e_rnode;
  123. map_node *rnode = (map_node *) maprnode;
  124. setzero(ret, sizeof(inet_prefix));
  125. if (rnode->flags & MAP_ERNODE) {
  126. e_rnode = (ext_rnode *) rnode;
  127. inet_copy(ret, &e_rnode->quadg.ipstart[0]);
  128. } else
  129. maptoip(mapstart, maprnode, ipstart, ret);
  130. }
  131. const char *
  132. rnode_to_ipstr(u_int mapstart, u_int maprnode, inet_prefix ipstart)
  133. {
  134. inet_prefix ip;
  135. rnodetoip(mapstart, maprnode, ipstart, &ip);
  136. return inet_to_str(ip);
  137. }
  138. /*
  139. * iptogid
  140. *
  141. * ip to gnode id, of the specified `level', conversion function.
  142. * Note: this function cannot fail! So be sure to pass a valid `level'.
  143. */
  144. int
  145. iptogid(inet_prefix * ip, int level)
  146. {
  147. u_char *h_ip = (u_char *) ip->data;
  148. int gid;
  149. /*
  150. * The formula is:
  151. * gid=(ip/MAXGROUPNODE^level) - (ip/MAXGROUPNODE^(level+1) * MAXGROUPNODE);
  152. * but since we have a MAXGROUPNODE equal to 2^8 we can just return
  153. * the `level'-th byte of ip.data.
  154. */
  155. #if BYTE_ORDER == LITTLE_ENDIAN
  156. gid = (int) h_ip[level];
  157. #else
  158. gid = (int) h_ip[GET_LEVELS(ip->family) - level - 1];
  159. #endif
  160. return gid;
  161. }
  162. /*
  163. * iptogids
  164. *
  165. * it fills the `gid' array which has `levels'# members with
  166. * gid[x] = iptogid(`ip', x);
  167. */
  168. void
  169. iptogids(inet_prefix * ip, int *gid, int levels)
  170. {
  171. int i;
  172. for (i = 0; i < levels; i++)
  173. gid[i] = iptogid(ip, i);
  174. }
  175. /*
  176. * gidtoipstart
  177. *
  178. * It sets in `*ip' the ipstart of the gnode using the `gid[x]' for
  179. * each level x.
  180. * `total_levels' is the total number of levels and the `gid' array
  181. * has `total_levels' elements.
  182. * `levels' is the number of array elements considered, gidtoipstart() will use
  183. * only the elements going from gid[total_levels-levels] to gid[total_levels-1].
  184. * `family' is used to fill the inet_prefix of ipstart.
  185. */
  186. void
  187. gidtoipstart(int *gid, u_char total_levels, u_char levels, int family,
  188. inet_prefix * ip)
  189. {
  190. int i, h_ip[MAX_IP_INT];
  191. u_char *ipstart;
  192. setzero(h_ip, MAX_IP_SZ);
  193. ipstart = (u_char *) h_ip;
  194. for (i = total_levels - ZERO_LEVEL; i >= total_levels - levels; i--) {
  195. /* The formula is:
  196. * ipstart += MAXGROUPNODE^i * gid[i];
  197. * but since MAXGROUPNODE is equal to 2^8 we just set each
  198. * single byte of ipstart. */
  199. #if BYTE_ORDER == LITTLE_ENDIAN
  200. ipstart[i] = (u_char) gid[i];
  201. #else
  202. ipstart[GET_LEVELS(family) - i - 1] = (u_char) gid[i];
  203. #endif
  204. }
  205. memcpy(ip->data, h_ip, MAX_IP_SZ);
  206. ip->family = family;
  207. ip->len = (family == AF_INET) ? 4 : 16;
  208. ip->bits = ip->len * 8;
  209. }
  210. /*
  211. * iptoquadg
  212. *
  213. * Using the given `ip' it fills the `qg' quadro_group struct. The `flags'
  214. * given specify what element fill in the struct (the flags are in gmap.h).
  215. */
  216. void
  217. iptoquadg(inet_prefix ip, map_gnode ** ext_map, quadro_group * qg,
  218. char flags)
  219. {
  220. int i;
  221. u_char levels;
  222. int gid[MAX_LEVELS];
  223. setzero(qg, sizeof(quadro_group));
  224. levels = GET_LEVELS(ip.family);
  225. qg->levels = levels;
  226. if (flags & QUADG_GID) {
  227. iptogids(&ip, qg->gid, levels);
  228. memcpy(gid, qg->gid, sizeof(gid));
  229. if (flags & QUADG_IPSTART)
  230. for (i = 0; i < levels; i++)
  231. gidtoipstart(gid, levels, levels - i, ip.family,
  232. &qg->ipstart[i]);
  233. }
  234. if (flags & QUADG_GNODE) {
  235. for (i = 0; i < levels - ZERO_LEVEL; i++)
  236. qg->gnode[i] = gnode_from_pos(qg->gid[i + 1], ext_map[i]);
  237. qg->gnode[levels - ZERO_LEVEL] = &ext_map[i][0];
  238. }
  239. }
  240. void
  241. quadg_setflags(quadro_group * qg, char flags)
  242. {
  243. map_gnode *gnode;
  244. int i;
  245. for (i = 1; i < qg->levels; i++)
  246. if ((gnode = qg->gnode[_EL(i)]))
  247. gnode->g.flags |= flags;
  248. }
  249. void
  250. quadg_free(quadro_group * qg)
  251. {
  252. setzero(qg, sizeof(quadro_group));
  253. }
  254. void
  255. quadg_destroy(quadro_group * qg)
  256. {
  257. quadg_free(qg);
  258. xfree(qg);
  259. }
  260. /*
  261. * gnode_inc_seeds
  262. *
  263. * it increments the seeds counter in the `qg'->gnode[_EL(`level'-1)] gnode,
  264. * setting the appropriate flag if the gnodes is full.
  265. */
  266. void
  267. gnode_inc_seeds(quadro_group * qg, int level)
  268. {
  269. if (level >= qg->levels - 1)
  270. return;
  271. if (qg->gnode[_EL(level + 1)]->seeds == MAXGROUPNODE - 1)
  272. qg->gnode[_EL(level + 1)]->flags |= GMAP_FULL;
  273. else
  274. qg->gnode[_EL(level + 1)]->seeds++;
  275. }
  276. /*
  277. * gnode_dec_seeds
  278. *
  279. * the same of gnode_inc_seeds, but it decrements instead.
  280. */
  281. void
  282. gnode_dec_seeds(quadro_group * qg, int level)
  283. {
  284. if (level >= qg->levels - 1)
  285. return;
  286. if (qg->gnode[_EL(level + 1)]->seeds - 1 >= 0)
  287. qg->gnode[_EL(level + 1)]->seeds--;
  288. qg->gnode[_EL(level + 1)]->flags &= ~GMAP_FULL;
  289. }
  290. /*
  291. * pack_quadro_group
  292. *
  293. * packs the `qg' quadro_group struct and stores it in `pack', which must be
  294. * QUADRO_GROUP_PACK_SZ bytes big. `pack' will be in network order.
  295. */
  296. void
  297. pack_quadro_group(quadro_group * qg, char *pack)
  298. {
  299. char *buf;
  300. int i;
  301. buf = pack;
  302. memcpy(buf, &qg->levels, sizeof(u_char));
  303. buf += sizeof(u_char);
  304. memcpy(buf, qg->gid, sizeof(int) * MAX_LEVELS);
  305. buf += sizeof(int) * MAX_LEVELS;
  306. for (i = 0; i < MAX_LEVELS; i++) {
  307. pack_inet_prefix(&qg->ipstart[i], buf);
  308. buf += INET_PREFIX_PACK_SZ;
  309. }
  310. ints_host_to_network(pack, quadro_group_iinfo);
  311. }
  312. /*
  313. * unpack_quadro_group
  314. *
  315. * restores in `qg' the quadro_group struct contained in `pack'.
  316. * Note that `pack' will be modified during the restoration.
  317. */
  318. void
  319. unpack_quadro_group(quadro_group * qg, char *pack)
  320. {
  321. char *buf;
  322. int i;
  323. buf = pack;
  324. ints_network_to_host(pack, quadro_group_iinfo);
  325. memcpy(&qg->levels, buf, sizeof(u_char));
  326. buf += sizeof(u_char);
  327. memcpy(qg->gid, buf, sizeof(int) * MAX_LEVELS);
  328. buf += sizeof(int) * MAX_LEVELS;
  329. for (i = 0; i < MAX_LEVELS; i++) {
  330. unpack_inet_prefix(&qg->ipstart[i], buf);
  331. buf += INET_PREFIX_PACK_SZ;
  332. }
  333. }
  334. /*
  335. * Functions used by increment_gids(), see below
  336. */
  337. int
  338. is_map_void_flag_set(map_node * node)
  339. {
  340. return node->flags & MAP_VOID;
  341. }
  342. int
  343. is_gmap_full_flag_set(map_gnode * gnode)
  344. {
  345. return gnode->flags & GMAP_FULL;
  346. }
  347. int
  348. is_gmap_void_flag_set(map_gnode * gnode)
  349. {
  350. return gnode->flags & GMAP_VOID;
  351. }
  352. int
  353. isnot_gmap_void_flag_set(map_gnode * gnode)
  354. {
  355. return !is_gmap_void_flag_set(gnode);
  356. }
  357. /*
  358. * increment_gids
  359. *
  360. * It increments the members of the `qg'->gid array until all its
  361. * gids point to gnodes present in the ext_map, which don't have
  362. * a particular gnode->flag or node->flag set.
  363. *
  364. * In order to verify that a gnode doesn't have the flag set the
  365. * `is_gnode_flag_set' function is called, the same is done for the nodes with
  366. * the `is_node_flag_set' function.
  367. * `is_gnode_flag_set' returns 1 if the flag is set.
  368. *
  369. * increment_gids() starts from the qg->gid[`level'] member and finishes to
  370. * qg->gid[qg->levels-1].
  371. * If all the gids point to gnodes, which have the gnode->flag set, -1 is
  372. * returned.
  373. * It's assumed that `ext_map' and `int_map' are the maps relative to the
  374. * `qg' quadro_group.
  375. */
  376. int
  377. increment_gids(quadro_group * qg, int level, map_gnode ** ext_map,
  378. map_node * int_map,
  379. int (*is_gnode_flag_set) (map_gnode * gnode),
  380. int (*is_node_flag_set) (map_node * node))
  381. {
  382. int g, groups, gid, i, e = 0, family;
  383. if (level >= qg->levels)
  384. return -1;
  385. family = qg->ipstart[level].family;
  386. g = level == qg->levels ? 0 : qg->gid[level];
  387. groups = get_groups(qg->levels, level);
  388. gid = qg->gid[level];
  389. if ((!level && !is_node_flag_set(&int_map[gid])) ||
  390. (level && is_gnode_flag_set(&ext_map[_EL(level)][g]))) {
  391. /*
  392. * find a gid in this `level' which isn't full
  393. */
  394. for (i = 0, e = 0; i < groups; i++) {
  395. qg->gid[level] = (gid + i) % groups;
  396. if (is_group_invalid(qg->gid, qg->gid[level], level, family))
  397. continue;
  398. if ((!level && is_node_flag_set(&int_map[qg->gid[level]])) ||
  399. (level
  400. &&
  401. !is_gnode_flag_set(&ext_map[_EL(level)][qg->gid[level]])))
  402. {
  403. e = 1;
  404. break;
  405. }
  406. }
  407. /*
  408. * not a single free gid was found
  409. */
  410. if (!e) {
  411. g = level + 1 == qg->levels ? 0 : qg->gid[level + 1];
  412. if ((is_gmap_full_flag_set == is_gnode_flag_set) &&
  413. !(ext_map[_EL(level + 1)][g].flags & GMAP_FULL)) {
  414. /*
  415. * There is a logical contradiction here:
  416. * we didn't find any free (g)nodes in this
  417. * level, but the upper gnode at level+1,
  418. * which is the parent of this level, isn't
  419. * marked as full! So what's happening here?
  420. * Ignore this absurd and mark it as full -_-
  421. */
  422. ext_map[_EL(level + 1)][g].flags |= GMAP_FULL;
  423. debug(DBG_NORMAL, ERROR_MSG "logical "
  424. "contradiction detected", ERROR_POS);
  425. }
  426. /*
  427. * Recurse by leveling up
  428. */
  429. if (!increment_gids(qg, level + 1, ext_map, int_map,
  430. is_gnode_flag_set, is_node_flag_set))
  431. /*
  432. * We changed one of our upper gid, we can
  433. * retake the old gid we had at this `level'
  434. */
  435. qg->gid[level] = gid;
  436. else
  437. /*
  438. * It's all full!
  439. */
  440. return -1;
  441. }
  442. }
  443. return 0;
  444. }
  445. /*
  446. * free_gids
  447. *
  448. * it uses increment_gids() to choose gids which don't point to FULL gnodes.
  449. */
  450. int
  451. free_gids(quadro_group * qg, int level, map_gnode ** ext_map,
  452. map_node * int_map)
  453. {
  454. return increment_gids(qg, level, ext_map, int_map,
  455. is_gmap_full_flag_set, is_map_void_flag_set);
  456. }
  457. /*
  458. * void_gids
  459. *
  460. * it uses increment_gids() to choose gids which point to VOID gnodes.
  461. */
  462. int
  463. void_gids(quadro_group * qg, int level, map_gnode ** ext_map,
  464. map_node * int_map)
  465. {
  466. return increment_gids(qg, level, ext_map, int_map,
  467. isnot_gmap_void_flag_set, is_map_void_flag_set);
  468. }
  469. /*
  470. * random_ip
  471. *
  472. * It generates a new random ip.
  473. * If `ipstart' is not NULL the new ip is restricted in the `final_gid' of
  474. * `final_level', so it'll be taken inside this range:
  475. * A=ipstart + (MAXGROUPNODE^( final_level + 1)) * final_gid;
  476. * B=ipstart + (MAXGROUPNODE^( final_level + 1)) * (final_gid + 1);
  477. * A <= x <= B
  478. * If `ipstart' is NULL a completely random ip is generated.
  479. * `total_levels' is the maximum number of levels.
  480. * `ext_map' is an external map.
  481. * If `only_free_gnode' is not 0, only the available and empty gnode are chosen.
  482. * In this case -1 may be returned if there aren't any free gnode to choose.
  483. * The new ip is stored in `new_ip' and on success 0 is returned.
  484. */
  485. int
  486. random_ip(inet_prefix * ipstart, int final_level, int final_gid,
  487. int total_levels, map_gnode ** ext_map, int only_free_gnode,
  488. inet_prefix * new_ip, int my_family)
  489. {
  490. int i, e, x, level, levels;
  491. int gid[total_levels];
  492. quadro_group qg;
  493. setzero(new_ip, sizeof(inet_prefix));
  494. if (!ipstart || final_level == total_levels) {
  495. u_int idata[MAX_IP_INT] = { 0, 0, 0, 0 };
  496. for (;;) {
  497. /*
  498. * Let's choose a completely random ip.
  499. */
  500. levels = total_levels;
  501. if (my_family == AF_INET)
  502. idata[0] = rand();
  503. else {
  504. idata[0] = rand();
  505. idata[1] = rand();
  506. idata[2] = rand();
  507. idata[3] = rand();
  508. }
  509. inet_setip(new_ip, idata, my_family);
  510. if (!inet_validate_ip(*new_ip))
  511. break;
  512. }
  513. return 0;
  514. }
  515. /*
  516. * We can choose only a random ip which is inside the final_gid.
  517. * `final_gid' is a gnode of the `final_level' level.
  518. * `final_level' has its `ipstart'; with it we determine
  519. * its higher levels.
  520. * The work is done in this way:
  521. * - ipstart is splitted in gnode_ids and they are placed in qg.gid.
  522. * - The final_level gid is set to `final_gid'.
  523. * - The gids of levels lower than `final_level' are chosen
  524. * randomly.
  525. * - The gids of levels higher than `final_level' are set to the
  526. * gids of qg.gid[x >= final_level].
  527. * - The ipstart is recomposed from the gids.
  528. */
  529. levels = final_level;
  530. iptoquadg(*ipstart, ext_map, &qg, QUADG_GID);
  531. gid[levels] = final_gid;
  532. for (i = final_level + 1; i < total_levels; i++)
  533. gid[i] = qg.gid[i];
  534. /* Change the gids if some of them point to full gnodes */
  535. free_gids(&qg, final_level + 1, ext_map, 0);
  536. /*
  537. * Now we choose random gids for each level so we'll have a random ip
  538. * with gidtoipstart();
  539. */
  540. for (level = levels - 1; level >= 0; level--) {
  541. gid[level] = rand_range(0, MAXGROUPNODE - 1);
  542. if (level && only_free_gnode) {
  543. /*
  544. * We have to be sure that we're not picking a gnode
  545. * already used in the ext_map. Generally when we hook
  546. * we have loaded the old ext_map, so skipping the
  547. * taken gnodes we increase the possibility to create a
  548. * brand new, and not already used, gnode.
  549. */
  550. if (!(ext_map[_EL(level)][gid[level]].flags & GMAP_VOID)) {
  551. /* Take a random position and loop trough the
  552. * map */
  553. i = rand_range(0, MAXGROUPNODE - 1);
  554. for (x = 0, e = i; e < MAXGROUPNODE; e++) {
  555. if (is_group_invalid(gid, e, level, my_family))
  556. continue;
  557. if (ext_map[_EL(level)][e].flags & GMAP_VOID) {
  558. gid[level] = e;
  559. x = 1;
  560. break;
  561. }
  562. }
  563. if (!x) {
  564. for (x = 0; i >= 0; i--) {
  565. if (is_group_invalid(gid, i, level, my_family))
  566. continue;
  567. if (ext_map[_EL(level)][i].flags & GMAP_VOID) {
  568. gid[level] = i;
  569. x = 1;
  570. break;
  571. }
  572. }
  573. }
  574. if (!x)
  575. /* not a single free gnode was found */
  576. return -1;
  577. }
  578. }
  579. }
  580. /*
  581. * Ok, we've set the gids of each level so we recompose them in the
  582. * new_ip.
  583. */
  584. gidtoipstart(gid, total_levels, total_levels, my_family, new_ip);
  585. return 0;
  586. }
  587. /*
  588. * gnodetoip
  589. *
  590. * It converts the gnode which has the given `gnodeid' at `level'
  591. * to its corresponding ipstart. The `quadg' struct must refer to the given
  592. * gnode.
  593. * The ip is stored in `ip', and the ip->bits are choosen carefully in the
  594. * CIDR blocks format, in this way the `ip' includes also the ranges of the
  595. * gnode's level: ip <= x <= ip+MAXGROUPNODE^(level+1).
  596. */
  597. void
  598. gnodetoip(quadro_group * quadg, int gnodeid, u_char level,
  599. inet_prefix * ip)
  600. {
  601. int gid[quadg->levels];
  602. if (level > quadg->levels || !level)
  603. return;
  604. memcpy(gid, quadg->gid, sizeof(int) * quadg->levels);
  605. gid[level] = gnodeid;
  606. gidtoipstart(gid, quadg->levels, quadg->levels - level,
  607. quadg->ipstart[0].family, ip);
  608. ip->bits -= (level * MAXGROUPNODE_BITS);
  609. }
  610. /*
  611. * gids_cmp
  612. *
  613. * compares the two `gids_a' and `gids_b' arrays starting from the
  614. * `lvl'th member to the `max_lvl-1'th. If the gids compared are the same,
  615. * zero is returned.
  616. */
  617. int
  618. gids_cmp(int *gids_a, int *gids_b, int lvl, int max_lvl)
  619. {
  620. int i;
  621. for (i = lvl; i < max_lvl; i++)
  622. if (gids_a[i] != gids_b[i])
  623. return 1;
  624. return 0;
  625. }
  626. /*
  627. * quadg_gids_cmp
  628. *
  629. * compares the gids of `a' and `b' starting from the `lvl'th
  630. * level. If the gids compared are the same, zero is returned.
  631. */
  632. int
  633. quadg_gids_cmp(quadro_group a, quadro_group b, int lvl)
  634. {
  635. if (a.levels != b.levels)
  636. return 1;
  637. return gids_cmp(a.gid, b.gid, lvl, a.levels);
  638. }
  639. /*
  640. * ip_gids_cmp
  641. *
  642. * a wrapper to quadg_gids_cmp() that takes inet_prefixes as argvs.
  643. */
  644. int
  645. ip_gids_cmp(inet_prefix a, inet_prefix b, int lvl)
  646. {
  647. quadro_group qa, qb;
  648. iptoquadg(a, 0, &qa, QUADG_GID);
  649. iptoquadg(b, 0, &qb, QUADG_GID);
  650. return quadg_gids_cmp(qa, qb, lvl);
  651. }
  652. /*
  653. * * * External rnodes functions * * *
  654. */
  655. /* e_rnode_init: Initialize an ext_rnode_cache list and zeros the `counter' */
  656. ext_rnode_cache *
  657. e_rnode_init(u_int * counter)
  658. {
  659. return (ext_rnode_cache *) clist_init(counter);
  660. }
  661. /* e_rnode_free: destroy an ext_rnode_cache list */
  662. void
  663. e_rnode_free(ext_rnode_cache ** erc, u_int * counter)
  664. {
  665. if (counter)
  666. *counter = 0;
  667. if (!*erc)
  668. return;
  669. list_destroy(*erc);
  670. *erc = 0;
  671. }
  672. /*
  673. * e_rnode_add
  674. *
  675. * adds an external node in the ext_rnode_cache list.
  676. */
  677. void
  678. e_rnode_add(ext_rnode_cache ** erc, ext_rnode * e_rnode, int rnode_pos,
  679. u_int * counter)
  680. {
  681. ext_rnode_cache *p;
  682. p = xzalloc(sizeof(ext_rnode_cache));
  683. p->e = e_rnode;
  684. p->rnode_pos = rnode_pos;
  685. clist_add(erc, counter, p);
  686. }
  687. void
  688. e_rnode_del(ext_rnode_cache ** erc_head, u_int * counter,
  689. ext_rnode_cache * erc)
  690. {
  691. if ((*counter) <= 0 || !*erc_head)
  692. return;
  693. if (erc->e) {
  694. xfree(erc->e);
  695. erc->e = 0;
  696. }
  697. clist_del(erc_head, counter, erc);
  698. }
  699. /*
  700. * erc_update_rnodepos
  701. *
  702. * When a rnode is deleted from the root_node all the
  703. * erc->rnode_pos vars must be updated. For example if there's
  704. * an erc->rnode_pos == 5 and the 4th rnode is deleted, than the 5th rnode
  705. * doesn't exist anymore because it is swapped in the 4th position.
  706. * The `old_rnode_pos' holds the deleted rnode position.
  707. * Note: it's assumed that the old rnode has been alread deleted.
  708. */
  709. void
  710. erc_update_rnodepos(ext_rnode_cache * erc, map_node * root_node,
  711. int old_rnode_pos)
  712. {
  713. ext_rnode_cache *p = erc;
  714. if (!erc)
  715. return;
  716. /* If the old rnode was in the last position, it wasn't swapped */
  717. if (old_rnode_pos == root_node->links)
  718. return;
  719. list_for(p) {
  720. if (!p->e)
  721. continue;
  722. /* If the ext_rnode was in the last position, now it is swapped
  723. * in `old_rnode_pos' */
  724. if (p->rnode_pos == root_node->links)
  725. p->rnode_pos = old_rnode_pos;
  726. }
  727. return;
  728. }
  729. /*
  730. * erc_reorder_rnodepos
  731. *
  732. * adjusts the erc->rnode_pos value contained in each ext_rnode_cache struct
  733. * of the `*erc' list. It checks if the rnode of `root_node' at
  734. * the erc->rnode_pos position points to erc->e->node, if not
  735. * it finds the right rnode and it updates the erc->rnode_pos value.
  736. * If an adequate rnode isn't find, the relative erc struct is removed.
  737. */
  738. void
  739. erc_reorder_rnodepos(ext_rnode_cache ** erc, u_int * erc_counter,
  740. map_node * root_node)
  741. {
  742. ext_rnode_cache *p = *erc, *next;
  743. if (!erc || !*erc)
  744. return;
  745. list_safe_for(p, next) {
  746. if (p->rnode_pos >= root_node->links ||
  747. root_node->r_node[p->rnode_pos].r_node !=
  748. (int *) &p->e->node) {
  749. /* Search the right rnode_pos */
  750. p->rnode_pos = rnode_find(root_node, &p->e->node);
  751. if (p->rnode_pos < 0) {
  752. debug(DBG_NOISE,
  753. "erc_reorder_rnodepos: Warning erc 0x%x delete. "
  754. "Something strange is happening", p);
  755. e_rnode_del(erc, erc_counter, p);
  756. }
  757. }
  758. }
  759. }
  760. /*
  761. * erc_find
  762. *
  763. * Searches in the `erc' ext_rnode_cache list a struct which has the
  764. * erc->e == e_rnode and returns it.
  765. */
  766. ext_rnode_cache *
  767. erc_find(ext_rnode_cache * erc, ext_rnode * e_rnode)
  768. {
  769. ext_rnode_cache *p = erc;
  770. if (!erc)
  771. return 0;
  772. list_for(p) {
  773. if (!p->e)
  774. continue;
  775. if (p->e == e_rnode)
  776. return p;
  777. }
  778. return 0;
  779. }
  780. /*
  781. * e_rnode_find
  782. *
  783. * It searches in the `erc' list a quadro_group struct equal to `qg', by
  784. * comparing their gids that goes from gid[`level'] to gid[`qg->levels'].
  785. * If an ext_rnode which has such struct is found it returns the pointer to the
  786. * struct.
  787. * If nothing is found 0 is returned.
  788. */
  789. ext_rnode_cache *
  790. e_rnode_find(ext_rnode_cache * erc, quadro_group * qg, int level)
  791. {
  792. ext_rnode_cache *p = erc;
  793. if (!erc)
  794. return 0;
  795. list_for(p) {
  796. if (!p->e)
  797. continue;
  798. if (!quadg_gids_cmp(p->e->quadg, *qg, level))
  799. return p;
  800. }
  801. return 0;
  802. }
  803. /*
  804. * erc_find_gnode; Returns the first ext_rnode_cache having
  805. * erc->e->quadg.gnode[_EL( `level' )] == `gnode'
  806. */
  807. ext_rnode_cache *
  808. erc_find_gnode(ext_rnode_cache * erc, map_gnode * gnode, u_char level)
  809. {
  810. ext_rnode_cache *p = erc;
  811. if (!erc || !level)
  812. return 0;
  813. list_for(p) {
  814. if (!p->e)
  815. continue;
  816. if (p->e->quadg.gnode[_EL(level)] == gnode)
  817. return p;
  818. }
  819. return 0;
  820. }
  821. /*
  822. * * * External map functions * * *
  823. */
  824. map_gnode *
  825. init_gmap(int groups)
  826. {
  827. map_gnode *gmap;
  828. size_t len;
  829. if (!groups)
  830. groups = MAXGROUPNODE;
  831. len = sizeof(map_gnode) * groups;
  832. gmap = (map_gnode *) xmalloc(len);
  833. setzero(gmap, len);
  834. reset_gmap(gmap, groups);
  835. return gmap;
  836. }
  837. void
  838. reset_gmap(map_gnode * gmap, int groups)
  839. {
  840. int i;
  841. if (!groups)
  842. groups = MAXGROUPNODE;
  843. for (i = 0; i < groups; i++)
  844. gmap_node_del(&gmap[i]);
  845. }
  846. /* init_gmap: Initialize an ext_map with `levels' gmap. Each gmap
  847. * has `groups' elements*/
  848. map_gnode **
  849. init_extmap(u_char levels, int groups)
  850. {
  851. map_gnode **ext_map;
  852. int i;
  853. if (!levels)
  854. levels = MAX_LEVELS;
  855. if (!groups)
  856. groups = MAXGROUPNODE;
  857. ext_map = (map_gnode **) xmalloc(sizeof(map_gnode *) * (levels));
  858. levels--; /*We strip off the Zero level */
  859. for (i = 0; i < levels; i++)
  860. ext_map[i] = init_gmap(groups);
  861. /*Ok, now we stealthy add the unity_level which has only one gmap. */
  862. ext_map[levels] = init_gmap(1);
  863. return ext_map;
  864. }
  865. /* free_extmap: Destroy the ext_map*/
  866. void
  867. free_extmap(map_gnode ** ext_map, u_char levels, int groups)
  868. {
  869. int e;
  870. if (!levels)
  871. levels = MAX_LEVELS;
  872. if (!groups)
  873. groups = MAXGROUPNODE;
  874. levels--;
  875. for (e = 0; e < levels; e++) {
  876. reset_gmap(ext_map[e], groups);
  877. xfree(ext_map[e]);
  878. }
  879. /*Free the unity_level map */
  880. reset_gmap(ext_map[levels], 1);
  881. xfree(ext_map[levels]);
  882. xfree(ext_map);
  883. }
  884. void
  885. reset_extmap(map_gnode ** ext_map, u_char levels, int groups)
  886. {
  887. int i;
  888. for (i = 1; i < levels; i++)
  889. reset_gmap(ext_map[_EL(i)], groups);
  890. gmap_node_del(&ext_map[_EL(levels)][0]);
  891. }
  892. /* g_rnode_find: It searches in `gnode'.g a rnode which points to the gnode `n'.
  893. * It then returns the position of that rnode.
  894. * If the rnode is not found it returns -1;*/
  895. int
  896. g_rnode_find(map_gnode * gnode, map_gnode * n)
  897. {
  898. return rnode_find(&gnode->g, (map_node *) n);
  899. }
  900. /* extmap_find_level: It returns the position of the gnode map which contains
  901. * the 'gnode`. This position corresponds to the level of that gmap.
  902. * The ext_map is given in `ext_map`. `max_level' is the maximum number of level
  903. * present in the `ext_map'.
  904. * ex: if gnode is in ext_map[i] it will return i;
  905. * On failure -1 is returned.*/
  906. int
  907. extmap_find_level(map_gnode ** ext_map, map_gnode * gnode,
  908. u_char max_level)
  909. {
  910. uintptr_t i, a, b, c;
  911. for (i = 1; i < max_level; i++) {
  912. a = (uintptr_t) gnode;
  913. b = (uintptr_t) &ext_map[_EL(i)][0];
  914. c = (uintptr_t) &ext_map[_EL(i)][MAXGROUPNODE - 1];
  915. if (a >= b && a <= c)
  916. return i;
  917. }
  918. return -1;
  919. }
  920. /* gmap_node_del: It deletes a `gnode' from the `gmap'. Really it sets the
  921. * gnode's flags to GMAP_VOID.*/
  922. void
  923. gmap_node_del(map_gnode * gnode)
  924. {
  925. map_node_del(&gnode->g);
  926. setzero(gnode, sizeof(map_gnode));
  927. gnode->flags |= GMAP_VOID;
  928. gnode->g.flags |= MAP_VOID;
  929. }
  930. /*
  931. * merge_lvl_ext_maps
  932. *
  933. * merges two ext_maps of a specific `level'. It is used by merge_ext_maps(),
  934. * see below.
  935. * This function is the exact replica of merge_maps() in map.c, that's why it
  936. * isn't commented.
  937. */
  938. int
  939. merge_lvl_ext_maps(map_gnode * base, map_gnode * new,
  940. quadro_group base_root, quadro_group new_root,
  941. int level)
  942. {
  943. map_gnode *gnode_gw, *new_root_in_base;
  944. int base_root_pos, ngpos;
  945. u_int base_trtt, new_trtt;
  946. int i, e, x;
  947. new_root_in_base = &base[new_root.gid[level]];
  948. base_root_pos = base_root.gid[level];
  949. for (i = 0; i < MAXGROUPNODE; i++) {
  950. if (base[i].g.flags & MAP_ME || new[i].g.flags & MAP_ME ||
  951. new[i].g.flags & MAP_VOID || base[i].flags & GMAP_ME ||
  952. new[i].flags & GMAP_ME || new[i].flags & GMAP_VOID)
  953. continue;
  954. for (e = 0; e < new[i].g.links; e++) {
  955. gnode_gw = (map_gnode *) new[i].g.r_node[e].r_node;
  956. ngpos = pos_from_gnode(gnode_gw, new);
  957. if (ngpos == base_root_pos)
  958. continue;
  959. if (new[i].g.flags & MAP_RNODE)
  960. new[i].g.r_node[e].r_node = (int *) new_root_in_base;
  961. else if (base[ngpos].g.flags & MAP_VOID ||
  962. base[ngpos].flags & GMAP_VOID || !base[ngpos].g.links)
  963. new[i].g.r_node[e].r_node = (int *) new_root_in_base;
  964. else
  965. new[i].g.r_node[e].r_node = base[ngpos].g.r_node[0].r_node;
  966. if (e >= base[i].g.links) {
  967. rnode_add(&base[i].g, &new[i].g.r_node[e]);
  968. rnode_trtt_order(&base[i].g);
  969. base[i].g.flags |= MAP_UPDATE;
  970. continue;
  971. }
  972. base_trtt = get_route_trtt(&base[i].g, base[i].g.links - 1);
  973. new_trtt = get_route_trtt(&new[i].g, e);
  974. if (base_trtt < new_trtt)
  975. continue;
  976. for (x = 0; x < base[i].g.links; x++) {
  977. base_trtt = get_route_trtt(&base[i].g, x);
  978. new_trtt = get_route_trtt(&new[i].g, e);
  979. if (base_trtt > new_trtt) {
  980. map_rnode_insert(&base[i].g, x, &new[i].g.r_node[e]);
  981. base[i].g.flags |= MAP_UPDATE;
  982. break;
  983. }
  984. }
  985. }
  986. if (base[i].g.links) {
  987. base[i].g.flags &= ~MAP_VOID;
  988. base[i].flags &= ~GMAP_VOID;
  989. } else
  990. gmap_node_del(&base[i]);
  991. }
  992. return 0;
  993. }
  994. /*
  995. * merge_ext_maps
  996. *
  997. * it fuses the `base' and `new' ext_maps generating a single
  998. * ext_map which has the best routes. The generated map is stored in `base'
  999. * `base_root' is the quadro_group related to `base'.
  1000. * `new_root' is the quadro_group of the `new' ext_map.
  1001. * On error -1 is returned.
  1002. */
  1003. int
  1004. merge_ext_maps(map_gnode ** base, map_gnode ** new, quadro_group base_root,
  1005. quadro_group new_root)
  1006. {
  1007. int level, i;
  1008. for (level = base_root.levels - 1; level >= 0; level--) {
  1009. /*
  1010. if (base_root.gid[level] != base_root.gid[level])
  1011. break;
  1012. */
  1013. if (level == 1)
  1014. /* The two maps are of the same quadro_group */
  1015. return -1;
  1016. }
  1017. for (i = level; i < base_root.levels; i++)
  1018. merge_lvl_ext_maps(base[_EL(i)], new[_EL(i)], base_root,
  1019. new_root, i);
  1020. return 0;
  1021. }
  1022. /*
  1023. * gmap_get_rblock
  1024. *
  1025. * It uses get_rnode_block to pack all the ext_map's rnodes
  1026. * `maxgroupnode' is the number of nodes present in the map.
  1027. * It returns a pointer to the start of the rnode block and stores in "count"
  1028. * the number of rnode structs packed.
  1029. */
  1030. map_rnode *
  1031. gmap_get_rblock(map_gnode * map, int maxgroupnode, int *count)
  1032. {
  1033. int i, c = 0, tot = 0;
  1034. map_rnode *rblock;
  1035. *count = 0;
  1036. for (i = 0; i < maxgroupnode; i++)
  1037. tot += map[i].g.links;
  1038. if (!tot)
  1039. return 0;
  1040. rblock = (map_rnode *) xmalloc(sizeof(map_rnode) * tot);
  1041. for (i = 0; i < maxgroupnode; i++)
  1042. c += get_rnode_block((int *) map, &map[i].g, rblock, c);
  1043. *count = c;
  1044. return rblock;
  1045. }
  1046. /* gmap_store_rblock: Given a correct ext_map with `maxgroupnode' elements it
  1047. * restores all the r_node structs in the map from the rnode_block using
  1048. * store_rnode_block.*/
  1049. int
  1050. gmap_store_rblock(map_gnode * gmap, int maxgroupnode, map_rnode * rblock)
  1051. {
  1052. int i, c = 0;
  1053. for (i = 0; i < maxgroupnode; i++)
  1054. c += store_rnode_block((int *) gmap, &gmap[i].g, rblock, c);
  1055. return c;
  1056. }
  1057. /*
  1058. * extmap_get_rblock
  1059. *
  1060. * It packs the rnode_block for each map present in the `ext_map'.
  1061. * There are a total of `levels' maps in the ext_map. Each map has
  1062. * `maxgroupnodes' nodes. In `*ret_count' is stored an array of map's rnodes
  1063. * count, so each element of the array represents the number of rnodes in the
  1064. * rblock of the relative map.
  1065. * It returns an array of rblock's pointer. Each array's element points to the
  1066. * rblock for the map in that level.
  1067. * Ex: ret_count[n] is the number of rnodes placed in rblock[n], and n is also
  1068. * the level of the map which has those rnodes. I hope I was clear ^_-
  1069. * PS: You'll have to xfree ret_count, rblock[0-levels], and rblock;
  1070. */
  1071. map_rnode **
  1072. extmap_get_rblock(map_gnode ** ext_map, u_char levels, int maxgroupnodes,
  1073. int **ret_count)
  1074. {
  1075. int i;
  1076. map_rnode **rblock;
  1077. int *count;
  1078. if (!levels)
  1079. return 0;
  1080. rblock = xmalloc(sizeof(map_rnode *) * levels);
  1081. count = xmalloc(sizeof(int) * levels);
  1082. for (i = 0; i < levels; i++)
  1083. rblock[i] = gmap_get_rblock(ext_map[i], maxgroupnodes, &count[i]);
  1084. *ret_count = count;
  1085. return rblock;
  1086. }
  1087. /* extmap_store_rblock: It [re]stores all the rnodes in all the maps of the `ext_map'.
  1088. * The maps have `maxgroupnode' nodes, while the `ext_map' has `levels' levels.
  1089. * The rnodes are taken from the `rblock'.
  1090. * The number of map restored is returned and it shall be equal to the number of `levels'.
  1091. */
  1092. int
  1093. extmap_store_rblock(map_gnode ** ext_map, u_char levels, int maxgroupnode,
  1094. map_rnode * rblock, size_t * rblock_sz)
  1095. {
  1096. int i;
  1097. for (i = 0; i < levels; i++) {
  1098. if (rblock_sz[i])
  1099. gmap_store_rblock(ext_map[i], maxgroupnode, rblock);
  1100. rblock = (map_rnode *) ((char *) rblock + rblock_sz[i]);
  1101. }
  1102. return i;
  1103. }
  1104. /*
  1105. * verify_ext_map_hdr
  1106. *
  1107. * It verifies the validity of an ext_map_hdr.
  1108. * `quadg' is the unpacked emap_hdr->quadg quadro_group.
  1109. */
  1110. int
  1111. verify_ext_map_hdr(struct ext_map_hdr *emap_hdr, quadro_group * quadg)
  1112. {
  1113. u_char levels;
  1114. int maxgroupnode, i;
  1115. levels = quadg->levels - UNITY_LEVEL;
  1116. maxgroupnode = emap_hdr->ext_map_sz / (MAP_GNODE_PACK_SZ * levels);
  1117. if (levels > MAX_LEVELS || maxgroupnode > MAXGROUPNODE ||
  1118. emap_hdr->total_rblock_sz > MAXRNODEBLOCK_PACK_SZ * levels ||
  1119. emap_hdr->ext_map_sz > maxgroupnode * MAP_GNODE_PACK_SZ * levels)
  1120. return 1;
  1121. for (i = 0; i < levels; i++)
  1122. if (quadg->gid[i] > maxgroupnode)
  1123. return 1;
  1124. return 0;
  1125. }
  1126. void
  1127. free_extmap_rblock(map_rnode ** rblock, u_char levels)
  1128. {
  1129. int i;
  1130. for (i = 0; i < levels; i++)
  1131. if (rblock[i])
  1132. xfree(rblock[i]);
  1133. xfree(rblock);
  1134. }
  1135. /*
  1136. * pack_map_gnode
  1137. *
  1138. * packs the `qg' map_gnode struct and stores it in
  1139. * `pack', which must be MAP_GNODE_PACK_SZ bytes big. `pack' will be in
  1140. * network order.
  1141. */
  1142. void
  1143. pack_map_gnode(map_gnode * gnode, char *pack)
  1144. {
  1145. char *buf;
  1146. buf = pack;
  1147. pack_map_node(&gnode->g, buf);
  1148. buf += MAP_NODE_PACK_SZ;
  1149. memcpy(buf, &gnode->flags, sizeof(char));
  1150. buf += sizeof(char);
  1151. memcpy(buf, &gnode->seeds, sizeof(char));
  1152. buf += sizeof(char);
  1153. memcpy(buf, &gnode->gcount, sizeof(u_int));
  1154. buf += sizeof(u_int);
  1155. ints_host_to_network(pack, map_gnode_iinfo);
  1156. }
  1157. /*
  1158. * unpack_map_gnode
  1159. *
  1160. * restores in `qg' the map_gnode struct contained in `pack'.
  1161. * Note that `pack' will be modified during the restoration.
  1162. */
  1163. void
  1164. unpack_map_gnode(map_gnode * gnode, char *pack)
  1165. {
  1166. char *buf;
  1167. buf = pack;
  1168. ints_network_to_host(pack, map_gnode_iinfo);
  1169. unpack_map_node(&gnode->g, buf);
  1170. buf += MAP_NODE_PACK_SZ;
  1171. memcpy(&gnode->flags, buf, sizeof(char));
  1172. buf += sizeof(char);
  1173. memcpy(&gnode->seeds, buf, sizeof(char));
  1174. buf += sizeof(char);
  1175. memcpy(&gnode->gcount, buf, sizeof(u_int));
  1176. buf += sizeof(u_int);
  1177. }
  1178. /*
  1179. * pack_extmap
  1180. *
  1181. * It returns the packed `ext_map', ready to be saved or sent. It stores
  1182. * in `pack_sz' the size of the package. Each gmaps, present in the `ext_map', has
  1183. * `maxgroupnode' nodes. `quadg' must be a valid quadro_group struct filled with
  1184. * valid values.
  1185. */
  1186. char *
  1187. pack_extmap(map_gnode ** ext_map, int maxgroupnode, quadro_group * quadg,
  1188. size_t * pack_sz)
  1189. {
  1190. struct ext_map_hdr emap_hdr;
  1191. map_rnode **rblock;
  1192. int *count, i, e;
  1193. char *package, *p = 0;
  1194. u_char levels = quadg->levels - UNITY_LEVEL;
  1195. /*Packing the rblocks */
  1196. rblock = extmap_get_rblock(ext_map, levels, maxgroupnode, &count);
  1197. /*Building the hdr... */
  1198. setzero(&emap_hdr, sizeof(struct ext_map_hdr));
  1199. emap_hdr.ext_map_sz = maxgroupnode * MAP_GNODE_PACK_SZ * levels;
  1200. for (i = 0; i < levels; i++) {
  1201. emap_hdr.rblock_sz[i] = count[i] * MAP_RNODE_PACK_SZ;
  1202. emap_hdr.total_rblock_sz += emap_hdr.rblock_sz[i];
  1203. }
  1204. pack_quadro_group(quadg, emap_hdr.quadg);
  1205. /*Let's fuse all in one */
  1206. *pack_sz =
  1207. EXT_MAP_BLOCK_SZ(emap_hdr.ext_map_sz, emap_hdr.total_rblock_sz);
  1208. package = xmalloc(*pack_sz);
  1209. memcpy(package, &emap_hdr, sizeof(struct ext_map_hdr));
  1210. ints_host_to_network(package, ext_map_hdr_iinfo);
  1211. p = package + sizeof(struct ext_map_hdr);
  1212. for (i = 0; i < levels; i++) {
  1213. for (e = 0; e < maxgroupnode; e++) {
  1214. pack_map_gnode(&ext_map[i][e], p);
  1215. p += MAP_GNODE_PACK_SZ;
  1216. }
  1217. }
  1218. /* If the rblock is not null copy it in the `package' */
  1219. if (rblock) {
  1220. for (i = 0; i < levels; i++) {
  1221. if (!emap_hdr.rblock_sz[i])
  1222. continue;
  1223. memcpy(p, rblock[i], emap_hdr.rblock_sz[i]);
  1224. p += emap_hdr.rblock_sz[i];
  1225. }
  1226. free_extmap_rblock(rblock, levels);
  1227. }
  1228. xfree(count);
  1229. return package;
  1230. }
  1231. /*
  1232. * unpack_extmap
  1233. *
  1234. * Given a valid ext_map package (packed with pack_extmap), it
  1235. * allocates a brand new ext_map and restores in it the gmaps and the rnodes.
  1236. * In `quadg' is stored the quadro_group referring to this ext_map.
  1237. * On success the a pointer to the new ext_map is retuned, otherwise 0 will be
  1238. * the fatal value.
  1239. * Note: `package' will be modified during the unpacking.
  1240. */
  1241. map_gnode **
  1242. unpack_extmap(char *package, quadro_group * quadg)
  1243. {
  1244. map_gnode **ext_map;
  1245. struct ext_map_hdr *emap_hdr = (struct ext_map_hdr *) package;
  1246. map_rnode *rblock;
  1247. u_char levels;
  1248. int err, i, e, maxgroupnode;
  1249. char *p;
  1250. ints_network_to_host(emap_hdr, ext_map_hdr_iinfo);
  1251. unpack_quadro_group(quadg, emap_hdr->quadg);
  1252. levels = quadg->levels - UNITY_LEVEL;
  1253. maxgroupnode = emap_hdr->ext_map_sz / (MAP_GNODE_PACK_SZ * levels);
  1254. if (verify_ext_map_hdr(emap_hdr, quadg)) {
  1255. error("Malformed ext_map_hdr. Aborting unpack_map().");
  1256. return 0;
  1257. }
  1258. /*Unpacking the ext_map */
  1259. p = package + sizeof(struct ext_map_hdr);
  1260. ext_map = init_extmap(quadg->levels, maxgroupnode);
  1261. for (i = 0; i < levels; i++) {
  1262. for (e = 0; e < maxgroupnode; e++) {
  1263. unpack_map_gnode(&ext_map[i][e], p);
  1264. p += MAP_GNODE_PACK_SZ;
  1265. }
  1266. }
  1267. /*Let's store in it the lost rnodes. */
  1268. if (emap_hdr->total_rblock_sz) {
  1269. rblock = (map_rnode *) p;
  1270. err = extmap_store_rblock(ext_map, levels, maxgroupnode, rblock,
  1271. emap_hdr->rblock_sz);
  1272. if (err != levels) {
  1273. error("unpack_extmap(): It was not possible to restore"
  1274. " all the rnodes in the ext_map");
  1275. free_extmap(ext_map, quadg->levels, maxgroupnode);
  1276. return 0;
  1277. }
  1278. }
  1279. /* We restore the quadro_group struct */
  1280. for (i = 0; i < levels; i++)
  1281. quadg->gnode[i] = gnode_from_pos(quadg->gid[i + 1], ext_map[i]);
  1282. return ext_map;
  1283. }
  1284. /* * * save/load ext_map * * */
  1285. int
  1286. save_extmap(map_gnode ** ext_map, int maxgroupnode, quadro_group * quadg,
  1287. char *file)
  1288. {
  1289. FILE *fd;
  1290. size_t pack_sz;
  1291. char *pack;
  1292. /*Pack! */
  1293. pack = pack_extmap(ext_map, maxgroupnode, quadg, &pack_sz);
  1294. if (!pack || !pack_sz)
  1295. return 0;
  1296. if ((fd = fopen(file, "w")) == NULL) {
  1297. error("Cannot save the map in %s: %s", file, strerror(errno));
  1298. return -1;
  1299. }
  1300. /*Write! */
  1301. fwrite(pack, pack_sz, 1, fd);
  1302. xfree(pack);
  1303. fclose(fd);
  1304. return 0;
  1305. }
  1306. map_gnode **
  1307. load_extmap(char *file, quadro_group * quadg)
  1308. {
  1309. map_gnode **ext_map;
  1310. FILE *fd;
  1311. struct ext_map_hdr emap_hdr;
  1312. size_t pack_sz;
  1313. char *pack;
  1314. if ((fd = fopen(file, "r")) == NULL) {
  1315. error("Cannot load the map from %s: %s", file, strerror(errno));
  1316. return 0;
  1317. }
  1318. if (!fread(&emap_hdr, sizeof(struct ext_map_hdr), 1, fd))
  1319. goto error;
  1320. ints_network_to_host(&emap_hdr, ext_map_hdr_iinfo);
  1321. unpack_quadro_group(quadg, emap_hdr.quadg);
  1322. if (verify_ext_map_hdr(&emap_hdr, quadg))
  1323. goto error;
  1324. rewind(fd);
  1325. pack_sz =
  1326. EXT_MAP_BLOCK_SZ(emap_hdr.ext_map_sz, emap_hdr.total_rblock_sz);
  1327. pack = xmalloc(pack_sz);
  1328. if (!fread(pack, pack_sz, 1, fd))
  1329. goto error;
  1330. ext_map = unpack_extmap(pack, quadg);
  1331. if (!ext_map)
  1332. error("Cannot unpack the ext_map!");
  1333. xfree(pack);
  1334. fclose(fd);
  1335. return ext_map;
  1336. error:
  1337. fclose(fd);
  1338. error("Malformed ext_map file. Aborting load_extmap().");
  1339. return 0;
  1340. }