⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radix.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
	return (x);    R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof(*x));    if ((saved_x = x) == 0)	return (0);    memset(x, '\0', max_keylen + 2 * sizeof(*x));    netmask = cp = (caddr_t) (x + 2);    memcpy(cp, addmask_key, mlen);    x = rn_insert(cp, mask_rnhead, &maskduplicated, x);    if (maskduplicated) {	fprintf(stderr, "rn_addmask: mask impossibly already in tree");	Free(saved_x);	return (x);    }    /*     * Calculate index of mask, and check for normalcy.     */    cplim = netmask + mlen;    isnormal = 1;    for (cp = netmask + skip; (cp < cplim) && *(u_char *) cp == 0xff;)	cp++;    if (cp != cplim) {	for (j = 0x80; (j & *cp) != 0; j >>= 1)	    b++;	if (*cp != normal_chars[b] || cp != (cplim - 1))	    isnormal = 0;    }    b += (cp - netmask) << 3;    x->rn_b = -1 - b;    if (isnormal)	x->rn_flags |= RNF_NORMAL;    return (x);}static int			/* XXX: arbitrary ordering for non-contiguous masks */rn_lexobetter(m_arg, n_arg)     void *m_arg, *n_arg;{    register u_char *mp = m_arg, *np = n_arg, *lim;    if (*mp > *np)	return 1;		/* not really, but need to check longer one first */    if (*mp == *np)	for (lim = mp + *mp; mp < lim;)	    if (*mp++ > *np++)		return 1;    return 0;}static struct radix_mask *rn_new_radix_mask(tt, next)     register struct radix_node *tt;     register struct radix_mask *next;{    register struct radix_mask *m;    MKGet(m);    if (m == 0) {	fprintf(stderr, "Mask for route not entered\n");	return (0);    }    memset(m, '\0', sizeof *m);    m->rm_b = tt->rn_b;    m->rm_flags = tt->rn_flags;    if (tt->rn_flags & RNF_NORMAL)	m->rm_leaf = tt;    else	m->rm_mask = tt->rn_mask;    m->rm_mklist = next;    tt->rn_mklist = m;    return m;}struct radix_node *rn_addroute(v_arg, n_arg, head, treenodes)     void *v_arg, *n_arg;     struct radix_node_head *head;     struct radix_node treenodes[2];{    caddr_t v = (caddr_t) v_arg, netmask = (caddr_t) n_arg;    register struct radix_node *t, *x = NULL, *tt;    struct radix_node *saved_tt, *top = head->rnh_treetop;    short b = 0, b_leaf = 0;    int keyduplicated;    caddr_t mmask;    struct radix_mask *m, **mp;    /*     * In dealing with non-contiguous masks, there may be     * many different routes which have the same mask.     * We will find it useful to have a unique pointer to     * the mask to speed avoiding duplicate references at     * nodes and possibly save time in calculating indices.     */    if (netmask) {	if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0)	    return (0);	b_leaf = x->rn_b;	b = -1 - x->rn_b;	netmask = x->rn_key;    }    /*     * Deal with duplicated keys: attach node to previous instance     */    saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);    if (keyduplicated) {	for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {	    if (tt->rn_mask == netmask)		return (0);	    if (netmask == 0 ||		(tt->rn_mask &&		    ((b_leaf < tt->rn_b) ||	/* index(netmask) > node */			rn_refines(netmask, tt->rn_mask) ||			rn_lexobetter(netmask, tt->rn_mask))))		break;	}	/*	 * If the mask is not duplicated, we wouldn't	 * find it among possible duplicate key entries	 * anyway, so the above test doesn't hurt.	 *	 * We sort the masks for a duplicated key the same way as	 * in a masklist -- most specific to least specific.	 * This may require the unfortunate nuisance of relocating	 * the head of the list.	 */	if (tt == saved_tt) {	    struct radix_node *xx = x;	    /* link in at head of list */	    (tt = treenodes)->rn_dupedkey = t;	    tt->rn_flags = t->rn_flags;	    tt->rn_p = x = t->rn_p;	    if (x->rn_l == t)		x->rn_l = tt;	    else		x->rn_r = tt;	    saved_tt = tt;	    x = xx;	} else {	    (tt = treenodes)->rn_dupedkey = t->rn_dupedkey;	    t->rn_dupedkey = tt;	}#ifdef RN_DEBUG	t = tt + 1;	tt->rn_info = rn_nodenum++;	t->rn_info = rn_nodenum++;	tt->rn_twin = t;	tt->rn_ybro = rn_clist;	rn_clist = tt;#endif	tt->rn_key = (caddr_t) v;	tt->rn_b = -1;	tt->rn_flags = RNF_ACTIVE;    }    /*     * Put mask in tree.     */    if (netmask) {	tt->rn_mask = netmask;	tt->rn_b = x->rn_b;	tt->rn_flags |= x->rn_flags & RNF_NORMAL;    }    t = saved_tt->rn_p;    if (keyduplicated)	goto on2;    b_leaf = -1 - t->rn_b;    if (t->rn_r == saved_tt)	x = t->rn_l;    else	x = t->rn_r;    /* Promote general routes from below */    if (x->rn_b < 0) {	for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)	    if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {		if ((*mp = m = rn_new_radix_mask(x, 0)))		    mp = &m->rm_mklist;	    }    } else if (x->rn_mklist) {	/*	 * Skip over masks whose index is > that of new node	 */	for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)	    if (m->rm_b >= b_leaf)		break;	t->rn_mklist = m;	*mp = 0;    }  on2:    /* Add new route to highest possible ancestor's list */    if ((netmask == 0) || (b > t->rn_b))	return tt;		/* can't lift at all */    b_leaf = tt->rn_b;    do {	x = t;	t = t->rn_p;    } while (b <= t->rn_b && x != top);    /*     * Search through routes associated with node to     * insert new route according to index.     * Need same criteria as when sorting dupedkeys to avoid     * double loop on deletion.     */    for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) {	if (m->rm_b < b_leaf)	    continue;	if (m->rm_b > b_leaf)	    break;	if (m->rm_flags & RNF_NORMAL) {	    mmask = m->rm_leaf->rn_mask;	    if (tt->rn_flags & RNF_NORMAL) {		fprintf(stderr,		    "Non-unique normal route, mask not entered");		return tt;	    }	} else	    mmask = m->rm_mask;	if (mmask == netmask) {	    m->rm_refs++;	    tt->rn_mklist = m;	    return tt;	}	if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask))	    break;    }    *mp = rn_new_radix_mask(tt, *mp);    return tt;}struct radix_node *rn_delete(v_arg, netmask_arg, head)     void *v_arg, *netmask_arg;     struct radix_node_head *head;{    register struct radix_node *t, *p, *x, *tt;    struct radix_mask *m, *saved_m, **mp;    struct radix_node *dupedkey, *saved_tt, *top;    caddr_t v, netmask;    int b, head_off, vlen;    v = v_arg;    netmask = netmask_arg;    x = head->rnh_treetop;    tt = rn_search(v, x);    head_off = x->rn_off;    vlen = *(u_char *) v;    saved_tt = tt;    top = x;    if (tt == 0 ||	memcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))	return (0);    /*     * Delete our route from mask lists.     */    if (netmask) {	if ((x = rn_addmask(netmask, 1, head_off)) == 0)	    return (0);	netmask = x->rn_key;	while (tt->rn_mask != netmask)	    if ((tt = tt->rn_dupedkey) == 0)		return (0);    }    if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)	goto on1;    if (tt->rn_flags & RNF_NORMAL) {	if (m->rm_leaf != tt || m->rm_refs > 0) {	    fprintf(stderr, "rn_delete: inconsistent annotation\n");	    return 0;		/* dangling ref could cause disaster */	}    } else {	if (m->rm_mask != tt->rn_mask) {	    fprintf(stderr, "rn_delete: inconsistent annotation\n");	    goto on1;	}	if (--m->rm_refs >= 0)	    goto on1;    }    b = -1 - tt->rn_b;    t = saved_tt->rn_p;    if (b > t->rn_b)	goto on1;		/* Wasn't lifted at all */    do {	x = t;	t = t->rn_p;    } while (b <= t->rn_b && x != top);    for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)	if (m == saved_m) {	    *mp = m->rm_mklist;	    MKFree(m);	    break;	}    if (m == 0) {	fprintf(stderr, "rn_delete: couldn't find our annotation\n");	if (tt->rn_flags & RNF_NORMAL)	    return (0);		/* Dangling ref to us */    }  on1:    /*     * Eliminate us from tree     */    if (tt->rn_flags & RNF_ROOT)	return (0);#ifdef RN_DEBUG    /* Get us out of the creation list */    for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {    }    if (t)	t->rn_ybro = tt->rn_ybro;#endif    t = tt->rn_p;    if ((dupedkey = saved_tt->rn_dupedkey)) {	if (tt == saved_tt) {	    x = dupedkey;	    x->rn_p = t;	    if (t->rn_l == tt)		t->rn_l = x;	    else		t->rn_r = x;	} else {	    for (x = p = saved_tt; p && p->rn_dupedkey != tt;)		p = p->rn_dupedkey;	    if (p)		p->rn_dupedkey = tt->rn_dupedkey;	    else		fprintf(stderr, "rn_delete: couldn't find us\n");	}	t = tt + 1;	if (t->rn_flags & RNF_ACTIVE) {#ifndef RN_DEBUG	    *++x = *t;	    p = t->rn_p;#else	    b = t->rn_info;	    *++x = *t;	    t->rn_info = b;	    p = t->rn_p;#endif	    if (p->rn_l == t)		p->rn_l = x;	    else		p->rn_r = x;	    x->rn_l->rn_p = x;	    x->rn_r->rn_p = x;	}	goto out;    }    if (t->rn_l == tt)	x = t->rn_r;    else	x = t->rn_l;    p = t->rn_p;    if (p->rn_r == t)	p->rn_r = x;    else	p->rn_l = x;    x->rn_p = p;    /*     * Demote routes attached to us.     */    if (t->rn_mklist) {	if (x->rn_b >= 0) {	    for (mp = &x->rn_mklist; (m = *mp);)		mp = &m->rm_mklist;	    *mp = t->rn_mklist;	} else {	    /* If there are any key,mask pairs in a sibling	     * duped-key chain, some subset will appear sorted	     * in the same order attached to our mklist */	    for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)		if (m == x->rn_mklist) {		    struct radix_mask *mm = m->rm_mklist;		    x->rn_mklist = 0;		    if (--(m->rm_refs) < 0)			MKFree(m);		    m = mm;		}#if RN_DEBUG	    if (m)		fprintf(stderr, "%s %x at %x\n",		    "rn_delete: Orphaned Mask", (int) m, (int) x);#else	    assert(m == NULL);#endif	}    }    /*     * We may be holding an active internal node in the tree.     */    x = tt + 1;    if (t != x) {#ifndef RN_DEBUG	*t = *x;#else	b = t->rn_info;	*t = *x;	t->rn_info = b;#endif	t->rn_l->rn_p = t;	t->rn_r->rn_p = t;	p = x->rn_p;	if (p->rn_l == x)	    p->rn_l = t;	else	    p->rn_r = t;    }  out:    tt->rn_flags &= ~RNF_ACTIVE;    tt[1].rn_flags &= ~RNF_ACTIVE;    return (tt);}intrn_walktree(h, f, w)     struct radix_node_head *h;     int (*f) ();     void *w;{    int error;    struct radix_node *base, *next;    register struct radix_node *rn = h->rnh_treetop;    /*     * This gets complicated because we may delete the node     * while applying the function f to it, so we need to calculate     * the successor node in advance.     */    /* First time through node, go left */    while (rn->rn_b >= 0)	rn = rn->rn_l;    for (;;) {	base = rn;	/* If at right child go back up, otherwise, go right */	while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0)	    rn = rn->rn_p;	/* Find the next *leaf* since next node might vanish, too */	for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;)	    rn = rn->rn_l;	next = rn;	/* Process leaves */	while ((rn = base)) {	    base = rn->rn_dupedkey;	    if (!(rn->rn_flags & RNF_ROOT) && (error = (*f) (rn, w)))		return (error);	}	rn = next;	if (rn->rn_flags & RNF_ROOT)	    return (0);    }    /* NOTREACHED */}intrn_inithead(head, off)     void **head;     int off;{    register struct radix_node_head *rnh;    register struct radix_node *t, *tt, *ttt;    if (*head)	return (1);    R_Malloc(rnh, struct radix_node_head *, sizeof(*rnh));    if (rnh == 0)	return (0);    memset(rnh, '\0', sizeof(*rnh));    *head = rnh;    t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);    ttt = rnh->rnh_nodes + 2;    t->rn_r = ttt;    t->rn_p = t;    tt = t->rn_l;    tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;    tt->rn_b = -1 - off;    *ttt = *tt;    ttt->rn_key = rn_ones;    rnh->rnh_addaddr = rn_addroute;    rnh->rnh_deladdr = rn_delete;    rnh->rnh_matchaddr = rn_match;    rnh->rnh_lookup = rn_lookup;    rnh->rnh_walktree = rn_walktree;    rnh->rnh_treetop = t;    return (1);}voidrn_init(){    char *cp, *cplim;#ifdef KERNEL    struct domain *dom;    for (dom = domains; dom; dom = dom->dom_next)	if (dom->dom_maxrtkey > max_keylen)	    max_keylen = dom->dom_maxrtkey;#endif    if (max_keylen == 0) {	fprintf(stderr,	    "rn_init: radix functions require max_keylen be set\n");	return;    }    R_Malloc(rn_zeros, char *, 3 * max_keylen);    if (rn_zeros == NULL) {	fprintf(stderr, "rn_init failed.\n");	exit(-1);    }    memset(rn_zeros, '\0', 3 * max_keylen);    rn_ones = cp = rn_zeros + max_keylen;    addmask_key = cplim = rn_ones + max_keylen;    while (cp < cplim)	*cp++ = -1;    if (rn_inithead((void **) &mask_rnhead, 0) == 0) {	fprintf(stderr, "rn_init2 failed.\n");	exit(-1);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -