/* * returns: -1 - address not found, 0 - addr is ok, 1 - addr is tentative */ int is_addr_tentative(char * ifacename, int iface, char * addr) { char buf[256]; char packed1[16]; char packed2[16]; struct rtattr * rta_tb[IFA_MAX+1]; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *head = NULL; struct rtnl_handle rth; int tentative = LOWLEVEL_TENTATIVE_DONT_KNOW; inet_pton6(addr,packed1); rtnl_open(&rth, 0); /* 2nd attribute: AF_UNSPEC, AF_INET, AF_INET6 */ /* rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK); */ rtnl_wilddump_request(&rth, AF_INET6, RTM_GETADDR); rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL); head = ainfo; while (ainfo) { struct nlmsghdr *n = &ainfo->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); memset(rta_tb, 0, sizeof(*rta_tb)); if (ifa->ifa_index == iface && ifa->ifa_family==AF_INET6) { parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); if (!rta_tb[IFA_LOCAL]) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; inet_ntop6(RTA_DATA(rta_tb[IFA_LOCAL]), buf /*, sizeof(buf)*/); memcpy(packed2,RTA_DATA(rta_tb[IFA_LOCAL]),16); /* print_packed(packed1); printf(" "); print_packed(packed2); printf("\n"); */ /* is this addr which are we looking for? */ if (!memcmp(packed1,packed2,16) ) { if (ifa->ifa_flags & IFA_F_TENTATIVE) tentative = LOWLEVEL_TENTATIVE_YES; else tentative = LOWLEVEL_TENTATIVE_NO; } } ainfo = ainfo->next; } /* now delete list */ while (head) { ainfo = head; head = head->next; free(ainfo); } rtnl_close(&rth); return tentative; }
static void load_info(void) { struct ifstat_ent *db, *n; struct rtnl_handle rth; if (rtnl_open(&rth, 0) < 0) exit(1); if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, get_netstat_nlmsg, NULL, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } rtnl_close(&rth); db = kern_db; kern_db = NULL; while (db) { n = db; db = db->next; n->next = kern_db; kern_db = n; } }
static int iprule_flush(int argc, char **argv) { int af = preferred_family; #ifdef HTC_IPRULE_DEBUG ALOGD("[IPROUTE2]iprule_flush +"); #endif if (af == AF_UNSPEC) af = AF_INET; if (argc > 0) { fprintf(stderr, "\"ip rule flush\" does not allow arguments\n"); return -1; } if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) { perror("Cannot send dump request"); return 1; } if (rtnl_dump_filter(&rth, flush_rule, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); return 1; } #ifdef HTC_IPRULE_DEBUG ALOGD("[IPROUTE2]iprule_flush -"); #endif return 0; }
struct rt_entry * rt_fetch(struct rt_entry *r) { struct rtnl_handle rth; // open netlink socket of NETLINK_ROUTE if (rtnl_open(&rth, 0) < 0) { printf("Can not initialize netlink interface...\n"); return NULL; } ll_init_map(&rth); if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETROUTE) < 0) { printf("Cannot send dump request\n"); close(rth.fd); return NULL; } if (rtnl_dump_filter(&rth, rt_filter, r, NULL, NULL) < 0) { printf("Dump terminated.\n"); close(rth.fd); return NULL; } close(rth.fd); return r; }
/**************************************************************** NAME : ipaddr_list 00/06/02 20:02:23 AIM : REMARK : ****************************************************************/ int ipaddr_list( int ifindex, uint32_t *array, int max_elem ) { struct rtnl_handle rth; iplist_ctx ctx; /* init the struct */ ctx.ifindex = ifindex; ctx.addr = array; ctx.max_elem = max_elem; ctx.nb_elem = 0; /* open the rtnetlink socket */ if( rtnl_open( &rth, 0) ) return -1; /* send the request */ if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETADDR) < 0) { perror("Cannot send dump request"); return -1; } /* parse the answer */ if (rtnl_dump_filter(&rth, get_addrinfo, &ctx, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } /* to close the clocket */ rtnl_close( &rth ); return ctx.nb_elem; }
/* * rule_flush_table_range: deletes all the rules which lookup the table X. * The table X is any table in the range of `a' <= X <= `b'. */ int rule_flush_table_range(int family, int a, int b) { struct rtnl_handle rth; int arg[2]; if (rtnl_open(&rth, 0) < 0) return 1; if (rtnl_wilddump_request(&rth, family, RTM_GETRULE) < 0) { error("Cannot dump the routing rule table"); return -1; } arg[0] = a; arg[1] = b; if (rtnl_dump_filter (&rth, rule_flush_table_range_filter, arg, NULL, NULL) < 0) { error("Flush terminated"); return -1; } rtnl_close(&rth); return 0; }
static int do_show(int argc, char **argv) { struct { struct nlmsghdr n; struct netconfmsg ncm; char buf[1024]; } req; ipnetconf_reset_filter(0); filter.family = preferred_family; if (filter.family == AF_UNSPEC) filter.family = AF_INET; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); filter.ifindex = ll_name_to_index(*argv); if (filter.ifindex <= 0) { fprintf(stderr, "Device \"%s\" does not exist.\n", *argv); return -1; } } argv++; argc--; } ll_init_map(&rth); if (filter.ifindex) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; req.n.nlmsg_type = RTM_GETNETCONF; req.ncm.ncm_family = filter.family; if (filter.ifindex) addattr_l(&req.n, sizeof(req), NETCONFA_IFINDEX, &filter.ifindex, sizeof(filter.ifindex)); if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) { perror("Can not send request"); exit(1); } rtnl_listen(&rth, print_netconf, stdout); } else { dump: if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNETCONF) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_netconf2, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } if (preferred_family == AF_UNSPEC) { preferred_family = AF_INET6; filter.family = AF_INET6; goto dump; } } return 0; }
static int iprule_list_or_save(int argc, char **argv, int save) { rtnl_filter_t filter = print_rule; int af = preferred_family; if (af == AF_UNSPEC) af = AF_INET; if (argc > 0) { fprintf(stderr, "\"ip rule %s\" does not take any arguments.\n", save ? "save" : "show"); return -1; } if (save) { if (save_rule_prep()) return -1; filter = save_rule; } if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) { perror("Cannot send dump request"); return 1; } if (rtnl_dump_filter(&rth, filter, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } return 0; }
static int fdb_show(int argc, char **argv) { char *filter_dev = NULL; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (filter_dev) duparg("dev", *argv); filter_dev = *argv; } argc--; argv++; } if (filter_dev) { filter_index = if_nametoindex(filter_dev); if (filter_index == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", filter_dev); return -1; } } if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETNEIGH) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_fdb, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
void neigh_flush_table(char *iface) { struct rtnl_handle rth; char flushb[4096-512]; DEBUG_MSG("neigh_flush_table %s", iface); memset(&filter, 0, sizeof(filter)); filter.state = ~0; filter.family = AF_INET; /* flush all but permanent and noarp */ filter.state = ~(NUD_PERMANENT|NUD_NOARP); /* open the netlink socket */ if (rtnl_open(&rth, 0) < 0) ERROR_MSG("rtnl_open()"); ll_init_map(&rth); /* fill the device data */ if ((filter.index = ll_name_to_index(iface)) == 0) ERROR_MSG("ll_name_to_index(%s)", iface); filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; filter.state &= ~NUD_FAILED; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNEIGH) < 0) ERROR_MSG("rtnl_wilddump_request()"); filter.flushed = 0; /* * count how many neigh are to be flushed * and prepare the data */ if (rtnl_dump_filter(&rth, count_neigh, stdout, NULL, NULL) < 0) ERROR_MSG("rtnl_dump_filter()"); if (filter.flushed == 0) return; if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) ERROR_MSG("rtnl_send()"); filter.flushp = 0; DEBUG_MSG("*** deleting %d entries ***", filter.flushed); } }
int iprule_list(int argc, char **argv) { struct rtnl_handle rth; int af = preferred_family; if (af == AF_UNSPEC) af = AF_INET; if (argc > 0) { fprintf(stderr, "\"ip rule show\" does not take any arguments.\n"); return -1; } if (rtnl_open(&rth, 0) < 0) return 1; if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) { perror("Cannot send dump request"); return 1; } if (rtnl_dump_filter(&rth, print_rule, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } return 0; }
static void load_initial_table(void) { if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH) < 0) { perror("dump request failed"); exit(1); } }
void TunManager::probe() { std::lock_guard<std::mutex> lock(mutex_); stop(); // stop all interfaces intfs_.clear(); // clear all interface info auto ret = rtnl_wilddump_request(&rth_, AF_UNSPEC, RTM_GETLINK); sysCheckError(ret, "Cannot send RTM_GETLINK request"); ret = rtnl_dump_filter(&rth_, getLinkRespParser, this); sysCheckError(ret, "Cannot process RTM_GETLINK response"); ret = rtnl_wilddump_request(&rth_, AF_UNSPEC, RTM_GETADDR); sysCheckError(ret, "Cannot send RTM_GETADDR request"); ret = rtnl_dump_filter(&rth_, getAddrRespParser, this); sysCheckError(ret, "Cannot process RTM_GETADDR response"); // Bring up all interfaces. Interfaces could be already up. for (const auto& intf : intfs_) { bringupIntf(intf.second->getName(), intf.second->getIfIndex()); } start(); }
int ll_init_map(struct rtnl_handle *rth) { if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { bb_perror_msg_and_die("cannot send dump request"); } if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { bb_error_msg_and_die("dump terminated"); } return 0; }
int ll_init_map(struct rtnl_handle *rth) { if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { // perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { // fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
/* Based on iproute2/ip/iproute.c:iproute_list_flush_or_save. */ static int dump(int tbl_id) { reset_filter(); filter.tb = tbl_id; if (rtnl_wilddump_request(&rth, AF_XIA, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
/* XXX This should become a function in a library, there're very * little variance of this repeated code instances */ static int showneighs(void) { reset_filter(); if (rtnl_wilddump_request(&rth, AF_XIA, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_neigh, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
static PyObject* pyrtnl_wilddump_request(PyObject* obj, PyObject* args) { PyRtnlObject* self = (PyRtnlObject*)obj; int family, type; if (!PyArg_ParseTuple(args, "ii", &family, &type)) return NULL; if (rtnl_wilddump_request(&self->rth, family, type) < 0) { PyErr_SetString(PyExc_IOError, "could not send dump request"); return NULL; } Py_INCREF(Py_None); return Py_None; }
void list(void) { struct rtnl_handle rth; if (rtnl_open(&rth,0)) { perror("Cannot open rtnetlink"); return; } if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { perror("Cannot send dump request"); return; } if (rtnl_dump_filter(&rth, print_link, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); return; } rtnl_close(&rth); }
int init_bridge_ops(void) { if(rtnl_open(&rth, RTMGRP_LINK) < 0) { fprintf(stderr, "Couldn't open rtnl socket for monitoring\n"); return -1; } if(rtnl_open(&rth_state, 0) < 0) { fprintf(stderr, "Couldn't open rtnl socket for setting state\n"); return -1; } if(rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) { //fprintf(stderr, "Cannot send dump request: %m\n"); fprintf(stderr, "Cannot send dump request: %s\n", strerror(errno)); return -1; } if(rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); return -1; } if(fcntl(rth.fd, F_SETFL, O_NONBLOCK) < 0) { //fprintf(stderr, "Error setting O_NONBLOCK: %m\n"); fprintf(stderr, "Error setting O_NONBLOCK: %s\n", strerror(errno)); return -1; } br_handler.fd = rth.fd; br_handler.arg = NULL; br_handler.handler = br_ev_handler; if(add_epoll(&br_handler) < 0){ return -1; } return 0; }
int do_show_ip_route(struct params* params) { struct rtnl_handle rth; if (rtnl_open(&rth,0) < 0) { printf("Could not open netlink socket\n"); return -1; } if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { printf("Cannot send dump request"); return -1; } /*if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { printf("Dump terminated\n"); return -1; }*/ return 0; }
int rtnl_iterate(int proto, int type, rtnl_filter_t func, void *extarg) { struct rtnl_handle rth; if (rtnl_open_byproto(&rth, 0, proto) < 0) return -1; if (rtnl_wilddump_request(&rth, AF_INET6, type) < 0) { rtnl_close(&rth); return -1; } if (rtnl_dump_filter(&rth, func, extarg, NULL, NULL) < 0) { rtnl_close(&rth); return -1; } rtnl_close(&rth); return 0; }
int ll_init_map(struct rtnl_handle *rth) { static int initialized; if (initialized) return 0; if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(rth, ll_remember_index, NULL, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } initialized = 1; return 0; }
int main(int argc, char *argv[]) { int i; int preferred_family = AF_PACKET; if (rtnl_open(&my_rth, 0) < 0) { fprintf(stderr, "Cannot open rtnetlink\n"); return -1; } if (rtnl_wilddump_request(&my_rth, preferred_family, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&my_rth, my_print_linkinfo, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } exit(0); }
/* * route_get_exact_prefix: it dumps the routing table and search for a route * which has the prefix equal to `prefix', if it is found its destination * address is stored in `dst' and its interface name in `dev_name' (which must * be IFNAMSIZ big). */ int route_get_exact_prefix_dst(inet_prefix prefix, inet_prefix * dst, char *dev_name) { int do_ipv6 = AF_UNSPEC; struct rtnl_handle rth; char dst_data[sizeof(inet_prefix) + IFNAMSIZ]; route_reset_filter(); filter.tb = RT_TABLE_MAIN; filter.mdst = prefix; filter.rdst = filter.mdst; if (do_ipv6 == AF_UNSPEC && filter.tb) do_ipv6 = AF_INET; if (rtnl_open(&rth, 0) < 0) return -1; ll_init_map(&rth); if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { error(ERROR_MSG "Cannot send dump request" ERROR_POS); return -1; } setzero(dst_data, sizeof(dst_data)); if (rtnl_dump_filter(&rth, route_get_gw, dst_data, NULL, NULL) < 0) { debug(DBG_NORMAL, ERROR_MSG "Dump terminated" ERROR_POS); return -1; } inet_copy(dst, (inet_prefix *) dst_data); memcpy(dev_name, dst_data + sizeof(inet_prefix), IFNAMSIZ); rtnl_close(&rth); return 0; }
int Label_show(int argc, char **argv) { int af = preferred_family; if (af == AF_UNSPEC) af = AF_INET6; if (argc > 0) { fprintf(stderr, "\"label show\" does not take any arguments.\n"); return -1; } if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) { perror("Can not send dump request"); return 1; } if (rtnl_dump_filter(&rth, print_addrlabel, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } return 0; }
static int ipntable_show(int argc, char **argv) { ipntable_reset_filter(); filter.family = preferred_family; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (strcmp("none", *argv) == 0) filter.index = NONE_DEV; else if ((filter.index = ll_name_to_index(*argv)) == 0) invarg("\"DEV\" is invalid", *argv); } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); strncpy(filter.name, *argv, sizeof(filter.name)); } else invarg("unknown", *argv); argc--; argv++; } if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETNEIGHTBL) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_ntable, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
static int ipaddrlabel_flush(int argc, char **argv) { int af = preferred_family; if (af == AF_UNSPEC) af = AF_INET6; if (argc > 0) { fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n"); return -1; } if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) { perror("Cannot send dump request"); return 1; } if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); return 1; } return 0; }
static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall) { char *selp = NULL; struct rtnl_handle rth; if (argc > 0) filter.use = 1; filter.xpinfo.sel.family = preferred_family; while (argc > 0) { if (strcmp(*argv, "dir") == 0) { NEXT_ARG(); xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv); filter.dir_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.index, *argv, 0)) invarg("\"INDEX\" is invalid", *argv); filter.index_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "ptype") == 0) { NEXT_ARG(); xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv); filter.ptype_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "action") == 0) { NEXT_ARG(); if (strcmp(*argv, "allow") == 0) filter.xpinfo.action = XFRM_POLICY_ALLOW; else if (strcmp(*argv, "block") == 0) filter.xpinfo.action = XFRM_POLICY_BLOCK; else invarg("\"ACTION\" is invalid\n", *argv); filter.action_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.priority, *argv, 0)) invarg("\"PRIORITY\" is invalid", *argv); filter.priority_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc, &argv); filter.policy_flags_mask = XFRM_FILTER_MASK_FULL; } else { if (selp) invarg("unknown", *argv); selp = *argv; xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = filter.xpinfo.sel.family; } argc--; argv++; } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (deleteall) { struct xfrm_buffer xb; char buf[NLMSG_DELETEALL_BUF_SIZE]; int i; xb.buf = buf; xb.size = sizeof(buf); xb.rth = &rth; for (i = 0; ; i++) { xb.offset = 0; xb.nlmsg_count = 0; if (show_stats > 1) fprintf(stderr, "Delete-all round = %d\n", i); if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) { fprintf(stderr, "Delete-all terminated\n"); exit(1); } if (xb.nlmsg_count == 0) { if (show_stats > 1) fprintf(stderr, "Delete-all completed\n"); break; } if (rtnl_send(&rth, xb.buf, xb.offset) < 0) { perror("Failed to send delete-all request\n"); exit(1); } if (show_stats > 1) fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count); xb.offset = 0; xb.nlmsg_count = 0; } } else { if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } rtnl_close(&rth); exit(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); }