From eb4b65c49994e44e6ad617fe3f60c063d0c331c4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 20 Aug 2013 20:24:26 +0200 Subject: nft: fix wrong flags handling in print_firewall_details Unfortunately, IPT_F_* and IP6T_F_* don't overlap, therefore, we have to add an specific function to print the fragment flag, otherwise xtables -6 misinterprets the protocol flag, ie. Chain INPUT (policy ACCEPT) tcp -f ::/0 ::/0 Note that -f should not show up. This problem was likely added with the IPv6 support for the compatibility layer. Signed-off-by: Pablo Neira Ayuso --- iptables/nft-ipv4.c | 17 +++++++++++-- iptables/nft-ipv6.c | 4 +-- iptables/nft-shared.c | 67 ++++++++++++++++++++++++++------------------------- iptables/nft-shared.h | 3 ++- 4 files changed, 53 insertions(+), 38 deletions(-) (limited to 'iptables') diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c index 08a8c653..a08df713 100644 --- a/iptables/nft-ipv4.c +++ b/iptables/nft-ipv4.c @@ -231,6 +231,18 @@ static void print_ipv4_addr(const struct iptables_command_state *cs, } } +static void print_fragment(unsigned int flags, unsigned int invflags, + unsigned int format) +{ + if (!(format & FMT_OPTIONS)) + return; + + if (format & FMT_NOTABLE) + fputs("opt ", stdout); + fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout); + fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout); + fputc(' ', stdout); +} static void nft_ipv4_print_firewall(struct nft_rule *r, unsigned int num, unsigned int format) @@ -241,9 +253,10 @@ static void nft_ipv4_print_firewall(struct nft_rule *r, unsigned int num, print_firewall_details(&cs, cs.jumpto, cs.fw.ip.flags, cs.fw.ip.invflags, cs.fw.ip.proto, - cs.fw.ip.iniface, cs.fw.ip.outiface, num, format); - + print_fragment(cs.fw.ip.flags, cs.fw.ip.invflags, format); + print_ifaces(cs.fw.ip.iniface, cs.fw.ip.outiface, cs.fw.ip.invflags, + format); print_ipv4_addr(&cs, format); if (format & FMT_NOTABLE) diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c index 91ef255c..9bb57981 100644 --- a/iptables/nft-ipv6.c +++ b/iptables/nft-ipv6.c @@ -161,9 +161,9 @@ static void nft_ipv6_print_firewall(struct nft_rule *r, unsigned int num, print_firewall_details(&cs, cs.jumpto, cs.fw6.ipv6.flags, cs.fw6.ipv6.invflags, cs.fw6.ipv6.proto, - cs.fw6.ipv6.iniface, cs.fw6.ipv6.outiface, num, format); - + print_ifaces(cs.fw6.ipv6.iniface, cs.fw6.ipv6.outiface, + cs.fw6.ipv6.invflags, format); print_ipv6_addr(&cs, format); if (format & FMT_NOTABLE) diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index ad5e80ea..e981c0d4 100644 --- a/iptables/nft-shared.c +++ b/iptables/nft-shared.c @@ -516,7 +516,6 @@ void print_num(uint64_t number, unsigned int format) void print_firewall_details(const struct iptables_command_state *cs, const char *targname, uint8_t flags, uint8_t invflags, uint8_t proto, - const char *iniface, const char *outiface, unsigned int num, unsigned int format) { if (format & FMT_LINENUMBERS) @@ -539,43 +538,45 @@ void print_firewall_details(const struct iptables_command_state *cs, else printf(FMT("%-5hu", "%hu "), proto); } +} - if (format & FMT_OPTIONS) { - if (format & FMT_NOTABLE) - fputs("opt ", stdout); - fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout); - fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout); - fputc(' ', stdout); - } +void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags, + unsigned int format) +{ + char iface[IFNAMSIZ+2]; - if (format & FMT_VIA) { - char iface[IFNAMSIZ+2]; - if (invflags & IPT_INV_VIA_IN) { - iface[0] = '!'; - iface[1] = '\0'; - } - else iface[0] = '\0'; + if (!(format & FMT_VIA)) + return; - if (iniface[0] != '\0') { - strcat(iface, iniface); - } - else if (format & FMT_NUMERIC) strcat(iface, "*"); - else strcat(iface, "any"); - printf(FMT(" %-6s ","in %s "), iface); + if (invflags & IPT_INV_VIA_IN) { + iface[0] = '!'; + iface[1] = '\0'; + } else + iface[0] = '\0'; - if (invflags & IPT_INV_VIA_OUT) { - iface[0] = '!'; - iface[1] = '\0'; - } - else iface[0] = '\0'; + if (iniface[0] != '\0') + strcat(iface, iniface); + else if (format & FMT_NUMERIC) + strcat(iface, "*"); + else + strcat(iface, "any"); - if (outiface[0] != '\0') { - strcat(iface, outiface); - } - else if (format & FMT_NUMERIC) strcat(iface, "*"); - else strcat(iface, "any"); - printf(FMT("%-6s ","out %s "), iface); - } + printf(FMT(" %-6s ","in %s "), iface); + + if (invflags & IPT_INV_VIA_OUT) { + iface[0] = '!'; + iface[1] = '\0'; + } else + iface[0] = '\0'; + + if (outiface[0] != '\0') + strcat(iface, outiface); + else if (format & FMT_NUMERIC) + strcat(iface, "*"); + else + strcat(iface, "any"); + + printf(FMT("%-6s ","out %s "), iface); } static void diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index e77b303d..6e45538c 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -90,8 +90,9 @@ void print_num(uint64_t number, unsigned int format); void print_firewall_details(const struct iptables_command_state *cs, const char *targname, uint8_t flags, uint8_t invflags, uint8_t proto, - const char *iniface, const char *outiface, unsigned int num, unsigned int format); +void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags, + unsigned int format); void print_matches_and_target(struct iptables_command_state *cs, unsigned int format); void save_firewall_details(const struct iptables_command_state *cs, -- cgit v1.2.3