static int nftnl_expr_target_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_target *target = nftnl_expr_data(e); struct nlattr *tb[NFTA_TARGET_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nftnl_expr_target_cb, tb) < 0) return -1; if (tb[NFTA_TARGET_NAME]) { snprintf(target->name, XT_EXTENSION_MAXNAMELEN, "%s", mnl_attr_get_str(tb[NFTA_TARGET_NAME])); target->name[XT_EXTENSION_MAXNAMELEN-1] = '\0'; e->flags |= (1 << NFTNL_EXPR_TG_NAME); } if (tb[NFTA_TARGET_REV]) { target->rev = ntohl(mnl_attr_get_u32(tb[NFTA_TARGET_REV])); e->flags |= (1 << NFTNL_EXPR_TG_REV); } if (tb[NFTA_TARGET_INFO]) { uint32_t len = mnl_attr_get_payload_len(tb[NFTA_TARGET_INFO]); void *target_data; if (target->data) xfree(target->data); target_data = calloc(1, len); if (target_data == NULL) return -1; memcpy(target_data, mnl_attr_get_payload(tb[NFTA_TARGET_INFO]), len); target->data = target_data; target->data_len = len; e->flags |= (1 << NFTNL_EXPR_TG_INFO); } return 0; }
static int data_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[CTA_MAX+1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb); if (tb[CTA_TUPLE_ORIG]) print_tuple(tb[CTA_TUPLE_ORIG]); if (tb[CTA_MARK]) printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK]))); if (tb[CTA_SECMARK]) printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK]))); if (tb[CTA_COUNTERS_ORIG]) { printf("original "); print_counters(tb[CTA_COUNTERS_ORIG]); } if (tb[CTA_COUNTERS_REPLY]) { printf("reply "); print_counters(tb[CTA_COUNTERS_REPLY]); } printf("\n"); return MNL_CB_OK; }
static int nft_rule_expr_ct_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_ct *ct = nft_expr_data(e); struct nlattr *tb[NFTA_CT_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_ct_cb, tb) < 0) return -1; if (tb[NFTA_CT_KEY]) { ct->key = ntohl(mnl_attr_get_u32(tb[NFTA_CT_KEY])); e->flags |= (1 << NFT_EXPR_CT_KEY); } if (tb[NFTA_CT_DREG]) { ct->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_DREG])); e->flags |= (1 << NFT_EXPR_CT_DREG); } if (tb[NFTA_CT_SREG]) { ct->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_SREG])); e->flags |= (1 << NFT_EXPR_CT_SREG); } if (tb[NFTA_CT_DIRECTION]) { ct->dir = mnl_attr_get_u8(tb[NFTA_CT_DIRECTION]); e->flags |= (1 << NFT_EXPR_CT_DIR); } return 0; }
static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {}; struct nlattr *info[TIPC_NLA_MAX + 1] = {}; uint16_t member_cnt; uint32_t applied; uint32_t dom_gen; uint64_t up_map; char status[16]; char monitored[16]; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_MON_PEER]) return MNL_CB_ERROR; open_json_object(NULL); mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs); (attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ? strcpy(monitored, "direct") : strcpy(monitored, "indirect"); attrs[TIPC_NLA_MON_PEER_UP] ? strcpy(status, "up") : strcpy(status, "down"); dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ? mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0; link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]), status, monitored, dom_gen); applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]); if (!applied) goto exit; up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]); member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]); /* each tipc address occupies 4 bytes of payload, hence compensate it */ member_cnt /= sizeof(uint32_t); link_mon_print_applied(applied, up_map); link_mon_print_non_applied(applied, member_cnt, up_map, mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS])); exit: print_string(PRINT_FP, NULL, "\n", ""); close_json_object(); return MNL_CB_OK; }
int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp) { struct nlattr *tb[CTA_EXPECT_MAX+1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(struct nfgenmsg), nlmsg_parse_expection_attr_cb, tb); if (tb[CTA_EXPECT_MASTER]) { exp->expected.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->expected.set); nfct_parse_tuple(tb[CTA_EXPECT_MASTER], &exp->master.orig, __DIR_ORIG, exp->master.set); set_bit(ATTR_EXP_MASTER, exp->set); } if (tb[CTA_EXPECT_TUPLE]) { exp->mask.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->mask.set); nfct_parse_tuple(tb[CTA_EXPECT_TUPLE], &exp->expected.orig, __DIR_ORIG, exp->expected.set); set_bit(ATTR_EXP_EXPECTED, exp->set); } if (tb[CTA_EXPECT_MASK]) { exp->master.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->master.set); nfct_parse_tuple(tb[CTA_EXPECT_MASK], &exp->mask.orig, __DIR_ORIG, exp->mask.set); set_bit(ATTR_EXP_MASK, exp->set); } if (tb[CTA_EXPECT_TIMEOUT]) { exp->timeout = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_TIMEOUT])); set_bit(ATTR_EXP_TIMEOUT, exp->set); } if (tb[CTA_EXPECT_ZONE]) { exp->zone = ntohs(mnl_attr_get_u16(tb[CTA_EXPECT_ZONE])); set_bit(ATTR_EXP_ZONE, exp->set); } if (tb[CTA_EXPECT_FLAGS]) { exp->flags = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_FLAGS])); set_bit(ATTR_EXP_FLAGS, exp->set); } if (tb[CTA_EXPECT_HELP_NAME]) { strncpy(exp->helper_name, mnl_attr_get_str(tb[CTA_EXPECT_HELP_NAME]), NFCT_HELPER_NAME_MAX); set_bit(ATTR_EXP_HELPER_NAME, exp->set); } return 0; }
static int nfct_parse_counters(const struct nlattr *attr, struct nf_conntrack *ct, int dir) { struct nlattr *tb[CTA_COUNTERS_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_counters_attr_cb, tb) < 0) return -1; if (tb[CTA_COUNTERS_PACKETS] || tb[CTA_COUNTERS32_PACKETS]) { if (tb[CTA_COUNTERS32_PACKETS]) { ct->counters[dir].packets = ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_PACKETS])); } if (tb[CTA_COUNTERS_PACKETS]) { ct->counters[dir].packets = be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS])); } switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set); break; case __DIR_REPL: set_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set); break; } } if (tb[CTA_COUNTERS_BYTES] || tb[CTA_COUNTERS32_BYTES]) { if (tb[CTA_COUNTERS32_BYTES]) { ct->counters[dir].bytes = ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_BYTES])); } if (tb[CTA_COUNTERS_BYTES]) { ct->counters[dir].bytes = be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES])); } switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set); break; case __DIR_REPL: set_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set); break; } } return 0; }
static int nfct_parse_nat_seq(const struct nlattr *attr, struct nf_conntrack *ct, int dir) { struct nlattr *tb[CTA_NAT_SEQ_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_nat_seq_attr_cb, tb) < 0) return -1; if (tb[CTA_NAT_SEQ_CORRECTION_POS]) { ct->natseq[dir].correction_pos = ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_CORRECTION_POS])); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set); break; case __DIR_REPL: set_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set); break; } } if (tb[CTA_NAT_SEQ_OFFSET_BEFORE]) { ct->natseq[dir].offset_before = ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_BEFORE])); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set); break; case __DIR_REPL: set_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set); break; } } if (tb[CTA_NAT_SEQ_OFFSET_AFTER]) { ct->natseq[dir].offset_after = ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_AFTER])); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set); break; case __DIR_REPL: set_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set); break; } } return 0; }
static int res_no_args_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_SUMMARY]) return MNL_CB_ERROR; idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); if (rd->json_output) { jsonw_uint_field(rd->jw, "ifindex", idx); jsonw_string_field(rd->jw, "ifname", name); } else { pr_out("%u: %s: ", idx, name); } res_print_summary(rd, tb); if (!rd->json_output) pr_out("\n"); return MNL_CB_OK; }
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; int ret = MNL_CB_OK; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_PD]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_PD]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (ret != MNL_CB_OK) break; ret = res_pd_line(rd, name, idx, nla_line); if (ret != MNL_CB_OK) break; } return ret; }
static int node_list_cb(const struct nlmsghdr *nlh, void *data) { uint32_t addr; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_NODE]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_NODE], parse_attrs, attrs); if (!attrs[TIPC_NLA_NODE_ADDR]) return MNL_CB_ERROR; addr = mnl_attr_get_u32(attrs[TIPC_NLA_NODE_ADDR]); printf("<%u.%u.%u>: ", tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); if (attrs[TIPC_NLA_NODE_UP]) printf("up\n"); else printf("down\n"); return MNL_CB_OK; }
//Function which parses the netlink message (*ADDR) we have received and extract //relevant information, which is parsed to OS-independent //neat_addr_update_src_list static void neat_linux_handle_addr(struct neat_ctx *nc, struct nlmsghdr *nl_hdr) { struct ifaddrmsg *ifm = (struct ifaddrmsg*) mnl_nlmsg_get_payload(nl_hdr); const struct nlattr *attr_table[IFA_MAX+1]; //IFA_MAX is the largest index I can store in my array. Since arrays are //zero-indexed, this is IFA_MAX and not IFA_MAX + 1. However, array has to //be of size IFA_MAX + 1. DOH! struct nlattr_storage tb_storage = {attr_table, IFA_MAX}; struct sockaddr_storage src_addr; struct sockaddr_in *src_addr4; struct sockaddr_in6 *src_addr6; struct ifa_cacheinfo *ci; uint32_t *addr6_ptr, ifa_pref = 0, ifa_valid = 0; uint8_t i; //On Linux, lo has a fixed index. We have no interest in that interface //TODO: Consider other filters - bridges, ifb, ... if (ifm->ifa_index == LO_DEV_IDX) return; if (ifm->ifa_scope == RT_SCOPE_LINK) return; memset(attr_table, 0, sizeof(attr_table)); memset(&src_addr, 0, sizeof(src_addr)); if (mnl_attr_parse(nl_hdr, sizeof(struct ifaddrmsg), neat_linux_parse_nlattr, &tb_storage) != MNL_CB_OK) { fprintf(stderr, "Failed to parse nlattr for msg of type %d\n", nl_hdr->nlmsg_type); return; } //v4 and v6 has to be handled differently, both due to address size and //available information if (ifm->ifa_family == AF_INET) { src_addr4 = (struct sockaddr_in*) &src_addr; src_addr4->sin_family = AF_INET; src_addr4->sin_addr.s_addr = mnl_attr_get_u32(attr_table[IFA_LOCAL]); } else { src_addr6 = (struct sockaddr_in6*) &src_addr; src_addr6->sin6_family = AF_INET6; addr6_ptr = (uint32_t*) mnl_attr_get_payload(attr_table[IFA_ADDRESS]); for (i=0; i<4; i++) src_addr6->sin6_addr.s6_addr32[i] = *(addr6_ptr + i); ci = (struct ifa_cacheinfo*) mnl_attr_get_payload(attr_table[IFA_CACHEINFO]); ifa_pref = ci->ifa_prefered; ifa_valid = ci->ifa_valid; } //TODO: Should this function be a callback instead? Will we have multiple //addresses handlers/types of context? neat_addr_update_src_list(nc, &src_addr, ifm->ifa_index, nl_hdr->nlmsg_type == RTM_NEWADDR, ifa_pref, ifa_valid); }
static void attributes_show_ipv4(struct nlattr *tb[]) { if (tb[RTA_TABLE]) { printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE])); } if (tb[RTA_DST]) { struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]); printf("dst=%s ", inet_ntoa(*addr)); } if (tb[RTA_SRC]) { struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]); printf("src=%s ", inet_ntoa(*addr)); } if (tb[RTA_OIF]) { printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF])); } if (tb[RTA_FLOW]) { printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW])); } if (tb[RTA_PREFSRC]) { struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]); printf("prefsrc=%s ", inet_ntoa(*addr)); } if (tb[RTA_GATEWAY]) { struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); printf("gw=%s ", inet_ntoa(*addr)); } if (tb[RTA_PRIORITY]) { printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY])); } if (tb[RTA_METRICS]) { int i; struct nlattr *tbx[RTAX_MAX+1] = {}; mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx); for (i=0; i<RTAX_MAX; i++) { if (tbx[i]) { printf("metrics[%d]=%u ", i, mnl_attr_get_u32(tbx[i])); } } } printf("\n"); }
static int cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[NLE_MAX]; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb); if (tb[NLE_MYVAR]) printf("myvar=%d\n", mnl_attr_get_u32(tb[NLE_MYVAR])); return MNL_CB_OK; }
static int nametable_show_cb(const struct nlmsghdr *nlh, void *data) { int *iteration = data; char port_id[PORTID_STR_LEN]; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_NAME_TABLE_MAX + 1] = {}; struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1] = {}; const char *scope[] = { "", "zone", "cluster", "node" }; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_NAME_TABLE]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_NAME_TABLE], parse_attrs, attrs); if (!attrs[TIPC_NLA_NAME_TABLE_PUBL]) return MNL_CB_ERROR; mnl_attr_parse_nested(attrs[TIPC_NLA_NAME_TABLE_PUBL], parse_attrs, publ); if (!publ[TIPC_NLA_NAME_TABLE_PUBL]) return MNL_CB_ERROR; if (!*iteration) printf("%-10s %-10s %-10s %-26s %-10s\n", "Type", "Lower", "Upper", "Port Identity", "Publication Scope"); (*iteration)++; snprintf(port_id, sizeof(port_id), "<%u.%u.%u:%u>", tipc_zone(mnl_attr_get_u32(publ[TIPC_NLA_PUBL_NODE])), tipc_cluster(mnl_attr_get_u32(publ[TIPC_NLA_PUBL_NODE])), tipc_node(mnl_attr_get_u32(publ[TIPC_NLA_PUBL_NODE])), mnl_attr_get_u32(publ[TIPC_NLA_PUBL_REF])); printf("%-10u %-10u %-10u %-26s %-12u", mnl_attr_get_u32(publ[TIPC_NLA_PUBL_TYPE]), mnl_attr_get_u32(publ[TIPC_NLA_PUBL_LOWER]), mnl_attr_get_u32(publ[TIPC_NLA_PUBL_UPPER]), port_id, mnl_attr_get_u32(publ[TIPC_NLA_PUBL_KEY])); printf("%s\n", scope[mnl_attr_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]); return MNL_CB_OK; }
static int link_get_cb(const struct nlmsghdr *nlh, void *data) { int *prop = data; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_LINK]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); if (!attrs[TIPC_NLA_LINK_PROP]) return MNL_CB_ERROR; mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props); if (!props[*prop]) return MNL_CB_ERROR; new_json_obj(json); open_json_object(NULL); switch (*prop) { case TIPC_NLA_PROP_PRIO: print_uint(PRINT_ANY, PRIORITY_STR, "%u\n", mnl_attr_get_u32(props[*prop])); break; case TIPC_NLA_PROP_TOL: print_uint(PRINT_ANY, TOLERANCE_STR, "%u\n", mnl_attr_get_u32(props[*prop])); break; case TIPC_NLA_PROP_WIN: print_uint(PRINT_ANY, WINDOW_STR, "%u\n", mnl_attr_get_u32(props[*prop])); break; default: break; } close_json_object(); delete_json_obj(); return MNL_CB_OK; }
static int nft_rule_expr_log_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_log *log = nft_expr_data(e); struct nlattr *tb[NFTA_LOG_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_log_cb, tb) < 0) return -1; if (tb[NFTA_LOG_PREFIX]) { if (log->prefix) xfree(log->prefix); log->prefix = strdup(mnl_attr_get_str(tb[NFTA_LOG_PREFIX])); e->flags |= (1 << NFT_EXPR_LOG_PREFIX); } if (tb[NFTA_LOG_GROUP]) { log->group = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_GROUP])); e->flags |= (1 << NFT_EXPR_LOG_GROUP); } if (tb[NFTA_LOG_SNAPLEN]) { log->snaplen = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_SNAPLEN])); e->flags |= (1 << NFT_EXPR_LOG_SNAPLEN); } if (tb[NFTA_LOG_QTHRESHOLD]) { log->qthreshold = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_QTHRESHOLD])); e->flags |= (1 << NFT_EXPR_LOG_QTHRESHOLD); } if (tb[NFTA_LOG_LEVEL]) { log->level = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_LEVEL])); e->flags |= (1 << NFT_EXPR_LOG_LEVEL); } if (tb[NFTA_LOG_FLAGS]) { log->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_FLAGS])); e->flags |= (1 << NFT_EXPR_LOG_FLAGS); } return 0; }
static int data_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[CTRL_ATTR_MAX+1] = {}; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb); if (tb[CTRL_ATTR_FAMILY_NAME]) { printf("name=%s\t", mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME])); } if (tb[CTRL_ATTR_FAMILY_ID]) { printf("id=%u\t", mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID])); } if (tb[CTRL_ATTR_VERSION]) { printf("version=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_VERSION])); } if (tb[CTRL_ATTR_HDRSIZE]) { printf("hdrsize=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE])); } if (tb[CTRL_ATTR_MAXATTR]) { printf("maxattr=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR])); } printf("\n"); if (tb[CTRL_ATTR_OPS]) { printf("ops:\n"); parse_genl_family_ops(tb[CTRL_ATTR_OPS]); } if (tb[CTRL_ATTR_MCAST_GROUPS]) { printf("grps:\n"); parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]); } printf("\n"); return MNL_CB_OK; }
static int nft_rule_expr_byteorder_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_byteorder *byteorder = nft_expr_data(e); struct nlattr *tb[NFTA_BYTEORDER_MAX+1] = {}; int ret = 0; if (mnl_attr_parse_nested(attr, nft_rule_expr_byteorder_cb, tb) < 0) return -1; if (tb[NFTA_BYTEORDER_SREG]) { byteorder->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SREG])); e->flags |= (1 << NFT_EXPR_BYTEORDER_SREG); } if (tb[NFTA_BYTEORDER_DREG]) { byteorder->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_DREG])); e->flags |= (1 << NFT_EXPR_BYTEORDER_DREG); } if (tb[NFTA_BYTEORDER_OP]) { byteorder->op = ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_OP])); e->flags |= (1 << NFT_EXPR_BYTEORDER_OP); } if (tb[NFTA_BYTEORDER_LEN]) { byteorder->len = ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_LEN])); e->flags |= (1 << NFT_EXPR_BYTEORDER_LEN); } if (tb[NFTA_BYTEORDER_SIZE]) { byteorder->size = ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SIZE])); e->flags |= (1 << NFT_EXPR_BYTEORDER_SIZE); } return ret; }
int nftnl_gen_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_gen *gen) { struct nlattr *tb[NFTA_GEN_MAX + 1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_gen_parse_attr_cb, tb) < 0) return -1; if (tb[NFTA_GEN_ID]) { gen->id = ntohl(mnl_attr_get_u32(tb[NFTA_GEN_ID])); gen->flags |= (1 << NFTNL_GEN_ID); } return 0; }
//Function which parses the netlink message (*ADDR) we have received and extract //relevant information, which is parsed to OS-independent //neat_addr_update_src_list static neat_error_code nt_linux_handle_addr(struct neat_ctx *ctx, struct nlmsghdr *nl_hdr) { struct ifaddrmsg *ifm = (struct ifaddrmsg*) mnl_nlmsg_get_payload(nl_hdr); const struct nlattr *attr_table[IFA_MAX+1]; //IFA_MAX is the largest index I can store in my array. Since arrays are //zero-indexed, this is IFA_MAX and not IFA_MAX + 1. However, array has to //be of size IFA_MAX + 1. DOH! struct nlattr_storage tb_storage = {attr_table, IFA_MAX}; struct sockaddr_storage src_addr; struct sockaddr_in *src_addr4; struct sockaddr_in6 *src_addr6; struct ifa_cacheinfo *ci; uint32_t ifa_pref = 0, ifa_valid = 0; if (ifm->ifa_scope == RT_SCOPE_LINK) return NEAT_ERROR_OK; memset(attr_table, 0, sizeof(attr_table)); memset(&src_addr, 0, sizeof(src_addr)); if (mnl_attr_parse(nl_hdr, sizeof(struct ifaddrmsg), neat_linux_parse_nlattr, &tb_storage) != MNL_CB_OK) { nt_log(ctx, NEAT_LOG_ERROR, "Failed to parse nlattr for msg of type %d", __func__, nl_hdr->nlmsg_type); return NEAT_ERROR_OK; } //v4 and v6 has to be handled differently, both due to address size and //available information if (ifm->ifa_family == AF_INET) { src_addr4 = (struct sockaddr_in*) &src_addr; src_addr4->sin_family = AF_INET; src_addr4->sin_addr.s_addr = mnl_attr_get_u32(attr_table[IFA_LOCAL]); } else { src_addr6 = (struct sockaddr_in6*) &src_addr; src_addr6->sin6_family = AF_INET6; memcpy(&src_addr6->sin6_addr, mnl_attr_get_payload(attr_table[IFA_ADDRESS]), sizeof(struct in6_addr)); ci = (struct ifa_cacheinfo*) mnl_attr_get_payload(attr_table[IFA_CACHEINFO]); ifa_pref = ci->ifa_prefered; ifa_valid = ci->ifa_valid; } //TODO: Should this function be a callback instead? Will we have multiple //addresses handlers/types of context? return nt_addr_update_src_list(ctx, (struct sockaddr*) &src_addr, ifm->ifa_index, nl_hdr->nlmsg_type == RTM_NEWADDR, ifm->ifa_prefixlen, ifa_pref, ifa_valid); }
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); return res_pd_line(rd, name, idx, tb); }
static int netid_get_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_NET]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs); if (!attrs[TIPC_NLA_NET_ID]) return MNL_CB_ERROR; printf("%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID])); return MNL_CB_OK; }
static void parse_genl_family_ops(struct nlattr *nested) { struct nlattr *pos; mnl_attr_for_each_nested(pos, nested) { struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {}; mnl_attr_parse_nested(pos, parse_family_ops_cb, tb); if (tb[CTRL_ATTR_OP_ID]) { printf("id-0x%x ", mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID])); } if (tb[CTRL_ATTR_OP_MAX]) { printf("flags "); } printf("\n"); } }
static void parse_genl_mc_grps(struct nlattr *nested) { struct nlattr *pos; mnl_attr_for_each_nested(pos, nested) { struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {}; mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); if (tb[CTRL_ATTR_MCAST_GRP_ID]) { printf("id-0x%x ", mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID])); } if (tb[CTRL_ATTR_MCAST_GRP_NAME]) { printf("name: %s ", mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME])); } printf("\n"); } }
static int nft_rule_expr_match_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_match *match = nft_expr_data(e); struct nlattr *tb[NFTA_MATCH_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_match_cb, tb) < 0) return -1; if (tb[NFTA_MATCH_NAME]) { snprintf(match->name, XT_EXTENSION_MAXNAMELEN, "%s", mnl_attr_get_str(tb[NFTA_MATCH_NAME])); match->name[XT_EXTENSION_MAXNAMELEN-1] = '\0'; e->flags |= (1 << NFT_EXPR_MT_NAME); } if (tb[NFTA_MATCH_REV]) { match->rev = ntohl(mnl_attr_get_u32(tb[NFTA_MATCH_REV])); e->flags |= (1 << NFT_EXPR_MT_REV); } if (tb[NFTA_MATCH_INFO]) { uint32_t len = mnl_attr_get_payload_len(tb[NFTA_MATCH_INFO]); void *match_data; if (match->data) xfree(match->data); match_data = calloc(1, len); if (match_data == NULL) return -1; memcpy(match_data, mnl_attr_get_payload(tb[NFTA_MATCH_INFO]), len); match->data = match_data; match->data_len = len; e->flags |= (1 << NFT_EXPR_MT_INFO); } return 0; }
static int nft_rule_expr_nat_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_nat *nat = nft_expr_data(e); struct nlattr *tb[NFTA_NAT_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_nat_cb, tb) < 0) return -1; if (tb[NFTA_NAT_TYPE]) { nat->type = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_TYPE])); e->flags |= (1 << NFT_EXPR_NAT_TYPE); } if (tb[NFTA_NAT_FAMILY]) { nat->family = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FAMILY])); e->flags |= (1 << NFT_EXPR_NAT_FAMILY); } if (tb[NFTA_NAT_REG_ADDR_MIN]) { nat->sreg_addr_min = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MIN])); e->flags |= (1 << NFT_EXPR_NAT_REG_ADDR_MIN); } if (tb[NFTA_NAT_REG_ADDR_MAX]) { nat->sreg_addr_max = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MAX])); e->flags |= (1 << NFT_EXPR_NAT_REG_ADDR_MAX); } if (tb[NFTA_NAT_REG_PROTO_MIN]) { nat->sreg_proto_min = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MIN])); e->flags |= (1 << NFT_EXPR_NAT_REG_PROTO_MIN); } if (tb[NFTA_NAT_REG_PROTO_MAX]) { nat->sreg_proto_max = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MAX])); e->flags |= (1 << NFT_EXPR_NAT_REG_PROTO_MAX); } if (tb[NFTA_NAT_FLAGS]) { nat->flags = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FLAGS])); e->flags |= (1 << NFT_EXPR_NAT_FLAGS); } return 0; }
static int link_mon_get_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_MON]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); if (!attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]) return MNL_CB_ERROR; new_json_obj(json); print_uint(PRINT_ANY, "threshold", "%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD])); delete_json_obj(); return MNL_CB_OK; }
static int log_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[NFULA_MAX+1] = {}; struct nfulnl_msg_packet_hdr *ph = NULL; const char *prefix = NULL; uint32_t mark = 0; mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb); if (tb[NFULA_PACKET_HDR]) ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]); if (tb[NFULA_PREFIX]) prefix = mnl_attr_get_str(tb[NFULA_PREFIX]); if (tb[NFULA_MARK]) mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK])); printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n", prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook, mark); return MNL_CB_OK; }
static void parse_genl_mc_grps(struct nlattr *nested, struct group_info *group_info) { struct nlattr *pos; const char *name; mnl_attr_for_each_nested(pos, nested) { struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1] = {}; mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); if (!tb[CTRL_ATTR_MCAST_GRP_NAME] || !tb[CTRL_ATTR_MCAST_GRP_ID]) continue; name = mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]); if (strcmp(name, group_info->name) != 0) continue; group_info->id = mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); group_info->found = true; } }
static int nftnl_expr_payload_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_payload *payload = nftnl_expr_data(e); struct nlattr *tb[NFTA_PAYLOAD_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nftnl_expr_payload_cb, tb) < 0) return -1; if (tb[NFTA_PAYLOAD_SREG]) { payload->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_SREG])); e->flags |= (1 << NFT_EXPR_PAYLOAD_SREG); } if (tb[NFTA_PAYLOAD_DREG]) { payload->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_DREG])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_DREG); } if (tb[NFTA_PAYLOAD_BASE]) { payload->base = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_BASE])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_BASE); } if (tb[NFTA_PAYLOAD_OFFSET]) { payload->offset = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_OFFSET])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_OFFSET); } if (tb[NFTA_PAYLOAD_LEN]) { payload->len = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_LEN])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_LEN); } if (tb[NFTA_PAYLOAD_CSUM_TYPE]) { payload->csum_type = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_CSUM_TYPE])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_CSUM_TYPE); } if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) { payload->csum_offset = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); e->flags |= (1 << NFTNL_EXPR_PAYLOAD_CSUM_OFFSET); } return 0; }