Ejemplo n.º 1
0
/*
 * Insert a route from a string containing a destination: "192.168.1/24"
 */
void
route_insert(unsigned int rid, sa_family_t af, char *string)
{
	struct sockaddr_storage	 ss, ms;
	struct sockaddr		*ndst, *dst = (struct sockaddr *)&ss;
	struct sockaddr		*mask = (struct sockaddr *)&ms;
	struct rtentry		*rt, *nrt;
	char			 ip[INET6_ADDRSTRLEN];
	int			 plen, error;

	rt = calloc(1, sizeof(*rt));
	if (rt == NULL)
		errx(1, "out of memory");

	plen = inet_net_ptosa(af, string, dst, mask);
	if (plen == -1)
		err(1, "wrong line: %s", string);

	/* Normalize sockaddr a la rtrequest1(9) */
	ndst = malloc(dst->sa_len);
	if (ndst == NULL)
		errx(1, "out of memory");
	rt_maskedcopy(dst, ndst, mask);

	if ((error = rtable_insert(rid, ndst, mask, NULL, 0, rt)) != 0) {
		inet_net_satop(af, rt_key(rt), plen, ip, sizeof(ip));
		errx(1, "can't add route: %s, %s\n", ip, strerror(error));
	}
	nrt = rtable_lookup(rid, dst, mask, NULL, RTP_ANY);
	if (nrt != rt) {
		inet_net_satop(af, rt_key(rt), plen, ip, sizeof(ip));
		errx(1, "added route not found: %s\n", ip);
	}
}
Ejemplo n.º 2
0
void
rtkey_to_sa6(struct rtentry *rt, struct sockaddr_in6 *sin6)
{
	VERIFY(rt_key(rt)->sa_family == AF_INET6);

	*sin6 = *((struct sockaddr_in6 *)(void *)rt_key(rt));
	sin6->sin6_scope_id = 0;
}
Ejemplo n.º 3
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int ifart_delete( struct radix_node *rn, struct in_addr *addr )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if (((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr == addr->s_addr)
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              rt->rt_flags, NULL);
	}
	return 0;
}
Ejemplo n.º 4
0
int
rtentry_dump(struct rtentry *rt, void *w, unsigned int rid)
{
	char			 dest[INET6_ADDRSTRLEN];
	sa_family_t		 af = rt_key(rt)->sa_family;

	inet_net_satop(af, rt_key(rt), rt_plen(rt), dest, sizeof(dest));
	printf("%s\n", dest);

	return (0);
}
Ejemplo n.º 5
0
static void
p_krtentry(struct rtentry *rt)
{
	static struct ifnet ifnet, *lastif;
	struct sockaddr_storage sock1, sock2;
	struct sockaddr *sa = (struct sockaddr *)&sock1;
	struct sockaddr *mask = (struct sockaddr *)&sock2;

	bcopy(kgetsa(rt_key(rt)), sa, sizeof(struct sockaddr));
	if (sa->sa_len > sizeof(struct sockaddr))
		bcopy(kgetsa(rt_key(rt)), sa, sa->sa_len);

	if (sa->sa_family == PF_KEY) {
		encap_print(rt);
		return;
	}

	if (rt_mask(rt)) {
		bcopy(kgetsa(rt_mask(rt)), mask, sizeof(struct sockaddr));
		if (sa->sa_len > sizeof(struct sockaddr))
			bcopy(kgetsa(rt_mask(rt)), mask, sa->sa_len);
	} else
		mask = 0;

	p_addr(sa, mask, rt->rt_flags);
	p_gwaddr(kgetsa(rt->rt_gateway), sa->sa_family);
	p_flags(rt->rt_flags, "%-6.6s ");
	printf("%5u %8lld ", rt->rt_refcnt, rt->rt_use);
	if (rt->rt_rmx.rmx_mtu)
		printf("%5u ", rt->rt_rmx.rmx_mtu);
	else
		printf("%5s ", "-");
	putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
	printf("  %2d", rt->rt_priority);

	if (rt->rt_ifp) {
		if (rt->rt_ifp != lastif) {
			kread((u_long)rt->rt_ifp, &ifnet, sizeof(ifnet));
			lastif = rt->rt_ifp;
		}
		printf(" %.16s%s", ifnet.if_xname,
		    rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
	}
	putchar('\n');
	if (vflag)
		printf("\texpire   %10lld%c\n",
		    (long long)rt->rt_rmx.rmx_expire,
		    (rt->rt_rmx.rmx_locks & RTV_EXPIRE) ? 'L' : ' ');
}
Ejemplo n.º 6
0
static void
p_rtentry(struct rtentry *rt)
{
	static struct ifnet ifnet, *lastif;
	struct rtentry parent;
	static char buffer[128];
	static char prettyname[128];
	struct sockaddr *sa;
	sa_u addr, mask;

	/*
	 * Don't print protocol-cloned routes unless -a.
	 */
	if (rt->rt_flags & RTF_WASCLONED && !aflag) {
		kget(rt->rt_parent, parent);
		if (parent.rt_flags & RTF_PRCLONING)
			return;
	}

	bzero(&addr, sizeof(addr));
	if ((sa = kgetsa(rt_key(rt))))
		bcopy(sa, &addr, sa->sa_len);
	bzero(&mask, sizeof(mask));
	if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
		bcopy(sa, &mask, sa->sa_len);
	p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst);
	p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
	snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
	p_flags(rt->rt_flags, buffer);
	if (addr.u_sa.sa_family == AF_INET || Wflag) {
		printf("%*ld %*lu ", wid_refs, rt->rt_refcnt,
				     wid_use, rt->rt_use);
		if (Wflag) {
			if (rt->rt_rmx.rmx_mtu != 0)
				printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
			else
				printf("%*s ", wid_mtu, "");
		}
	}
	if (rt->rt_ifp) {
		if (rt->rt_ifp != lastif) {
			kget(rt->rt_ifp, ifnet);
			kread((u_long)ifnet.if_name, buffer, sizeof(buffer));
			lastif = rt->rt_ifp;
			snprintf(prettyname, sizeof(prettyname),
				 "%s%d", buffer, ifnet.if_unit);
		}
		printf("%*.*s", wid_if, wid_if, prettyname);
		if (rt->rt_rmx.rmx_expire) {
			time_t expire_time;

			if ((expire_time =
			    rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0)
				printf(" %*d", wid_expire, (int)expire_time);
		}
		if (rt->rt_nodes[0].rn_dupedkey)
			printf(" =>");
	}
	putchar('\n');
}
Ejemplo n.º 7
0
/*
 * Get rid of old routes.  When draining, this deletes everything, even when
 * the timeout is not expired yet.  When updating, this makes sure that
 * nothing has a timeout longer than the current value of rtq_reallyold.
 */
static int
in6_rtqkill(struct radix_node *rn, void *rock)
{
	struct rtqk_arg *ap = rock;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;

	if (rt->rt_flags & RTPRF_OURS) {
		ap->found++;

		if (ap->draining || rt->rt_rmx.rmx_expire <= time_second) {
			if (rt->rt_refcnt > 0)
				panic("rtqkill route really not free");

			err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
					rt_mask(rt), rt->rt_flags, NULL);
			if (err)
				log(LOG_WARNING, "in6_rtqkill: error %d", err);
			else
				ap->killed++;
		} else {
			if (ap->updating &&
			    (rt->rt_rmx.rmx_expire - time_second >
			     rtq_reallyold)) {
				rt->rt_rmx.rmx_expire =
				    time_second + rtq_reallyold;
			}
			ap->nextstop = lmin(ap->nextstop,
					    rt->rt_rmx.rmx_expire);
		}
	}

	return 0;
}
Ejemplo n.º 8
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int dump_arp(struct radix_node *rn, void *req)
{
    struct rtentry *rt = (struct rtentry *)rn;
    struct sockaddr *dst;
    struct sockaddr_dl *sdl;

    dst = rt_key(rt);
    sdl = (struct sockaddr_dl *)rt->rt_gateway;
    if ((rt->rt_flags & (RTF_UP | RTF_LLINFO)) == (RTF_UP | RTF_LLINFO)) 
    {
    		if(((struct arp_req *)req)->buf)
    		{
    			switch(((struct arp_req *)req)->flg)
    			{
    				case IP_ADDR_IDX:
    					if(((struct arp_req *)req)->dst == ((struct sockaddr_in *)dst)->sin_addr.s_addr)
    						memcpy(((struct arp_req *)req)->buf, LLADDR(sdl), 6);
    					break;
    				case HW_ADDR_IDX:
    					if(!memcmp(((struct arp_req *)req)->buf, LLADDR(sdl), 6))
    						*(int *)(((struct arp_req *)req)->dst) = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
    					break;
    			}
    		}
    		else 
    		{
    			diag_printf("%s at ", inet_ntoa(((struct sockaddr_in *)dst)->sin_addr));
    			diag_printf("%s\n", ether_ntoa((struct ether_addr *)LLADDR(sdl)));
    		}
    }

    return 0;
}
Ejemplo n.º 9
0
void
rtfree(struct rtentry *rt)
{
	struct ifaddr	*ifa;

	if (rt == NULL)
		panic("rtfree");

	rt->rt_refcnt--;

	if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
		if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
			panic("rtfree 2");
		rttrash--;
		if (rt->rt_refcnt < 0) {
			printf("rtfree: %p not freed (neg refs)\n", rt);
			return;
		}
		rt_timer_remove_all(rt);
		ifa = rt->rt_ifa;
		if (ifa)
			IFAFREE(ifa);
		rtlabel_unref(rt->rt_labelid);
		Free(rt_key(rt));
		pool_put(&rtentry_pool, rt);
	}
}
Ejemplo n.º 10
0
static void
size_cols_rtentry(struct rtentry *rt)
{
	static struct ifnet ifnet, *lastif;
	static char buffer[100];
	const char *bp;
	struct sockaddr *sa;
	sa_u addr, mask;
	int len;

	bzero(&addr, sizeof(addr));
	if ((sa = kgetsa(rt_key(rt))))
		bcopy(sa, &addr, sa->sa_len);
	bzero(&mask, sizeof(mask));
	if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
		bcopy(sa, &mask, sa->sa_len);
	bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags);
	len = strlen(bp);
	wid_dst = MAX(len, wid_dst);

	bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST);
	len = strlen(bp);
	wid_gw = MAX(len, wid_gw);

	bp = fmt_flags(rt->rt_flags);
	len = strlen(bp);
	wid_flags = MAX(len, wid_flags);

	if (addr.u_sa.sa_family == AF_INET || Wflag) {
		len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt);
		wid_refs = MAX(len, wid_refs);
		len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use);
		wid_use = MAX(len, wid_use);
		if (Wflag && rt->rt_rmx.rmx_mtu != 0) {
			len = snprintf(buffer, sizeof(buffer),
				       "%lu", rt->rt_rmx.rmx_mtu);
			wid_mtu = MAX(len, wid_mtu);
		}
	}
	if (rt->rt_ifp) {
		if (rt->rt_ifp != lastif) {
			if (kget(rt->rt_ifp, ifnet) == 0) 
				len = strlen(ifnet.if_xname);
			else
				len = strlen("---");
			lastif = rt->rt_ifp;
			wid_if = MAX(len, wid_if);
		}
		if (rt->rt_rmx.rmx_expire) {
			time_t expire_time;

			if ((expire_time =
			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) {
				len = snprintf(buffer, sizeof(buffer), "%d",
					       (int)expire_time);
				wid_expire = MAX(len, wid_expire);
			}
		}
	}
}
Ejemplo n.º 11
0
static void
fib6_rte_to_nh_basic(struct rtentry *rte, const struct in6_addr *dst,
    uint32_t flags, struct nhop6_basic *pnh6)
{
	struct sockaddr_in6 *gw;

	/* Do explicit nexthop zero unless we're copying it */
	memset(pnh6, 0, sizeof(*pnh6));

	if ((flags & NHR_IFAIF) != 0)
		pnh6->nh_ifp = fib6_get_ifaifp(rte);
	else
		pnh6->nh_ifp = rte->rt_ifp;

	pnh6->nh_mtu = min(rte->rt_mtu, IN6_LINKMTU(rte->rt_ifp));
	if (rte->rt_flags & RTF_GATEWAY) {
		gw = (struct sockaddr_in6 *)rte->rt_gateway;
		pnh6->nh_addr = gw->sin6_addr;
		in6_clearscope(&pnh6->nh_addr);
	} else
		pnh6->nh_addr = *dst;
	/* Set flags */
	pnh6->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
	gw = (struct sockaddr_in6 *)rt_key(rte);
	if (IN6_IS_ADDR_UNSPECIFIED(&gw->sin6_addr))
		pnh6->nh_flags |= NHF_DEFAULT;
}
Ejemplo n.º 12
0
static int
_radix_walk(int fd, struct radix_node *rn, arp_handler callback, void *arg)
{
	struct radix_node rnode;
	struct rtentry rt;
	struct sockaddr_in sin;
	struct arptab at;
	struct arp_entry entry;
	int ret = 0;
 again:
	_kread(fd, rn, &rnode, sizeof(rnode));
	if (rnode.rn_b < 0) {
		if (!(rnode.rn_flags & RNF_ROOT)) {
			_kread(fd, rn, &rt, sizeof(rt));
			_kread(fd, rt_key(&rt), &sin, sizeof(sin));
			addr_ston((struct sockaddr *)&sin, &entry.arp_pa);
			_kread(fd, rt.rt_llinfo, &at, sizeof(at));
			if (at.at_flags & ATF_COM) {
				addr_pack(&entry.arp_ha, ADDR_TYPE_ETH,
				    ETH_ADDR_BITS, at.at_hwaddr, ETH_ADDR_LEN);
				if ((ret = callback(&entry, arg)) != 0)
					return (ret);
			}
		}
		if ((rn = rnode.rn_dupedkey))
			goto again;
	} else {
		rn = rnode.rn_r;
		if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0)
			return (ret);
		if ((ret = _radix_walk(fd, rn, callback, arg)) != 0)
			return (ret);
	}
	return (ret);
}
Ejemplo n.º 13
0
/*
 * Free an arp entry.
 */
static void
arptfree(struct llinfo_arp *la)
{
	struct rtentry *rt = la->la_rt;
	struct sockaddr_dl *sdl;

	lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
	RT_LOCK_ASSERT_HELD(rt);

	if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
	    sdl->sdl_family == AF_LINK) {
		sdl->sdl_alen = 0;
		la->la_asked = 0;
		rt->rt_flags &= ~RTF_REJECT;
		RT_UNLOCK(rt);
	} else {
		/*
		 * Safe to drop rt_lock and use rt_key, since holding
		 * rnh_lock here prevents another thread from calling
		 * rt_setgate() on this route.
		 */
		RT_UNLOCK(rt);
		rtrequest_locked(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt),
		    0, NULL);
	}
}
Ejemplo n.º 14
0
/*
 * Delete a route and generate a message
 */
int
rtdeletemsg(struct rtentry *rt, u_int tableid)
{
	int			error;
	struct rt_addrinfo	info;
	struct ifnet		*ifp;

	/*
	 * Request the new route so that the entry is not actually
	 * deleted.  That will allow the information being reported to
	 * be accurate (and consistent with route_output()).
	 */
	bzero((caddr_t)&info, sizeof(info));
	info.rti_info[RTAX_DST] = rt_key(rt);
	info.rti_info[RTAX_NETMASK] = rt_mask(rt);
	info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
	info.rti_flags = rt->rt_flags;
	ifp = rt->rt_ifp;
	error = rtrequest1(RTM_DELETE, &info, rt->rt_priority, &rt, tableid);

	rt_missmsg(RTM_DELETE, &info, info.rti_flags, ifp, error, tableid);

	/* Adjust the refcount */
	if (error == 0 && rt->rt_refcnt <= 0) {
		rt->rt_refcnt++;
		rtfree(rt);
	}
	return (error);
}
Ejemplo n.º 15
0
/*
 * Check for alternatives when higher level complains
 * about service problems.  For now, invalidate cached
 * routing information.  If the route was created dynamically
 * (by a redirect), time to try a default gateway again.
 */
void
in_losing(struct inpcb *inp)
{
	register struct rtentry *rt;
	struct rt_addrinfo info;

	if ((rt = inp->inp_route.ro_rt)) {
		inp->inp_route.ro_rt = 0;
		bzero((caddr_t)&info, sizeof(info));
		info.rti_info[RTAX_DST] =
			(struct sockaddr *)&inp->inp_route.ro_dst;
		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
		if (rt->rt_flags & RTF_DYNAMIC)
			(void) rtrequest(RTM_DELETE, rt_key(rt),
				rt->rt_gateway, rt_mask(rt), rt->rt_flags,
				(struct rtentry **)0);
		else
		/*
		 * A new route can be allocated
		 * the next time output is attempted.
		 */
			rtfree(rt);
	}
}
Ejemplo n.º 16
0
/* Gateway selection by Hash-Threshold (RFC 2992) */
struct rtentry *
rn_mpath_select(struct rtentry *rt, uint32_t *srcaddrp)
{
	struct radix_node *rn;
	int hash, npaths, threshold;

	rn = (struct radix_node *)rt;
	npaths = rn_mpath_active_count(rn);
	hash = rn_mpath_hash(rt_key(rt), srcaddrp) & 0xffff;
	threshold = 1 + (0xffff / npaths);
	while (hash > threshold && rn) {
		/* stay within the multipath routes */
		rn = rn_mpath_next(rn, RMP_MODE_ACTIVE);
		hash -= threshold;
	}

	/* if gw selection fails, use the first match (default) */
	if (rn != NULL) {
		rtfree(rt);
		rt = (struct rtentry *)rn;
		rt->rt_refcnt++;
	}

	return (rt);
}
Ejemplo n.º 17
0
struct ifaddr *
ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway,
    u_int rtableid)
{
	struct ifaddr	*ifa;

#ifdef IPSEC
	/*
	 * If the destination is a PF_KEY address, we'll look
	 * for the existence of a encap interface number or address
	 * in the options list of the gateway. By default, we'll return
	 * enc0.
	 */
	if (dst && (dst->sa_family == PF_KEY))
		return (encap_findgwifa(gateway));
#endif

	if ((flags & RTF_GATEWAY) == 0) {
		/*
		 * If we are adding a route to an interface,
		 * and the interface is a pt to pt link
		 * we should search for the destination
		 * as our clue to the interface.  Otherwise
		 * we can use the local address.
		 */
		ifa = NULL;
		if (flags & RTF_HOST)
			ifa = ifa_ifwithdstaddr(dst, rtableid);
		if (ifa == NULL)
			ifa = ifa_ifwithaddr(gateway, rtableid);
	} else {
		/*
		 * If we are adding a route to a remote net
		 * or host, the gateway may still be on the
		 * other end of a pt to pt link.
		 */
		ifa = ifa_ifwithdstaddr(gateway, rtableid);
	}
	if (ifa == NULL)
		ifa = ifa_ifwithnet(gateway, rtableid);
	if (ifa == NULL) {
		struct rtentry	*rt = rtalloc1(gateway, 0, rtable_l2(rtableid));
		if (rt == NULL)
			return (NULL);
		rt->rt_refcnt--;
		/* The gateway must be local if the same address family. */
		if ((rt->rt_flags & RTF_GATEWAY) &&
		    rt_key(rt)->sa_family == dst->sa_family)
			return (0);
		if ((ifa = rt->rt_ifa) == NULL)
			return (NULL);
	}
	if (ifa->ifa_addr->sa_family != dst->sa_family) {
		struct ifaddr	*oifa = ifa;
		ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
		if (ifa == NULL)
			ifa = oifa;
	}
	return (ifa);
}
Ejemplo n.º 18
0
static int
in_ifadownkill(struct radix_node *rn, void *xap)
{
	struct in_ifadown_arg *ap = xap;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;

	if (rt->rt_ifa == ap->ifa && !(rt->rt_flags & RTF_STATIC)) {
		/*
		 * We need to disable the automatic prune that happens
		 * in this case in rtrequest() because it will blow
		 * away the pointers that rn_walktree() needs in order
		 * continue our descent.  We will end up deleting all
		 * the routes that rtrequest() would have in any case,
		 * so that behavior is not needed there.
		 */
		rt->rt_flags &= ~RTF_PRCLONING;
		err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
				rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
		if (err) {
			log(LOG_WARNING, "in_ifadownkill: error %d\n", err);
		}
	}
	return 0;
}
Ejemplo n.º 19
0
/*
 * On last reference drop, mark the route as belong to us so that it can be
 * timed out.
 */
static void
in_clsroute(struct radix_node *rn, struct radix_node_head *head)
{
	struct rtentry *rt = (struct rtentry *)rn;

	if(!(rt->rt_flags & RTF_UP))
		return;		/* prophylactic measures */

	if((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
		return;

	if((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS))
	   != RTF_WASCLONED)
		return;

	/*
	 * As requested by David Greenman:
	 * If rtq_reallyold is 0, just delete the route without
	 * waiting for a timeout cycle to kill it.
	 */
	if(rtq_reallyold != 0) {
		rt->rt_flags |= RTPRF_OURS;
		rt->rt_rmx.rmx_expire = time_second + rtq_reallyold;
	} else {
		rtrequest(RTM_DELETE,
			  (struct sockaddr *)rt_key(rt),
			  rt->rt_gateway, rt_mask(rt),
			  rt->rt_flags, 0);
	}
}
Ejemplo n.º 20
0
static void
fib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst,
    uint32_t flags, struct nhop4_extended *pnh4)
{
	struct sockaddr_in *gw;
	struct in_ifaddr *ia;

	if ((flags & NHR_IFAIF) != 0)
		pnh4->nh_ifp = rte->rt_ifa->ifa_ifp;
	else
		pnh4->nh_ifp = rte->rt_ifp;
	pnh4->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
	if (rte->rt_flags & RTF_GATEWAY) {
		gw = (struct sockaddr_in *)rte->rt_gateway;
		pnh4->nh_addr = gw->sin_addr;
	} else
		pnh4->nh_addr = dst;
	/* Set flags */
	pnh4->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
	gw = (struct sockaddr_in *)rt_key(rte);
	if (gw->sin_addr.s_addr == 0)
		pnh4->nh_flags |= NHF_DEFAULT;
	/* XXX: Set RTF_BROADCAST if GW address is broadcast */

	ia = ifatoia(rte->rt_ifa);
	pnh4->nh_src = IA_SIN(ia)->sin_addr;
}
Ejemplo n.º 21
0
void
rtfree(struct rtentry *rt)
{
	struct ifaddr	*ifa;

	if (rt == NULL)
		panic("rtfree");

	rt->rt_refcnt--;

	if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
		if (rt->rt_refcnt == 0 && (rt->rt_nodes->rn_flags & RNF_ACTIVE))
			return; /* route still active but currently down */
		if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
			panic("rtfree 2");
		rttrash--;
		if (rt->rt_refcnt < 0) {
			printf("rtfree: %p not freed (neg refs)\n", rt);
			return;
		}
		rt_timer_remove_all(rt);
		ifa = rt->rt_ifa;
		if (ifa)
			IFAFREE(ifa);
		rtlabel_unref(rt->rt_labelid);
#ifdef MPLS
		if (rt->rt_flags & RTF_MPLS)
			free(rt->rt_llinfo, M_TEMP);
#endif
		Free(rt_key(rt));
		pool_put(&rtentry_pool, rt);
	}
}
Ejemplo n.º 22
0
struct rtentry *
rtalloc1(struct sockaddr *dst, int report, u_int tableid)
{
	struct radix_node_head	*rnh;
	struct rtentry		*rt;
	struct radix_node	*rn;
	struct rtentry		*newrt = 0;
	struct rt_addrinfo	 info;
	int			 s = splsoftnet(), err = 0, msgtype = RTM_MISS;

	rnh = rt_gettable(dst->sa_family, tableid);
	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
	    ((rn->rn_flags & RNF_ROOT) == 0)) {
		newrt = rt = (struct rtentry *)rn;
		if (report && (rt->rt_flags & RTF_CLONING)) {
			err = rtrequest(RTM_RESOLVE, dst, SA(NULL),
			    SA(NULL), 0, &newrt, tableid);
			if (err) {
				newrt = rt;
				rt->rt_refcnt++;
				goto miss;
			}
			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
				msgtype = RTM_RESOLVE;
				goto miss;
			}
			/* Inform listeners of the new route */
			bzero(&info, sizeof(info));
			info.rti_info[RTAX_DST] = rt_key(rt);
			info.rti_info[RTAX_NETMASK] = rt_mask(rt);
			info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
			if (rt->rt_ifp != NULL) {
				info.rti_info[RTAX_IFP] =
				    TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr;
				info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
			}
			rt_missmsg(RTM_ADD, &info, rt->rt_flags,
			    rt->rt_ifp, 0, tableid);
		} else
			rt->rt_refcnt++;
	} else {
		if (dst->sa_family != PF_KEY)
			rtstat.rts_unreach++;
	/*
	 * IP encapsulation does lots of lookups where we don't need nor want
	 * the RTM_MISSes that would be generated.  It causes RTM_MISS storms
	 * sent upward breaking user-level routing queries.
	 */
miss:
		if (report && dst->sa_family != PF_KEY) {
			bzero((caddr_t)&info, sizeof(info));
			info.rti_info[RTAX_DST] = dst;
			rt_missmsg(msgtype, &info, 0, NULL, err, tableid);
		}
	}
	splx(s);
	return (newrt);
}
Ejemplo n.º 23
0
struct sockaddr *
rt_plen2mask(struct rtentry *rt, struct sockaddr_in6 *sa_mask)
{
#ifndef ART
	return (rt_mask(rt));
#else
	return (rt_plentosa(rt_key(rt)->sa_family, rt_plen(rt), sa_mask));
#endif /* ART */
}
Ejemplo n.º 24
0
int
rtentry_delete(struct rtentry *rt, void *w, unsigned int rid)
{
	char			 dest[INET6_ADDRSTRLEN];
	sa_family_t		 af = rt_key(rt)->sa_family;
	struct sockaddr_in6	 sa_mask;
	struct sockaddr		*mask = rt_plen2mask(rt, &sa_mask);
	int			 error;

	assert(rt_plen(rt) == rtable_satoplen(af, mask));

	if ((error = rtable_delete(0, rt_key(rt), mask, rt)) != 0) {
		inet_net_satop(af, rt_key(rt), rt_plen(rt), dest, sizeof(dest));
		errx(1, "can't rm route: %s, %s\n", dest, strerror(error));
	}

	return (0);
}
Ejemplo n.º 25
0
/*
 * Get rid of old routes.  When draining, this deletes everything, even when
 * the timeout is not expired yet.  This also applies if the route is dynamic
 * and there are sufficiently large number of such routes (more than a half of
 * maximum).  When updating, this makes sure that nothing has a timeout longer
 * than the current value of rtq_reallyold.
 */
static int
in6_rtqkill(struct radix_node *rn, void *rock)
{
	struct rtqk_arg *ap = rock;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;
	struct timeval timenow;

	getmicrotime(&timenow);
	lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);

	RT_LOCK(rt);
	if (rt->rt_flags & RTPRF_OURS) {
		ap->found++;

		if (ap->draining || rt->rt_rmx.rmx_expire <= timenow.tv_sec ||
		    ((rt->rt_flags & RTF_DYNAMIC) != 0 &&
		    ip6_maxdynroutes >= 0 &&
		    in6dynroutes > ip6_maxdynroutes / 2)) {
			if (rt->rt_refcnt > 0)
				panic("rtqkill route really not free");

			/*
			 * Delete this route since we're done with it;
			 * the route may be freed afterwards, so we
			 * can no longer refer to 'rt' upon returning
			 * from rtrequest().  Safe to drop rt_lock and
			 * use rt_key, rt_gateway, since holding rnh_lock
			 * here prevents another thread from calling
			 * rt_setgate() on this route.
			 */
			RT_UNLOCK(rt);
			err = rtrequest_locked(RTM_DELETE, rt_key(rt),
			    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
			if (err) {
				log(LOG_WARNING, "in6_rtqkill: error %d", err);
			} else {
				ap->killed++;
			}
		} else {
			if (ap->updating
			   && (rt->rt_rmx.rmx_expire - timenow.tv_sec
			       > rtq_reallyold)) {
				rt->rt_rmx.rmx_expire = timenow.tv_sec
					+ rtq_reallyold;
			}
			ap->nextstop = lmin(ap->nextstop,
					    rt->rt_rmx.rmx_expire);
			RT_UNLOCK(rt);
		}
	} else {
		RT_UNLOCK(rt);
	}

	return 0;
}
Ejemplo n.º 26
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int staticrt_delete( struct radix_node *rn, void *vifp )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if((rt->rt_flags & RTF_STATIC) && !(rt->rt_flags & RTF_LLINFO))
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              0, NULL);
	}
	return 0;
}
Ejemplo n.º 27
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int ifprt_delete( struct radix_node *rn, void *ifp )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if(rt->rt_ifp == ifp)
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              rt->rt_flags, NULL);
	}
	return 0;
}
Ejemplo n.º 28
0
static void
p_rtentry(struct rtentry *rt)
{
	static struct ifnet ifnet, *lastif;
	static char buffer[128];
	static char prettyname[128];
	struct sockaddr *sa;
	sa_u addr, mask;

	bzero(&addr, sizeof(addr));
	if ((sa = kgetsa(rt_key(rt))))
		bcopy(sa, &addr, sa->sa_len);
	bzero(&mask, sizeof(mask));
	if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
		bcopy(sa, &mask, sa->sa_len);
	p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst);
	p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
	snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
	p_flags(rt->rt_flags, buffer);
	if (addr.u_sa.sa_family == AF_INET || Wflag) {
#if 0
		printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
				     wid_use, rt->rt_use);
#endif
		if (Wflag) {
			if (rt->rt_rmx.rmx_mtu != 0)
				printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
			else
				printf("%*s ", wid_mtu, "");
		}
	}
	if (rt->rt_ifp) {
		if (rt->rt_ifp != lastif) {
			if (kget(rt->rt_ifp, ifnet) == 0)
				strlcpy(prettyname, ifnet.if_xname,
				    sizeof(prettyname));
			else
				strlcpy(prettyname, "---", sizeof(prettyname));
			lastif = rt->rt_ifp;
		}
		printf("%*.*s", wid_if, wid_if, prettyname);
		if (rt->rt_rmx.rmx_expire) {
			time_t expire_time;

			if ((expire_time =
			    rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0)
				printf(" %*d", wid_expire, (int)expire_time);
		}
		if (rt->rt_nodes[0].rn_dupedkey)
			printf(" =>");
	}
	putchar('\n');
}
Ejemplo n.º 29
0
void
bootpboot_p_rtentry(struct rtentry *rt)
{

	bootpboot_p_sa(rt_key(rt), rt_mask(rt));
	printf(" ");
	bootpboot_p_sa(rt->rt_gateway, NULL);
	printf(" ");
	printf("flags %x", (unsigned short) rt->rt_flags);
	printf(" %d", (int) rt->rt_rmx.rmx_expire);
	printf(" %s\n", rt->rt_ifp->if_xname);
}
Ejemplo n.º 30
0
/*
 * On last reference drop, mark the route as belong to us so that it can be
 * timed out.
 */
static void
in6_clsroute(struct radix_node *rn, __unused struct radix_node_head *head)
{
	struct rtentry *rt = (struct rtentry *)rn;

	lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
	RT_LOCK_ASSERT_HELD(rt);

	if (!(rt->rt_flags & RTF_UP))
		return;		/* prophylactic measures */

	if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
		return;

	if (rt->rt_flags & RTPRF_OURS)
		return;

	if (!(rt->rt_flags & (RTF_WASCLONED | RTF_DYNAMIC)))
		return;

	/*
	 * Delete the route immediately if RTF_DELCLONE is set or
	 * if route caching is disabled (rtq_reallyold set to 0).
	 * Otherwise, let it expire and be deleted by in6_rtqkill().
	 */
	if ((rt->rt_flags & RTF_DELCLONE) || rtq_reallyold == 0) {
		/*
		 * Delete the route from the radix tree but since we are
		 * called when the route's reference count is 0, don't
		 * deallocate it until we return from this routine by
		 * telling rtrequest that we're interested in it.
		 * Safe to drop rt_lock and use rt_key, rt_gateway,
		 * since holding rnh_lock here prevents another thread
		 * from calling rt_setgate() on this route.
		 */
		RT_UNLOCK(rt);
		if (rtrequest_locked(RTM_DELETE, rt_key(rt),
		    rt->rt_gateway, rt_mask(rt), rt->rt_flags, &rt) == 0) {
			/* Now let the caller free it */
			RT_LOCK(rt);
			RT_REMREF_LOCKED(rt);
		} else {
			RT_LOCK(rt);
		}
	} else {
		struct timeval timenow;

		getmicrotime(&timenow);
		rt->rt_flags |= RTPRF_OURS;
		rt->rt_rmx.rmx_expire = timenow.tv_sec + rtq_reallyold;
	}
}