void multi_link_get_iface_info(struct multi_link_info *li){ //MNL_SOCKET_BUFFER_SIZE is 8k, which is the max nlmsg size (see //linux/netlink.h) uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtgenmsg *rt; uint32_t seq; //It seems like I cant request one interface, has to dump! ////Play with this later and see what is up nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = RTM_GETADDR; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); //How will this work with event? Send 0? rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); //I need all interfaces, also those without IP (check) rt->rtgen_family = AF_UNSPEC; if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT(stderr, "Cannot request info dump\n"); return; } if(li->state == LINK_DOWN_PPP) multi_link_filter(seq, multi_link_filter_ppp, (void*) li); else if(li->state == LINK_DOWN_AP) multi_link_filter(seq, multi_link_filter_ap, (void*) li); }
static int32_t multi_link_flush_links(){ struct ip_info ip_info; uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtgenmsg *rt; uint32_t seq; memset(buf, 0, MNL_SOCKET_BUFFER_SIZE); memset(&ip_info, 0, sizeof(ip_info)); //Initialize list TAILQ_INIT(&(ip_info.ip_addr_n)); TAILQ_INIT(&(ip_info.ip_rules_n)); TAILQ_INIT(&(ip_info.ip_routes_n)); //Sets room for one nlmsghdr in buffer buf nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = RTM_GETADDR; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); //How will this work with event? Send 0? rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); rt->rtgen_family = AF_INET; //I need all interfaces //Address if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Cannot request address dump\n"); return EXIT_FAILURE; } multi_link_filter(seq, multi_link_filter_ipaddr, &ip_info); //Rules nlh->nlmsg_type = RTM_GETRULE; if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Cannot request rules dump\n"); return EXIT_FAILURE; } multi_link_filter(seq, multi_link_filter_iprules, &ip_info); //Routes nlh->nlmsg_type = RTM_GETROUTE; if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Cannot request rules dump\n"); return EXIT_FAILURE; } multi_link_filter(seq, multi_link_filter_iproutes, &ip_info); /* Remove existing information and free memory */ multi_link_del_info(ip_info.ip_routes_n, RTM_DELROUTE); multi_link_del_info(ip_info.ip_rules_n, RTM_DELRULE); multi_link_del_info(ip_info.ip_addr_n, RTM_DELADDR); multi_link_free_ip_info(&ip_info); return EXIT_SUCCESS; }
static void multi_link_populate_links_list(){ //MNL_SOCKET_BUFFER_SIZE is 8k, which is the max nlmsg size (see //linux/netlink.h) uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtgenmsg *rt; uint32_t seq; memset(buf, 0, MNL_SOCKET_BUFFER_SIZE); //Sets room for one nlmsghdr in buffer buf nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = RTM_GETLINK; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); //How will this work with event? Send 0? rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); rt->rtgen_family = AF_UNSPEC; //I need all interfaces if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Cannot request info dump\n"); return; } multi_link_filter(seq, multi_link_filter_links, NULL); }
//Addresses and routes are always deleted when an interface goes down, but not //rules. Netlink is not reliable and there are scenarios where we will loose //messages and not clean up properly. We therefore need to make sure that there //exists no rules poining to this address/interface static int32_t multi_link_rules_sanity(struct multi_link_info *li) { struct ip_info ip_info; uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtgenmsg *rt; uint32_t seq; int32_t ret; struct multi_link_filter_iprule filter_iprule = {0}; memset(buf, 0, MNL_SOCKET_BUFFER_SIZE); memset(&ip_info, 0, sizeof(ip_info)); //I am lazy and will use ip_info for now TAILQ_INIT(&(ip_info.ip_rules_n)); filter_iprule.li = li; ip_info.data = &filter_iprule; //Sets room for one nlmsghdr in buffer buf nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = RTM_GETRULE; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); rt->rtgen_family = AF_INET; //Multi only supports v4 MULTI_DEBUG_PRINT_SYSLOG(stderr, "Will check for dirty rules\n"); if(mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Cannot request rules dump\n"); return EXIT_FAILURE; } ret = multi_link_filter(seq, multi_link_filter_iprules_addr, &ip_info); if (ret) { //Some rules might have been added multi_link_free_ip_info(&ip_info); MULTI_DEBUG_PRINT_SYSLOG(stderr, "Sanity check failed (memory)\n"); return EXIT_FAILURE; } if (!ip_info.ip_rules_n.tqh_first) return EXIT_SUCCESS; MULTI_DEBUG_PRINT_SYSLOG(stderr, "Will delete dirty rules\n"); multi_link_del_info(ip_info.ip_rules_n, RTM_DELRULE); multi_link_free_ip_info(&ip_info); return EXIT_SUCCESS; }