int tc_qdisc_list(int argc, char **argv) { struct tcmsg t; struct rtnl_handle rth; char d[16]; memset(&t, 0, sizeof(t)); t.tcm_family = AF_UNSPEC; memset(&d, 0, sizeof(d)); while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(d, *argv, sizeof(d)-1); #ifdef TC_H_INGRESS } else if (strcmp(*argv, "ingress") == 0) { if (t.tcm_parent) { fprintf(stderr, "Duplicate parent ID\n"); usage(); } t.tcm_parent = TC_H_INGRESS; #endif } else if (matches(*argv, "help") == 0) { usage(); } else { fprintf(stderr, "What is \"%s\"? Try \"tc qdisc help\".\n", *argv); return -1; } argc--; argv++; } if (rtnl_open(&rth, 0) < 0) { fprintf(stderr, "Cannot open rtnetlink\n"); exit(1); } ll_init_map(&rth); if (d[0]) { if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); exit(1); } filter_ifindex = t.tcm_ifindex; } if (rtnl_dump_request(&rth, RTM_GETQDISC, &t, sizeof(t)) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_qdisc, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } rtnl_close(&rth); return 0; }
void add_classes() { // call dump of classes, these needs to be dumped on per device basis struct tcmsg t; struct rtnl_handle rth; char d[16]; char line[1024]; FILE *dev; char *p; memset(&rth,0,sizeof(struct rtnl_handle)); memset(&t, 0, sizeof(t)); t.tcm_family = AF_UNSPEC; memset(&d, 0, sizeof(d)); if (rtnl_open(&rth, 0) < 0) { snmp_log(LOG_NOTICE, "Cannot open rtnetlink"); return; } dev=fopen("/proc/net/dev","r"); if(dev==NULL) { snmp_log(LOG_WARNING,"qos-ext: cannot open /proc/net/dev for reading, class stats won't be avaiable"); return; } while(fscanf(dev,"%s",line)!=EOF) { //find existing devices p=index(line,':'); if(p==NULL) continue; *p='\0'; // line contains device_name.... need to translate name into index t.tcm_ifindex = ll_name_to_index(line); if (rtnl_dump_request(&rth, RTM_GETTCLASS, &t, sizeof(t)) < 0) { //dump all classes on device with index t.tcm_ifindex snmp_log(LOG_WARNING,"qos-ext: add_new_entries to table: cannot send dump request"); fclose(dev); return; } if (rtnl_dump_filter(&rth, insert_entry, NULL, NULL, NULL) < 0) { //append all classes entris into the internal table snmp_log(LOG_WARNING, "qos-ext: add_new entries to table: class dump terminated"); fclose(dev); return; } } fclose(dev); rtnl_close(&rth); }
static PyObject* pyrtnl_dump_request(PyObject* obj, PyObject* args) { PyRtnlObject* self = (PyRtnlObject*)obj; int type; char* req; int len; if (!PyArg_ParseTuple(args, "is#", &type, &req, &len)) return NULL; if (rtnl_dump_request(&self->rth, type, req, len) < 0) { PyErr_SetString(PyExc_IOError, "could not send dump request"); return NULL; } Py_INCREF(Py_None); return Py_None; }
void add_new_entries_to_table() { // call dump of netlink qos layer in kernel and adds received object into qos_table //(specifically their statistics values & some parts of configuration (htb)) struct tcmsg t; struct rtnl_handle rth; extern int rth_initialized; char d[16]; memset(&rth,0,sizeof(struct rtnl_handle)); memset(&t, 0, sizeof(t)); t.tcm_family = AF_UNSPEC; memset(&d, 0, sizeof(d)); if (rtnl_open(&rth, 0) < 0) { snmp_log(LOG_NOTICE, "Cannot open rtnetlink"); return; } // if(rth_initialized==0) { ll_init_map(&rth); // rth_initialized=1; // } if (rtnl_dump_request(&rth, RTM_GETQDISC, &t, sizeof(t)) < 0) { snmp_log(LOG_WARNING,"qos-ext: add_new_entries to table: cannot send dump request"); return; } if (rtnl_dump_filter(&rth, insert_entry, NULL, NULL, NULL) < 0) { snmp_log(LOG_WARNING, "qos-ext: add_new entries to table: qdisc dump terminated"); return; } rtnl_close(&rth); add_classes(); }
int do_vrf_show(void) { struct rtnl_handle rth; struct vrfmsg r; memset(&r, 0, sizeof(r)); r.va_family = PF_INET; xrtnl_open(&rth); if (rtnl_dump_request(&rth, RTM_GETVRF, &r, sizeof(r)) < 0) { perror("Cannot send dump request"); exit(1); } if (xrtnl_dump_filter(&rth, print_vrf, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return (0); }
static int do_show_or_flush(int argc, char **argv, int flush) { char *filter_dev = NULL; int state_given = 0; struct ndmsg ndm = { 0 }; ipneigh_reset_filter(); if (!filter.family) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } filter.state = ~(NUD_PERMANENT|NUD_NOARP); } else filter.state = 0xFF & ~NUD_NOARP; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (filter_dev) duparg("dev", *argv); filter_dev = *argv; } else if (strcmp(*argv, "unused") == 0) { filter.unused_only = 1; } else if (strcmp(*argv, "nud") == 0) { unsigned state; NEXT_ARG(); if (!state_given) { state_given = 1; filter.state = 0; } if (nud_state_a2n(&state, *argv)) { if (strcmp(*argv, "all") != 0) invarg("nud state is bad", *argv); state = ~0; if (flush) state &= ~NUD_NOARP; } if (state == 0) state = 0x100; filter.state |= state; } else if (strcmp(*argv, "proxy") == 0) ndm.ndm_flags = NTF_PROXY; else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } argc--; argv++; } ll_init_map(&rth); if (filter_dev) { if ((filter.index = ll_name_to_index(filter_dev)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\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.state &= ~NUD_FAILED; while (round < MAX_ROUNDS) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNEIGH) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_neigh, stdout) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { if (show_stats) { if (round == 0) printf("Nothing to flush.\n"); else 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 entries ***\n", round, filter.flushed); fflush(stdout); } } printf("*** Flush not complete bailing out after %d rounds\n", MAX_ROUNDS); return 1; } ndm.ndm_family = filter.family; if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_neigh, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
int tc_act_list_or_flush(int argc, char **argv, int event) { int ret = 0, prio = 0, msg_size = 0; char k[16]; struct rtattr *tail,*tail2; struct action_util *a = NULL; struct { struct nlmsghdr n; struct tcamsg t; char buf[MAX_MSG]; } req; req.t.tca_family = AF_UNSPEC; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)); tail = NLMSG_TAIL(&req.n); addattr_l(&req.n, MAX_MSG, TCA_ACT_TAB, NULL, 0); tail2 = NLMSG_TAIL(&req.n); strncpy(k, *argv, sizeof (k) - 1); #ifdef CONFIG_GACT if (!gact_ld) { get_action_kind("gact"); } #endif a = get_action_kind(k); if (NULL == a) { fprintf(stderr,"bad action %s\n",k); goto bad_val; } if (strcmp(a->id, k) != 0) { fprintf(stderr,"bad action %s\n",k); goto bad_val; } strncpy(k, *argv, sizeof (k) - 1); addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0); addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1); tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2; tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr)); if (event == RTM_GETACTION) { if (rtnl_dump_request(&rth, event, (void *)&req.t, msg_size) < 0) { perror("Cannot send dump request"); return 1; } ret = rtnl_dump_filter(&rth, print_action, stdout); } if (event == RTM_DELACTION) { req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len); req.n.nlmsg_type = RTM_DELACTION; req.n.nlmsg_flags |= NLM_F_ROOT; req.n.nlmsg_flags |= NLM_F_REQUEST; if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { fprintf(stderr, "We have an error flushing\n"); return 1; } } bad_val: return ret; }
vector get_routes_by_table(int table,int family){ vector routes; vector_init(&routes); struct{ struct nlmsghdr n; struct rtmsg r; char buf[1024]; }route_req; memset(&route_req, 0, sizeof(route_req)); struct rtnl_handle rth; if (rtnl_open(&rth, 0) < 0){ printf("cannot open rtnetlink\n"); return routes; } route_req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); route_req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; route_req.n.nlmsg_type = RTM_GETROUTE; route_req.r.rtm_family = family; route_req.r.rtm_table = table; route_req.r.rtm_dst_len = 0; route_req.r.rtm_src_len = 0; int nbytes=0,reply_len=0;//ret, count=0; ssize_t counter = 5000; char reply_ptr[5000]; char* buf = reply_ptr; struct nlmsghdr *nlp; struct rtmsg *rtp; struct rtattr *rtap; int rtl; unsigned long bufsize ; nlp = malloc(sizeof(struct nlmsghdr)); memset(nlp, 0, sizeof(struct nlmsghdr)); int rbytes __attribute__((unused)) = rtnl_dump_request(&rth,RTM_GETROUTE,&route_req,sizeof(route_req)); for(;;){ if( counter < sizeof(struct nlmsghdr)){ printf("Routing table is bigger than %lu\n", sizeof(reply_ptr)); vector_free(&routes); return routes; } nbytes = recv(rth.fd, &reply_ptr[reply_len], counter, 0); if(nbytes < 0 ){ printf("Error in recv\n"); break; } if(nbytes == 0) printf("EOF in netlink\n"); nlp = (struct nlmsghdr*)(&reply_ptr[reply_len]); if (nlp->nlmsg_type == NLMSG_DONE){ // All data has been received. // Truncate the reply to exclude this message, // i.e. do not increase reply_len. break; } if (nlp->nlmsg_type == NLMSG_ERROR){ printf("Error in msg\n"); vector_free(&routes); return routes; } reply_len += nbytes; counter -= nbytes; } bufsize = reply_len; nlp = (struct nlmsghdr*)buf; for (;NLMSG_OK(nlp, bufsize); nlp = NLMSG_NEXT(nlp, bufsize)){ /* Get the route data */ rtp = (struct rtmsg *) NLMSG_DATA(nlp); /* We only need route from the specific protocol*/ if (rtp->rtm_table != table) continue; /* Get attributes of route_entry */ rtap = (struct rtattr *) RTM_RTA(rtp); /* Get the route atttibutes len */ rtl = RTM_PAYLOAD(nlp); /* Loop through all attributes */ struct netlink_route *route = malloc(sizeof(struct netlink_route)); route->proto = rtp->rtm_protocol; route->prefix = rtp->rtm_dst_len; for ( ; RTA_OK(rtap, rtl);rtap = RTA_NEXT(rtap, rtl)){ if(rtap->rta_type == RTA_DST){ struct sockaddr_storage dest; if(family == AF_INET){ ((struct sockaddr_in*)&dest)->sin_addr.s_addr = (unsigned long) RTA_DATA(rtap); dest.ss_family = AF_INET; }else{ memcpy(&((struct sockaddr_in6*)&dest)->sin6_addr.s6_addr,RTA_DATA(rtap),16); dest.ss_family = AF_INET6; } route->dest = dest; } if(rtap->rta_type == RTA_GATEWAY){ struct sockaddr_storage dest; if(family == AF_INET){ ((struct sockaddr_in*)&dest)->sin_addr.s_addr = (unsigned long) RTA_DATA(rtap); dest.ss_family = AF_INET; }else{ memcpy(&((struct sockaddr_in6*)&dest)->sin6_addr.s6_addr,RTA_DATA(rtap),16); dest.ss_family = AF_INET6; } route->gateway = dest; } if(rtap->rta_type == RTA_PRIORITY){ route->metric = *(unsigned long *) RTA_DATA(rtap); } } vector_add(&routes,route); } rtnl_close(&rth); return routes; }
// This function forms the netlink packet to add a route to the kernel routing // table bool check_if_status(int index){ struct rtnl_handle rth; // structure of the netlink packet. struct{ struct nlmsghdr n; struct ifinfomsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); if (rtnl_open(&rth, 0) < 0){ printf("cannot open rtnetlink\n"); return false; } // Initialisation of a few parameters req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; req.n.nlmsg_type = RTM_GETLINK; req.r.ifi_index = index; int nbytes=0,reply_len=0;//ret, count=0; ssize_t counter = 5000; char reply_ptr[5000]; char* buf = reply_ptr; struct ifinfomsg *iface; struct nlmsghdr *nlp; unsigned long bufsize ; nlp = malloc(sizeof(struct nlmsghdr)); struct nlmsghdr *original_pointer = nlp; memset(nlp, 0, sizeof(struct nlmsghdr)); int rbytes __attribute__((unused)) = rtnl_dump_request(&rth,RTM_GETLINK,&req,sizeof(req)); for(;;){ if( counter < sizeof(struct nlmsghdr)){ printf("Reply is bugger than %lu\n", sizeof(reply_ptr)); free(original_pointer); return false; } nbytes = recv(rth.fd, &reply_ptr[reply_len], counter, 0); if(nbytes < 0 ){ printf("Error in recv\n"); break; } if(nbytes == 0) printf("EOF in netlink\n"); nlp = (struct nlmsghdr*)(&reply_ptr[reply_len]); if (nlp->nlmsg_type == NLMSG_DONE){ // All data has been received. // Truncate the reply to exclude this message, // i.e. do not increase reply_len. break; } if (nlp->nlmsg_type == NLMSG_ERROR){ printf("Error in msg\n"); free(original_pointer); return false; } reply_len += nbytes; counter -= nbytes; } bufsize = reply_len; nlp = (struct nlmsghdr*)buf; for (;NLMSG_OK(nlp, bufsize); nlp = NLMSG_NEXT(nlp, bufsize)){ /* Get the route data */ iface = (struct ifinfomsg *) NLMSG_DATA(nlp); /* We only need the link of the specific index*/ if (iface->ifi_index != index) continue; if(iface->ifi_flags & IFF_RUNNING){ free(original_pointer); rtnl_close(&rth); return true; }else{ free(original_pointer); rtnl_close(&rth); return false; } } free(original_pointer); rtnl_close(&rth); return false; }