static void print_proto(const struct nlattr *nest) { struct nlattr *tb[CTA_PROTO_MAX+1] = {}; mnl_attr_parse_nested(nest, parse_proto_cb, tb); if (tb[CTA_PROTO_NUM]) { printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM])); } if (tb[CTA_PROTO_SRC_PORT]) { printf("sport=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]))); } if (tb[CTA_PROTO_DST_PORT]) { printf("dport=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]))); } if (tb[CTA_PROTO_ICMP_ID]) { printf("id=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]))); } if (tb[CTA_PROTO_ICMP_TYPE]) { printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE])); } if (tb[CTA_PROTO_ICMP_CODE]) { printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE])); } }
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 get_family_id_cb(const struct nlmsghdr *nlh, void *data) { uint32_t *p_id = data; struct nlattr *tb[CTRL_ATTR_MAX + 1] = {}; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*genl), get_family_id_attr_cb, tb); if (!tb[CTRL_ATTR_FAMILY_ID]) return MNL_CB_ERROR; *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); return MNL_CB_OK; }
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; }
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 genl_ctrl_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[CTRL_ATTR_MAX + 1] = {}; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); int32_t *genl_id = data; mnl_attr_parse(nlh, sizeof(*genl), genl_ctrl_validate_cb, tb); if (tb[CTRL_ATTR_FAMILY_ID]) *genl_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); else *genl_id = -1; return MNL_CB_OK; }
static int nftnl_expr_queue_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_queue *queue = nftnl_expr_data(e); struct nlattr *tb[NFTA_QUEUE_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nftnl_expr_queue_cb, tb) < 0) return -1; if (tb[NFTA_QUEUE_NUM]) { queue->queuenum = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_NUM])); e->flags |= (1 << NFTNL_EXPR_QUEUE_NUM); } if (tb[NFTA_QUEUE_TOTAL]) { queue->queues_total = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_TOTAL])); e->flags |= (1 << NFTNL_EXPR_QUEUE_TOTAL); } if (tb[NFTA_QUEUE_FLAGS]) { queue->flags = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_FLAGS])); e->flags |= (1 << NFTNL_EXPR_QUEUE_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; }
int nfct_payload_parse(const void *payload, size_t payload_len, uint16_t l3num, struct nf_conntrack *ct) { struct nlattr *tb[CTA_MAX+1] = {}; if (mnl_attr_parse_payload(payload, payload_len, nfct_parse_conntrack_attr_cb, tb) < 0) return -1; if (tb[CTA_TUPLE_ORIG]) { ct->head.orig.l3protonum = l3num; set_bit(ATTR_ORIG_L3PROTO, ct->head.set); if (nfct_parse_tuple(tb[CTA_TUPLE_ORIG], &ct->head.orig, __DIR_ORIG, ct->head.set) < 0) return -1; } if (tb[CTA_TUPLE_REPLY]) { ct->repl.l3protonum = l3num; set_bit(ATTR_REPL_L3PROTO, ct->head.set); if (nfct_parse_tuple(tb[CTA_TUPLE_REPLY], &ct->repl, __DIR_REPL, ct->head.set) < 0) return -1; } if (tb[CTA_TUPLE_MASTER]) { ct->master.l3protonum = l3num; set_bit(ATTR_MASTER_L3PROTO, ct->head.set); if (nfct_parse_tuple(tb[CTA_TUPLE_MASTER], &ct->master, __DIR_MASTER, ct->head.set) < 0) return -1; } if (tb[CTA_NAT_SEQ_ADJ_ORIG]) { if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_ORIG], ct, __DIR_ORIG) < 0) return -1; } if (tb[CTA_NAT_SEQ_ADJ_REPLY]) { if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_REPLY], ct, __DIR_REPL) < 0) return -1; } if (tb[CTA_STATUS]) { ct->status = ntohl(mnl_attr_get_u32(tb[CTA_STATUS])); set_bit(ATTR_STATUS, ct->head.set); } if (tb[CTA_PROTOINFO]) { if (nfct_parse_protoinfo(tb[CTA_PROTOINFO], ct) < 0) return -1; } if (tb[CTA_TIMEOUT]) { ct->timeout = ntohl(mnl_attr_get_u32(tb[CTA_TIMEOUT])); set_bit(ATTR_TIMEOUT, ct->head.set); } if (tb[CTA_MARK]) { ct->mark = ntohl(mnl_attr_get_u32(tb[CTA_MARK])); set_bit(ATTR_MARK, ct->head.set); } if (tb[CTA_SECMARK]) { ct->secmark = ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])); set_bit(ATTR_SECMARK, ct->head.set); } if (tb[CTA_COUNTERS_ORIG]) { if (nfct_parse_counters(tb[CTA_COUNTERS_ORIG], ct, __DIR_ORIG) < 0) return -1; } if (tb[CTA_COUNTERS_REPLY]) { if (nfct_parse_counters(tb[CTA_COUNTERS_REPLY], ct, __DIR_REPL) < 0) return -1; } if (tb[CTA_USE]) { ct->use = ntohl(mnl_attr_get_u32(tb[CTA_USE])); set_bit(ATTR_USE, ct->head.set); } if (tb[CTA_ID]) { ct->id = ntohl(mnl_attr_get_u32(tb[CTA_ID])); set_bit(ATTR_ID, ct->head.set); } if (tb[CTA_HELP]) { if (nfct_parse_helper(tb[CTA_HELP], ct) < 0) return -1; } if (tb[CTA_ZONE]) { ct->zone = ntohs(mnl_attr_get_u16(tb[CTA_ZONE])); set_bit(ATTR_ZONE, ct->head.set); } if (tb[CTA_SECCTX]) { if (nfct_parse_secctx(tb[CTA_SECCTX], ct) < 0) return -1; } if (tb[CTA_TIMESTAMP]) { if (nfct_parse_timestamp(tb[CTA_TIMESTAMP], ct) < 0) return -1; } if (tb[CTA_LABELS]) { if (nfct_parse_labels(tb[CTA_LABELS], ct) < 0) return -1; } /* CTA_LABELS_MASK: never sent by kernel */ return 0; }
static int nfct_parse_proto(const struct nlattr *attr, struct __nfct_tuple *tuple, const int dir, u_int32_t *set) { struct nlattr *tb[CTA_PROTO_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_proto_attr_cb, tb) < 0) return -1; if (tb[CTA_PROTO_NUM]) { tuple->protonum = mnl_attr_get_u8(tb[CTA_PROTO_NUM]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_L4PROTO, set); break; case __DIR_REPL: set_bit(ATTR_REPL_L4PROTO, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_L4PROTO, set); break; } } if (tb[CTA_PROTO_SRC_PORT]) { tuple->l4src.tcp.port = mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_PORT_SRC, set); break; case __DIR_REPL: set_bit(ATTR_REPL_PORT_SRC, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_PORT_SRC, set); break; } } if (tb[CTA_PROTO_DST_PORT]) { tuple->l4dst.tcp.port = mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_PORT_DST, set); break; case __DIR_REPL: set_bit(ATTR_REPL_PORT_DST, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_PORT_DST, set); break; } } if (tb[CTA_PROTO_ICMP_TYPE]) { tuple->l4dst.icmp.type = mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]); set_bit(ATTR_ICMP_TYPE, set); } if (tb[CTA_PROTO_ICMP_CODE]) { tuple->l4dst.icmp.code = mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]); set_bit(ATTR_ICMP_CODE, set); } if (tb[CTA_PROTO_ICMP_ID]) { tuple->l4src.icmp.id = mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]); set_bit(ATTR_ICMP_ID, set); } if (tb[CTA_PROTO_ICMPV6_TYPE]) { tuple->l4dst.icmp.type = mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); set_bit(ATTR_ICMP_TYPE, set); } if (tb[CTA_PROTO_ICMPV6_CODE]) { tuple->l4dst.icmp.code = mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); set_bit(ATTR_ICMP_CODE, set); } if (tb[CTA_PROTO_ICMPV6_ID]) { tuple->l4src.icmp.id = mnl_attr_get_u16(tb[CTA_PROTO_ICMPV6_ID]); set_bit(ATTR_ICMP_ID, set); } return 0; }
/* returns negative on error * or returns remainded nlmsghdr length */ static int _unpack_nlmsg(const struct nlmsghdr *nlh, const char *format, va_list ap) { struct nlattr *attr = mnl_nlmsg_get_payload(nlh); int remains = (int)mnl_nlmsg_get_payload_len(nlh); size_t len; uint16_t atype, alen; void *p; while (*format != '\0' ) { if (!mnl_attr_ok(attr, remains)) { errno = EOVERFLOW; return -1; } remains -= MY_NLATTR_HDRLEN; atype = mnl_attr_get_type(attr); alen = mnl_attr_get_payload_len(attr); switch (*format) { case 'B': /* byte */ if (atype != MNL_TYPE_U8 || alen != sizeof(uint8_t)) { errno =EINVAL; return -1; } *(va_arg(ap, uint8_t *)) = mnl_attr_get_u8(attr); break; case 'H': /* 2byte */ if (atype != MNL_TYPE_U16 || alen != sizeof(uint16_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint16_t *)) = mnl_attr_get_u16(attr); break; case 'I': /* 4byte */ if (atype != MNL_TYPE_U32 || alen != sizeof(uint32_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint32_t *)) = mnl_attr_get_u32(attr); break; case 'K': /* 8byte */ if (atype != MNL_TYPE_U64 || alen != sizeof(uint64_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint64_t *)) = mnl_attr_get_u64(attr); break; case 'p': /* pointer */ if (atype != MNL_TYPE_BINARY || alen != sizeof(void *)) { errno = EINVAL; return -1; } *(va_arg(ap, void **)) = *((void **)mnl_attr_get_payload(attr)); break; case 'z': /* null string */ if (atype != MNL_TYPE_NUL_STRING) { errno = EINVAL; return -1; } p = va_arg(ap, void *); if (*(format + 1) == '#') { format++; len = va_arg(ap, size_t); if (alen > len) { errno = EINVAL; return -1; } } strncpy(p, mnl_attr_get_payload(attr), alen); break; case 'y': /* bytes with size */ format++; if (*format != '#') { errno = EINVAL; return -1; } p = va_arg(ap, void *); len = va_arg(ap, size_t); if (alen > len) return -EINVAL; memcpy(p, mnl_attr_get_payload(attr), alen); break; default: errno =EINVAL; return -1; } remains -= MY_ATTR_ALIGN(alen); format++; attr = mnl_attr_next(attr); } if (remains) { errno = EMSGSIZE; nurs_log(NURS_NOTICE, "unpack remains: %d\n", remains); } return remains; }