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 <pablo@netfilter.org>
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 08a8c65..a08df71 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -231,6 +231,18 @@
 	}
 }
 
+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 @@
 
 	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 91ef255..9bb5798 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -161,9 +161,9 @@
 
 	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 ad5e80e..e981c0d 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -516,7 +516,6 @@
 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 @@
 		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 e77b303..6e45538 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -90,8 +90,9 @@
 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,