Exemple #1
0
int main(int argc, char const* argv[]) {
	Input default_gateway_input;
	Input address;
	const Entry* entry;

	RouterTrie rt;
	// default_gateway_input = rt_create_default_gateway_input(
	// 		rt_convert_string_to_address("2001::1"), 0);

	rt_setup(&rt);
	// rt_default_gateway(&rt, &default_gateway_input);


	address.prefix_length = 64;
	address.interface = 1;
	address.next_hop = rt_convert_string_to_address("::1");
	address.address = rt_convert_string_to_address("2a00:1450:4001:817::0");
	rt_insert(&rt, &address);

	address.prefix_length = 64;
	address.interface = 2;
	address.next_hop = rt_convert_string_to_address("::2");
	address.address = rt_convert_string_to_address("2aff:1450:4001:817::0");
	rt_insert(&rt, &address);

	address.address = rt_convert_string_to_address("2aff:1450:4001:817::0");

	entry = rt_match(&rt, &address.address);
	printf("%d\n", entry ? entry->interface : 0);

	rt_destroy(&rt);
	return 0;
}
Exemple #2
0
/**
 * Handles incoming routing-request packets.
 */
static void krip_dispatch_in()
{
	fd_set fds;
	struct timeval timeout;
	int rc;
	int i;
	list_position pos;
	rip_info *ri;

	FD_ZERO(&fds);
	FD_SET(_sock, &fds);
	timeout.tv_sec = 0;
	timeout.tv_usec = 0;

	/* The main loop of the RIP daemon. */
	while ((rc = select(_sock + 1, &fds, NULL, NULL, &timeout)) > 0) {
		rip_buf buf;
		uint32_t now = krip_get_mtime();
		size_t len = RIP_PACKET_MAXSIZ;
		struct sockaddr_in from;
		size_t fromlen = sizeof(from);
		len = recvfrom(_sock, buf.buf, len, 0, (struct sockaddr *)&from, &fromlen);

		/* Find the sender by matching IP addresses and ports. */
		neighbor_info *ni = NULL;
		pos = list_get_head_position(_neighbor_info_list);
		for (; pos; pos = list_get_next_position(pos)) {
			ni = list_get_at(pos);
			if (from.sin_addr.s_addr == ni->krip_addr.sin_addr.s_addr &&
					from.sin_port == ni->krip_addr.sin_port)
				break;
			/* Should be reset to perform below check routines correctly.
			   (ref http://noah.kaist.ac.kr/view.jsp?board=1353&serial=517685) */
			ni = NULL;
		}

		/* If the sender is not recoginized, skip the RIP message. */
		if (!ni) {
			L_ROUTE("krip_dispatch_in(): unknown neighbor %s:%d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
			continue;
		}

		/* If the interface received is disabled, also skip it. */
		if (!ni->ifp->if_enabled) {
			L_ROUTE("krip_dispatch_in(): ignored response from %s {%08x}", inet_ntoa(ni->virtual_addr), ni->ifp);
			continue;
		}

		/* Process RIP packets. */
		switch (buf.rip_packet.command) {
		case RIP_REQUEST:

			/* Response to the request. */
			L_ROUTE("krip_dispatch_in(): RIP_REQUEST from %s {%08x}", inet_ntoa(ni->virtual_addr), ni->ifp);
			krip_send_response(ni, 0);
			break;

		case RIP_RESPONSE:
			/* RIP 응답 패킷을 받으면 그것을 바탕으로 자신의 routing table 정보를 업데이트한다. */

			i = 0;
			L_ROUTE("krip_dispatch_in(): RIP_RESPONSE from %s {%08x} with %d entries.",
				inet_ntoa(ni->virtual_addr),
				ni->ifp,
				(len - RIP_HEADER_SIZE) / RIP_RTE_SIZE);

			/* Look up the received routing table entries. */
			while (1) {
				bool found = false;
				rte *rte = buf.rip_packet.rte + i;
				/* Convert endians. */
				rte->family = ntohs(rte->family);
				rte->tag = ntohs(rte->tag);
				rte->metric = ntohl(rte->metric);

				/* Stop if the index reaches the number of available routing entries in the packet. */
				if (i == (len - RIP_HEADER_SIZE) / RIP_RTE_SIZE)
					break;
				L_ROUTE("krip_dispatch_in(): processing entry %d (prefix=%s, mask=%s, metric=%d)", i + 1,
						inet_ntoa(rte->prefix),
						inet_ntoa(rte->mask),
						rte->metric);

				/* 여기에서 distance vector 알고리즘이 구현된다. */
				/* Choose minimum of received metric + 1 and inifinity. */
				uint32_t new_metric = MIN(rte->metric + 1, RIP_METRIC_INFINITY);

				for (pos = list_get_head_position(_rip_info_list); pos; pos = list_get_next_position(pos)) {
					ri = list_get_at(pos);

					/* 여기에서 match된다는 뜻은 어디로 해당 IP 대역을 담당하는 routing entry를 찾았다는 뜻이다. */

					/* If a routing_info matches an entry, update related information. */
					if (ri->assoc_rte->dst.s_addr == rte->prefix.s_addr) {
						L_ROUTE("krip_dispatch_in(): ri->assoc_rte->dst = %s {%08x} has to be updated.",
							inet_ntoa(ri->assoc_rte->dst),
							ri->from);
						found = true;

						/* If ri is from the neighbor which sent the RIP message, refresh timeout. */
						if (ri->from == ni->ifp) {
							ri->timeout = now + _timeout;
						}

						/* 현재 보고 있는 rip_info가 RIP message를 받은 interface로부터 온 것이고 metric 값이 바뀌거나,
						   새 metric 값이 더 낮을 경우(더 좋은 route임을 뜻함) rip_info를 새로 업데이트한다.
						   (ref http://noah.kaist.ac.kr/view.jsp?board=1248&serial=509303) */
						if ((ri->from == ni->ifp && new_metric != ri->metric) || (ri->metric > new_metric)) {
							/* If previous ri was advertised by the sender, or the new route has lower metric,
							   update ri. */
							L_ROUTE("krip_dispatch_in(): updating existing routing info... (gw = %s {%08x}, metric = %d)",
								inet_ntoa(ni->virtual_addr),
								ni->ifp,
								new_metric);
							ri->assoc_rte->gw.s_addr = ni->virtual_addr.s_addr;
							ri->assoc_rte->rt_ifp = ni->ifp;
							ri->metric = new_metric;
							ri->change_flag = 1; /* Mark it as modified. */
							ri->from = ni->ifp;
							ip_invalidate_forward_rt_cache();
							_trigger = true;
						}
					}
				}
				if (!found) {
					/* If matching routing info is not found, create a new routing entry and routing info. */
					L_ROUTE("krip_dispatch_in(): creating a new routing entry...");
					rtentry *new_rte = (rtentry *)malloc(sizeof(rtentry));
					new_rte->dst = rte->prefix;
					new_rte->mask = rte->mask;
					new_rte->gw = ni->virtual_addr;
					new_rte->rt_ifp = ni->ifp;
					if (rt_insert(new_rte)) {
						L_ROUTE("krip_dispatch_in(): failed to insert new route");
						free(new_rte);
						break;
					}
					ri = (rip_info *)malloc(sizeof(rip_info));
					ri->assoc_rte = new_rte;
					ri->metric = new_metric;
					ri->change_flag = 1; /* Mark it as modified. */
					ri->timeout = now + _timeout; /* Initialize timeout. */
					ri->from = ni->ifp;
					list_add_tail(_rip_info_list, ri);
					ip_invalidate_forward_rt_cache();
					_trigger = true;
				}
				i++;
			}
			break;

		default:
			L_ROUTE("krip_dispatch_in(): unrecognized RIP command type (%d) from %s.",
				buf.rip_packet.command,
				inet_ntoa(ni->virtual_addr));
			break;
		}
	}
	
	if (rc < 0)
		perror("krip");
}
Exemple #3
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);
}
Exemple #4
0
/* ARGSUSED */
void
rde_dispatch_parent(int fd, short event, void *bula)
{
	struct imsg		 imsg;
	struct rt_node		*rt;
	struct kroute		 kr;
	struct imsgev		*iev = bula;
	struct imsgbuf		*ibuf = &iev->ibuf;
	ssize_t			 n;
	int			 shut = 0;

	if (event & EV_READ) {
		if ((n = imsg_read(ibuf)) == -1)
			fatal("imsg_read error");
		if (n == 0)	/* connection closed */
			shut = 1;
	}
	if (event & EV_WRITE) {
		if (msgbuf_write(&ibuf->w) == -1 && errno != EAGAIN)
			fatal("msgbuf_write");
	}

	for (;;) {
		if ((n = imsg_get(ibuf, &imsg)) == -1)
			fatal("rde_dispatch_parent: imsg_read error");
		if (n == 0)
			break;

		switch (imsg.hdr.type) {
		case IMSG_NETWORK_ADD:
			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) {
				log_warnx("rde_dispatch: wrong imsg len");
				break;
			}

			memcpy(&kr, imsg.data, sizeof(kr));

			rt = rt_new_kr(&kr);
			rt_insert(rt);
			break;
		case IMSG_NETWORK_DEL:
			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) {
				log_warnx("rde_dispatch: wrong imsg len");
				break;
			}
			memcpy(&kr, imsg.data, sizeof(kr));

			if ((rt = rt_find(kr.prefix.s_addr,
			    kr.netmask.s_addr)) != NULL)
				rt_remove(rt);
			break;
		default:
			log_debug("rde_dispatch_parent: unexpected imsg %d",
			    imsg.hdr.type);
			break;
		}
		imsg_free(&imsg);
	}
	if (!shut)
		imsg_event_add(iev);
	else {
		/* this pipe is dead, so remove the event handler */
		event_del(&iev->ev);
		event_loopexit(NULL);
	}
}