/* 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; }
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); }
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; }
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; }
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; }
static void put_msg(char *buf, uint16_t i, int seq) { struct nlmsghdr *nlh; struct nfgenmsg *nfh; struct nlattr *nest1, *nest2; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW; nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; nlh->nlmsg_seq = seq; nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = AF_INET; nfh->version = NFNETLINK_V0; nfh->res_id = 0; nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG); nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP); mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("1.1.1.1")); mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("2.2.2.2")); mnl_attr_nest_end(nlh, nest2); nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO); mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP); mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(i)); mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(1025)); mnl_attr_nest_end(nlh, nest2); mnl_attr_nest_end(nlh, nest1); nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY); nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP); mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("2.2.2.2")); mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("1.1.1.1")); mnl_attr_nest_end(nlh, nest2); nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO); mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP); mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(1025)); mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(i)); mnl_attr_nest_end(nlh, nest2); mnl_attr_nest_end(nlh, nest1); nest1 = mnl_attr_nest_start(nlh, CTA_PROTOINFO); nest2 = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP); mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE, TCP_CONNTRACK_SYN_SENT); mnl_attr_nest_end(nlh, nest2); mnl_attr_nest_end(nlh, nest1); mnl_attr_put_u32(nlh, CTA_STATUS, htonl(IPS_CONFIRMED)); mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(1000)); }
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; }
static void nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq) { struct nlmsghdr *nlh; struct nfgenmsg *nfg; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_seq = seq; nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_INET; nfg->version = NFNETLINK_V0; nfg->res_id = NFNL_SUBSYS_NFTABLES; }
/* 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; }
/** * nflog_nlmsg_put_header - reserve and prepare room for nflog Netlink header * \param buf memory already allocated to store the Netlink header * \param type message type one of the enum nfulnl_msg_types * \param family protocol family to be an object of * \param qnum queue number to be an object of * * This function creates Netlink header in the memory buffer passed * as parameter that will send to nfnetlink log. This function * returns a pointer to the Netlink header structure. */ struct nlmsghdr * nflog_nlmsg_put_header(char *buf, uint8_t type, uint8_t family, uint16_t qnum) { struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); struct nfgenmsg *nfg; nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | type; nlh->nlmsg_flags = NLM_F_REQUEST; nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = family; nfg->version = NFNETLINK_V0; nfg->res_id = htons(qnum); return nlh; }
//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); }
struct nlmsghdr *nftnl_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq) { struct nlmsghdr *nlh; struct nfgenmsg *nfh; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | cmd; nlh->nlmsg_flags = NLM_F_REQUEST | type; nlh->nlmsg_seq = seq; nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = family; nfh->version = NFNETLINK_V0; nfh->res_id = 0; return nlh; }
struct nlmsghdr * genl_nlmsg_build_hdr(char *buf, uint16_t type, uint16_t flags, uint32_t seq, uint8_t cmd) { struct nlmsghdr *nlh; struct genlmsghdr *genl; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = seq; genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = cmd; genl->version = 0; return nlh; }
/** * nfacct_nlmsg_build_hdr - build netlink message header for nfacct subsystem * \param buf: buffer where this function outputs the netlink message. * \param cmd: nfacct nfnetlink command. * \param flags: netlink flags. * \param seq: sequence number for this message. * * Possible commands: * - NFNL_MSG_ACCT_NEW: new accounting object. * - NFNL_MSG_ACCT_GET: get accounting object. * - NFNL_MSG_ACCT_GET_CTRZERO: get accounting object and atomically reset. * * Examples: * - Command NFNL_MSG_ACCT_NEW + flags NLM_F_CREATE | NLM_F_ACK, to create * one new accounting object (if it does not already exists). You receive * one acknoledgment in any case with the result of the operation. * * - Command NFNL_MSG_ACCT_GET + flags NLM_F_DUMP, to obtain all the * existing accounting objects. * * - Command NFNL_MSG_ACCT_GET_CTRZERO + flags NLM_F_DUMP, to atomically * obtain all the existing accounting objects and reset them. * * - Command NFNL_MSG_ACCT_DEL, to delete all existing unused objects. * * - Command NFNL_MSG_ACCT_DEL, to delete one specific nfacct object (if * unused, otherwise you hit EBUSY). */ struct nlmsghdr * nfacct_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq) { struct nlmsghdr *nlh; struct nfgenmsg *nfh; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | cmd; nlh->nlmsg_flags = NLM_F_REQUEST | flags; nlh->nlmsg_seq = seq; nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = AF_UNSPEC; nfh->version = NFNETLINK_V0; nfh->res_id = 0; return nlh; }
static struct nlmsghdr * nflog_build_cfg_pf_request(char *buf, uint8_t command) { struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG; nlh->nlmsg_flags = NLM_F_REQUEST; struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_INET; nfg->version = NFNETLINK_V0; struct nfulnl_msg_config_cmd cmd = { .command = command, }; mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd); return nlh; }
/* 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 struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, uint16_t flags, uint32_t id, uint8_t version) { struct nlmsghdr *nlh; struct genlmsghdr *genl; nlh = mnl_nlmsg_put_header(nlg->buf); nlh->nlmsg_type = id; nlh->nlmsg_flags = flags; nlg->seq = time(NULL); nlh->nlmsg_seq = nlg->seq; genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = cmd; genl->version = version; return nlh; }
static struct nlmsghdr * nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num) { struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; nlh->nlmsg_flags = NLM_F_REQUEST; struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_UNSPEC; nfg->version = NFNETLINK_V0; nfg->res_id = htons(queue_num); struct nfqnl_msg_config_params params = { .copy_range = htonl(range), .copy_mode = mode, }; mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), ¶ms); return nlh; }
static struct nlmsghdr * nfq_build_cfg_request(char *buf, uint8_t command, int queue_num) { struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; nlh->nlmsg_flags = NLM_F_REQUEST; struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_UNSPEC; nfg->version = NFNETLINK_V0; nfg->res_id = htons(queue_num); struct nfqnl_msg_config_cmd cmd = { .command = command, .pf = htons(AF_INET), }; mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd); return nlh; }
static struct nlmsghdr * genl_nlmsg_build_lookup(char *buf, const char *subsys_name) { struct nlmsghdr *nlh; struct genlmsghdr *genl; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = GENL_ID_CTRL; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_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, subsys_name); return nlh; }
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; }
static struct nlmsghdr * nfq_build_verdict(char *buf, int id, int queue_num, int verd) { struct nlmsghdr *nlh; struct nfgenmsg *nfg; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT; nlh->nlmsg_flags = NLM_F_REQUEST; nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_UNSPEC; nfg->version = NFNETLINK_V0; nfg->res_id = htons(queue_num); struct nfqnl_msg_verdict_hdr vh = { .verdict = htonl(verd), .id = htonl(id), }; mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh); return nlh; }
struct nlmsghdr *msg_init(char *buf, int cmd) { int family; struct nlmsghdr *nlh; struct genlmsghdr *genl; family = get_family(); if (family <= 0) { fprintf(stderr, "Unable to get TIPC nl family id (module loaded?)\n"); return NULL; } nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = family; genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = cmd; genl->version = 1; return nlh; }
/* 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; }
static int get_family(void) { int err; int nl_family; struct nlmsghdr *nlh; struct genlmsghdr *genl; char buf[MNL_SOCKET_BUFFER_SIZE]; nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = GENL_ID_CTRL; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); genl->cmd = CTRL_CMD_GETFAMILY; genl->version = 1; mnl_attr_put_u16(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL); mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, TIPC_GENL_V2_NAME); if ((err = msg_query(nlh, family_id_cb, &nl_family))) return err; return nl_family; }