## modules/rx/rx_node.c

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

## FUNCTIONS

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

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