1077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka/* 2933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso * (C) 2012-2014 by Pablo Neira Ayuso <pablo@netfilter.org> 3077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> 4077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * 5077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * This program is free software; you can redistribute it and/or modify 6077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * it under the terms of the GNU General Public License as published by 7077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * the Free Software Foundation; either version 2 of the License, or 8077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * (at your option) any later version. 9077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * 10077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka * This code has been sponsored by Sophos Astaro <http://www.sophos.com> 11077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka */ 12077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 13077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <string.h> 14077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <stdio.h> 15077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 16077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <sys/socket.h> 17077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <netinet/in.h> 18077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <arpa/inet.h> 19077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <netinet/ip.h> 20933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso#include <netdb.h> 21077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 22077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <xtables.h> 23077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 24077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include <linux/netfilter/nf_tables.h> 25077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 26c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso#include "nft.h" 27077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include "nft-shared.h" 28077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 29742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int nft_ipv4_add(struct nftnl_rule *r, void *data) 30077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 31e83e35e236a33dfdf3e401adb7d7e18362cf1961Pablo Neira Ayuso struct iptables_command_state *cs = data; 32c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso struct xtables_rule_match *matchp; 33077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka uint32_t op; 34d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay int ret; 35077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 36c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero if (cs->fw.ip.iniface[0] != '\0') { 37c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_VIA_IN); 38c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero add_iniface(r, cs->fw.ip.iniface, op); 39c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero } 40077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 41c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero if (cs->fw.ip.outiface[0] != '\0') { 42c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_VIA_OUT); 43c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero add_outiface(r, cs->fw.ip.outiface, op); 44c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero } 45077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 46c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero if (cs->fw.ip.proto != 0) { 47c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, XT_INV_PROTO); 48d579c3cba69ec958ca93216a77f15acfa1487e09Giuseppe Longo add_proto(r, offsetof(struct iphdr, protocol), 1, 49c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero cs->fw.ip.proto, op); 50c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero } 51d579c3cba69ec958ca93216a77f15acfa1487e09Giuseppe Longo 522c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso if (cs->fw.ip.src.s_addr != 0) { 53c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP); 54077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka add_addr(r, offsetof(struct iphdr, saddr), 552c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso &cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr, 56c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero sizeof(struct in_addr), op); 572c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso } 582c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso if (cs->fw.ip.dst.s_addr != 0) { 59c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP); 60077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka add_addr(r, offsetof(struct iphdr, daddr), 612c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso &cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr, 62c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero sizeof(struct in_addr), op); 632c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso } 64077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (cs->fw.ip.flags & IPT_F_FRAG) { 658acf8315a44fbee8227433daabb262b6de1e70f6Arturo Borrero add_payload(r, offsetof(struct iphdr, frag_off), 2, 668acf8315a44fbee8227433daabb262b6de1e70f6Arturo Borrero NFT_PAYLOAD_NETWORK_HEADER); 67077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka /* get the 13 bits that contain the fragment offset */ 68077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka add_bitwise_u16(r, 0x1fff, !0x1fff); 69077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 70077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka /* if offset is non-zero, this is a fragment */ 71c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_FRAG); 72077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka add_cmp_u16(r, 0, op); 73077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 74077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 754ef77b6d1b52e1fe52a7fd48d38d9233f0961640Pablo Neira Ayuso add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags); 764ef77b6d1b52e1fe52a7fd48d38d9233f0961640Pablo Neira Ayuso 77c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso for (matchp = cs->matches; matchp; matchp = matchp->next) { 78d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay /* Use nft built-in comments support instead of comment match */ 79d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay if (strcmp(matchp->match->name, "comment") == 0) { 80d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay ret = add_comment(r, (char *)matchp->match->m->data); 81d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay if (ret < 0) 82d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay return ret; 83d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay } else { 84d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay ret = add_match(r, matchp->match->m); 85d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay if (ret < 0) 86d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay return ret; 87d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay } 88c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso } 89c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso 90c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso /* Counters need to me added before the target, otherwise they are 91c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso * increased for each rule because of the way nf_tables works. 92c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso */ 93c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso if (add_counters(r, cs->counters.pcnt, cs->counters.bcnt) < 0) 94c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso return -1; 95c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso 96d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso return add_action(r, cs, !!(cs->fw.ip.flags & IPT_F_GOTO)); 97077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 98077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 99217f021925872dcbce4187408762845ae3f6f182Giuseppe Longostatic bool nft_ipv4_is_same(const void *data_a, 100217f021925872dcbce4187408762845ae3f6f182Giuseppe Longo const void *data_b) 101077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 102217f021925872dcbce4187408762845ae3f6f182Giuseppe Longo const struct iptables_command_state *a = data_a; 103217f021925872dcbce4187408762845ae3f6f182Giuseppe Longo const struct iptables_command_state *b = data_b; 104217f021925872dcbce4187408762845ae3f6f182Giuseppe Longo 105077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr 106077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr 107077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr 108077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr 109077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.proto != b->fw.ip.proto 110077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.flags != b->fw.ip.flags 111077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka || a->fw.ip.invflags != b->fw.ip.invflags) { 112077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka DEBUGP("different src/dst/proto/flags/invflags\n"); 113077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka return false; 114077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 115077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 116077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka return is_same_interfaces(a->fw.ip.iniface, a->fw.ip.outiface, 117077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka a->fw.ip.iniface_mask, a->fw.ip.outiface_mask, 118077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka b->fw.ip.iniface, b->fw.ip.outiface, 119077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka b->fw.ip.iniface_mask, b->fw.ip.outiface_mask); 120077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 121077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 122742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void get_frag(struct nft_xt_ctx *ctx, struct nftnl_expr *e, bool *inv) 123077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 124077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka uint8_t op; 125077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 126077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka /* we assume correct mask and xor */ 1272c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso if (!(ctx->flags & NFT_XT_CTX_BITWISE)) 128077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka return; 129077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 130077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka /* we assume correct data */ 131742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP); 132077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (op == NFT_CMP_EQ) 133077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka *inv = true; 134077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else 135077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka *inv = false; 1366c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso 1376c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso ctx->flags &= ~NFT_XT_CTX_BITWISE; 138077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 139077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 140077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztykastatic const char *mask_to_str(uint32_t mask) 141077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 142077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka static char mask_str[sizeof("255.255.255.255")]; 143077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka uint32_t bits, hmask = ntohl(mask); 144077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka struct in_addr mask_addr = { 145077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka .s_addr = mask, 146077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka }; 147077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka int i; 148077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 149077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (mask == 0xFFFFFFFFU) { 150077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka sprintf(mask_str, "32"); 151077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka return mask_str; 152077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 153077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 154077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka i = 32; 155077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka bits = 0xFFFFFFFEU; 156077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka while (--i >= 0 && hmask != bits) 157077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka bits <<= 1; 158077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (i >= 0) 159077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka sprintf(mask_str, "%u", i); 160077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else 161077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka sprintf(mask_str, "%s", inet_ntoa(mask_addr)); 162077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 163077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka return mask_str; 164077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 165077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 166742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void nft_ipv4_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, 16704d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo void *data) 168077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 16904d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo struct iptables_command_state *cs = data; 17004d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 1712c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso parse_meta(e, ctx->meta.key, cs->fw.ip.iniface, cs->fw.ip.iniface_mask, 172077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.outiface, cs->fw.ip.outiface_mask, 173077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka &cs->fw.ip.invflags); 174077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 175077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 1762c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayusostatic void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask) 177077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 1782c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso mask->s_addr = ctx->bitwise.mask[0]; 1792c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso} 18004d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 1812c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayusostatic void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx, 182742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso struct nftnl_expr *e, void *data) 1832c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso{ 1842c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso struct iptables_command_state *cs = data; 185077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka struct in_addr addr; 186077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka uint8_t proto; 187077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka bool inv; 188077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 1892c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso switch(ctx->payload.offset) { 190077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka case offsetof(struct iphdr, saddr): 1912c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso get_cmp_data(e, &addr, sizeof(addr), &inv); 192077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.src.s_addr = addr.s_addr; 1936c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso if (ctx->flags & NFT_XT_CTX_BITWISE) { 1942c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso parse_mask_ipv4(ctx, &cs->fw.ip.smsk); 1956c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso ctx->flags &= ~NFT_XT_CTX_BITWISE; 1966c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso } else { 1972c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso cs->fw.ip.smsk.s_addr = 0xffffffff; 1986c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso } 1992c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso 200077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (inv) 201077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.invflags |= IPT_INV_SRCIP; 202077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka break; 203077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka case offsetof(struct iphdr, daddr): 2042c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso get_cmp_data(e, &addr, sizeof(addr), &inv); 205077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.dst.s_addr = addr.s_addr; 2066c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso if (ctx->flags & NFT_XT_CTX_BITWISE) { 2072c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso parse_mask_ipv4(ctx, &cs->fw.ip.dmsk); 2086c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso ctx->flags &= ~NFT_XT_CTX_BITWISE; 2096c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso } else { 2102c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso cs->fw.ip.dmsk.s_addr = 0xffffffff; 2116c8db125b258da070313f20cdf9bc4124bba5383Pablo Neira Ayuso } 2122c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso 213077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (inv) 214077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.invflags |= IPT_INV_DSTIP; 215077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka break; 216077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka case offsetof(struct iphdr, protocol): 2172c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso get_cmp_data(e, &proto, sizeof(proto), &inv); 218077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.proto = proto; 219077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (inv) 220077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.invflags |= IPT_INV_PROTO; 221077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka break; 222077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka case offsetof(struct iphdr, frag_off): 223077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.flags |= IPT_F_FRAG; 2242c4a34c30cb4db93653dbd139e04f7df963c3a41Pablo Neira Ayuso get_frag(ctx, e, &inv); 225077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (inv) 226077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka cs->fw.ip.invflags |= IPT_INV_FRAG; 227077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka break; 228077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka default: 2292dde9356888733a98867a4e769609f9f59a3bf65Giuseppe Longo DEBUGP("unknown payload offset %d\n", ctx->payload.offset); 230077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka break; 231077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 232077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 233077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 23404d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longostatic void nft_ipv4_parse_immediate(const char *jumpto, bool nft_goto, 23504d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo void *data) 236077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 23704d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo struct iptables_command_state *cs = data; 23804d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 23904d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo cs->jumpto = jumpto; 24004d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 24104d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo if (nft_goto) 24204d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo cs->fw.ip.flags |= IPT_F_GOTO; 243077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 244077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 2454272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayusostatic void nft_ipv4_print_header(unsigned int format, const char *chain, 2464272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso const char *pol, 2474272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso const struct xt_counters *counters, 2484272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso bool basechain, uint32_t refs) 2494272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso{ 2504272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso print_header(format, chain, pol, counters, basechain, refs); 2514272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso} 2524272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso 253077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztykastatic void print_ipv4_addr(const struct iptables_command_state *cs, 254077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka unsigned int format) 255077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 256077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka char buf[BUFSIZ]; 257077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 258077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout); 259077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC)) 260077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka printf(FMT("%-19s ","%s "), "anywhere"); 261077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else { 262077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (format & FMT_NUMERIC) 263077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src)); 264077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else 265077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src)); 266077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk)); 267077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka printf(FMT("%-19s ","%s "), buf); 268077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 269077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 270077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout); 271077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC)) 272077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), "anywhere"); 273077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else { 274077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka if (format & FMT_NUMERIC) 275077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst)); 276077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka else 277077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst)); 278077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk)); 279077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), buf); 280077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka } 281077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 282077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 283eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayusostatic void print_fragment(unsigned int flags, unsigned int invflags, 284eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso unsigned int format) 285eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso{ 286eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso if (!(format & FMT_OPTIONS)) 287eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso return; 288eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso 289eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso if (format & FMT_NOTABLE) 290eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso fputs("opt ", stdout); 291eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout); 292eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout); 293eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso fputc(' ', stdout); 294eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso} 295077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 296742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void nft_ipv4_print_firewall(struct nftnl_rule *r, unsigned int num, 297e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka unsigned int format) 298077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka{ 299e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka struct iptables_command_state cs = {}; 300e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka 301e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka nft_rule_to_iptables_command_state(r, &cs); 302e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka 303cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka print_firewall_details(&cs, cs.jumpto, cs.fw.ip.flags, 304e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka cs.fw.ip.invflags, cs.fw.ip.proto, 305077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka num, format); 306eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso print_fragment(cs.fw.ip.flags, cs.fw.ip.invflags, format); 307eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso print_ifaces(cs.fw.ip.iniface, cs.fw.ip.outiface, cs.fw.ip.invflags, 308eb4b65c49994e44e6ad617fe3f60c063d0c331c4Pablo Neira Ayuso format); 309e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka print_ipv4_addr(&cs, format); 310077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 311e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka if (format & FMT_NOTABLE) 312e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka fputs(" ", stdout); 313e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka 314e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka#ifdef IPT_F_GOTO 315e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka if (cs.fw.ip.flags & IPT_F_GOTO) 316e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka printf("[goto] "); 317e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka#endif 318e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka 319cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka print_matches_and_target(&cs, format); 320e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka 321e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka if (!(format & FMT_NONEWLINE)) 322e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka fputc('\n', stdout); 323077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka} 324077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka 325cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztykastatic void save_ipv4_addr(char letter, const struct in_addr *addr, 326cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka uint32_t mask, int invert) 327cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka{ 328cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka if (!mask && !invert && !addr->s_addr) 329cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka return; 330cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 331cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka printf("%s-%c %s/%s ", invert ? "! " : "", letter, inet_ntoa(*addr), 332cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka mask_to_str(mask)); 333cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka} 334cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 3358877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longostatic void nft_ipv4_save_firewall(const void *data, unsigned int format) 336cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka{ 3378877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo const struct iptables_command_state *cs = data; 3388877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo 339cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka save_firewall_details(cs, cs->fw.ip.invflags, cs->fw.ip.proto, 340cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka cs->fw.ip.iniface, cs->fw.ip.iniface_mask, 3411aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo cs->fw.ip.outiface, cs->fw.ip.outiface_mask); 342cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 343cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka if (cs->fw.ip.flags & IPT_F_FRAG) { 344cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka if (cs->fw.ip.invflags & IPT_INV_FRAG) 345cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka printf("! "); 346cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka printf("-f "); 347cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka } 348cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 349cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka save_ipv4_addr('s', &cs->fw.ip.src, cs->fw.ip.smsk.s_addr, 350cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka cs->fw.ip.invflags & IPT_INV_SRCIP); 351cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka save_ipv4_addr('d', &cs->fw.ip.dst, cs->fw.ip.dmsk.s_addr, 352cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka cs->fw.ip.invflags & IPT_INV_DSTIP); 353cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 3548877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo save_matches_and_target(cs->matches, cs->target, 3558877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo cs->jumpto, cs->fw.ip.flags, &cs->fw); 356d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso 357d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso if (cs->target == NULL && strlen(cs->jumpto) > 0) { 358d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso printf("-%c %s", cs->fw.ip.flags & IPT_F_GOTO ? 'g' : 'j', 359d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso cs->jumpto); 360d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso } 361d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso printf("\n"); 362cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka} 363cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka 3644b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayusostatic void nft_ipv4_proto_parse(struct iptables_command_state *cs, 3654b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso struct xtables_args *args) 3664b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso{ 3674b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso cs->fw.ip.proto = args->proto; 3684b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso cs->fw.ip.invflags = args->invflags; 3694b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso} 3704b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso 3716838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayusostatic void nft_ipv4_post_parse(int command, 3726838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso struct iptables_command_state *cs, 3736838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso struct xtables_args *args) 3746838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso{ 3756838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso cs->fw.ip.flags = args->flags; 376ee595bc702ca80f72c522406f6a06ba7c31eb8dfPablo Neira Ayuso /* We already set invflags in proto_parse, but we need to refresh it 377ee595bc702ca80f72c522406f6a06ba7c31eb8dfPablo Neira Ayuso * to include new parsed options. 378ee595bc702ca80f72c522406f6a06ba7c31eb8dfPablo Neira Ayuso */ 379ee595bc702ca80f72c522406f6a06ba7c31eb8dfPablo Neira Ayuso cs->fw.ip.invflags = args->invflags; 3806838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 3816838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso strncpy(cs->fw.ip.iniface, args->iniface, IFNAMSIZ); 3826838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso memcpy(cs->fw.ip.iniface_mask, 3836838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso args->iniface_mask, IFNAMSIZ*sizeof(unsigned char)); 3846838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 3856838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso strncpy(cs->fw.ip.outiface, args->outiface, IFNAMSIZ); 3866838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso memcpy(cs->fw.ip.outiface_mask, 3876838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso args->outiface_mask, IFNAMSIZ*sizeof(unsigned char)); 3886838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 3896838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (args->goto_set) 3906838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso cs->fw.ip.flags |= IPT_F_GOTO; 3916838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 3926838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso cs->counters.pcnt = args->pcnt_cnt; 3936838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso cs->counters.bcnt = args->bcnt_cnt; 3946838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 3956838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (command & (CMD_REPLACE | CMD_INSERT | 3966838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso CMD_DELETE | CMD_APPEND | CMD_CHECK)) { 3976838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (!(cs->options & OPT_DESTINATION)) 3986838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso args->dhostnetworkmask = "0.0.0.0/0"; 3996838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (!(cs->options & OPT_SOURCE)) 4006838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso args->shostnetworkmask = "0.0.0.0/0"; 4016838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso } 4026838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 4036838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (args->shostnetworkmask) 4046838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso xtables_ipparse_multiple(args->shostnetworkmask, 4056838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso &args->s.addr.v4, &args->s.mask.v4, 4066838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso &args->s.naddrs); 4076838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if (args->dhostnetworkmask) 4086838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso xtables_ipparse_multiple(args->dhostnetworkmask, 4096838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso &args->d.addr.v4, &args->d.mask.v4, 4106838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso &args->d.naddrs); 4116838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 4126838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso if ((args->s.naddrs > 1 || args->d.naddrs > 1) && 4136838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso (cs->fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) 4146838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso xtables_error(PARAMETER_PROBLEM, 4156838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso "! not allowed with multiple" 4166838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso " source or destination IP addresses"); 4176838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso} 4186838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso 41904d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longostatic void nft_ipv4_parse_target(struct xtables_target *t, void *data) 42004d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo{ 42104d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo struct iptables_command_state *cs = data; 42204d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 42304d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo cs->target = t; 42404d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo} 42504d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo 426e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayusostatic bool nft_ipv4_rule_find(struct nft_family_ops *ops, 427742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso struct nftnl_rule *r, void *data) 428e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso{ 429e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso struct iptables_command_state *cs = data; 430e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso 431e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso return nft_ipv46_rule_find(ops, r, cs); 432e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso} 433e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso 4341aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longostatic void nft_ipv4_save_counters(const void *data) 4351aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo{ 4361aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo const struct iptables_command_state *cs = data; 4371aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo 4381aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo save_counters(cs->counters.pcnt, cs->counters.bcnt); 4391aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo} 4401aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo 4416b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayusostatic int nft_ipv4_xlate(const void *data, struct xt_xlate *xl) 442933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso{ 443933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso const struct iptables_command_state *cs = data; 444a9a599ab675b8feb942355a24934901a9adcef1bShivani Bhardwaj const char *comment; 445933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso int ret; 446933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 4470ddd663e9c167f9f0451dac8c02bbfcda25fe15eLiping Zhang xlate_ifname(xl, "iifname", cs->fw.ip.iniface, 4480ddd663e9c167f9f0451dac8c02bbfcda25fe15eLiping Zhang cs->fw.ip.invflags & IPT_INV_VIA_IN); 4490ddd663e9c167f9f0451dac8c02bbfcda25fe15eLiping Zhang xlate_ifname(xl, "oifname", cs->fw.ip.outiface, 4500ddd663e9c167f9f0451dac8c02bbfcda25fe15eLiping Zhang cs->fw.ip.invflags & IPT_INV_VIA_OUT); 451933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 452933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (cs->fw.ip.flags & IPT_F_FRAG) { 4536b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso xt_xlate_add(xl, "ip frag-off %s%x ", 454933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso cs->fw.ip.invflags & IPT_INV_FRAG? "" : "!= ", 0); 455933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso } 456933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 457933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (cs->fw.ip.proto != 0) { 458933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso const struct protoent *pent = 459933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso getprotobynumber(cs->fw.ip.proto); 460933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso char protonum[strlen("255") + 1]; 461933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 462933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (!xlate_find_match(cs, pent->p_name)) { 463933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso snprintf(protonum, sizeof(protonum), "%u", 464933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso cs->fw.ip.proto); 465933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso protonum[sizeof(protonum) - 1] = '\0'; 4666b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso xt_xlate_add(xl, "ip protocol %s%s ", 467933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso cs->fw.ip.invflags & IPT_INV_PROTO ? 468933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso "!= " : "", 469933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso pent ? pent->p_name : protonum); 470933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso } 471933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso } 472933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 473933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (cs->fw.ip.src.s_addr != 0) { 474f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter xt_xlate_add(xl, "ip saddr %s%s%s ", 475933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso cs->fw.ip.invflags & IPT_INV_SRCIP ? "!= " : "", 476f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter inet_ntoa(cs->fw.ip.src), 477f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter xtables_ipmask_to_numeric(&cs->fw.ip.smsk)); 478933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso } 479933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (cs->fw.ip.dst.s_addr != 0) { 480f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter xt_xlate_add(xl, "ip daddr %s%s%s ", 481933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso cs->fw.ip.invflags & IPT_INV_DSTIP ? "!= " : "", 482f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter inet_ntoa(cs->fw.ip.dst), 483f1cd86ddcf1726b91aedb9ef916b380edc8c2b61Phil Sutter xtables_ipmask_to_numeric(&cs->fw.ip.dmsk)); 484933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso } 485933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 4866b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso ret = xlate_matches(cs, xl); 487933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso if (!ret) 488933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso return ret; 489933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 490933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso /* Always add counters per rule, as in iptables */ 4916b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso xt_xlate_add(xl, "counter "); 492933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 493a9a599ab675b8feb942355a24934901a9adcef1bShivani Bhardwaj comment = xt_xlate_get_comment(xl); 494a9a599ab675b8feb942355a24934901a9adcef1bShivani Bhardwaj if (comment) 495b2b811ed4a8261430def40b7d600ccb0f4927492Pablo M. Bermudo Garay xt_xlate_add(xl, "comment %s", comment); 496a9a599ab675b8feb942355a24934901a9adcef1bShivani Bhardwaj 4976b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso ret = xlate_action(cs, !!(cs->fw.ip.flags & IPT_F_GOTO), xl); 498933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 499933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso return ret; 500933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso} 501933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso 502077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztykastruct nft_family_ops nft_family_ops_ipv4 = { 503077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka .add = nft_ipv4_add, 504077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka .is_same = nft_ipv4_is_same, 505077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka .parse_meta = nft_ipv4_parse_meta, 506077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka .parse_payload = nft_ipv4_parse_payload, 5076838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso .parse_immediate = nft_ipv4_parse_immediate, 5084272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso .print_header = nft_ipv4_print_header, 5096838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso .print_firewall = nft_ipv4_print_firewall, 510cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka .save_firewall = nft_ipv4_save_firewall, 5111aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo .save_counters = nft_ipv4_save_counters, 5124b7a4afaa240e5d2039e612e125b045d5d1cb7faPablo Neira Ayuso .proto_parse = nft_ipv4_proto_parse, 5136838a7f51e6d95f904093e05e8bdc75ada70b93fPablo Neira Ayuso .post_parse = nft_ipv4_post_parse, 51404d9ad94a40e795dfa8d4cfd0bf3f092d60ecc47Giuseppe Longo .parse_target = nft_ipv4_parse_target, 515e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso .rule_find = nft_ipv4_rule_find, 516933400b37d0966980d07d32b64403830429761edPablo Neira Ayuso .xlate = nft_ipv4_xlate, 517077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka}; 518