Пример #1
0
/* ARGSNOTUSED */
void
kev_dispatch_msg(int fd, short event, void *bula)
{
	char			 buf[RT_BUF_SIZE];
	char			*next, *lim;
	ssize_t			 n;
	struct rt_msghdr	*rtm;
	struct if_msghdr	 ifm;
	struct iface		*iface;

	if ((n = read(kev_state.fd, &buf, sizeof(buf))) == -1)
		fatal("kev_dispatch_rtmsg: read error");

	if (n == 0)
		fatalx("kernel event socket closed");

	lim = buf + n;
	for (next = buf; next < lim; next += rtm->rtm_msglen) {
		memcpy(&ifm, next, sizeof(ifm));
		rtm = (struct rt_msghdr *)next;
		if (rtm->rtm_version != RTM_VERSION)
			continue;

		iface = if_find_index(ifm.ifm_index);
		if (iface == NULL) /* this interface isn't configured */
			continue;

		switch (rtm->rtm_type) {
		case RTM_IFINFO:
			log_debug("RTM_IFINFO");
			if (LINK_STATE_IS_UP(ifm.ifm_data.ifi_link_state))
				if_fsm(iface, IF_EVT_UP);
			else
				if_fsm(iface, IF_EVT_DOWN);

			break;
		case RTM_IFANNOUNCE:
			log_debug("RTM_IFANNOUNCE");
			break;
		case RTM_NEWADDR:
			/* TODO */
			log_debug("RTM_NEWADDR");
			break;
		case RTM_DELADDR:
			/* TODO */
			log_debug("RTM_DELADDR");
			break;
		default:
			/* ignore for now */
			break;
		}
	}
}
Пример #2
0
int
rde_check_route(struct rip_route *e)
{
	struct timeval	 tv, now;
	struct rt_node	*rn;
	struct iface	*iface;
	u_int8_t	 metric;

	if ((e->nexthop.s_addr & htonl(IN_CLASSA_NET)) ==
	    htonl(INADDR_LOOPBACK & IN_CLASSA_NET) ||
	    e->nexthop.s_addr == INADDR_ANY)
		return (-1);

	if ((iface = if_find_index(e->ifindex)) == NULL)
		return (-1);

	metric = MIN(INFINITY, e->metric + iface->cost);

	if ((rn = rt_find(e->address.s_addr, e->mask.s_addr)) == NULL) {
		if (metric >= INFINITY)
			return (0);
		rn = rt_new_rr(e, metric);
		rt_insert(rn);
		rde_send_change_kroute(rn);
		route_start_timeout(rn);
		triggered_update(rn);
	} else {
		/*
		 * XXX don't we have to track all incoming routes?
		 * what happens if the kernel route is removed later.
		 */
		if (rn->flags & F_KERNEL)
			return (0);

		if (metric < rn->metric) {
			rn->metric = metric;
			rn->nexthop.s_addr = e->nexthop.s_addr;
			rn->ifindex = e->ifindex;
			rde_send_change_kroute(rn);
			triggered_update(rn);
		} else if (e->nexthop.s_addr == rn->nexthop.s_addr &&
		    metric > rn->metric) {
				rn->metric = metric;
				rde_send_change_kroute(rn);
				triggered_update(rn);
				if (rn->metric == INFINITY)
					route_start_garbage(rn);
		} else if (e->nexthop.s_addr != rn->nexthop.s_addr &&
		    metric == rn->metric) {
			/* If the new metric is the same as the old one,
			 * examine the timeout for the existing route.  If it
			 * is at least halfway to the expiration point, switch
			 * to the new route.
			 */
			timerclear(&tv);
			gettimeofday(&now, NULL);
			evtimer_pending(&rn->timeout_timer, &tv);
			if (tv.tv_sec - now.tv_sec < ROUTE_TIMEOUT / 2) {
				rn->nexthop.s_addr = e->nexthop.s_addr;
				rn->ifindex = e->ifindex;
				rde_send_change_kroute(rn);
			}
		}

		if (e->nexthop.s_addr == rn->nexthop.s_addr &&
		    rn->metric < INFINITY)
			route_reset_timers(rn);
	}

	return (0);
}