int do_ipmonitor(int argc, char **argv)
{
	char *file = NULL;
	unsigned groups = ~RTMGRP_TC;
	int llink=0;
	int laddr=0;
	int lroute=0;
	int lprefix=0;
	int lneigh=0;

	rtnl_close(&rth);
	ipaddr_reset_filter(1);
	iproute_reset_filter();
	ipneigh_reset_filter();

	while (argc > 0) {
		if (matches(*argv, "file") == 0) {
			NEXT_ARG();
			file = *argv;
		} else if (matches(*argv, "link") == 0) {
			llink=1;
			groups = 0;
		} else if (matches(*argv, "address") == 0) {
			laddr=1;
			groups = 0;
		} else if (matches(*argv, "route") == 0) {
			lroute=1;
			groups = 0;
		} else if (matches(*argv, "prefix") == 0) {
			lprefix=1;
			groups = 0;
		} else if (matches(*argv, "neigh") == 0) {
			lneigh = 1;
			groups = 0;
		} else if (strcmp(*argv, "all") == 0) {
			groups = ~RTMGRP_TC;
			prefix_banner=1;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv);
			exit(-1);
		}
		argc--;	argv++;
	}

	if (llink)
		groups |= nl_mgrp(RTNLGRP_LINK);
	if (laddr) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
	}
	if (lroute) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
	}
	if (lprefix) {
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
	}
	if (lneigh) {
		groups |= nl_mgrp(RTNLGRP_NEIGH);
	}
	if (file) {
		FILE *fp;
		fp = fopen(file, "r");
		if (fp == NULL) {
			perror("Cannot fopen");
			exit(-1);
		}
		return rtnl_from_file(fp, accept_msg, stdout);
	}

	if (rtnl_open(&rth, groups) < 0)
		exit(1);
	ll_init_map(&rth);

	if (rtnl_listen(&rth, accept_msg, stdout) < 0)
		exit(2);

	return 0;
}
int do_ipmonitor(int argc, char **argv)
{
	struct rtnl_handle rth;
	char *file = NULL;
	unsigned groups = ~RTMGRP_TC;
	int llink=0;
	int laddr=0;
	int lroute=0;

	ipaddr_reset_filter(1);
	iproute_reset_filter();
	ipneigh_reset_filter();

	while (argc > 0) {
		if (matches(*argv, "file") == 0) {
			NEXT_ARG();
			file = *argv;
		} else if (matches(*argv, "link") == 0) {
			llink=1;
			groups = 0;
		} else if (matches(*argv, "address") == 0) {
			laddr=1;
			groups = 0;
		} else if (matches(*argv, "route") == 0) {
			lroute=1;
			groups = 0;
		} else if (strcmp(*argv, "all") == 0) {
			groups = ~RTMGRP_TC;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv);
			exit(-1);
		}
		argc--;	argv++;
	}

	if (llink)
		groups |= RTMGRP_LINK;
	if (laddr) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= RTMGRP_IPV4_IFADDR;
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= RTMGRP_IPV6_IFADDR;
	}
	if (lroute) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= RTMGRP_IPV4_ROUTE;
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= RTMGRP_IPV6_ROUTE;
	}

	if (file) {
		FILE *fp;
		fp = fopen(file, "r");
		if (fp == NULL) {
			perror("Cannot fopen");
			exit(-1);
		}
		return rtnl_from_file(fp, accept_msg, (void*)stdout);
	}

	if (rtnl_open(&rth, groups) < 0)
		exit(1);

	ll_init_map(&rth);

	if (rtnl_listen(&rth, accept_msg, (void*)stdout) < 0)
		exit(2);

	exit(0);
}
Esempio n. 3
0
static int iproute_get(int argc, char **argv)
{
	struct rtnl_handle rth;
	struct {
		struct nlmsghdr 	n;
		struct rtmsg 		r;
		char   			buf[1024];
	} req;
	char  *idev = NULL;
	char  *odev = NULL;
	int connected = 0;
	int from_ok = 0;
	const char *options[] = { "from", "iif", "oif", "dev", "notify", "connected", "to", 0 };

	memset(&req, 0, sizeof(req));

	iproute_reset_filter();

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_GETROUTE;
	req.r.rtm_family = preferred_family;
	req.r.rtm_table = 0;
	req.r.rtm_protocol = 0;
	req.r.rtm_scope = 0;
	req.r.rtm_type = 0;
	req.r.rtm_src_len = 0;
	req.r.rtm_dst_len = 0;
	req.r.rtm_tos = 0;
	
	while (argc > 0) {
		switch (compare_string_array(options, *argv)) {
			case 0: /* from */
			{
				inet_prefix addr;
				NEXT_ARG();
				from_ok = 1;
				get_prefix(&addr, *argv, req.r.rtm_family);
				if (req.r.rtm_family == AF_UNSPEC) {
					req.r.rtm_family = addr.family;
				}
				if (addr.bytelen) {
					addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen);
				}
				req.r.rtm_src_len = addr.bitlen;
				break;
			}
			case 1: /* iif */
				NEXT_ARG();
				idev = *argv;
				break;
			case 2: /* oif */
			case 3: /* dev */
				NEXT_ARG();
				odev = *argv;
				break;
			case 4: /* notify */
				req.r.rtm_flags |= RTM_F_NOTIFY;
				break;
			case 5: /* connected */
				connected = 1;
				break;
			case 6: /* to */
				NEXT_ARG();
			default:
			{
				inet_prefix addr;
				get_prefix(&addr, *argv, req.r.rtm_family);
				if (req.r.rtm_family == AF_UNSPEC) {
					req.r.rtm_family = addr.family;
				}
				if (addr.bytelen) {
					addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen);
				}
				req.r.rtm_dst_len = addr.bitlen;
			}
			argc--; argv++;
		}
	}

	if (req.r.rtm_dst_len == 0) {
		bb_error_msg_and_die("need at least destination address");
	}

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	ll_init_map(&rth);

	if (idev || odev)  {
		int idx;

		if (idev) {
			if ((idx = ll_name_to_index(idev)) == 0) {
				bb_error_msg("Cannot find device \"%s\"", idev);
				return -1;
			}
			addattr32(&req.n, sizeof(req), RTA_IIF, idx);
		}
		if (odev) {
			if ((idx = ll_name_to_index(odev)) == 0) {
				bb_error_msg("Cannot find device \"%s\"", odev);
				return -1;
			}
			addattr32(&req.n, sizeof(req), RTA_OIF, idx);
		}
	}

	if (req.r.rtm_family == AF_UNSPEC) {
		req.r.rtm_family = AF_INET;
	}

	if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
		exit(2);
	}

	if (connected && !from_ok) {
		struct rtmsg *r = NLMSG_DATA(&req.n);
		int len = req.n.nlmsg_len;
		struct rtattr * tb[RTA_MAX+1];

		if (print_route(NULL, &req.n, (void*)stdout) < 0) {
			bb_error_msg_and_die("An error :-)");
		}

		if (req.n.nlmsg_type != RTM_NEWROUTE) {
			bb_error_msg("Not a route?");
			return -1;
		}
		len -= NLMSG_LENGTH(sizeof(*r));
		if (len < 0) {
			bb_error_msg("Wrong len %d", len);
			return -1;
		}

		memset(tb, 0, sizeof(tb));
		parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);

		if (tb[RTA_PREFSRC]) {
			tb[RTA_PREFSRC]->rta_type = RTA_SRC;
			r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
		} else if (!tb[RTA_SRC]) {
			bb_error_msg("Failed to connect the route");
			return -1;
		}
		if (!odev && tb[RTA_OIF]) {
			tb[RTA_OIF]->rta_type = 0;
		}
		if (tb[RTA_GATEWAY]) {
			tb[RTA_GATEWAY]->rta_type = 0;
		}
		if (!idev && tb[RTA_IIF]) {
			tb[RTA_IIF]->rta_type = 0;
		}
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETROUTE;

		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
			exit(2);
		}
	}

	if (print_route(NULL, &req.n, (void*)stdout) < 0) {
		bb_error_msg_and_die("An error :-)");
	}

	exit(0);
}
Esempio n. 4
0
static int iproute_list_or_flush(int argc, char **argv, int flush)
{
	int do_ipv6 = preferred_family;
	struct rtnl_handle rth;
	char *id = NULL;
	char *od = NULL;

	iproute_reset_filter();
	filter.tb = RT_TABLE_MAIN;

	if (flush && argc <= 0) {
		fprintf(stderr, "\"ip route flush\" requires arguments.\n");
		return -1;
	}

	while (argc > 0) {
		if (matches(*argv, "protocol") == 0) {
			int prot = 0;
			NEXT_ARG();
			filter.protocolmask = -1;
			if (rtnl_rtprot_a2n(&prot, *argv)) {
				if (strcmp(*argv, "all") != 0) {
					invarg("invalid \"protocol\"\n", *argv);
				}
				prot = 0;
				filter.protocolmask = 0;
			}
			filter.protocol = prot;
		} else if (strcmp(*argv, "dev") == 0 ||
			   strcmp(*argv, "oif") == 0) {
			NEXT_ARG();
			od = *argv;
		} else if (strcmp(*argv, "iif") == 0) {
			NEXT_ARG();
			id = *argv;
		} else if (matches(*argv, "from") == 0) {
			NEXT_ARG();
			if (matches(*argv, "root") == 0) {
				NEXT_ARG();
				get_prefix(&filter.rsrc, *argv, do_ipv6);
			} else if (matches(*argv, "match") == 0) {
				NEXT_ARG();
				get_prefix(&filter.msrc, *argv, do_ipv6);
			} else {
				if (matches(*argv, "exact") == 0) {
					NEXT_ARG();
				}
				get_prefix(&filter.msrc, *argv, do_ipv6);
				filter.rsrc = filter.msrc;
			}
		} else {
			if (matches(*argv, "to") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "root") == 0) {
				NEXT_ARG();
				get_prefix(&filter.rdst, *argv, do_ipv6);
			} else if (matches(*argv, "match") == 0) {
				NEXT_ARG();
				get_prefix(&filter.mdst, *argv, do_ipv6);
			} else {
				if (matches(*argv, "exact") == 0) {
					NEXT_ARG();
				}
				get_prefix(&filter.mdst, *argv, do_ipv6);
				filter.rdst = filter.mdst;
			}
		}
		argc--; argv++;
	}

	if (do_ipv6 == AF_UNSPEC && filter.tb) {
		do_ipv6 = AF_INET;
	}

	if (rtnl_open(&rth, 0) < 0) {
		exit(1);
	}

	ll_init_map(&rth);

	if (id || od)  {
		int idx;

		if (id) {
			if ((idx = ll_name_to_index(id)) == 0) {
				bb_error_msg("Cannot find device \"%s\"", id);
				return -1;
			}
			filter.iif = idx;
			filter.iifmask = -1;
		}
		if (od) {
			if ((idx = ll_name_to_index(od)) == 0) {
				bb_error_msg("Cannot find device \"%s\"", od);
			}
			filter.oif = idx;
			filter.oifmask = -1;
		}
	}

	if (flush) {
		int round = 0;
		char flushb[4096-512];

		if (filter.tb == -1) {
			if (do_ipv6 != AF_INET6)
				iproute_flush_cache();
			if (do_ipv6 == AF_INET)
				return 0;
		}

		filter.flushb = flushb;
		filter.flushp = 0;
		filter.flushe = sizeof(flushb);
		filter.rth = &rth;

		for (;;) {
			if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
				perror("Cannot send dump request");
				return -1;
			}
			filter.flushed = 0;
			if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
				bb_error_msg("Flush terminated\n");
				return -1;
			}
			if (filter.flushed == 0) {
				if (round == 0) {
					if (filter.tb != -1 || do_ipv6 == AF_INET6)
						fprintf(stderr, "Nothing to flush.\n");
				}
				fflush(stdout);
				return 0;
			}
			round++;
			if (flush_update() < 0)
				exit(1);
		}
	}

	if (filter.tb != -1) {
		if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
			bb_perror_msg_and_die("Cannot send dump request");
		}
	} else {
		if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
			bb_perror_msg_and_die("Cannot send dump request");
		}
	}

	if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
		bb_error_msg_and_die("Dump terminated");
	}

	exit(0);
}
Esempio n. 5
0
int do_ipmonitor(int argc, char **argv)
{
	char *file = NULL;
	unsigned int groups = 0;
	int llink = 0;
	int laddr = 0;
	int lroute = 0;
	int lmroute = 0;
	int lprefix = 0;
	int lneigh = 0;
	int lnetconf = 0;
	int lrule = 0;
	int lnsid = 0;
	int ifindex = 0;

	groups |= nl_mgrp(RTNLGRP_LINK);
	groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
	groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
	groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
	groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
	groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE);
	groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE);
	groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE);
	groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
	groups |= nl_mgrp(RTNLGRP_NEIGH);
	groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF);
	groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
	groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
	groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
	groups |= nl_mgrp(RTNLGRP_NSID);
	groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF);

	rtnl_close(&rth);

	while (argc > 0) {
		if (matches(*argv, "file") == 0) {
			NEXT_ARG();
			file = *argv;
		} else if (matches(*argv, "label") == 0) {
			prefix_banner = 1;
		} else if (matches(*argv, "link") == 0) {
			llink = 1;
			groups = 0;
		} else if (matches(*argv, "address") == 0) {
			laddr = 1;
			groups = 0;
		} else if (matches(*argv, "route") == 0) {
			lroute = 1;
			groups = 0;
		} else if (matches(*argv, "mroute") == 0) {
			lmroute = 1;
			groups = 0;
		} else if (matches(*argv, "prefix") == 0) {
			lprefix = 1;
			groups = 0;
		} else if (matches(*argv, "neigh") == 0) {
			lneigh = 1;
			groups = 0;
		} else if (matches(*argv, "netconf") == 0) {
			lnetconf = 1;
			groups = 0;
		} else if (matches(*argv, "rule") == 0) {
			lrule = 1;
			groups = 0;
		} else if (matches(*argv, "nsid") == 0) {
			lnsid = 1;
			groups = 0;
		} else if (strcmp(*argv, "all") == 0) {
			prefix_banner = 1;
		} else if (matches(*argv, "all-nsid") == 0) {
			listen_all_nsid = 1;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();

			ifindex = ll_name_to_index(*argv);
			if (!ifindex)
				invarg("Device does not exist\n", *argv);
		} else {
			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv);
			exit(-1);
		}
		argc--;	argv++;
	}

	ipaddr_reset_filter(1, ifindex);
	iproute_reset_filter(ifindex);
	ipmroute_reset_filter(ifindex);
	ipneigh_reset_filter(ifindex);
	ipnetconf_reset_filter(ifindex);

	if (llink)
		groups |= nl_mgrp(RTNLGRP_LINK);
	if (laddr) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
	}
	if (lroute) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
		if (!preferred_family || preferred_family == AF_MPLS)
			groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE);
	}
	if (lmroute) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE);
	}
	if (lprefix) {
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
	}
	if (lneigh) {
		groups |= nl_mgrp(RTNLGRP_NEIGH);
	}
	if (lnetconf) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
		if (!preferred_family || preferred_family == AF_MPLS)
			groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF);
	}
	if (lrule) {
		if (!preferred_family || preferred_family == AF_INET)
			groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
		if (!preferred_family || preferred_family == AF_INET6)
			groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
	}
	if (lnsid) {
		groups |= nl_mgrp(RTNLGRP_NSID);
	}
	if (file) {
		FILE *fp;
		int err;

		fp = fopen(file, "r");
		if (fp == NULL) {
			perror("Cannot fopen");
			exit(-1);
		}
		err = rtnl_from_file(fp, accept_msg, stdout);
		fclose(fp);
		return err;
	}

	if (rtnl_open(&rth, groups) < 0)
		exit(1);
	if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
		exit(1);

	ll_init_map(&rth);
	netns_nsid_socket_init();
	netns_map_init();

	if (rtnl_listen(&rth, accept_msg, stdout) < 0)
		exit(2);

	return 0;
}
Esempio n. 6
0
REQ iproute_get(int argc, char *argv)
{
	REQ req;
	char  *idev = NULL;
	char  *odev = NULL;
	int connected = 0;
	int from_ok = 0;

	memset(&req, 0, sizeof(req));

	iproute_reset_filter();

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_GETROUTE;
	req.r.rtm_family = preferred_family;
	req.r.rtm_table = 0;
	req.r.rtm_protocol = 0;
	req.r.rtm_scope = 0;
	req.r.rtm_type = 0;
	req.r.rtm_src_len = 0;
	req.r.rtm_dst_len = 0;
	req.r.rtm_tos = 0;
	
	while (argc > 0) {
		if(strcmp(argv, "tos") == 0 ||
		    matches(argv, "dsfield") == 0) {
			__u32 tos;
			NEXT_ARG();
			if(rtnl_dsfield_a2n(&tos, argv))
				invarg("TOS value is invalid\n", argv);
			req.r.rtm_tos = tos;
		} else if(matches(argv, "from") == 0) {
			inet_prefix addr;
			NEXT_ARG();
			from_ok = 1;
			get_prefix(&addr, argv, req.r.rtm_family);
			if(req.r.rtm_family == AF_UNSPEC)
				req.r.rtm_family = addr.family;
			if(addr.bytelen)
				addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen);
			req.r.rtm_src_len = addr.bitlen;
		} else if(matches(argv, "iif") == 0) {
			NEXT_ARG();
			idev = argv;
		} else if(matches(argv, "oif") == 0 ||
			   strcmp(argv, "dev") == 0) {
			NEXT_ARG();
			odev = argv;
		} else if(matches(argv, "notify") == 0) {
			req.r.rtm_flags |= RTM_F_NOTIFY;
		} else if(matches(argv, "connected") == 0) {
			connected = 1;
		} else {
			inet_prefix addr;
			if(strcmp(argv, "to") == 0) {
				NEXT_ARG();
			}
			get_prefix(&addr, argv, req.r.rtm_family);
			if(req.r.rtm_family == AF_UNSPEC)
				req.r.rtm_family = addr.family;
			if(addr.bytelen)
				addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen);
			req.r.rtm_dst_len = addr.bitlen;
		}
		argc--; argv++;
	}

	if(req.r.rtm_dst_len == 0) {
		fprintf(stderr, "need at least destination address\n");
		exit(1);
	}

	ll_init_map(&rth);

	if(idev || odev)  {
		int idx;

		if(idev) {
			if((idx = ll_name_to_index(idev)) == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n", idev);
				//return -1;
				exit(1);
			}
			addattr32(&req.n, sizeof(req), RTA_IIF, idx);
		}
		if(odev) {
			if((idx = ll_name_to_index(odev)) == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n", odev);
				//return -1;
				exit(1);
			}
			addattr32(&req.n, sizeof(req), RTA_OIF, idx);
		}
	}

	if(req.r.rtm_family == AF_UNSPEC)
		req.r.rtm_family = AF_INET;

	if(rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
		exit(2);

	if(connected && !from_ok) {
		struct rtmsg *r = NLMSG_DATA(&req.n);
		int len = req.n.nlmsg_len;
		struct rtattr * tb[RTA_MAX+1];

//		if(print_route(NULL, &req.n, (void*)stdout) < 0) {
//			fprintf(stderr, "An error :-)\n");
//			exit(1);
//		}

		if(req.n.nlmsg_type != RTM_NEWROUTE) {
			fprintf(stderr, "Not a route?\n");
			//return -1;
			exit(1);
		}
		len -= NLMSG_LENGTH(sizeof(*r));
		if(len < 0) {
			fprintf(stderr, "Wrong len %d\n", len);
			//return -1;
			exit(1);
		}

		parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);

		if(tb[RTA_PREFSRC]) {
			tb[RTA_PREFSRC]->rta_type = RTA_SRC;
			r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
		} else if(!tb[RTA_SRC]) {
			fprintf(stderr, "Failed to connect the route\n");
			//return -1;
			exit(1);
		}
		if(!odev && tb[RTA_OIF])
			tb[RTA_OIF]->rta_type = 0;
		if(tb[RTA_GATEWAY])
			tb[RTA_GATEWAY]->rta_type = 0;
		if(!idev && tb[RTA_IIF])
			tb[RTA_IIF]->rta_type = 0;
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETROUTE;

		if(rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
			exit(2);
	}

//	if(print_route(NULL, &req.n, (void*)stdout) < 0) {
//		fprintf(stderr, "An error :-)\n");
//		exit(1);
//	}
//	exit(0);
	return req;
}