void nft_rule_to_iptables_command_state(struct nftnl_rule *r, struct iptables_command_state *cs) { struct nftnl_expr_iter *iter; struct nftnl_expr *expr; int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY); struct nft_xt_ctx ctx = { .state.cs = cs, .family = family, }; iter = nftnl_expr_iter_create(r); if (iter == NULL) return; ctx.iter = iter; expr = nftnl_expr_iter_next(iter); while (expr != NULL) { const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); if (strcmp(name, "counter") == 0) nft_parse_counter(expr, &ctx.state.cs->counters); else if (strcmp(name, "payload") == 0) nft_parse_payload(&ctx, expr); else if (strcmp(name, "meta") == 0) nft_parse_meta(&ctx, expr); else if (strcmp(name, "bitwise") == 0) nft_parse_bitwise(&ctx, expr); else if (strcmp(name, "cmp") == 0) nft_parse_cmp(&ctx, expr); else if (strcmp(name, "immediate") == 0) nft_parse_immediate(&ctx, expr); else if (strcmp(name, "match") == 0) nft_parse_match(&ctx, expr); else if (strcmp(name, "target") == 0) nft_parse_target(&ctx, expr); expr = nftnl_expr_iter_next(iter); } nftnl_expr_iter_destroy(iter); if (nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) { const void *data; uint32_t len; struct xtables_match *match; struct xt_entry_match *m; data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len); match = xtables_find_match("comment", XTF_TRY_LOAD, &cs->matches); if (match == NULL) return; m = calloc(1, sizeof(struct xt_entry_match) + len); if (m == NULL) { fprintf(stderr, "OOM"); exit(EXIT_FAILURE); } memcpy(&m->data, get_comment(data, len), len); m->u.match_size = len + XT_ALIGN(sizeof(struct xt_entry_match)); m->u.user.revision = 0; strcpy(m->u.user.name, match->name); match->m = m; } if (cs->target != NULL) cs->jumpto = cs->target->name; else if (cs->jumpto != NULL) cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); else cs->jumpto = ""; } void print_header(unsigned int format, const char *chain, const char *pol, const struct xt_counters *counters, bool basechain, uint32_t refs) { printf("Chain %s", chain); if (basechain) { printf(" (policy %s", pol); if (!(format & FMT_NOCOUNTS)) { fputc(' ', stdout); xtables_print_num(counters->pcnt, (format|FMT_NOTABLE)); fputs("packets, ", stdout); xtables_print_num(counters->bcnt, (format|FMT_NOTABLE)); fputs("bytes", stdout); } printf(")\n"); } else { printf(" (%u references)\n", refs); } if (format & FMT_LINENUMBERS) printf(FMT("%-4s ", "%s "), "num"); if (!(format & FMT_NOCOUNTS)) { if (format & FMT_KILOMEGAGIGA) { printf(FMT("%5s ","%s "), "pkts"); printf(FMT("%5s ","%s "), "bytes"); } else { printf(FMT("%8s ","%s "), "pkts"); printf(FMT("%10s ","%s "), "bytes"); } } if (!(format & FMT_NOTARGET)) printf(FMT("%-9s ","%s "), "target"); fputs(" prot ", stdout); if (format & FMT_OPTIONS) fputs("opt", stdout); if (format & FMT_VIA) { printf(FMT(" %-6s ","%s "), "in"); printf(FMT("%-6s ","%s "), "out"); } printf(FMT(" %-19s ","%s "), "source"); printf(FMT(" %-19s "," %s "), "destination"); printf("\n"); }
void nft_rule_to_iptables_command_state(struct nftnl_rule *r, struct iptables_command_state *cs) { struct nftnl_expr_iter *iter; struct nftnl_expr *expr; int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY); struct nft_xt_ctx ctx = { .state.cs = cs, .family = family, }; iter = nftnl_expr_iter_create(r); if (iter == NULL) return; ctx.iter = iter; expr = nftnl_expr_iter_next(iter); while (expr != NULL) { const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); if (strcmp(name, "counter") == 0) nft_parse_counter(expr, &ctx.state.cs->counters); else if (strcmp(name, "payload") == 0) nft_parse_payload(&ctx, expr); else if (strcmp(name, "meta") == 0) nft_parse_meta(&ctx, expr); else if (strcmp(name, "bitwise") == 0) nft_parse_bitwise(&ctx, expr); else if (strcmp(name, "cmp") == 0) nft_parse_cmp(&ctx, expr); else if (strcmp(name, "immediate") == 0) nft_parse_immediate(&ctx, expr); else if (strcmp(name, "match") == 0) nft_parse_match(&ctx, expr); else if (strcmp(name, "target") == 0) nft_parse_target(&ctx, expr); expr = nftnl_expr_iter_next(iter); } nftnl_expr_iter_destroy(iter); if (cs->target != NULL) cs->jumpto = cs->target->name; else if (cs->jumpto != NULL) cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); else cs->jumpto = ""; } void print_header(unsigned int format, const char *chain, const char *pol, const struct xt_counters *counters, bool basechain, uint32_t refs) { printf("Chain %s", chain); if (basechain) { printf(" (policy %s", pol); if (!(format & FMT_NOCOUNTS)) { fputc(' ', stdout); xtables_print_num(counters->pcnt, (format|FMT_NOTABLE)); fputs("packets, ", stdout); xtables_print_num(counters->bcnt, (format|FMT_NOTABLE)); fputs("bytes", stdout); } printf(")\n"); } else { printf(" (%u references)\n", refs); } if (format & FMT_LINENUMBERS) printf(FMT("%-4s ", "%s "), "num"); if (!(format & FMT_NOCOUNTS)) { if (format & FMT_KILOMEGAGIGA) { printf(FMT("%5s ","%s "), "pkts"); printf(FMT("%5s ","%s "), "bytes"); } else { printf(FMT("%8s ","%s "), "pkts"); printf(FMT("%10s ","%s "), "bytes"); } } if (!(format & FMT_NOTARGET)) printf(FMT("%-9s ","%s "), "target"); fputs(" prot ", stdout); if (format & FMT_OPTIONS) fputs("opt", stdout); if (format & FMT_VIA) { printf(FMT(" %-6s ","%s "), "in"); printf(FMT("%-6s ","%s "), "out"); } printf(FMT(" %-19s ","%s "), "source"); printf(FMT(" %-19s "," %s "), "destination"); printf("\n"); }
int main(int argc, char *argv[]) { struct mnl_socket *nl; struct nftnl_rule *r; struct nlmsghdr *nlh; struct mnl_nlmsg_batch *batch; uint8_t family; char buf[MNL_SOCKET_BUFFER_SIZE]; uint32_t seq = time(NULL); int ret; if (argc < 4 || argc > 5) { fprintf(stderr, "Usage: %s <family> <table> <chain>\n", argv[0]); exit(EXIT_FAILURE); } if (strcmp(argv[1], "ip") == 0) family = NFPROTO_IPV4; else if (strcmp(argv[1], "ip6") == 0) family = NFPROTO_IPV6; else { fprintf(stderr, "Unknown family: ip, ip6\n"); exit(EXIT_FAILURE); } if (argc != 5) r = setup_rule(family, argv[2], argv[3], NULL); else r = setup_rule(family, argv[2], argv[3], argv[4]); 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); } batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_BEGIN, seq++); mnl_nlmsg_batch_next(batch); nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWRULE, nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); nftnl_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, seq++); mnl_nlmsg_batch_next(batch); ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); if (ret == -1) { perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } mnl_nlmsg_batch_stop(batch); ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL); if (ret < 0) { perror("mnl_cb_run"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return EXIT_SUCCESS; }