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); }
static struct mnl_socket *msg_send(struct nlmsghdr *nlh) { int ret; struct mnl_socket *nl; nl = mnl_socket_open(NETLINK_GENERIC); if (nl == NULL) { perror("mnl_socket_open"); return NULL; } ret = mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID); if (ret < 0) { perror("mnl_socket_bind"); return NULL; } ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret < 0) { perror("mnl_socket_send"); return NULL; } return nl; }
/* Add/delete ip rule */ static int32_t multi_link_modify_rule(uint32_t msg_type, uint32_t flags, uint32_t table_id, struct multi_link_info *li){ uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtmsg *rt; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = msg_type; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = 0; rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); rt->rtm_family = AF_INET; rt->rtm_dst_len = 0; rt->rtm_table = table_id; //The table to perform the lookup in rt->rtm_protocol = RTPROT_BOOT; rt->rtm_scope = RT_SCOPE_UNIVERSE; rt->rtm_type = RTN_UNICAST; //Need the length of the src address that will be provided later on rt->rtm_src_len = 32; mnl_attr_put_u32(nlh, FRA_SRC, li->cfg.address.s_addr); if(mnl_socket_sendto(multi_link_nl_set, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT(stderr,"Could not send gateway to kernel " "(can be ignored if caused by an interface that went down, " "iface idx %u)\n", li->ifi_idx); return -1; } return 0; }
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); }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct genlmsghdr *genl; int ret; unsigned int seq, portid; if (argc != 2) { printf("%s [family name]\n", argv[0]); exit(EXIT_FAILURE); } nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = GENL_ID_CTRL; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = CTRL_CMD_GETFAMILY; genl->version = 1; mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL); mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]); nl = mnl_socket_open(NETLINK_GENERIC); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtmsg *rtm; int ret; unsigned int seq, portid; if (argc != 2) { fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]); exit(EXIT_FAILURE); } nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = RTM_GETROUTE; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); if (strcmp(argv[1], "inet") == 0) rtm->rtm_family = AF_INET; else if (strcmp(argv[1], "inet6") == 0) rtm->rtm_family = AF_INET6; nl = mnl_socket_open(NETLINK_ROUTE); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); if (ret <= MNL_CB_STOP) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
int nftnl_batch_is_supported(void) { struct mnl_socket *nl; struct mnl_nlmsg_batch *b; char buf[MNL_SOCKET_BUFFER_SIZE]; uint32_t seq = time(NULL), req_seq; int ret; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) return -1; if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) return -1; b = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(b), seq++); mnl_nlmsg_batch_next(b); req_seq = seq; nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), NFT_MSG_NEWSET, AF_INET, NLM_F_ACK, seq++); mnl_nlmsg_batch_next(b); nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++); mnl_nlmsg_batch_next(b); ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b), mnl_nlmsg_batch_size(b)); if (ret < 0) goto err; mnl_nlmsg_batch_stop(b); ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, req_seq, mnl_socket_get_portid(nl), NULL, NULL); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } mnl_socket_close(nl); /* We're sending an incomplete message to see if the kernel supports * set messages in batches. EINVAL means that we sent an incomplete * message with missing attributes. The kernel just ignores messages * that we cannot include in the batch. */ return (ret == -1 && errno == EINVAL) ? 1 : 0; err: mnl_nlmsg_batch_stop(b); return -1; }
int main(void) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct nfgenmsg *nfh; uint32_t seq, portid; int ret; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET; nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; nlh->nlmsg_seq = seq = time(NULL); nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = AF_INET; nfh->version = NFNETLINK_V0; nfh->res_id = 0; ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); while (1) { ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); if (ret == -1) { perror("mnl_cb_run"); exit(EXIT_FAILURE); } else if (ret <= MNL_CB_STOP) break; } mnl_socket_close(nl); return 0; }
int main(int argc, char *argv[]) { char buf[getpagesize()]; struct nlmsghdr *nlh; struct genlmsghdr *genl; struct mnl_socket *nl; int ret; unsigned int seq, oper, portid; if (argc != 2) { printf("%s <genetlink family ID>\n", argv[0]); exit(EXIT_FAILURE); } nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = atoi(argv[1]); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = NLEX_CMD_GET; nl = mnl_socket_open(NETLINK_GENERIC); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } ret = mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID); if (ret == -1) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_cb_run(buf, ret, seq, portid, cb, NULL); if (ret == -1) { perror("mnl_cb_run"); exit(EXIT_FAILURE); } mnl_socket_close(nl); printf("done\n"); return 0; }
int resolve_genladdr(const char *name, struct tcpe_client* cl) { struct mnl_socket *sock = cl->mnl_sock; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct genlmsghdr *genl; int ret; unsigned int seq, portid; struct nlattr *tb[CTRL_ATTR_MAX+1] = {}; int fmly_id = 0; const char *mcast_grp_name; int mcast_grp_id = 0; struct nlattr *pos; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = GENL_ID_CTRL; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = CTRL_CMD_GETFAMILY; genl->version = 0; mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, name); portid = mnl_socket_get_portid(sock); if (mnl_socket_sendto(sock, nlh, nlh->nlmsg_len) < 0) { dbgprintf("mnl_socket_send"); return -1; } while (1) { ret = mnl_socket_recvfrom(sock, buf, sizeof(buf)); if (ret == -1) { dbgprintf("mnl_socket_recvfrom"); break; } ret = mnl_cb_run(buf, ret, seq, portid, data_cb, tb); if (ret == -1) { dbgprintf("mnl_cb_run"); break; } else if (ret == 0) break; } if (tb[CTRL_ATTR_FAMILY_ID]) { fmly_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); } cl->fam_id = fmly_id; return 0; }
//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; }
/* method: sendto */ static int mnl_socket__sendto__meth(lua_State *L) { mnl_socket * this_idx1; const void * req_idx2; size_t siz_idx3; ssize_t rc_mnl_socket_sendto_idx1 = 0; this_idx1 = obj_type_mnl_socket_check(L,1); req_idx2 = lua_touserdata(L,2); siz_idx3 = luaL_checkinteger(L,3); rc_mnl_socket_sendto_idx1 = mnl_socket_sendto(this_idx1, req_idx2, siz_idx3); lua_pushinteger(L, rc_mnl_socket_sendto_idx1); return 1; }
static void multi_link_del_info(struct filter_list nlmsg_list, uint16_t nlmsg_type){ struct filter_msg *msg; struct nlmsghdr *nlh; uint32_t seq; for(msg = nlmsg_list.tqh_first; msg != NULL; msg = msg->list_ptr.tqe_next){ nlh = (struct nlmsghdr*) &(msg->nlh); nlh->nlmsg_type = nlmsg_type; nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_seq = seq = time(NULL); mnl_socket_sendto(multi_link_nl_request, nlh, nlh->nlmsg_len); } }
int main(void) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtgenmsg *rt; int ret; unsigned int seq, portid; 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); rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); rt->rtgen_family = AF_PACKET; nl = mnl_socket_open(NETLINK_ROUTE); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); if (ret <= MNL_CB_STOP) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
/* Adds/deletes route. The reason for having metric as a seperate parameter is * that the value depends on wether this is the private table (0) or not. If the * route is intended for the private table, then ignore metric */ static int32_t multi_link_modify_route(uint32_t msg_type, uint32_t flags, uint32_t table_id, struct multi_link_info *li, uint32_t metric){ uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtmsg *rt; uint32_t nw_ip = 0; //The desired destination IP is store in different places for PPP and //"normal" interfaces. This is the network route! if(li->state == GOT_IP_PPP || li->state == LINK_UP_PPP) nw_ip = li->cfg.broadcast.s_addr; else nw_ip = li->cfg.address.s_addr & li->cfg.netmask.s_addr; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = msg_type; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = 0; rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); rt->rtm_scope = RT_SCOPE_NOWHERE; rt->rtm_type = RTN_UNICAST; rt->rtm_family = AF_INET; rt->rtm_dst_len = 32 - (ffs(ntohl(li->cfg.netmask.s_addr)) - 1); rt->rtm_table = table_id; if(msg_type != RTM_DELROUTE){ rt->rtm_protocol = RTPROT_BOOT; rt->rtm_scope = RT_SCOPE_LINK; } mnl_attr_put_u32(nlh, RTA_DST, nw_ip); mnl_attr_put_u32(nlh, RTA_PREFSRC, li->cfg.address.s_addr); mnl_attr_put_u32(nlh, RTA_OIF, li->ifi_idx); if(metric) mnl_attr_put_u32(nlh, RTA_PRIORITY, metric); if(mnl_socket_sendto(multi_link_nl_set, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT(stderr,"Could not send private route to kernel " "(can be ignored if caused by an interface that went down, " "iface idx %u)\n", li->ifi_idx); return -1; } return 0; }
//In order to build a list of available source addresses, we need to start by //requesting all available addresses. That is the work of this function static ssize_t neat_linux_request_addrs(struct mnl_socket *mnl_sock) { uint8_t snd_buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nl_hdr = mnl_nlmsg_put_header(snd_buf); nl_hdr->nlmsg_type = RTM_GETADDR; nl_hdr->nlmsg_pid = getpid(); nl_hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; struct rtgenmsg* rt_msg = (struct rtgenmsg*) mnl_nlmsg_put_extra_header(nl_hdr, sizeof(struct rtgenmsg)); rt_msg->rtgen_family = AF_UNSPEC; //We should probably have used libuv send function, but right here it does //not really matter return mnl_socket_sendto(mnl_sock, snd_buf, nl_hdr->nlmsg_len); }
/* Add/delete gateway */ static int32_t multi_link_modify_gateway(uint32_t msg_type, uint32_t flags, uint32_t table_id, struct multi_link_info *li, uint32_t metric){ uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct rtmsg *rt; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = msg_type; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = 0; rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); rt->rtm_family = AF_INET; //There is no destination (the destination is global, i.e. netmask 0) rt->rtm_dst_len = 0; rt->rtm_table = table_id; rt->rtm_protocol = RTPROT_UNSPEC; /* This is all copied from iproute */ if(msg_type != RTM_DELROUTE){ rt->rtm_scope = RT_SCOPE_UNIVERSE; rt->rtm_type = RTN_UNICAST; rt->rtm_protocol = RTPROT_BOOT; } else rt->rtm_scope = RT_SCOPE_NOWHERE; if(li->cfg.gateway.s_addr > 0) mnl_attr_put_u32(nlh, RTA_GATEWAY, li->cfg.gateway.s_addr); mnl_attr_put_u32(nlh, RTA_PREFSRC, li->cfg.address.s_addr); mnl_attr_put_u32(nlh, RTA_OIF, li->ifi_idx); if(metric) mnl_attr_put_u32(nlh, RTA_PRIORITY, metric); if(mnl_socket_sendto(multi_link_nl_set, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT(stderr,"Could not send gateway to kernel " "(can be ignored if caused by an interface that went down, " "iface idx %u)\n", li->ifi_idx); return -1; } return 0; }
static int send_and_dispatch(struct mnl_socket *nl, const void *req, size_t req_size, enum callback_return_type callback_type, uint64_t *callback_value) { struct callback_data cb = {}; uint32_t portid; int err; debug_mnl_dump_rule(req, req_size); err = mnl_socket_sendto(nl, req, req_size); if (err < 0) return -errno; portid = mnl_socket_get_portid(nl); cb.type = callback_type; for (;;) { char buf[MNL_SOCKET_BUFFER_SIZE]; err = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (err <= 0) break; err = mnl_cb_run(buf, err, 0, portid, events_cb, &cb); if (err <= 0) break; } if (err < 0) return -errno; if (callback_type == CALLBACK_RETURN_NONE) return 0; if (cb.success) { if (callback_value) *callback_value = cb.value; return 0; } return -ENOENT; }
int main(void) { char buf[getpagesize()]; struct nlmsghdr *nlh; struct mnl_socket *nl; int ret; unsigned int seq, portid; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = NLEX_MSG_UPD; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); nlh->nlmsg_pid = getpid(); mnl_attr_put_u32(nlh, NLE_MYVAR, 31337); nl = mnl_socket_open(NETLINK_EXAMPLE); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); if (ret == -1) { perror("mnl_cb_callback"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
int genl_socket_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, int (*cb)(const struct nlmsghdr *nlh, void *data), void *data) { char buf[MNL_SOCKET_BUFFER_SIZE]; int ret; if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); return -1; } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, mnl_socket_get_portid(nl), cb, data); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } return ret; }
/* Adds or deletes the IP of an interface. This function is never called for PPP * interfaces, thus, there are no special cases. */ static int32_t multi_link_modify_ip(uint32_t msg_type, uint32_t flags, struct multi_link_info *li){ uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct ifaddrmsg *ifa; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = msg_type; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = 0; ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg)); /* Fill in info related to address */ ifa->ifa_family = AF_INET; //Currently only IPv4 //To avoid this rule that is generated automatically, set bitlen to 32 ifa->ifa_prefixlen = 32 - (ffs(ntohl(li->cfg.netmask.s_addr)) - 1); //Only reason for changing this is if loopback ifa->ifa_scope = RT_SCOPE_UNIVERSE; ifa->ifa_index = li->ifi_idx; mnl_attr_put_u32(nlh, IFA_LOCAL, li->cfg.address.s_addr); mnl_attr_put_u32(nlh, IFA_ADDRESS, li->cfg.address.s_addr); if(li->cfg.broadcast.s_addr) mnl_attr_put_u32(nlh, IFA_BROADCAST, li->cfg.broadcast.s_addr); if(mnl_socket_sendto(multi_link_nl_set, nlh, nlh->nlmsg_len) < 0){ MULTI_DEBUG_PRINT(stderr,"Could not send IP to kernel (can be ignored " "if caused by an interface that went down, iface idx %u)\n", li->ifi_idx); return -1; } return 0; }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; int ret; unsigned int portid, queue_num; if (argc != 2) { printf("Usage: %s [queue_num]\n", argv[0]); exit(EXIT_FAILURE); } queue_num = atoi(argv[1]); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } while (ret > 0) { uint32_t id; ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL); if (ret < 0){ perror("mnl_cb_run"); exit(EXIT_FAILURE); } id = ret - MNL_CB_OK; nlh = nfq_build_verdict(buf, id, queue_num, NF_ACCEPT); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } } mnl_socket_close(nl); return 0; }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct mnl_nlmsg_batch *batch; uint32_t portid, seq; struct nft_rule *r = NULL; int ret, family; if (argc < 4 || argc > 5) { fprintf(stderr, "Usage: %s <family> <table> <chain> [<handle>]\n", argv[0]); exit(EXIT_FAILURE); } r = nft_rule_alloc(); if (r == NULL) { perror("OOM"); exit(EXIT_FAILURE); } if (strcmp(argv[1], "ip") == 0) family = NFPROTO_IPV4; else if (strcmp(argv[1], "ip6") == 0) family = NFPROTO_IPV6; else if (strcmp(argv[1], "bridge") == 0) family = NFPROTO_BRIDGE; else if (strcmp(argv[1], "arp") == 0) family = NFPROTO_ARP; else { fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n"); exit(EXIT_FAILURE); } seq = time(NULL); nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, argv[2]); nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, argv[3]); /* If no handle is specified, delete all rules in the chain */ if (argc == 5) nft_rule_attr_set_u64(r, NFT_RULE_ATTR_HANDLE, atoi(argv[4])); batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_BEGIN, seq++); mnl_nlmsg_batch_next(batch); nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_DELRULE, family, NLM_F_ACK, seq++); nft_rule_nlmsg_build_payload(nlh, r); nft_rule_free(r); mnl_nlmsg_batch_next(batch); nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, seq++); mnl_nlmsg_batch_next(batch); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } mnl_nlmsg_batch_stop(batch); ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, 0, portid, NULL, NULL); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; int ret; unsigned int portid, qnum; atexit(cleanup); if (argc != 2) { printf("Usage: %s [queue_num]\n", argv[0]); exit(EXIT_FAILURE); } qnum = atoi(argv[1]); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_UNBIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_BIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_request(buf, NFULNL_CFG_CMD_BIND, qnum); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_params(buf, NFULNL_COPY_PACKET, 0xFFFF, qnum); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { if(errno == ENOSPC || errno == ENOBUFS) { /* ignore these (hopefully) recoverable errors */ } else { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } } while (1) { if (ret == -1) { /* reset ret and skip mnl_cb_run if previous recvfrom had an error */ ret = 0; } else { ret = mnl_cb_run(buf, ret, 0, portid, log_cb, NULL); if (ret < 0) { perror("mnl_cb_run"); exit(EXIT_FAILURE); } } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { if (errno == ENOSPC || errno == ENOBUFS) { /* ignore these (hopefully) recoverable errors */ continue; } else { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } } } return 0; }
void *nfacct_main(void *ptr) { if(ptr) { ; } info("NFACCT thread created with task id %d", gettid()); if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("nfacct.plugin: Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("nfacct.plugin: Cannot set pthread cancel state to ENABLE."); char buf[MNL_SOCKET_BUFFER_SIZE]; struct mnl_socket *nl = NULL; struct nlmsghdr *nlh = NULL; unsigned int seq = 0, portid = 0; seq = time(NULL) - 1; nl = mnl_socket_open(NETLINK_NETFILTER); if(!nl) { error("nfacct.plugin: mnl_socket_open() failed"); pthread_exit(NULL); return NULL; } if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { mnl_socket_close(nl); error("nfacct.plugin: mnl_socket_bind() failed"); pthread_exit(NULL); return NULL; } portid = mnl_socket_get_portid(nl); // ------------------------------------------------------------------------ struct timeval last, now; unsigned long long usec = 0, susec = 0; RRDSET *st = NULL; gettimeofday(&last, NULL); // ------------------------------------------------------------------------ while(1) { if(unlikely(netdata_exit)) break; seq++; nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq); if(!nlh) { mnl_socket_close(nl); error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed"); pthread_exit(NULL); return NULL; } if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { error("nfacct.plugin: mnl_socket_send"); pthread_exit(NULL); return NULL; } if(nfacct_list) nfacct_list->len = 0; int ret; while((ret = mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0) { if((ret = mnl_cb_run(buf, ret, seq, portid, nfacct_callback, NULL)) <= 0) break; } if (ret == -1) { error("nfacct.plugin: error communicating with kernel."); pthread_exit(NULL); return NULL; } // -------------------------------------------------------------------- gettimeofday(&now, NULL); usec = usecdiff(&now, &last) - susec; debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec); if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec; else susec = rrd_update_every * 1000000ULL / 2ULL; // -------------------------------------------------------------------- if(nfacct_list && nfacct_list->len) { int i; st = rrdset_find_bytype("netfilter", "nfacct_packets"); if(!st) { st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 1006, rrd_update_every, RRDSET_TYPE_STACKED); for(i = 0; i < nfacct_list->len ; i++) rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; i < nfacct_list->len ; i++) { RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name); if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL); if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].pkts); } rrdset_done(st); // ---------------------------------------------------------------- st = rrdset_find_bytype("netfilter", "nfacct_bytes"); if(!st) { st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, rrd_update_every, RRDSET_TYPE_STACKED); for(i = 0; i < nfacct_list->len ; i++) rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; i < nfacct_list->len ; i++) { RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name); if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].bytes); } rrdset_done(st); } // -------------------------------------------------------------------- usleep(susec); // copy current to last bcopy(&now, &last, sizeof(struct timeval)); } mnl_socket_close(nl); pthread_exit(NULL); return NULL; }
int main(void) { struct mnl_socket *nl; struct nlmsghdr *nlh; struct nfgenmsg *nfh; char buf[MNL_SOCKET_BUFFER_SIZE]; unsigned int seq, portid; struct nf_conntrack *ct; int ret; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_DELETE; nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = AF_INET; nfh->version = NFNETLINK_V0; nfh->res_id = 0; ct = nfct_new(); if (ct == NULL) { perror("nfct_new"); return 0; } nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20)); nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10)); nfct_nlmsg_build(nlh, ct); ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); if (ret <= MNL_CB_STOP) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
int main(int argc, char *argv[]){ struct mnl_socket *nl_sock = NULL; struct nlmsghdr *nlh = NULL; struct nlmsgerr *nlerr = NULL; struct nlattr *linkinfo = NULL, *tunnelinfo = NULL; struct ifinfomsg *ifinfo = NULL; uint8_t buf[MNL_SOCKET_BUFFER_SIZE]; size_t numbytes = 0; struct in_addr addr; memset(buf, 0, sizeof(buf)); if((nl_sock = mnl_socket_open(NETLINK_ROUTE)) == NULL){ perror("mnl_socket_open: "); exit(EXIT_FAILURE); } //Add and configure header nlh = mnl_nlmsg_put_header(buf); //Create only if interface does not exists from before (EXCL) nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK; nlh->nlmsg_type = RTM_NEWLINK; //see rtnl_newlink in net/core/rtnetlink.c for observing how this function //works ifinfo = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg)); ifinfo->ifi_family = AF_UNSPEC; //Add a name and mtu, for testing mnl_attr_put_str(nlh, IFLA_IFNAME, "kre2"); mnl_attr_put_u32(nlh, IFLA_MTU, 1234); //Type is required, set to IPIP linkinfo = mnl_attr_nest_start(nlh, IFLA_LINKINFO); mnl_attr_put_str(nlh, IFLA_INFO_KIND, "ipip"); //Add information about the tunnel tunnelinfo = mnl_attr_nest_start(nlh, IFLA_INFO_DATA); inet_pton(AF_INET, "192.168.203.19", &addr); mnl_attr_put_u32(nlh, IFLA_IPTUN_LOCAL, addr.s_addr); inet_pton(AF_INET, "10.0.0.2", &addr); mnl_attr_put_u32(nlh, IFLA_IPTUN_REMOTE, addr.s_addr); mnl_attr_nest_end(nlh, tunnelinfo); mnl_attr_nest_end(nlh, linkinfo); numbytes = mnl_socket_sendto(nl_sock, nlh, nlh->nlmsg_len); numbytes = mnl_socket_recvfrom(nl_sock, buf, sizeof(buf)); nlh = (struct nlmsghdr*) buf; if(nlh->nlmsg_type == NLMSG_ERROR){ nlerr = mnl_nlmsg_get_payload(nlh); //error==0 for ack if(nlerr->error) printf("Error: %s\n", strerror(-nlerr->error)); } else { printf("Link added\n"); } return EXIT_FAILURE; }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq, family, data; struct nft_set *s; struct nft_set_elem *e; int ret; if (argc != 4) { fprintf(stderr, "%s <family> <table> <set>\n", argv[0]); exit(EXIT_FAILURE); } s = nft_set_alloc(); if (s == NULL) { perror("OOM"); exit(EXIT_FAILURE); } seq = time(NULL); if (strcmp(argv[1], "ip") == 0) family = NFPROTO_IPV4; else if (strcmp(argv[1], "ip6") == 0) family = NFPROTO_IPV6; else if (strcmp(argv[1], "bridge") == 0) family = NFPROTO_BRIDGE; else if (strcmp(argv[1], "arp") == 0) family = NFPROTO_ARP; else { fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n"); exit(EXIT_FAILURE); } nft_set_attr_set(s, NFT_SET_ATTR_TABLE, argv[2]); nft_set_attr_set(s, NFT_SET_ATTR_NAME, argv[3]); /* Add to dummy elements to set */ e = nft_set_elem_alloc(); if (e == NULL) { perror("OOM"); exit(EXIT_FAILURE); } data = 0x1; nft_set_elem_attr_set(e, NFT_SET_ELEM_ATTR_KEY, &data, sizeof(data)); nft_set_elem_add(s, e); e = nft_set_elem_alloc(); if (e == NULL) { perror("OOM"); exit(EXIT_FAILURE); } data = 0x2; nft_set_elem_attr_set(e, NFT_SET_ELEM_ATTR_KEY, &data, sizeof(data)); nft_set_elem_add(s, e); nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_NEWSETELEM, family, NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK, seq); nft_set_elems_nlmsg_build_payload(nlh, s); nft_set_free(s); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq, family; uint32_t type = NFT_OUTPUT_DEFAULT; struct nft_set *t = NULL; int ret; if (argc < 4 || argc > 5) { fprintf(stderr, "%s <family> <table> <set> [<json|xml>]\n", argv[0]); return EXIT_FAILURE; } t = nft_set_alloc(); if (t == NULL) { perror("OOM"); exit(EXIT_FAILURE); } seq = time(NULL); if (strcmp(argv[1], "ip") == 0) family = NFPROTO_IPV4; else if (strcmp(argv[1], "ip6") == 0) family = NFPROTO_IPV6; else if (strcmp(argv[1], "bridge") == 0) family = NFPROTO_BRIDGE; else if (strcmp(argv[1], "arp") == 0) family = NFPROTO_ARP; else { fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n"); exit(EXIT_FAILURE); } if (argc == 5 && strcmp(argv[4], "json") == 0 ) type = NFT_OUTPUT_JSON; else if (argc == 5 && strcmp(argv[4], "xml") == 0) type = NFT_OUTPUT_XML; nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family, NLM_F_DUMP|NLM_F_ACK, seq); nft_set_attr_set(t, NFT_SET_ATTR_NAME, argv[3]); nft_set_attr_set(t, NFT_SET_ATTR_TABLE, argv[2]); nft_set_elems_nlmsg_build_payload(nlh, t); nft_set_free(t); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, set_cb, &type); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return EXIT_SUCCESS; }