1 | /*************************************** 2 | $Revision: 1.32 $ 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 ( 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 | unsigned 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_DET, "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_DET, "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_DET, "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_DET, "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) 309 | { 310 | rx_dataleaf_t *leaffound = NULL; 311 | GList *qitem; 312 | int leavesum=0; 313 | 314 | /*+ RX_FAM_IP implies there's no dataleaf!!! 315 | The structure in place of a dataleaf is payload 316 | +*/ 317 | 318 | /* go through leaves, comparing the objectID (data_key) */ 319 | for( qitem = g_list_first(curnode->leaves_ptr); 320 | qitem != NULL; 321 | qitem = g_list_next(qitem)) { 322 | rx_dataleaf_t *leafptr = qitem->data; 323 | 324 | if( tree->family == RX_FAM_IP /* do not look at the pointers */ 325 | || leafptr->data_key == dataleaf->data_key ) { /* if RX_FAM_IP */ 326 | leaffound = leafptr; 327 | /* no break - we're counting leaves..*/ 328 | } 329 | leavesum++; 330 | } 331 | 332 | 333 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "%d dataleaves at the node", leavesum); 334 | 335 | /* return error if none of the dataleaves matched */ 336 | if( leaffound == NULL ) die; 337 | 338 | /* NO error? good. Remove the leaf from the list */ 339 | curnode->leaves_ptr = g_list_remove ( curnode->leaves_ptr, leaffound ); 340 | 341 | 342 | if(tree->family == RX_FAM_IP ) { 343 | /* again: do not look at the leaf if RX_FAM_IP */ 344 | /* Just free the payload, there must be one and just one. */ 345 | wr_free(leaffound); 346 | } 347 | else { /* other families */ 348 | /* if not >composed< then delete dataleaf */ 349 | if( leaffound->composed == 0 ) { 350 | if( leaffound->data_ptr != NULL /* allow dataleafs without attached */ 351 | && leaffound->data_len > 0 ) { /* data */ 352 | wr_free(leaffound->data_ptr); 353 | } 354 | wr_free(leaffound); 355 | 356 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount = 0, removed"); 357 | 358 | } 359 | /* else decrement the reference number ( == number of prefixes 360 | composing the range minus 1 == the >composed< flag */ 361 | else { 362 | leaffound->composed--; 363 | 364 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount -- to %d ", 365 | leaffound->composed ); 366 | } 367 | } /* if family != RX_FAM_IP */ 368 | 369 | /* if that was the last leave at this node, then delete node. */ 370 | if( leavesum == 1 ) { 371 | rx_node_t *parent = curnode->parent_ptr; 372 | 373 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "last dataleaf, removing node"); 374 | 375 | assert(curnode->leaves_ptr == NULL); 376 | /* To do this, check the number of children: */ 377 | 378 | /* 0 - just delete this node and the link to it */ 379 | if( curnode->child_ptr[0] == NULL && curnode->child_ptr[1] == NULL ) { 380 | 381 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "no children, just removing"); 382 | 383 | if( parent != NULL ) { /* watch the head! */ 384 | int plink = (parent->child_ptr[1] == curnode); 385 | parent->child_ptr[plink] = NULL; 386 | } 387 | else { 388 | assert(tree->top_ptr == curnode); 389 | tree->top_ptr = NULL; 390 | } 391 | tree->num_nodes--; 392 | wr_free(curnode); 393 | 394 | 395 | /* now, if we deleted curnode, let's see if the parent node is a glue. 396 | If it is, then hook the remaining child up the grandparent, 397 | and delete the parent */ 398 | if( parent != NULL && parent->glue ) { 399 | int slink = (parent->child_ptr[1] != NULL ); 400 | rx_node_t *schild = parent->child_ptr[slink]; 401 | rx_node_t *gparent = parent->parent_ptr; 402 | 403 | assert( schild != NULL && parent->child_ptr[ ! slink] == NULL); 404 | 405 | /* upd parent */ 406 | if( gparent != NULL ) { /* watch the head! */ 407 | int plink = (gparent->child_ptr[1] == parent); 408 | gparent->child_ptr[plink] = parent->child_ptr[slink]; 409 | } else { 410 | assert(tree->top_ptr == parent); 411 | tree->top_ptr = parent->child_ptr[slink]; 412 | } 413 | 414 | /* update the child's parent link too */ 415 | parent->child_ptr[slink]->parent_ptr = gparent; 416 | 417 | /* del */ 418 | tree->num_nodes--; 419 | wr_free(parent); 420 | 421 | } /* if parent glue */ 422 | } 423 | /* 2 - turn into a glue */ 424 | else if( curnode->child_ptr[0] != NULL 425 | && curnode->child_ptr[1] != NULL ) { 426 | 427 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "two children, turning into a glue"); 428 | 429 | curnode->glue = 1; 430 | 431 | } 432 | /* 1 - copy the child's link to parent. then delete */ 433 | else { 434 | int clink = (curnode->child_ptr[1] != NULL ); 435 | 436 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "one child at %d, shifting it up", 437 | clink); 438 | 439 | /* upd parent */ 440 | if( parent != NULL ) { /* watch the head! */ 441 | int plink = (parent->child_ptr[1] == curnode); 442 | parent->child_ptr[plink] = curnode->child_ptr[clink]; 443 | } else { 444 | /* no parent; the child becomes the top node now */ 445 | tree->top_ptr = curnode->child_ptr[clink]; 446 | } 447 | 448 | /* update the child's parent link too */ 449 | curnode->child_ptr[clink]->parent_ptr = parent; 450 | 451 | /* del */ 452 | tree->num_nodes--; 453 | wr_free(curnode); 454 | } 455 | 456 | 457 | } /* leavesum == 1 <=> that was the last data leaf */ 458 | } /* rx_delete_node */ 459 | 460 | /*+++++++++++++++++++ 461 | 462 | General function to operate on dataleaves attached to a single node 463 | (create / modify / delete). 464 | 465 | searches tree, finds and creates/deletes a node, 466 | copies modified nodes to disk using rx_sql_node_set (not yet implemented). 467 | Updates memory rollback info. 468 | 469 | 470 | 471 | 472 | creation: 473 | Add a dataleaf at the node defined by prefix. 474 | Create a new node if it doesn't exist yet. 475 | 476 | 477 | MT notes: requires the tree to be locked. 478 | 479 | Returns: RX_OK or error code. 480 | 481 | Errors from: 482 | rx_bin_search, 483 | memory alloc routines. 484 | 485 | - no such node (if not in create mode) 486 | 487 | - too many nodes found (strange). 488 | 489 | +++++++++++++++++*/ 490 | 491 | /*static*/ 492 | er_ret_t 493 | rx_bin_node ( 494 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 495 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 496 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 497 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 498 | ) 499 | 500 | { 501 | GList *nodlist = NULL; 502 | int nodesfound, stackdepth; 503 | int glue; 504 | rx_nodcpy_t *curcpy; 505 | rx_node_t *curnode; 506 | /* rx_nodcpy_t *stack;*/ 507 | rx_nodcpy_t stack[128]; 508 | er_ret_t err; 509 | char bbf[IP_PREFSTR_MAX]; 510 | 511 | 512 | if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_DET)) { 513 | IP_pref_b2a( newpref , bbf, IP_PREFSTR_MAX); 514 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN, 515 | "rx_bin_node: %s in spc %d /fam %d operation %d", 516 | bbf, tree->space, tree->family, mode); 517 | } 518 | 519 | /* first check: are we using the correct tree ???*/ 520 | if( tree->space != newpref->ip.space ) { 521 | /* trying to insert a prefix of space %d into a tree of space %d\n", 522 | tree->space, 523 | newpref->ip.space); 524 | */ 525 | die; 526 | } 527 | 528 | assert( dataleaf ); 529 | assert( newpref->bits <= IP_sizebits(tree->space) ); 530 | 531 | /* fix the prefix, to make sure all insignificant bits are 0*/ 532 | IP_pref_bit_fix( newpref ); 533 | 534 | if( (err=rx_build_stack(stack, &stackdepth, tree, newpref, RX_STK_CREAT)) 535 | != RX_OK ) { 536 | return err; /*die*/ 537 | } 538 | 539 | /* rx_stk_print(stack, stackdepth);*/ 540 | 541 | /* perform a search on the stack. The result is a list, and it must*/ 542 | /* be properly deleted after use!!*/ 543 | 544 | if( (err=rx_nod_search(RX_SRCH_CREAT, 0, 0, 545 | tree, newpref, stack, stackdepth, 546 | &nodlist, RX_ANS_ALL)) != RX_OK ) { 547 | return err; /* die;*/ 548 | } 549 | 550 | 551 | /* count number of nodes in the answer */ 552 | nodesfound = g_list_length (nodlist); 553 | 554 | switch( nodesfound ) { 555 | case 0: 556 | /* no such node (yet). See what we're up to. 557 | if( mode==cre ) create, else - program error, die */ 558 | 559 | /* C R E A T I O N */ 560 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 561 | "rx_bin_node: Creating a new node %s in spc %d /fam %d ", 562 | bbf, tree->space, tree->family); 563 | if( mode != RX_OPER_CRE) { 564 | die; 565 | } 566 | 567 | rx_creat_node( newpref, tree, dataleaf, stack, stackdepth ); 568 | break; 569 | case 1: /* found */ 570 | /* set the curnode pointer */ 571 | curcpy = g_list_nth_data(nodlist, 0); 572 | curnode = curcpy->srcptr; 573 | 574 | switch( mode ) { 575 | case RX_OPER_CRE: 576 | /* attach the data at the node that was found;*/ 577 | 578 | /* was it glue ?*/ 579 | glue = curnode->glue; 580 | 581 | curnode->leaves_ptr = g_list_prepend(curnode->leaves_ptr, dataleaf); 582 | /* now it's not a glue anymore */ 583 | curnode->glue = 0; 584 | 585 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Appended data to a %s node", 586 | glue ? "glue" : "data"); 587 | 588 | break; 589 | case RX_OPER_DEL: 590 | 591 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 592 | "rx_bin_node: Deleting node %s in spc %d /fam %d ", 593 | bbf, tree->space, tree->family); 594 | rx_delete_node( tree, curnode, dataleaf); 595 | break; 596 | } 597 | break; 598 | default: 599 | /* too many nodes found! from an exact/exact-less-1 search. 600 | this cannot happen. Call Ghostbusters now. 601 | */ 602 | die; 603 | } 604 | 605 | wr_clear_list( &nodlist ); 606 | 607 | return RX_OK; 608 | } 609 | 610 | 611 | 612 | /***************************************************************************/ 613 | /* ++++++++++++++++ 614 | A wrapper around RX_bin_node. 615 | 616 | It's there only to control the freeing of dataleaf copies passed 617 | for comparison during deletion. 618 | 619 | +++++++++++++++++*/ 620 | er_ret_t 621 | RX_rt_node ( 622 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 623 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 624 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 625 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/ 626 | ) 627 | { 628 | er_ret_t reterr; 629 | 630 | IP_pref_2_rang( & leafptr->iprange, newpref); 631 | leafptr->preflen = IP_pref_b2_len(newpref); 632 | 633 | /* store the object's range, used in rp.search */ 634 | 635 | reterr = rx_bin_node(mode, newpref, tree, leafptr); 636 | 637 | return reterr; 638 | } 639 | 640 | /***************************************************************************/ 641 | /*+++++++++++++++ 642 | performs the actual update for inetnums (possibly composed of many prefixes). 643 | Decomposes the ranges into prefixes and then falls back to rx_bin_node 644 | to perform changes at the nodes. 645 | 646 | Requires/returns - practically the same as rx_bin_node. 647 | ++++++++++++++++*/ 648 | 649 | er_ret_t 650 | RX_in_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 651 | ip_range_t *rang, /*+ range of IP addresses +*/ 652 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 653 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/ 654 | ) 655 | { 656 | unsigned i, prefcount; 657 | GList *preflist = NULL; 658 | char buf[IP_RANGSTR_MAX]; 659 | 660 | if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_GEN)) { 661 | IP_rang_b2a(rang, buf, IP_RANGSTR_MAX ); 662 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN, 663 | "rx_inum_node: adding %s", buf); 664 | } 665 | 666 | /* decompose, put links to the data leaf into every prefix*/ 667 | /* that makes up this range.*/ 668 | IP_rang_decomp(rang, &preflist); 669 | 670 | /* see if there is more than 1 prefix, set the composed flag*/ 671 | prefcount = g_list_length(preflist); 672 | leafptr->composed = (prefcount - 1) ; 673 | 674 | leafptr->iprange = *rang; 675 | 676 | /* XXX */ 677 | if(prefcount==0) { 678 | fprintf(stderr, "**** prefcount=0 range: [%s][%u-%u]\n", buf, (rang->begin).words[0], (rang->end).words[0]); 679 | } 680 | 681 | for(i=0; i < prefcount; i++) { 682 | ip_prefix_t *mypref = g_list_nth_data(preflist, i); 683 | 684 | rx_bin_node(mode, mypref, tree, leafptr); 685 | } 686 | 687 | /* free the storage from decomposition*/ 688 | wr_clear_list( &preflist ); 689 | 690 | return RX_OK; 691 | }