| 484 | } |
| 485 | |
| 486 | static struct radix_node * |
| 487 | rn_addmask(void *n_arg, struct radix_mask_head *maskhead, int search, int skip) |
| 488 | { |
| 489 | unsigned char *netmask = n_arg; |
| 490 | unsigned char *cp, *cplim; |
| 491 | struct radix_node *x; |
| 492 | int b = 0, mlen, j; |
| 493 | int maskduplicated, isnormal; |
| 494 | struct radix_node *saved_x; |
| 495 | unsigned char addmask_key[RADIX_MAX_KEY_LEN]; |
| 496 | |
| 497 | if ((mlen = LEN(netmask)) > RADIX_MAX_KEY_LEN) |
| 498 | mlen = RADIX_MAX_KEY_LEN; |
| 499 | if (skip == 0) |
| 500 | skip = 1; |
| 501 | if (mlen <= skip) |
| 502 | return (maskhead->mask_nodes); |
| 503 | |
| 504 | bzero(addmask_key, RADIX_MAX_KEY_LEN); |
| 505 | if (skip > 1) |
| 506 | bcopy(rn_ones + 1, addmask_key + 1, skip - 1); |
| 507 | bcopy(netmask + skip, addmask_key + skip, mlen - skip); |
| 508 | /* |
| 509 | * Trim trailing zeroes. |
| 510 | */ |
| 511 | for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) |
| 512 | cp--; |
| 513 | mlen = cp - addmask_key; |
| 514 | if (mlen <= skip) |
| 515 | return (maskhead->mask_nodes); |
| 516 | *addmask_key = mlen; |
| 517 | x = rn_search(addmask_key, maskhead->head.rnh_treetop); |
| 518 | if (bcmp(addmask_key, x->rn_key, mlen) != 0) |
| 519 | x = NULL; |
| 520 | if (x || search) |
| 521 | return (x); |
| 522 | R_Zalloc(x, struct radix_node *, RADIX_MAX_KEY_LEN + 2 * sizeof (*x)); |
| 523 | if ((saved_x = x) == NULL) |
| 524 | return (0); |
| 525 | netmask = cp = (unsigned char *)(x + 2); |
| 526 | bcopy(addmask_key, cp, mlen); |
| 527 | x = rn_insert(cp, &maskhead->head, &maskduplicated, x); |
| 528 | if (maskduplicated) { |
| 529 | log(LOG_ERR, "rn_addmask: mask impossibly already in tree"); |
| 530 | R_Free(saved_x); |
| 531 | return (x); |
| 532 | } |
| 533 | /* |
| 534 | * Calculate index of mask, and check for normalcy. |
| 535 | * First find the first byte with a 0 bit, then if there are |
| 536 | * more bits left (remember we already trimmed the trailing 0's), |
| 537 | * the bits should be contiguous, otherwise we have got |
| 538 | * a non-contiguous mask. |
| 539 | */ |
| 540 | #define CONTIG(_c) (((~(_c) + 1) & (_c)) == (unsigned char)(~(_c) + 1)) |
| 541 | cplim = netmask + mlen; |
| 542 | isnormal = 1; |
| 543 | for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) |