コード例 #1
0
ファイル: radix.c プロジェクト: 7shi/openbsd-loongson-vc
struct radix_node *
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
	struct radix_node *x;
	caddr_t netmask = 0;

	if (m_arg) {
		if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
			return (0);
		netmask = x->rn_key;
	}
	x = rn_match(v_arg, head);
	if (x && netmask) {
		while (x && x->rn_mask != netmask)
			x = x->rn_dupedkey;
	}
	return x;
}
コード例 #2
0
ファイル: radix.c プロジェクト: mmanley/Antares
struct radix_node *
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
	register struct radix_node *x;
	uint8 *netmask = NULL;

	if (m_arg) {
		x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_offset);
		if (x == 0)
			return 0;
		netmask = x->rn_key;
	}
	x = rn_match(v_arg, head);
	if (x && netmask) {
		while (x && x->rn_mask != netmask)
			x = x->rn_dupedkey;
	}
	return x;
}
コード例 #3
0
ファイル: radix.c プロジェクト: appleorange1/bitrig
struct radix_node *
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
	struct radix_node *x, *tm;
	caddr_t netmask = 0;

	if (m_arg) {
		tm = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off);
		if (tm == NULL)
			return (NULL);
		netmask = tm->rn_key;
	}
	x = rn_match(v_arg, head);
	if (x && netmask) {
		while (x && x->rn_mask != netmask)
			x = x->rn_dupedkey;
	}
	return x;
}
コード例 #4
0
ファイル: radix.c プロジェクト: kusumi/DragonFlyBSD
struct radix_node *
rn_lookup(char *key, char *mask, struct radix_node_head *head)
{
	struct radix_node *x;
	char *netmask = NULL;

	if (mask != NULL) {
		x = rn_addmask(mask, TRUE, head->rnh_treetop->rn_offset,
			       head->rnh_maskhead);
		if (x == NULL)
			return (NULL);
		netmask = x->rn_key;
	}
	x = rn_match(key, head);
	if (x != NULL && netmask != NULL) {
		while (x != NULL && x->rn_mask != netmask)
			x = x->rn_dupedkey;
	}
	return x;
}
コード例 #5
0
ファイル: radix.c プロジェクト: ryo/netbsd-src
struct radix_node *
rn_lookup(
	const void *v_arg,
	const void *m_arg,
	struct radix_node_head *head)
{
	struct radix_node *x;
	const char *netmask = NULL;

	if (m_arg) {
		if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
			return NULL;
		netmask = x->rn_key;
	}
	x = rn_match(v_arg, head);
	if (x != NULL && netmask != NULL) {
		while (x != NULL && x->rn_mask != netmask)
			x = x->rn_dupedkey;
	}
	return x;
}
コード例 #6
0
ファイル: radix.c プロジェクト: ironpillow/netmap-fwd
/*
 * Search for exact match in given @head.
 * Assume host bits are cleared in @v_arg if @m_arg is not NULL
 * Note that prefixes with /32 or /128 masks are treated differently
 * from host routes.
 */
struct radix_node *
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
	struct radix_node *x;
	caddr_t netmask;

	if (m_arg != NULL) {
		/*
		 * Most common case: search exact prefix/mask
		 */
		x = rn_addmask(m_arg, head->rnh_masks, 1,
		    head->rnh_treetop->rn_offset);
		if (x == NULL)
			return (NULL);
		netmask = x->rn_key;

		x = rn_match(v_arg, head);

		while (x != NULL && x->rn_mask != netmask)
			x = x->rn_dupedkey;

		return (x);
	}

	/*
	 * Search for host address.
	 */
	if ((x = rn_match(v_arg, head)) == NULL)
		return (NULL);

	/* Check if found key is the same */
	if (LEN(x->rn_key) != LEN(v_arg) || bcmp(x->rn_key, v_arg, LEN(v_arg)))
		return (NULL);

	/* Check if this is not host route */
	if (x->rn_mask != NULL)
		return (NULL);

	return (x);
}
コード例 #7
0
ファイル: routeUtilLib.c プロジェクト: andy345/vxworks5
ROUTE_ENTRY * routeLookup
    (
    struct sockaddr * pDest, 	/* IP address reachable with matching route */
    ULONG * pMask, 		/* netmask value, in network byte order */
    int	protoId 		/* route source from m2Lib.h, or 0 for any. */
    )
    {
    struct radix_node_head * pHead = rt_tables[pDest->sa_family];

    struct radix_node * pNode;        /* radix tree entry for route */
    struct rtentry * pRoute = NULL;   /* candidate for matching route */
    ROUTE_ENTRY * pMatch = NULL;      /* matching route entry */

    struct sockaddr_in netmask;       /* netmask value, internal format */
    char * pNetmask = NULL;           /* target netmask value from tree */

    struct rtentry * pNextRoute;

    STATUS result = ERROR;            /* OK indicates a successful search */
    int  s;

    if (pHead == NULL)
        {
        /* No route table exists for the given address family. */

        return (NULL);
        }

    bzero ( (char *)&netmask, sizeof (struct sockaddr_in));

    s = splnet ();

    /*
     * If a specific netmask match is required, find the target value
     * (a pointer to the stored netmask entry) which will determine
     * whether the match exists. A mask value of zero indicates a
     * host-specific route, which does not contain a netmask entry.
     */

    if (pMask && *pMask)
        {
        /* Setup data structure to search mask's tree for given value. */

        netmask.sin_family = AF_INET;
        netmask.sin_len = sizeof (struct sockaddr_in);
        netmask.sin_addr.s_addr = *pMask;

        TOS_SET (&netmask, 0x1f);

        in_socktrim (&netmask);    /* Adjust length field for tree search. */

        /* Search for netmask from corresponding tree. */

        pNode = rn_addmask (&netmask, 1, pHead->rnh_treetop->rn_off);
        if (pNode == 0)
            {
            /* No route currently uses the specified netmask. */

#ifdef DEBUG
            logMsg ("routeLookup: requested mask does not exist.\n",
                    0, 0, 0, 0, 0, 0);
#endif
            splx(s);
            return (NULL);
            }

        pNetmask = pNode->rn_key;
        }

    pNode = pHead->rnh_matchaddr ((caddr_t)pDest, pHead);
    if (pNode && ((pNode->rn_flags & RNF_ROOT) == 0))
        {
        /* Possible match found. Save for later use. */

        pRoute = (struct rtentry *)pNode;
        }
    else
        {
        /* No route matches the given key. */

        splx (s);
        return (NULL);
        }

#ifdef DEBUG
    logMsg ("routeLookup: candidate for match at %p.\n", pNode,
            0, 0, 0, 0, 0);
#endif

    /*
     * Compare the set of routes available with the initial key
     * against the desired values. Each entry in the chain of
     * routes with duplicate keys uses a different netmask value.
     *
     * NOTE: The pNode value is not necessarily the start of the
     * chain. It is the first entry in the chain with a short
     * enough netmask to produce a match against the destination.
     */

    for ( ; pRoute != NULL; pRoute = pNextRoute)
        {
        /* Select the next route candidate in case a test fails. */

        pNextRoute = (struct rtentry *)
                           ((struct radix_node *)pRoute)->rn_dupedkey;

        if (pMask)
            {
            /*
             * Check mask of route against corresponding entry from
             * the stored netmasks (derived from the given value).
             */

#ifdef DEBUG
            logMsg ("routeLookup: checking against specific mask.\n",
                    0, 0, 0, 0, 0, 0);
#endif

            if (*pMask)
                {
                if ( ((struct radix_node *)pRoute)->rn_mask != pNetmask)
                    continue;   /* Mask values do not match. */
                }
            else if ( ( (struct sockaddr_in *)pDest)->sin_addr.s_addr)
                {
                /* Searching for a host-specific route (no netmask entry). */

                if ( ((struct radix_node *)pRoute)->rn_mask != 0)
                    continue;   /* Entry is not a host route. */
                }
            }

        /*
         * Candidate passed any mask requirements. Search for entries
         * which match the specified route source.
         */

#ifdef DEBUG
        logMsg ("routeLookup: Current mask is OK.\n", 0, 0, 0, 0, 0, 0);
#endif

        if (protoId)
            {
            /* Check source of route against specified value. */

#ifdef DEBUG
            logMsg ("routeLookup: testing protocol ID.\n",
                    0, 0, 0, 0, 0, 0);
#endif

            for (pMatch = (ROUTE_ENTRY *)pRoute; pMatch != NULL;
                   pMatch = pMatch->diffNode.pFrwd)
                {
                if (RT_PROTO_GET(ROUTE_ENTRY_KEY(pMatch)) == protoId)
                    break;
                }

            if (pMatch == NULL)   /* Route protocol values do not match. */
                continue;

#ifdef DEBUG
            logMsg ("routeLookup: Current protocol ID is OK.\n",
                    0, 0, 0, 0, 0, 0);
#endif
            }
        else
            {
            /*
             * No route source is specified. Accept the entry
             * which met any mask criteria.
             */

            pMatch = (ROUTE_ENTRY *)pRoute;
            }
 
        /* The candidate route entry met all criteria. Stop the search. */

        result = OK;
        break;
        }

    if (result == OK)
        {
        /* Increase the reference count before returning the matching entry. */

        pMatch->rtEntry.rt_refcnt++;
        }
    else
        pMatch = NULL;

    splx (s);

    return (pMatch);
    }
コード例 #8
0
static struct radix_node *
rn_delete(void *v_arg,
	  void *netmask_arg,
	  struct radix_node_head *head)
{
	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 ||
	    Bcmp(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) {
			log(LOG_ERR, "rn_delete: inconsistent annotation\n");
			return 0;  /* dangling ref could cause disaster */
		}
	} else {
		if (m->rm_mask != tt->rn_mask) {
			log(LOG_ERR, "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) {
		log(LOG_ERR, "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 log(LOG_ERR, "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 (m)
				syslog(LOG_ERR, "%s 0x%lx at 0x%lx\n",
				       "rn_delete: Orphaned Mask",
				       (unsigned long)m,
				       (unsigned long)x);
		}
	}
	/*
	 * 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);
}
コード例 #9
0
static struct radix_node *
rn_addroute(void *v_arg,
	    void *n_arg,
	    struct radix_node_head *head,
	    struct radix_node treenodes[2])
{
	caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
	struct radix_node *t, *x = 0, *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) {
				log(LOG_ERR,
				   "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;
}