| 749 | } |
| 750 | |
| 751 | struct radix_node * |
| 752 | rn_delete(void *v_arg, void *netmask_arg, struct radix_head *head) |
| 753 | { |
| 754 | struct radix_node *t, *p, *x, *tt; |
| 755 | struct radix_mask *m, *saved_m, **mp; |
| 756 | struct radix_node *dupedkey, *saved_tt, *top; |
| 757 | caddr_t v, netmask; |
| 758 | int b, head_off, vlen; |
| 759 | |
| 760 | v = v_arg; |
| 761 | netmask = netmask_arg; |
| 762 | x = head->rnh_treetop; |
| 763 | tt = rn_search(v, x); |
| 764 | head_off = x->rn_offset; |
| 765 | vlen = LEN(v); |
| 766 | saved_tt = tt; |
| 767 | top = x; |
| 768 | if (tt == NULL || |
| 769 | bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) |
| 770 | return (0); |
| 771 | /* |
| 772 | * Delete our route from mask lists. |
| 773 | */ |
| 774 | if (netmask) { |
| 775 | x = rn_addmask(netmask, head->rnh_masks, 1, head_off); |
| 776 | if (x == NULL) |
| 777 | return (0); |
| 778 | netmask = x->rn_key; |
| 779 | while (tt->rn_mask != netmask) |
| 780 | if ((tt = tt->rn_dupedkey) == NULL) |
| 781 | return (0); |
| 782 | } |
| 783 | if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == NULL) |
| 784 | goto on1; |
| 785 | if (tt->rn_flags & RNF_NORMAL) { |
| 786 | if (m->rm_leaf != tt || m->rm_refs > 0) { |
| 787 | log(LOG_ERR, "rn_delete: inconsistent annotation\n"); |
| 788 | return (0); /* dangling ref could cause disaster */ |
| 789 | } |
| 790 | } else { |
| 791 | if (m->rm_mask != tt->rn_mask) { |
| 792 | log(LOG_ERR, "rn_delete: inconsistent annotation\n"); |
| 793 | goto on1; |
| 794 | } |
| 795 | if (--m->rm_refs >= 0) |
| 796 | goto on1; |
| 797 | } |
| 798 | b = -1 - tt->rn_bit; |
| 799 | t = saved_tt->rn_parent; |
| 800 | if (b > t->rn_bit) |
| 801 | goto on1; /* Wasn't lifted at all */ |
| 802 | do { |
| 803 | x = t; |
| 804 | t = t->rn_parent; |
| 805 | } while (b <= t->rn_bit && x != top); |
| 806 | for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) |
| 807 | if (m == saved_m) { |
| 808 | *mp = m->rm_mklist; |
no test coverage detected