/* Return value becomes exitcode. It's okay to not return at all */ int ipaddr_list_or_flush(int argc, char **argv, int flush) { static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0"; struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { bb_error_msg_and_die(bb_msg_requires_arg, "flush"); } if (filter.family == AF_PACKET) { bb_error_msg_and_die("cannot flush link addresses"); } } while (argc > 0) { const int option_num = index_in_strings(option, *argv); switch (option_num) { case 0: /* to */ NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) { filter.family = filter.pfx.family; } break; case 1: /* scope */ { uint32_t scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) { invarg(*argv, "scope"); } scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; break; } case 2: /* up */ filter.up = 1; break; case 3: /* label */ NEXT_ARG(); filter.label = *argv; break; case 4: /* dev */ NEXT_ARG(); default: if (filter_dev) { duparg2("dev", *argv); } filter_dev = *argv; } argv++; argc--; } xrtnl_open(&rth); xrtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK); xrtnl_dump_filter(&rth, store_nlmsg, &linfo); if (filter_dev) { filter.ifindex = xll_name_to_index(filter_dev); } if (flush) { char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR); filter.flushed = 0; xrtnl_dump_filter(&rth, print_addrinfo, stdout); if (filter.flushed == 0) { return 0; } if (flush_update() < 0) return 1; } } if (filter.family != AF_PACKET) { xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR); xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l = linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); /* why? */ } return 0; }
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; }
extern int ipaddr_list_or_flush(int argc, char **argv, int flush) { const char *option[] = { "to", "scope", "up", "label", "dev", 0 }; struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } if (filter.family == AF_PACKET) { fprintf(stderr, "Cannot flush link addresses.\n"); return -1; } } while (argc > 0) { const unsigned short option_num = compare_string_array(option, *argv); switch (option_num) { case 0: /* to */ NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) { filter.family = filter.pfx.family; } break; case 1: /* scope */ { int scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) { invarg("invalid \"scope\"\n", *argv); } scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; break; } case 2: /* up */ filter.up = 1; break; case 3: /* label */ NEXT_ARG(); filter.label = *argv; break; case 4: /* dev */ NEXT_ARG(); default: if (filter_dev) { duparg2("dev", *argv); } filter_dev = *argv; } argv++; argc--; } if (rtnl_open(&rth, 0) < 0) exit(1); if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { bb_error_msg_and_die("Dump terminated"); } if (filter_dev) { filter.ifindex = ll_name_to_index(filter_dev); if (filter.ifindex <= 0) { bb_error_msg("Device \"%s\" does not exist.", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { #if 0 if (round == 0) fprintf(stderr, "Nothing to flush.\n"); #endif fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); } } if (filter.family != AF_PACKET) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { bb_error_msg_and_die("Dump terminated"); } } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l=linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); } exit(0); }
static int ipaddr_list_or_flush(int argc, char **argv, int flush) { struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l, *n; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } if (filter.family == AF_PACKET) { fprintf(stderr, "Cannot flush link addresses.\n"); return -1; } } while (argc > 0) { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } else if (strcmp(*argv, "scope") == 0) { unsigned scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) invarg("invalid \"scope\"\n", *argv); scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; } else if (strcmp(*argv, "up") == 0) { filter.up = 1; } else if (strcmp(*argv, "dynamic") == 0) { filter.flags &= ~IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "permanent") == 0) { filter.flags |= IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "secondary") == 0 || strcmp(*argv, "temporary") == 0) { filter.flags |= IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "primary") == 0) { filter.flags &= ~IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "tentative") == 0) { filter.flags |= IFA_F_TENTATIVE; filter.flagmask |= IFA_F_TENTATIVE; } else if (strcmp(*argv, "deprecated") == 0) { filter.flags |= IFA_F_DEPRECATED; filter.flagmask |= IFA_F_DEPRECATED; } else if (strcmp(*argv, "home") == 0) { filter.flags |= IFA_F_HOMEADDRESS; filter.flagmask |= IFA_F_HOMEADDRESS; } else if (strcmp(*argv, "nodad") == 0) { filter.flags |= IFA_F_NODAD; filter.flagmask |= IFA_F_NODAD; } else if (strcmp(*argv, "dadfailed") == 0) { filter.flags |= IFA_F_DADFAILED; filter.flagmask |= IFA_F_DADFAILED; } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); filter.label = *argv; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (filter_dev) duparg2("dev", *argv); filter_dev = *argv; } argv++; argc--; } if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } if (filter_dev) { filter.ifindex = ll_name_to_index(filter_dev); if (filter.ifindex <= 0) { fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); while (round < MAX_ROUNDS) { const struct rtnl_dump_filter_arg a[3] = { { .filter = print_addrinfo_secondary, .arg1 = stdout, .junk = NULL, .arg2 = NULL }, { .filter = print_addrinfo_primary, .arg1 = stdout, .junk = NULL, .arg2 = NULL }, { .filter = NULL, .arg1 = NULL, .junk = NULL, .arg2 = NULL }, };
int ipaddr_list_or_flush(int argc, char **argv, int flush) { struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } if (filter.family == AF_PACKET) { fprintf(stderr, "Cannot flush link addresses.\n"); return -1; } } while (argc > 0) { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } else if (strcmp(*argv, "scope") == 0) { int scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) invarg("invalid \"scope\"\n", *argv); scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; } else if (strcmp(*argv, "up") == 0) { filter.up = 1; } else if (strcmp(*argv, "dynamic") == 0) { filter.flags &= ~IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "permanent") == 0) { filter.flags |= IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "secondary") == 0) { filter.flags |= IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "primary") == 0) { filter.flags &= ~IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "tentative") == 0) { filter.flags |= IFA_F_TENTATIVE; filter.flagmask |= IFA_F_TENTATIVE; } else if (strcmp(*argv, "deprecated") == 0) { filter.flags |= IFA_F_DEPRECATED; filter.flagmask |= IFA_F_DEPRECATED; } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); filter.label = *argv; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (filter_dev) duparg2("dev", *argv); filter_dev = *argv; } argv++; argc--; } if (rtnl_open(&rth, 0) < 0) exit(1); if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } if (filter_dev) { filter.ifindex = ll_name_to_index(filter_dev); if (filter.ifindex <= 0) { fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { if (round == 0) { fprintf(stderr, "Nothing to flush.\n"); } else if (show_stats) printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed); fflush(stdout); } } } if (filter.family != AF_PACKET) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l=linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); } exit(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); }
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; }