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); }
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); }
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); }
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; }
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; }