## modules/rx/rx_node.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following functions.

1. rx_creat_node
2. rx_delete_node
3. rx_bin_node
4. RX_rt_node
5. RX_in_node

       1 /***************************************
       2   $Revision: 1.35 $
       3
       4   Radix tree (rx).  rx_node.c - functions to operate on nodes of the tree
       5   (creation/deletion).
       6
       7   Status: NOT REVUED, TESTED, INCOMPLETE
       8
       9   Design and implementation by: Marek Bukowy
      10
      11   ******************/ /******************
      12   Copyright (c) 1999,2000,2001,2002               RIPE NCC
      13
      14   All Rights Reserved
      15
      16   Permission to use, copy, modify, and distribute this software and its
      17   documentation for any purpose and without fee is hereby granted,
      18   provided that the above copyright notice appear in all copies and that
      19   both that copyright notice and this permission notice appear in
      20   supporting documentation, and that the name of the author not be
      21   used in advertising or publicity pertaining to distribution of the
      22   software without specific, written prior permission.
      23
      24   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      25   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      26   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      27   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      28   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      29   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      30   ***************************************/
      31
      32 #include "rip.h"
      33 #include <glib.h>
      34
      35
      36 /***************************************************************************/
      37 /*++++++++++++++++
      38   rx_creat_node = create a new data node
      39   (empty{glue} nodes get created automatically).
      40
      41   Takes a pointer to the (already allocated) data leaf to be included
      42   in the list of data nodes (presumably empty as the node is only now being
      43   created).
      44
      45   Requires a stack of nodes created in CREAT mode (with glue nodes,
      46   until deep enough and the last node being non-glue).
      47
      48   MT notes: requires the tree to be locked.
      49
      50   Returns: RX_OK or error code.
      51
      52   +++++++++++++++++*/
      53 static
      54 er_ret_t
      55 rx_creat_node (
         /* [<][>][^][v][top][bottom][index][help] */
      56                ip_prefix_t   *newpref,  /*+ prefix of the node to be added +*/
      57                rx_tree_t     *tree,     /*+ tree the new node goes to +*/
      58                rx_dataleaf_t *dataleaf, /*+ dataleaf to attach at this node+*/
      59                rx_nodcpy_t   stack[],   /*+ stack==array of node_copies +*/
      60                int           stackdepth /*+ length of the stack +*/
      61              )
      62 {
      63   rx_node_t *newnode, *curnode, *memnode, *gluenode;
      64   unsigned chk_bit, dif_bit, link, curpos;
      65   char buf[1024];
      66
      67   /* assume no such node yet. Will die if there is one.*/
      68
      69   /* calloc, because parent/child keys and child ptrs are not always set.*/
      70
      71   newnode = (rx_node_t *)UT_calloc(1, sizeof(rx_node_t));
      72
      73   /* increment the number of nodes in the tree*/
      74   tree -> num_nodes ++;
      75
      76   newnode -> prefix = *newpref;
      77
      78   /* attach the leaf to a (presumably empty?! hence NULL) list...*/
      79   newnode->leaves_ptr = g_list_prepend(NULL, dataleaf);
      80   newnode->glue = 0;
      81
      82   /* OK, so take a look at the tree*/
      83
      84   if ( tree -> num_nodes == 1 ) {
      85     /* The tree was empty. Create a new top node.*/
      86
      87     tree -> top_ptr = newnode;
      88     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Created as the top node");
      89     return RX_OK;
      90   }
      91
      92   /* OK, there is at least one node in the tree. Take a look at the stack.*/
      93
      94   /*    we've got a real node there (not a glue), but we may be too deep.*/
      95   /*   (it's not a glue, because glues have always two children.*/
      96   /*    we had to go that deep because from a glue alone one doesn't know */
      97   /*    what it glues)*/
      98   /* GO UP.*/
      99   /* take the first differing bit from comparing */
     100   /* the new and the found nodes' prefixes. */
     101   /* (not deeper than the shorter of the two)*/
     102
     103   curpos =   stackdepth-1;
     104   curnode =  & stack[curpos].cpy;
     105
     106   chk_bit = smaller(curnode->prefix.bits, newpref->bits );
     107
     108   for(dif_bit = 0; dif_bit < chk_bit; dif_bit++) {
     109     /* break the loop when the first different bit is found*/
     110
     111     if( IP_addr_bit_get( & curnode->prefix.ip, dif_bit)
     112         !=  IP_addr_bit_get( & newpref->ip, dif_bit) ) {
     113       break;
     114     }
     115   }
     116
     117   ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET,
     118             "cur = %d, new = %d, chk_bit = %d, dif_bit = %d",
     119             curnode->prefix.bits, newpref->bits, chk_bit, dif_bit );
     120
     121   if(dif_bit == IP_sizebits(newpref->ip.space)) die; /* it mustn't happen!!!*/
     122
     123   /* go up to that level (watch the head of the tree!)*/
     124
     125   while( curpos > 0 && stack[curpos-1].cpy.prefix.bits >= dif_bit) {
     126     curpos--;
     127     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET,
     128               "up to level %d", curpos );
     129   }
     130
     131   /*
     132     if the bit lenghts of the node, new prefix and the diffbit are equal
     133     {
     134     YOU'VE GOT THE NODE where the new one will be attached.
     135     Either it has data (and will be moved accordingly),
     136     or is a glue (and will be turned into a regular node).
     137     }
     138   */
     139
     140   curnode =  & stack[curpos].cpy;
     141
     142   /* RAM: set a pointer to the real node in memory*/
     143   memnode = stack[curpos].srcptr;
     144
     145   if(    dif_bit == newpref->bits
     146          && dif_bit == curnode->prefix.bits ) {
     147
     148     /* such node already exists, nothing to change in the tree!!!*/
     149     /* this should be checked before calling this function, so..*/
     150
     151     die;
     152   }
     153   /*
     154     else  ** the branch ends here; we must create a new node... **
     155     {
     156     OK, how is the new node's prefix length w.r.t the dif_bit ?
     157     longer  -> make it a child of the node found
     158     shorter -> make it the parent of the node found and take its place
     159     equal   -> make a glue node the parent of both
     160     }
     161
     162     WHEN ATTACHING THE NODE, VALUES FROM THE STACK ARE USED,
     163     TO PREVENT EXCESSIVE LOOKUPS AGAIN.
     164
     165   */
     166   else {
     167
     168     /* **** attach it.*/
     169     if( ER_is_traced(FAC_RX, ASP_RX_NODCRE_DET) ) {
     170       rx_nod_print(curnode, buf, 1024);
     171       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Looking at node %s", buf);
     172     }
     173
     174     if( curnode -> prefix.bits == dif_bit ) {
     175
     176       /* attach here as a child of the node found      */
     177       link = IP_addr_bit_get( &newpref->ip, dif_bit );
     178
     179       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "attaching as child %d", link);
     180
     181       if( memnode -> child_ptr[link] != NULL ) {
     182         die;
     183       }
     184
     185       memnode -> child_ptr[link] = newnode;
     186       newnode -> parent_ptr = memnode;
     187     }
     188     else if ( newpref->bits == dif_bit ) {
     189       /* make it the parent of the node found and take its place,*/
     190       /* moving it down.*/
     191
     192       /* set the link from the NEW node to the OLD one (different than before)*/
     193
     194       link = IP_addr_bit_get( &curnode->prefix.ip, dif_bit );
     195
     196       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "shifting down as child %d", link);
     197
     198       /* PARENT<->NEW LINKS*/
     199       /* see if the node was the top_node*/
     200       if (curnode -> parent_ptr == NULL) {
     201         /*  update tree struct */
     202         tree -> top_ptr = newnode;
     203       } else {
     204         /* no - fix the child link at the parent.*/
     205         /* at the link where it was attached*/
     206         int link = (curnode->parent_ptr->child_ptr[1] == memnode);
     207         memnode -> parent_ptr -> child_ptr[link] = newnode;
     208       }
     209       memnode -> parent_ptr = newnode;
     210
     211       /* NEW<->CHILD LINKS*/
     212       newnode -> parent_ptr = curnode->parent_ptr;
     213       newnode -> child_ptr[link] = memnode;
     214     }
     215     else {
     216       /* create a glue and shift the curnode below the glue,*/
     217       /* then attach the new node at the glue*/
     218
     219       /* calloc, because parent/child keys are not set.*/
     220
     221       gluenode = UT_calloc(1, sizeof(rx_node_t));
     222       tree -> num_nodes ++;
     223
     224       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "created glue node at %p", gluenode);
     225
     226       gluenode -> prefix.bits = dif_bit;
     227
     228       /* fill in the address. The glue node should get the prefix*/
     229       /* shorter by one than the shorter of the two prefixes that are glued*/
     230       /* (difbit)*/
     231       /**/
     232
     233       gluenode -> prefix.ip = newpref->ip;
     234       gluenode -> prefix.bits = dif_bit;
     235
     236       /* the ip in this prefix is probably incorrect. Fix it.*/
     237       IP_pref_bit_fix(  & gluenode -> prefix );
     238
     239       gluenode -> leaves_ptr = NULL;
     240       gluenode -> glue = 1;
     241
     242       /* 1. Fix the link to and from the parent to the gluenode.*/
     243
     244       gluenode -> parent_ptr = curnode->parent_ptr;
     245       if (gluenode->parent_ptr == NULL) {
     246         tree -> top_ptr = gluenode;
     247       }
     248       else {
     249         /* fix the child link in the parent. */
     250         /* if it was at 1, then let fix the link 1, 0 otherwise*/
     251
     252         link = (curnode->parent_ptr->child_ptr[1] == memnode);
     253
     254         memnode->parent_ptr->child_ptr[link] = gluenode;
     255       }
     256
     257       /* 2. Fix the links between gluenode and the OLD node*/
     258
     259       link = IP_addr_bit_get( &newpref->ip, dif_bit );
     260
     261       gluenode -> child_ptr[ ! link ] = memnode;
     262       memnode->parent_ptr = gluenode;
     263
     264       /* 3. Fix the links between gluenode and the NEW node*/
     265
     266       gluenode -> child_ptr[ link ] = newnode;
     267       newnode -> parent_ptr = gluenode;
     268     }
     269     return RX_OK;
     270   }
     271   die;
     272   return -1; /*this is just to calm down the compiler*/
     273 }
     274
     275
     276 /******************************************************************
     277  an auxiliary function to delete data from a node
     278  (and delete the node or turn it into a glue afterwards)
     279
     280  takes
     281
     282  tree              tree
     283  curnode           pointer to the node
     284  dataleaf          pointer to a dataleaf with ObjectID (dataleaf->data_key)
     285                    set; which is used to choose the right dataleaf
     286                    when browsing data leaves. It is never assumed to be
     287                    allocated via malloc, can be a local variable as well.
     288
     289     If the composed flag of the dataleaf in the tree
     290     (being the reference count at the same time)
     291     is non zero, decrements the count.
     292     Deletes the dataleaf when it reaches zero.
     293
     294  suceeds always or dies when dataleaf with such data cannot be found
     295  in the node
     296 */
     297
     298 void
     299 rx_delete_node (rx_tree_t *tree, rx_node_t *curnode, rx_dataleaf_t *dataleaf)
         /* [<][>][^][v][top][bottom][index][help] */
     300 {
     301   rx_dataleaf_t *leaffound = NULL;
     302   GList *qitem;
     303   int leavesum=0;
     304
     305   /*+ RX_FAM_IP implies there's no dataleaf!!!
     306     The structure in place of a dataleaf is payload
     307     +*/
     308
     309   /* go through leaves, comparing the objectID (data_key) */
     310   for( qitem = g_list_first(curnode->leaves_ptr);
     311        qitem != NULL;
     312        qitem = g_list_next(qitem)) {
     313     rx_dataleaf_t *leafptr = qitem->data;
     314
     315     if( tree->family == RX_FAM_IP    /* do not look at the pointers */
     316         || leafptr->data_key == dataleaf->data_key ) { /* if RX_FAM_IP */
     317       leaffound = leafptr;
     318       /* no break - we're counting leaves..*/
     319     }
     320     leavesum++;
     321   }
     322
     323
     324   ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "%d dataleaves at the node", leavesum);
     325
     326   /* return error if none of the dataleaves matched */
     327   if( leaffound == NULL ) die;
     328
     329   /* NO error? good. Remove the leaf from the list */
     330   curnode->leaves_ptr = g_list_remove ( curnode->leaves_ptr, leaffound );
     331
     332
     333   if(tree->family == RX_FAM_IP ) {
     334     /* again: do not look at the leaf if  RX_FAM_IP */
     335     /* Just free the payload, there must be one and just one. */
     336     UT_free(leaffound);
     337   }
     338   else { /* other families */
     339     /* if not >composed< then delete dataleaf */
     340     if( leaffound->composed == 0 ) {
     341       if( leaffound->data_ptr != NULL        /* allow dataleafs without attached */
     342           && leaffound->data_len > 0 ) {     /* data */
     343         UT_free(leaffound->data_ptr);
     344       }
     345       UT_free(leaffound);
     346
     347       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount = 0, removed");
     348
     349     }
     350   /* else decrement the reference number ( == number of prefixes
     351      composing the range minus 1 == the >composed< flag */
     352     else {
     353       leaffound->composed--;
     354
     355       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount -- to %d ",
     356                 leaffound->composed );
     357     }
     358   } /* if family != RX_FAM_IP */
     359
     360   /* if that was the last leave at this node, then delete node. */
     361   if( leavesum == 1 ) {
     362     rx_node_t *parent = curnode->parent_ptr;
     363
     364     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "last dataleaf, removing node");
     365
     366     assert(curnode->leaves_ptr == NULL);
     367     /* To do this, check the number of children: */
     368
     369     /*  0 - just delete this node and the link to it */
     370     if( curnode->child_ptr[0] == NULL && curnode->child_ptr[1] == NULL ) {
     371
     372       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "no children, just removing");
     373
     374       if( parent != NULL ) { /* watch the head! */
     375         int plink = (parent->child_ptr[1] == curnode);
     376         parent->child_ptr[plink] = NULL;
     377       }
     378       else {
     379         assert(tree->top_ptr == curnode);
     380         tree->top_ptr = NULL;
     381       }
     382       tree->num_nodes--;
     383       UT_free(curnode);
     384
     385
     386     /* now, if we deleted curnode, let's see if the parent node is a glue.
     387        If it is, then hook the remaining child up the grandparent,
     388        and delete the parent */
     389       if( parent != NULL && parent->glue ) {
     390         int slink = (parent->child_ptr[1] != NULL );
     391         rx_node_t *schild = parent->child_ptr[slink];
     392         rx_node_t *gparent = parent->parent_ptr;
     393
     394         assert( schild != NULL && parent->child_ptr[ ! slink] == NULL);
     395
     396         /* upd parent */
     397         if( gparent != NULL ) { /* watch the head! */
     398           int plink = (gparent->child_ptr[1] == parent);
     399           gparent->child_ptr[plink] = parent->child_ptr[slink];
     400         } else {
     401           assert(tree->top_ptr == parent);
     402           tree->top_ptr = parent->child_ptr[slink];
     403         }
     404
     405         /* update the child's parent link too */
     406         parent->child_ptr[slink]->parent_ptr = gparent;
     407
     408         /* del */
     409         tree->num_nodes--;
     410         UT_free(parent);
     411
     412       } /* if parent glue */
     413     }
     414     /*  2 - turn into a glue  */
     415     else if(    curnode->child_ptr[0] != NULL
     416              && curnode->child_ptr[1] != NULL ) {
     417
     418       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "two children, turning into a glue");
     419
     420       curnode->glue = 1;
     421
     422     }
     423     /*  1 - copy the child's link to parent. then delete */
     424     else {
     425       int clink = (curnode->child_ptr[1] != NULL );
     426
     427       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "one child at %d, shifting it up",
     428                 clink);
     429
     430       /* upd parent */
     431       if( parent != NULL ) { /* watch the head! */
     432         int plink = (parent->child_ptr[1] == curnode);
     433         parent->child_ptr[plink] = curnode->child_ptr[clink];
     434       } else {
     435         /* no parent; the child becomes the top node now */
     436         tree->top_ptr = curnode->child_ptr[clink];
     437       }
     438
     439       /* update the child's parent link too */
     440       curnode->child_ptr[clink]->parent_ptr = parent;
     441
     442       /* del */
     443       tree->num_nodes--;
     444       UT_free(curnode);
     445     }
     446
     447
     448   } /* leavesum == 1 <=> that was the last data leaf */
     449 } /* rx_delete_node */
     450
     451 /*+++++++++++++++++++
     452
     453   General function to operate on dataleaves attached to a single node
     454   (create / modify / delete).
     455
     456   searches tree, finds and creates/deletes a node,
     457   copies modified nodes to disk using rx_sql_node_set (not yet implemented).
     458   Updates memory rollback info.
     459
     460
     461
     462
     463   creation:
     464     Add a dataleaf at the node defined by prefix.
     465     Create a new node if it doesn't exist yet.
     466
     467
     468   MT notes: requires the tree to be locked.
     469
     470   Returns: RX_OK or error code.
     471
     472   Errors from:
     473   rx_bin_search,
     474   memory alloc routines.
     475
     476   - no such node (if not in create mode)
     477
     478   - too many nodes found (strange).
     479
     480   +++++++++++++++++*/
     481
     482 /*static*/
     483 er_ret_t
     484 rx_bin_node (
         /* [<][>][^][v][top][bottom][index][help] */
     485              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
     486              ip_prefix_t *newpref,    /*+ prefix of the node +*/
     487              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
     488              rx_dataleaf_t *dataleaf  /*+ dataleaf to attach at the node +*/
     489              )
     490
     491 {
     492   GList *nodlist = NULL;
     493   int nodesfound, stackdepth;
     494   int glue;
     495   rx_nodcpy_t *curcpy;
     496   rx_node_t *curnode;
     497   /* rx_nodcpy_t *stack;*/
     498   rx_nodcpy_t stack[128];
     499   er_ret_t err;
     500   char bbf[IP_PREFSTR_MAX];
     501
     502
     503   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_DET)) {
     504     IP_pref_b2a( newpref , bbf, IP_PREFSTR_MAX);
     505     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN,
     506               "rx_bin_node: %s in spc %d /fam %d operation %d",
     507               bbf, tree->space, tree->family, mode);
     508   }
     509
     510   /* first check: are we using the correct tree ???*/
     511   if( tree->space != newpref->ip.space ) {
     512     /* trying to insert a prefix of space %d into a tree of space %d\n",
     513            tree->space,
     514            newpref->ip.space);
     515     */
     516     die;
     517   }
     518
     519   assert( dataleaf );
     520   assert( newpref->bits <= IP_sizebits(tree->space) );
     521
     522   /* fix the prefix, to make sure all insignificant bits are 0*/
     523   IP_pref_bit_fix( newpref );
     524
     525   if( (err=rx_build_stack(stack, &stackdepth, tree, newpref, RX_STK_CREAT))
     526        != RX_OK ) {
     527     return err; /*die*/
     528   }
     529
     530   /*   rx_stk_print(stack, stackdepth);*/
     531
     532   /* perform a search on the stack. The result is a list, and it must*/
     533   /* be properly deleted after use!!*/
     534
     535   if( (err=rx_nod_search(RX_SRCH_CREAT, 0, 0,
     536                          tree, newpref, stack, stackdepth,
     537                          &nodlist, RX_ANS_ALL)) != RX_OK ) {
     538     return err; /* die;*/
     539   }
     540
     541
     542   /* count number of nodes in the answer */
     543   nodesfound = g_list_length (nodlist);
     544
     545   switch( nodesfound ) {
     546   case 0:
     547     /* no such node (yet). See what we're up to.
     548        if( mode==cre )  create, else - program error, die */
     549
     550     /*  C R E A T I O N */
     551     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET,
     552               "rx_bin_node: Creating a new node %s in spc %d /fam %d ",
     553               bbf, tree->space, tree->family);
     554     if( mode != RX_OPER_CRE) {
     555       die;
     556     }
     557
     558     rx_creat_node(  newpref, tree, dataleaf, stack, stackdepth );
     559     break;
     560   case 1: /* found */
     561     /* set the curnode pointer   */
     562     curcpy = g_list_nth_data(nodlist, 0);
     563     curnode = curcpy->srcptr;
     564
     565     switch( mode ) {
     566     case RX_OPER_CRE:
     567       /*  attach the data at the node that was found;*/
     568
     569       /* was it glue ?*/
     570       glue = curnode->glue;
     571
     572       curnode->leaves_ptr = g_list_prepend(curnode->leaves_ptr, dataleaf);
     573       /* now it's not a glue anymore */
     574       curnode->glue = 0;
     575
     576       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Appended data to a %s node",
     577                 glue ? "glue" : "data");
     578
     579       break;
     580     case RX_OPER_DEL:
     581
     582       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET,
     583                 "rx_bin_node: Deleting node %s in spc %d /fam %d ",
     584                 bbf, tree->space, tree->family);
     585       rx_delete_node( tree, curnode, dataleaf);
     586       break;
     587     }
     588     break;
     589   default:
     590     /* too many nodes found! from an exact/exact-less-1 search.
     591        this cannot happen. Call Ghostbusters now.
     592      */
     593     die;
     594   }
     595
     596   wr_clear_list( &nodlist );
     597
     598   return RX_OK;
     599 }
     600
     601
     602
     603 /***************************************************************************/
     604 /* ++++++++++++++++
     605    A wrapper around RX_bin_node.
     606
     607    It's there only to control the freeing of dataleaf copies passed
     608    for comparison during deletion.
     609
     610    +++++++++++++++++*/
     611 er_ret_t
     612 RX_rt_node (
         /* [<][>][^][v][top][bottom][index][help] */
     613              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
     614              ip_prefix_t *newpref,    /*+ prefix of the node +*/
     615              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
     616              rx_dataleaf_t *leafptr  /*+ dataleaf to attach at the node +*/
     617              )
     618 {
     619   er_ret_t reterr;
     620
     621   IP_pref_2_rang( & leafptr->iprange, newpref);
     622   leafptr->preflen = IP_pref_b2_len(newpref);
     623
     624   /* store the object's range, used in rp.search */
     625
     626   reterr = rx_bin_node(mode, newpref, tree, leafptr);
     627
     628   return reterr;
     629 }
     630
     631 /***************************************************************************/
     632 /*+++++++++++++++
     633   performs the actual update for inetnums (possibly composed of many prefixes).
     634   Decomposes the ranges into prefixes and then falls back to rx_bin_node
     635   to perform changes at the nodes.
     636
     637   Requires/returns - practically the same as rx_bin_node.
     638 ++++++++++++++++*/
     639
     640 er_ret_t
     641 RX_in_node(   rx_oper_mt mode,       /*+ MODE={cre|mod|del} +*/
         /* [<][>][^][v][top][bottom][index][help] */
     642               ip_range_t *rang,      /*+ range of IP addresses +*/
     643               rx_tree_t *tree,       /*+ pointer to the tree structure +*/
     644               rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
     645               )
     646 {
     647   unsigned i, prefcount;
     648   GList *preflist = NULL;
     649   char buf[IP_RANGSTR_MAX];
     650
     651   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_GEN)) {
     652     IP_rang_b2a(rang, buf, IP_RANGSTR_MAX );
     653     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN,
     654               "rx_inum_node: adding %s", buf);
     655   }
     656
     657   /* decompose, put links to the data leaf into every prefix*/
     658   /* that makes up this range.*/
     659   IP_rang_decomp(rang, &preflist);
     660
     661   /* see if there is more than 1 prefix, set the composed flag*/
     662   prefcount = g_list_length(preflist);
     663   leafptr->composed = (prefcount - 1) ;
     664
     665   leafptr->iprange = *rang;
     666
     667 #if 0
     668 /* XXX */
     669 if(prefcount==0) {
     670         fprintf(stderr, "**** prefcount=0 range: [%s][%u-%u]\n", buf, (rang->begin).words[0], (rang->end).words[0]);
     671 }
     672 #endif
     673
     674   if(prefcount==0) {
     675   /* XXX This indicates that some inetnum ranges are not correct (e.g. start>end) */
     676   /* XXX Should not happen and may break normal operation of the rx lookups */
     677   /* XXX maybe we need to die here, but this is too harsh at this point */
     678       IP_rang_b2a(rang, buf, IP_RANGSTR_MAX );
     679       ER_perror(FAC_RX, RX_BADKEY, "prefcount=0 range: [%s][%u-%u]\n",
     680                       buf, (rang->begin).words[0], (rang->end).words[0]);
     681   }
     682
     683
     684
     685
     686   for(i=0; i < prefcount; i++) {
     687     ip_prefix_t *mypref = g_list_nth_data(preflist, i);
     688
     689     rx_bin_node(mode, mypref, tree, leafptr);
     690   }
     691
     692   /* free the storage from decomposition*/
     693   wr_clear_list( &preflist );
     694
     695   return RX_OK;
     696 }

/* [<][>][^][v][top][bottom][index][help] */