/* This file is part of Netsukuku * (c) Copyright 2005 Andrea Lo Pumo aka AlpT * * This source code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * Please refer to the GNU Public License for more details. * * You should have received a copy of the GNU Public License along with * this source code; if not, write to: * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * -- * bmap.c: * Border node map code. */ #include "includes.h" #include "common.h" #include "inet.h" #include "endianness.h" #include "map.h" #include "gmap.h" #include "bmap.h" void bmap_levels_init(u_char levels, map_bnode ***bmap, u_int **bmap_nodes) { *bmap=xmalloc(sizeof(map_bnode *) * levels); *bmap_nodes=(u_int *)xmalloc(sizeof(u_int) * levels); setzero(*bmap, sizeof(map_bnode *) * levels); bmap_counter_reset(levels, *bmap_nodes); } void bmap_levels_free(map_bnode **bmap, u_int *bmap_nodes) { xfree(bmap); xfree(bmap_nodes); } void bmap_counter_init(u_char levels, u_int **bnodes_closed, u_int **bnodes_opened) { *bnodes_closed=(u_int *)xmalloc(sizeof(u_int) * levels); *bnodes_opened=(u_int *)xmalloc(sizeof(u_int) * levels); bmap_counter_reset(levels, *bnodes_closed); bmap_counter_reset(levels, *bnodes_opened); } void bmap_counter_free(u_int *bnodes_closed, u_int *bnodes_opened) { xfree(bnodes_closed); xfree(bnodes_opened); } void bmap_counter_reset(u_char levels, u_int *counter) { setzero(counter, sizeof(u_int) * levels); } /* * map_add_bnode: It adds a new bnode in the `bmap' and then returns its position * in the bmap. It also increments the `*bmap_nodes' counter. The bnode_ptr is set * to `bnode' and the links to `links'. * Note that the `bmap' argument must be an adress of a pointer. */ int map_add_bnode(map_bnode **bmap, u_int *bmap_nodes, u_int bnode, u_int links) { map_bnode *bnode_map; u_int bm; bm=*bmap_nodes; (*bmap_nodes)++; if(!bm) *bmap=xmalloc(sizeof(map_bnode)); else *bmap=xrealloc(*bmap, sizeof(map_bnode) * *bmap_nodes); bnode_map=*bmap; setzero(bnode_map, sizeof(map_bnode)); bnode_map[bm].bnode_ptr=bnode; bnode_map[bm].links=links; return bm; } /* * map_bnode_del: It deletes the `bnode' in the `bmap' which has `bmap_nodes'. * It returns the newly rescaled `bmap'. * It returns 0 if the `bmap' doesn't exist anymore.*/ map_bnode *map_bnode_del(map_bnode *bmap, u_int *bmap_nodes, map_bnode *bnode) { map_node_del((map_node *)bnode); if( ((char *)bnode-(char *)bmap)/sizeof(map_bnode) != (*bmap_nodes)-1 ) memcpy(bnode, &bmap[*bmap_nodes-1], sizeof(map_bnode)); (*bmap_nodes)--; if(*bmap_nodes) return xrealloc(bmap, (*bmap_nodes) * sizeof(map_bnode)); else { *bmap_nodes=0; xfree(bmap); return 0; } } /* * bmap_del_rnode_by_level: it is pretty specific, it deletes all the rnodes * of `bnode' which point to a gnode located in a level not equal to `level'. * The number of rnode deleted is returned. * `total_levels' must be equal to the maximum levels * available (use FAMILY_LVLS). */ int bmap_del_rnode_by_level(map_bnode *bnode, int level, map_gnode **ext_map, int total_levels) { map_gnode *gn; int i, ret=0, lvl; for(i=0; i < bnode->links; i++) { gn=(map_gnode *)bnode->r_node[i].r_node; lvl=extmap_find_level(ext_map, gn, total_levels); if(lvl != level) { rnode_del(bnode, i); ret++; } } return ret; } /* * map_find_bnode: Find the given `node' (in the pos_from_node() format) in the * given map_bnode `bmap'. */ int map_find_bnode(map_bnode *bmap, int bmap_nodes, int node) { int e; for(e=0; elevels; pack_sz=bmaps_hdr->bmaps_block_sz; if(levels > max_levels || pack_sz < sizeof(struct bnode_maps_hdr)) return 0; bmap_levels_init(levels, &bmap, bmap_nodes); buf=pack+sizeof(struct bnode_maps_hdr); for(i=0; ibnode_map_sz) { buf+=sizeof(struct bnode_map_hdr); continue; } /*Extracting the map...*/ bblock=(char *)bmap_hdr; unpacked_bmap=unpack_map(bblock, (int *)ext_map[_EL(i+1)], 0, maxbnodes, maxbnode_rnodeblock); if(!unpacked_bmap) { error("Cannot unpack the bnode_map at level %d ! Skipping...", i); e++; continue; } (*bmap_nodes)[i]=bmap_hdr->bnode_map_sz/MAP_BNODE_PACK_SZ; bblock_sz=INT_MAP_BLOCK_SZ(bmap_hdr->bnode_map_sz, bmap_hdr->rblock_sz); bmap[i]=unpacked_bmap; buf+=bblock_sz; } if(e == levels) /* Not a single map was restored */ return 0; return bmap; } /* * * save/load bnode_map * * */ /* * save_bmap: It saves the bnode maps `bmaps' in `file'. The each `bmaps[x]' has * `bmap_nodes[x]' nodes. `ext_map' is the pointer to the external map the bmap is * referring to. */ int save_bmap(map_bnode **bmaps, u_int *bmap_nodes, map_gnode **ext_map, quadro_group quadg, char *file) { FILE *fd; char *pack; size_t pack_sz; pack=pack_all_bmaps(bmaps, bmap_nodes, ext_map, quadg, &pack_sz); if(!pack_sz || !pack) return 0; if((fd=fopen(file, "w"))==NULL) { error("Cannot save the bnode_map in %s: %s", file, strerror(errno)); return -1; } fwrite(pack, pack_sz, 1, fd); xfree(pack); fclose(fd); return 0; } /* * load_bmap: It loads all the bnode maps from `file' and returns the address * of the array of pointer to the loaded bmaps. `ext_map' is the external maps * the bmap shall refer to. In `bmap_nodes' the address of the u_int array, used * to count the nodes in each bmaps, is stored. On error 0 is returned. */ map_bnode **load_bmap(char *file, map_gnode **ext_map, u_char max_levels, u_int **bmap_nodes) { map_bnode **bmap=0; FILE *fd; struct bnode_maps_hdr bmaps_hdr; size_t pack_sz; u_char levels; char *pack=0; if((fd=fopen(file, "r"))==NULL) { error("Cannot load the bmap from %s: %s", file, strerror(errno)); return 0; } if(!fread(&bmaps_hdr, sizeof(struct bnode_maps_hdr), 1, fd)) goto finish; ints_network_to_host(&bmaps_hdr, bnode_maps_hdr_iinfo); levels=bmaps_hdr.levels; pack_sz=bmaps_hdr.bmaps_block_sz; if(levels > max_levels || pack_sz < sizeof(struct bnode_maps_hdr)) goto finish; /* Extracting the map... */ rewind(fd); pack=xmalloc(pack_sz); if(!fread(pack, pack_sz, 1, fd)) goto finish; bmap=unpack_all_bmaps(pack, max_levels, ext_map, bmap_nodes, MAXGROUPNODE, MAXBNODE_RNODEBLOCK); finish: fclose(fd); if(pack) xfree(pack); if(!bmap) error("Malformed bmap file. Cannot load the bnode maps."); return bmap; }