netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [iptables PATCH 0/7] De-duplicate code here and there
@ 2022-11-12  0:20 Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 1/7] xshared: Share make_delete_mask() between ip{,6}tables Phil Sutter
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

A series of unrelated patches reducing code size in different ways:

Patch 1 is a typical "move function to xshared.c for common use", patch
2 eliminates some c'n'p programming in nft-shared.c, patch 3 merges
libipt_LOG.c and libip6t_LOG.c, patch 4 removes code from libebt_ip.c by
including the right header, patch 5 drops some local IP address parsers
in favor of the respective libxtables function and patches 6 and 7 move
duplicate definitions and code into a header shared by multiple
extensions.

Phil Sutter (7):
  xshared: Share make_delete_mask() between ip{,6}tables
  nft-shared: Introduce port_match_single_to_range()
  extensions: libip*t_LOG: Merge extensions
  extensions: libebt_ip: Include kernel header
  extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any()
  extensions: Collate ICMP types/codes in libxt_icmp.h
  extensions: Unify ICMP parser into libxt_icmp.h

 extensions/libebt_arp.c                   |  89 +-------
 extensions/libebt_arp.t                   |   3 +
 extensions/libebt_ip.c                    | 262 ++--------------------
 extensions/libebt_ip6.c                   | 111 +--------
 extensions/libip6t_icmp6.c                |  97 +-------
 extensions/libipt_LOG.c                   | 250 ---------------------
 extensions/libipt_icmp.c                  | 110 +--------
 extensions/{libip6t_LOG.c => libxt_LOG.c} | 158 +++++--------
 extensions/libxt_icmp.h                   | 242 +++++++++++++++++++-
 include/linux/netfilter_bridge/ebt_ip.h   |  15 +-
 iptables/ip6tables.c                      |  38 +---
 iptables/iptables.c                       |  38 +---
 iptables/nft-shared.c                     | 130 +++--------
 iptables/xshared.c                        |  34 +++
 iptables/xshared.h                        |   4 +
 15 files changed, 409 insertions(+), 1172 deletions(-)
 delete mode 100644 extensions/libipt_LOG.c
 rename extensions/{libip6t_LOG.c => libxt_LOG.c} (52%)

-- 
2.38.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [iptables PATCH 1/7] xshared: Share make_delete_mask() between ip{,6}tables
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 2/7] nft-shared: Introduce port_match_single_to_range() Phil Sutter
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

Function bodies were mostly identical, the only difference being the use
of struct ipt_entry or ip6t_entry for size calculation. Pass this value
via parameter to make them fully identical.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/ip6tables.c | 38 ++------------------------------------
 iptables/iptables.c  | 38 ++------------------------------------
 iptables/xshared.c   | 34 ++++++++++++++++++++++++++++++++++
 iptables/xshared.h   |  4 ++++
 4 files changed, 42 insertions(+), 72 deletions(-)

diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index 75984cc1bcdd8..ae2670357264b 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -277,40 +277,6 @@ insert_entry(const xt_chainlabel chain,
 	return ret;
 }
 
-static unsigned char *
-make_delete_mask(const struct xtables_rule_match *matches,
-		 const struct xtables_target *target)
-{
-	/* Establish mask for comparison */
-	unsigned int size;
-	const struct xtables_rule_match *matchp;
-	unsigned char *mask, *mptr;
-
-	size = sizeof(struct ip6t_entry);
-	for (matchp = matches; matchp; matchp = matchp->next)
-		size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-
-	mask = xtables_calloc(1, size
-			 + XT_ALIGN(sizeof(struct xt_entry_target))
-			 + target->size);
-
-	memset(mask, 0xFF, sizeof(struct ip6t_entry));
-	mptr = mask + sizeof(struct ip6t_entry);
-
-	for (matchp = matches; matchp; matchp = matchp->next) {
-		memset(mptr, 0xFF,
-		       XT_ALIGN(sizeof(struct xt_entry_match))
-		       + matchp->match->userspacesize);
-		mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-	}
-
-	memset(mptr, 0xFF,
-	       XT_ALIGN(sizeof(struct xt_entry_target))
-	       + target->userspacesize);
-
-	return mask;
-}
-
 static int
 delete_entry(const xt_chainlabel chain,
 	     struct ip6t_entry *fw,
@@ -329,7 +295,7 @@ delete_entry(const xt_chainlabel chain,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(matches, target);
+	mask = make_delete_mask(matches, target, sizeof(*fw));
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ipv6.src = saddrs[i];
 		fw->ipv6.smsk = smasks[i];
@@ -359,7 +325,7 @@ check_entry(const xt_chainlabel chain, struct ip6t_entry *fw,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(matches, target);
+	mask = make_delete_mask(matches, target, sizeof(fw));
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ipv6.src = saddrs[i];
 		fw->ipv6.smsk = smasks[i];
diff --git a/iptables/iptables.c b/iptables/iptables.c
index e5207ba106057..591ec17886562 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -276,40 +276,6 @@ insert_entry(const xt_chainlabel chain,
 	return ret;
 }
 
-static unsigned char *
-make_delete_mask(const struct xtables_rule_match *matches,
-		 const struct xtables_target *target)
-{
-	/* Establish mask for comparison */
-	unsigned int size;
-	const struct xtables_rule_match *matchp;
-	unsigned char *mask, *mptr;
-
-	size = sizeof(struct ipt_entry);
-	for (matchp = matches; matchp; matchp = matchp->next)
-		size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-
-	mask = xtables_calloc(1, size
-			 + XT_ALIGN(sizeof(struct xt_entry_target))
-			 + target->size);
-
-	memset(mask, 0xFF, sizeof(struct ipt_entry));
-	mptr = mask + sizeof(struct ipt_entry);
-
-	for (matchp = matches; matchp; matchp = matchp->next) {
-		memset(mptr, 0xFF,
-		       XT_ALIGN(sizeof(struct xt_entry_match))
-		       + matchp->match->userspacesize);
-		mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-	}
-
-	memset(mptr, 0xFF,
-	       XT_ALIGN(sizeof(struct xt_entry_target))
-	       + target->userspacesize);
-
-	return mask;
-}
-
 static int
 delete_entry(const xt_chainlabel chain,
 	     struct ipt_entry *fw,
@@ -328,7 +294,7 @@ delete_entry(const xt_chainlabel chain,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(matches, target);
+	mask = make_delete_mask(matches, target, sizeof(*fw));
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ip.src.s_addr = saddrs[i].s_addr;
 		fw->ip.smsk.s_addr = smasks[i].s_addr;
@@ -358,7 +324,7 @@ check_entry(const xt_chainlabel chain, struct ipt_entry *fw,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(matches, target);
+	mask = make_delete_mask(matches, target, sizeof(*fw));
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ip.src.s_addr = saddrs[i].s_addr;
 		fw->ip.smsk.s_addr = smasks[i].s_addr;
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 695157896d521..0beacee61d487 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -2000,3 +2000,37 @@ void ipv6_post_parse(int command, struct iptables_command_state *cs,
 			      "! not allowed with multiple"
 			      " source or destination IP addresses");
 }
+
+unsigned char *
+make_delete_mask(const struct xtables_rule_match *matches,
+		 const struct xtables_target *target,
+		 size_t entry_size)
+{
+	/* Establish mask for comparison */
+	unsigned int size = entry_size;
+	const struct xtables_rule_match *matchp;
+	unsigned char *mask, *mptr;
+
+	for (matchp = matches; matchp; matchp = matchp->next)
+		size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
+
+	mask = xtables_calloc(1, size
+			 + XT_ALIGN(sizeof(struct xt_entry_target))
+			 + target->size);
+
+	memset(mask, 0xFF, entry_size);
+	mptr = mask + entry_size;
+
+	for (matchp = matches; matchp; matchp = matchp->next) {
+		memset(mptr, 0xFF,
+		       XT_ALIGN(sizeof(struct xt_entry_match))
+		       + matchp->match->userspacesize);
+		mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
+	}
+
+	memset(mptr, 0xFF,
+	       XT_ALIGN(sizeof(struct xt_entry_target))
+	       + target->userspacesize);
+
+	return mask;
+}
diff --git a/iptables/xshared.h b/iptables/xshared.h
index f43c28f519a9c..bfae4b4e1b5d3 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -293,4 +293,8 @@ void ipv6_post_parse(int command, struct iptables_command_state *cs,
 extern char *arp_opcodes[];
 #define ARP_NUMOPCODES 9
 
+unsigned char *make_delete_mask(const struct xtables_rule_match *matches,
+				const struct xtables_target *target,
+				size_t entry_size);
+
 #endif /* IPTABLES_XSHARED_H */
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 2/7] nft-shared: Introduce port_match_single_to_range()
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 1/7] xshared: Share make_delete_mask() between ip{,6}tables Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 3/7] extensions: libip*t_LOG: Merge extensions Phil Sutter
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

The same algorithm was present four times, outsource it. Also use
max()/min() macros for a more readable boundary notation.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-shared.c | 130 ++++++++++++------------------------------
 1 file changed, 37 insertions(+), 93 deletions(-)

diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 996cff996c151..e5e3ac0bada56 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -747,6 +747,35 @@ static void nft_parse_tcp_range(struct nft_xt_ctx *ctx,
 	}
 }
 
+static void port_match_single_to_range(__u16 *ports, __u8 *invflags,
+				       uint8_t op, int port, __u8 invflag)
+{
+	if (port < 0)
+		return;
+
+	switch (op) {
+	case NFT_CMP_NEQ:
+		*invflags |= invflag;
+		/* fallthrough */
+	case NFT_CMP_EQ:
+		ports[0] = port;
+		ports[1] = port;
+		break;
+	case NFT_CMP_LT:
+		ports[1] = max(port - 1, 1);
+		break;
+	case NFT_CMP_LTE:
+		ports[1] = port;
+		break;
+	case NFT_CMP_GT:
+		ports[0] = min(port + 1, UINT16_MAX);
+		break;
+	case NFT_CMP_GTE:
+		ports[0] = port;
+		break;
+	}
+}
+
 static void nft_parse_udp(struct nft_xt_ctx *ctx,
 			  struct iptables_command_state *cs,
 			  int sport, int dport,
@@ -757,52 +786,10 @@ static void nft_parse_udp(struct nft_xt_ctx *ctx,
 	if (!udp)
 		return;
 
-	if (sport >= 0) {
-		switch (op) {
-		case NFT_CMP_NEQ:
-			udp->invflags |= XT_UDP_INV_SRCPT;
-			/* fallthrough */
-		case NFT_CMP_EQ:
-			udp->spts[0] = sport;
-			udp->spts[1] = sport;
-			break;
-		case NFT_CMP_LT:
-			udp->spts[1] = sport > 1 ? sport - 1 : 1;
-			break;
-		case NFT_CMP_LTE:
-			udp->spts[1] = sport;
-			break;
-		case NFT_CMP_GT:
-			udp->spts[0] = sport < 0xffff ? sport + 1 : 0xffff;
-			break;
-		case NFT_CMP_GTE:
-			udp->spts[0] = sport;
-			break;
-		}
-	}
-	if (dport >= 0) {
-		switch (op) {
-		case NFT_CMP_NEQ:
-			udp->invflags |= XT_UDP_INV_DSTPT;
-			/* fallthrough */
-		case NFT_CMP_EQ:
-			udp->dpts[0] = dport;
-			udp->dpts[1] = dport;
-			break;
-		case NFT_CMP_LT:
-			udp->dpts[1] = dport > 1 ? dport - 1 : 1;
-			break;
-		case NFT_CMP_LTE:
-			udp->dpts[1] = dport;
-			break;
-		case NFT_CMP_GT:
-			udp->dpts[0] = dport < 0xffff ? dport + 1 : 0xffff;
-			break;
-		case NFT_CMP_GTE:
-			udp->dpts[0] = dport;
-			break;
-		}
-	}
+	port_match_single_to_range(udp->spts, &udp->invflags,
+				   op, sport, XT_UDP_INV_SRCPT);
+	port_match_single_to_range(udp->dpts, &udp->invflags,
+				   op, dport, XT_UDP_INV_DSTPT);
 }
 
 static void nft_parse_tcp(struct nft_xt_ctx *ctx,
@@ -815,53 +802,10 @@ static void nft_parse_tcp(struct nft_xt_ctx *ctx,
 	if (!tcp)
 		return;
 
-	if (sport >= 0) {
-		switch (op) {
-		case NFT_CMP_NEQ:
-			tcp->invflags |= XT_TCP_INV_SRCPT;
-			/* fallthrough */
-		case NFT_CMP_EQ:
-			tcp->spts[0] = sport;
-			tcp->spts[1] = sport;
-			break;
-		case NFT_CMP_LT:
-			tcp->spts[1] = sport > 1 ? sport - 1 : 1;
-			break;
-		case NFT_CMP_LTE:
-			tcp->spts[1] = sport;
-			break;
-		case NFT_CMP_GT:
-			tcp->spts[0] = sport < 0xffff ? sport + 1 : 0xffff;
-			break;
-		case NFT_CMP_GTE:
-			tcp->spts[0] = sport;
-			break;
-		}
-	}
-
-	if (dport >= 0) {
-		switch (op) {
-		case NFT_CMP_NEQ:
-			tcp->invflags |= XT_TCP_INV_DSTPT;
-			/* fallthrough */
-		case NFT_CMP_EQ:
-			tcp->dpts[0] = dport;
-			tcp->dpts[1] = dport;
-			break;
-		case NFT_CMP_LT:
-			tcp->dpts[1] = dport > 1 ? dport - 1 : 1;
-			break;
-		case NFT_CMP_LTE:
-			tcp->dpts[1] = dport;
-			break;
-		case NFT_CMP_GT:
-			tcp->dpts[0] = dport < 0xffff ? dport + 1 : 0xffff;
-			break;
-		case NFT_CMP_GTE:
-			tcp->dpts[0] = dport;
-			break;
-		}
-	}
+	port_match_single_to_range(tcp->spts, &tcp->invflags,
+				   op, sport, XT_TCP_INV_SRCPT);
+	port_match_single_to_range(tcp->dpts, &tcp->invflags,
+				   op, dport, XT_TCP_INV_DSTPT);
 }
 
 static void nft_parse_th_port(struct nft_xt_ctx *ctx,
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 3/7] extensions: libip*t_LOG: Merge extensions
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 1/7] xshared: Share make_delete_mask() between ip{,6}tables Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 2/7] nft-shared: Introduce port_match_single_to_range() Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 4/7] extensions: libebt_ip: Include kernel header Phil Sutter
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

Data structures were identical already, make use of the names in
xt_LOG.h and merge all code into a single extension of family
NFPROTO_UNSPEC.

While being at it, define SYSLOG_NAMES and use the array in syslog.h
instead of dragging along an own level->name mapping two times.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libipt_LOG.c                   | 250 ----------------------
 extensions/{libip6t_LOG.c => libxt_LOG.c} | 158 +++++---------
 2 files changed, 58 insertions(+), 350 deletions(-)
 delete mode 100644 extensions/libipt_LOG.c
 rename extensions/{libip6t_LOG.c => libxt_LOG.c} (52%)

diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c
deleted file mode 100644
index 36e2e73b7e360..0000000000000
--- a/extensions/libipt_LOG.c
+++ /dev/null
@@ -1,250 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <xtables.h>
-#include <linux/netfilter_ipv4/ipt_LOG.h>
-
-#define LOG_DEFAULT_LEVEL LOG_WARNING
-
-#ifndef IPT_LOG_UID /* Old kernel */
-#define IPT_LOG_UID	0x08	/* Log UID owning local socket */
-#undef  IPT_LOG_MASK
-#define IPT_LOG_MASK	0x0f
-#endif
-
-enum {
-	O_LOG_LEVEL = 0,
-	O_LOG_PREFIX,
-	O_LOG_TCPSEQ,
-	O_LOG_TCPOPTS,
-	O_LOG_IPOPTS,
-	O_LOG_UID,
-	O_LOG_MAC,
-};
-
-static void LOG_help(void)
-{
-	printf(
-"LOG target options:\n"
-" --log-level level		Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix		Prefix log messages with this prefix.\n\n"
-" --log-tcp-sequence		Log TCP sequence numbers.\n\n"
-" --log-tcp-options		Log TCP options.\n\n"
-" --log-ip-options		Log IP options.\n\n"
-" --log-uid			Log UID owning the local socket.\n\n"
-" --log-macdecode		Decode MAC addresses and protocol.\n\n");
-}
-
-#define s struct ipt_log_info
-static const struct xt_option_entry LOG_opts[] = {
-	{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
-	 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
-	{.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
-	 .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
-	{.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
-	{.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
-	{.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
-	{.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
-	{.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
-	XTOPT_TABLEEND,
-};
-#undef s
-
-static void LOG_init(struct xt_entry_target *t)
-{
-	struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
-
-	loginfo->level = LOG_DEFAULT_LEVEL;
-
-}
-
-struct ipt_log_names {
-	const char *name;
-	unsigned int level;
-};
-
-struct ipt_log_xlate {
-	const char *name;
-	unsigned int level;
-};
-
-static const struct ipt_log_names ipt_log_names[]
-= { { .name = "alert",   .level = LOG_ALERT },
-    { .name = "crit",    .level = LOG_CRIT },
-    { .name = "debug",   .level = LOG_DEBUG },
-    { .name = "emerg",   .level = LOG_EMERG },
-    { .name = "error",   .level = LOG_ERR },		/* DEPRECATED */
-    { .name = "info",    .level = LOG_INFO },
-    { .name = "notice",  .level = LOG_NOTICE },
-    { .name = "panic",   .level = LOG_EMERG },		/* DEPRECATED */
-    { .name = "warning", .level = LOG_WARNING }
-};
-
-static void LOG_parse(struct xt_option_call *cb)
-{
-	struct ipt_log_info *info = cb->data;
-
-	xtables_option_parse(cb);
-	switch (cb->entry->id) {
-	case O_LOG_PREFIX:
-		if (strchr(cb->arg, '\n') != NULL)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Newlines not allowed in --log-prefix");
-		break;
-	case O_LOG_TCPSEQ:
-		info->logflags |= IPT_LOG_TCPSEQ;
-		break;
-	case O_LOG_TCPOPTS:
-		info->logflags |= IPT_LOG_TCPOPT;
-		break;
-	case O_LOG_IPOPTS:
-		info->logflags |= IPT_LOG_IPOPT;
-		break;
-	case O_LOG_UID:
-		info->logflags |= IPT_LOG_UID;
-		break;
-	case O_LOG_MAC:
-		info->logflags |= IPT_LOG_MACDECODE;
-		break;
-	}
-}
-
-static void LOG_print(const void *ip, const struct xt_entry_target *target,
-                      int numeric)
-{
-	const struct ipt_log_info *loginfo
-		= (const struct ipt_log_info *)target->data;
-	unsigned int i = 0;
-
-	printf(" LOG");
-	if (numeric)
-		printf(" flags %u level %u",
-		       loginfo->logflags, loginfo->level);
-	else {
-		for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
-			if (loginfo->level == ipt_log_names[i].level) {
-				printf(" level %s", ipt_log_names[i].name);
-				break;
-			}
-		if (i == ARRAY_SIZE(ipt_log_names))
-			printf(" UNKNOWN level %u", loginfo->level);
-		if (loginfo->logflags & IPT_LOG_TCPSEQ)
-			printf(" tcp-sequence");
-		if (loginfo->logflags & IPT_LOG_TCPOPT)
-			printf(" tcp-options");
-		if (loginfo->logflags & IPT_LOG_IPOPT)
-			printf(" ip-options");
-		if (loginfo->logflags & IPT_LOG_UID)
-			printf(" uid");
-		if (loginfo->logflags & IPT_LOG_MACDECODE)
-			printf(" macdecode");
-		if (loginfo->logflags & ~(IPT_LOG_MASK))
-			printf(" unknown-flags");
-	}
-
-	if (strcmp(loginfo->prefix, "") != 0)
-		printf(" prefix \"%s\"", loginfo->prefix);
-}
-
-static void LOG_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct ipt_log_info *loginfo
-		= (const struct ipt_log_info *)target->data;
-
-	if (strcmp(loginfo->prefix, "") != 0) {
-		printf(" --log-prefix");
-		xtables_save_string(loginfo->prefix);
-	}
-
-	if (loginfo->level != LOG_DEFAULT_LEVEL)
-		printf(" --log-level %d", loginfo->level);
-
-	if (loginfo->logflags & IPT_LOG_TCPSEQ)
-		printf(" --log-tcp-sequence");
-	if (loginfo->logflags & IPT_LOG_TCPOPT)
-		printf(" --log-tcp-options");
-	if (loginfo->logflags & IPT_LOG_IPOPT)
-		printf(" --log-ip-options");
-	if (loginfo->logflags & IPT_LOG_UID)
-		printf(" --log-uid");
-	if (loginfo->logflags & IPT_LOG_MACDECODE)
-		printf(" --log-macdecode");
-}
-
-static const struct ipt_log_xlate ipt_log_xlate_names[] = {
-	{"alert",	LOG_ALERT },
-	{"crit",	LOG_CRIT },
-	{"debug",	LOG_DEBUG },
-	{"emerg",	LOG_EMERG },
-	{"err",		LOG_ERR },
-	{"info",	LOG_INFO },
-	{"notice",	LOG_NOTICE },
-	{"warn",	LOG_WARNING }
-};
-
-static int LOG_xlate(struct xt_xlate *xl,
-		     const struct xt_xlate_tg_params *params)
-{
-	const struct ipt_log_info *loginfo =
-		(const struct ipt_log_info *)params->target->data;
-	unsigned int i = 0;
-
-	xt_xlate_add(xl, "log");
-	if (strcmp(loginfo->prefix, "") != 0) {
-		if (params->escape_quotes)
-			xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
-		else
-			xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(ipt_log_xlate_names); ++i)
-		if (loginfo->level != LOG_DEFAULT_LEVEL &&
-		    loginfo->level == ipt_log_xlate_names[i].level) {
-			xt_xlate_add(xl, " level %s",
-				   ipt_log_xlate_names[i].name);
-			break;
-		}
-
-	if ((loginfo->logflags & IPT_LOG_MASK) == IPT_LOG_MASK) {
-		xt_xlate_add(xl, " flags all");
-	} else {
-		if (loginfo->logflags & (IPT_LOG_TCPSEQ | IPT_LOG_TCPOPT)) {
-			const char *delim = " ";
-
-			xt_xlate_add(xl, " flags tcp");
-			if (loginfo->logflags & IPT_LOG_TCPSEQ) {
-				xt_xlate_add(xl, " sequence");
-				delim = ",";
-			}
-			if (loginfo->logflags & IPT_LOG_TCPOPT)
-				xt_xlate_add(xl, "%soptions", delim);
-		}
-		if (loginfo->logflags & IPT_LOG_IPOPT)
-			xt_xlate_add(xl, " flags ip options");
-		if (loginfo->logflags & IPT_LOG_UID)
-			xt_xlate_add(xl, " flags skuid");
-		if (loginfo->logflags & IPT_LOG_MACDECODE)
-			xt_xlate_add(xl, " flags ether");
-	}
-
-	return 1;
-}
-static struct xtables_target log_tg_reg = {
-	.name          = "LOG",
-	.version       = XTABLES_VERSION,
-	.family        = NFPROTO_IPV4,
-	.size          = XT_ALIGN(sizeof(struct ipt_log_info)),
-	.userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
-	.help          = LOG_help,
-	.init          = LOG_init,
-	.print         = LOG_print,
-	.save          = LOG_save,
-	.x6_parse      = LOG_parse,
-	.x6_options    = LOG_opts,
-	.xlate	       = LOG_xlate,
-};
-
-void _init(void)
-{
-	xtables_register_target(&log_tg_reg);
-}
diff --git a/extensions/libip6t_LOG.c b/extensions/libxt_LOG.c
similarity index 52%
rename from extensions/libip6t_LOG.c
rename to extensions/libxt_LOG.c
index 40adc69d85ed4..e3f4290ba003f 100644
--- a/extensions/libip6t_LOG.c
+++ b/extensions/libxt_LOG.c
@@ -1,25 +1,22 @@
 #include <stdio.h>
 #include <string.h>
+#define SYSLOG_NAMES
 #include <syslog.h>
 #include <xtables.h>
-#include <linux/netfilter_ipv6/ip6t_LOG.h>
-
-#ifndef IP6T_LOG_UID	/* Old kernel */
-#define IP6T_LOG_UID	0x08
-#undef  IP6T_LOG_MASK
-#define IP6T_LOG_MASK	0x0f
-#endif
+#include <linux/netfilter/xt_LOG.h>
 
 #define LOG_DEFAULT_LEVEL LOG_WARNING
 
 enum {
-	O_LOG_LEVEL = 0,
-	O_LOG_PREFIX,
-	O_LOG_TCPSEQ,
+	/* make sure the values correspond with XT_LOG_* bit positions */
+	O_LOG_TCPSEQ = 0,
 	O_LOG_TCPOPTS,
 	O_LOG_IPOPTS,
 	O_LOG_UID,
+	__O_LOG_NFLOG,
 	O_LOG_MAC,
+	O_LOG_LEVEL,
+	O_LOG_PREFIX,
 };
 
 static void LOG_help(void)
@@ -35,7 +32,7 @@ static void LOG_help(void)
 " --log-macdecode		Decode MAC addresses and protocol.\n");
 }
 
-#define s struct ip6t_log_info
+#define s struct xt_log_info
 static const struct xt_option_entry LOG_opts[] = {
 	{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
@@ -52,37 +49,14 @@ static const struct xt_option_entry LOG_opts[] = {
 
 static void LOG_init(struct xt_entry_target *t)
 {
-	struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
+	struct xt_log_info *loginfo = (void *)t->data;
 
 	loginfo->level = LOG_DEFAULT_LEVEL;
-
 }
 
-struct ip6t_log_names {
-	const char *name;
-	unsigned int level;
-};
-
-struct ip6t_log_xlate {
-	const char *name;
-	unsigned int level;
-};
-
-static const struct ip6t_log_names ip6t_log_names[]
-= { { .name = "alert",   .level = LOG_ALERT },
-    { .name = "crit",    .level = LOG_CRIT },
-    { .name = "debug",   .level = LOG_DEBUG },
-    { .name = "emerg",   .level = LOG_EMERG },
-    { .name = "error",   .level = LOG_ERR },		/* DEPRECATED */
-    { .name = "info",    .level = LOG_INFO },
-    { .name = "notice",  .level = LOG_NOTICE },
-    { .name = "panic",   .level = LOG_EMERG },		/* DEPRECATED */
-    { .name = "warning", .level = LOG_WARNING }
-};
-
 static void LOG_parse(struct xt_option_call *cb)
 {
-	struct ip6t_log_info *info = cb->data;
+	struct xt_log_info *info = cb->data;
 
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
@@ -92,53 +66,53 @@ static void LOG_parse(struct xt_option_call *cb)
 				   "Newlines not allowed in --log-prefix");
 		break;
 	case O_LOG_TCPSEQ:
-		info->logflags |= IP6T_LOG_TCPSEQ;
-		break;
 	case O_LOG_TCPOPTS:
-		info->logflags |= IP6T_LOG_TCPOPT;
-		break;
 	case O_LOG_IPOPTS:
-		info->logflags |= IP6T_LOG_IPOPT;
-		break;
 	case O_LOG_UID:
-		info->logflags |= IP6T_LOG_UID;
-		break;
 	case O_LOG_MAC:
-		info->logflags |= IP6T_LOG_MACDECODE;
+		info->logflags |= 1 << cb->entry->id;
 		break;
 	}
 }
 
+static const char *priority2name(unsigned char level)
+{
+	int i;
+
+	for (i = 0; prioritynames[i].c_name; ++i) {
+		if (level == prioritynames[i].c_val)
+			return prioritynames[i].c_name;
+	}
+	return NULL;
+}
+
 static void LOG_print(const void *ip, const struct xt_entry_target *target,
                       int numeric)
 {
-	const struct ip6t_log_info *loginfo
-		= (const struct ip6t_log_info *)target->data;
-	unsigned int i = 0;
+	const struct xt_log_info *loginfo = (const void *)target->data;
 
 	printf(" LOG");
 	if (numeric)
 		printf(" flags %u level %u",
 		       loginfo->logflags, loginfo->level);
 	else {
-		for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
-			if (loginfo->level == ip6t_log_names[i].level) {
-				printf(" level %s", ip6t_log_names[i].name);
-				break;
-			}
-		if (i == ARRAY_SIZE(ip6t_log_names))
+		const char *pname = priority2name(loginfo->level);
+
+		if (pname)
+			printf(" level %s", pname);
+		else
 			printf(" UNKNOWN level %u", loginfo->level);
-		if (loginfo->logflags & IP6T_LOG_TCPSEQ)
+		if (loginfo->logflags & XT_LOG_TCPSEQ)
 			printf(" tcp-sequence");
-		if (loginfo->logflags & IP6T_LOG_TCPOPT)
+		if (loginfo->logflags & XT_LOG_TCPOPT)
 			printf(" tcp-options");
-		if (loginfo->logflags & IP6T_LOG_IPOPT)
+		if (loginfo->logflags & XT_LOG_IPOPT)
 			printf(" ip-options");
-		if (loginfo->logflags & IP6T_LOG_UID)
+		if (loginfo->logflags & XT_LOG_UID)
 			printf(" uid");
-		if (loginfo->logflags & IP6T_LOG_MACDECODE)
+		if (loginfo->logflags & XT_LOG_MACDECODE)
 			printf(" macdecode");
-		if (loginfo->logflags & ~(IP6T_LOG_MASK))
+		if (loginfo->logflags & ~(XT_LOG_MASK))
 			printf(" unknown-flags");
 	}
 
@@ -148,8 +122,7 @@ static void LOG_print(const void *ip, const struct xt_entry_target *target,
 
 static void LOG_save(const void *ip, const struct xt_entry_target *target)
 {
-	const struct ip6t_log_info *loginfo
-		= (const struct ip6t_log_info *)target->data;
+	const struct xt_log_info *loginfo = (const void *)target->data;
 
 	if (strcmp(loginfo->prefix, "") != 0) {
 		printf(" --log-prefix");
@@ -159,35 +132,23 @@ static void LOG_save(const void *ip, const struct xt_entry_target *target)
 	if (loginfo->level != LOG_DEFAULT_LEVEL)
 		printf(" --log-level %d", loginfo->level);
 
-	if (loginfo->logflags & IP6T_LOG_TCPSEQ)
+	if (loginfo->logflags & XT_LOG_TCPSEQ)
 		printf(" --log-tcp-sequence");
-	if (loginfo->logflags & IP6T_LOG_TCPOPT)
+	if (loginfo->logflags & XT_LOG_TCPOPT)
 		printf(" --log-tcp-options");
-	if (loginfo->logflags & IP6T_LOG_IPOPT)
+	if (loginfo->logflags & XT_LOG_IPOPT)
 		printf(" --log-ip-options");
-	if (loginfo->logflags & IP6T_LOG_UID)
+	if (loginfo->logflags & XT_LOG_UID)
 		printf(" --log-uid");
-	if (loginfo->logflags & IP6T_LOG_MACDECODE)
+	if (loginfo->logflags & XT_LOG_MACDECODE)
 		printf(" --log-macdecode");
 }
 
-static const struct ip6t_log_xlate ip6t_log_xlate_names[] = {
-	{"alert",       LOG_ALERT },
-	{"crit",        LOG_CRIT },
-	{"debug",       LOG_DEBUG },
-	{"emerg",       LOG_EMERG },
-	{"err",         LOG_ERR },
-	{"info",        LOG_INFO },
-	{"notice",      LOG_NOTICE },
-	{"warn",        LOG_WARNING }
-};
-
 static int LOG_xlate(struct xt_xlate *xl,
 		     const struct xt_xlate_tg_params *params)
 {
-	const struct ip6t_log_info *loginfo =
-		(const struct ip6t_log_info *)params->target->data;
-	unsigned int i = 0;
+	const struct xt_log_info *loginfo = (const void *)params->target->data;
+	const char *pname = priority2name(loginfo->level);
 
 	xt_xlate_add(xl, "log");
 	if (strcmp(loginfo->prefix, "") != 0) {
@@ -197,44 +158,41 @@ static int LOG_xlate(struct xt_xlate *xl,
 			xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(ip6t_log_xlate_names); ++i)
-		if (loginfo->level == ip6t_log_xlate_names[i].level &&
-		    loginfo->level != LOG_DEFAULT_LEVEL) {
-			xt_xlate_add(xl, " level %s",
-				   ip6t_log_xlate_names[i].name);
-			break;
-		}
+	if (loginfo->level != LOG_DEFAULT_LEVEL && pname)
+		xt_xlate_add(xl, " level %s", pname);
+	else if (!pname)
+		return 0;
 
-	if ((loginfo->logflags & IP6T_LOG_MASK) == IP6T_LOG_MASK) {
+	if ((loginfo->logflags & XT_LOG_MASK) == XT_LOG_MASK) {
 		xt_xlate_add(xl, " flags all");
 	} else {
-		if (loginfo->logflags & (IP6T_LOG_TCPSEQ | IP6T_LOG_TCPOPT)) {
+		if (loginfo->logflags & (XT_LOG_TCPSEQ | XT_LOG_TCPOPT)) {
 			const char *delim = " ";
 
 			xt_xlate_add(xl, " flags tcp");
-			if (loginfo->logflags & IP6T_LOG_TCPSEQ) {
+			if (loginfo->logflags & XT_LOG_TCPSEQ) {
 				xt_xlate_add(xl, " sequence");
 				delim = ",";
 			}
-			if (loginfo->logflags & IP6T_LOG_TCPOPT)
+			if (loginfo->logflags & XT_LOG_TCPOPT)
 				xt_xlate_add(xl, "%soptions", delim);
 		}
-		if (loginfo->logflags & IP6T_LOG_IPOPT)
+		if (loginfo->logflags & XT_LOG_IPOPT)
 			xt_xlate_add(xl, " flags ip options");
-		if (loginfo->logflags & IP6T_LOG_UID)
+		if (loginfo->logflags & XT_LOG_UID)
 			xt_xlate_add(xl, " flags skuid");
-		if (loginfo->logflags & IP6T_LOG_MACDECODE)
+		if (loginfo->logflags & XT_LOG_MACDECODE)
 			xt_xlate_add(xl, " flags ether");
 	}
 
 	return 1;
 }
-static struct xtables_target log_tg6_reg = {
+static struct xtables_target log_tg_reg = {
 	.name          = "LOG",
 	.version       = XTABLES_VERSION,
-	.family        = NFPROTO_IPV6,
-	.size          = XT_ALIGN(sizeof(struct ip6t_log_info)),
-	.userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
+	.family        = NFPROTO_UNSPEC,
+	.size          = XT_ALIGN(sizeof(struct xt_log_info)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_log_info)),
 	.help          = LOG_help,
 	.init          = LOG_init,
 	.print         = LOG_print,
@@ -246,5 +204,5 @@ static struct xtables_target log_tg6_reg = {
 
 void _init(void)
 {
-	xtables_register_target(&log_tg6_reg);
+	xtables_register_target(&log_tg_reg);
 }
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 4/7] extensions: libebt_ip: Include kernel header
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
                   ` (2 preceding siblings ...)
  2022-11-12  0:20 ` [iptables PATCH 3/7] extensions: libip*t_LOG: Merge extensions Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 5/7] extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any() Phil Sutter
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

Update the local copy of linux/netfilter_bridge/ebt_ip.h and include it
instead of keeping the local copy of struct ebt_ip_info et al.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libebt_ip.c                  | 32 +------------------------
 include/linux/netfilter_bridge/ebt_ip.h | 15 +++++++++---
 2 files changed, 13 insertions(+), 34 deletions(-)

diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 51649ffb3c305..8413a5aa8dd57 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -20,40 +20,10 @@
 #include <netdb.h>
 #include <inttypes.h>
 #include <xtables.h>
+#include <linux/netfilter_bridge/ebt_ip.h>
 
 #include "libxt_icmp.h"
 
-#define EBT_IP_SOURCE 0x01
-#define EBT_IP_DEST 0x02
-#define EBT_IP_TOS 0x04
-#define EBT_IP_PROTO 0x08
-#define EBT_IP_SPORT 0x10
-#define EBT_IP_DPORT 0x20
-#define EBT_IP_ICMP 0x40
-#define EBT_IP_IGMP 0x80
-#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
-		     EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
-
-struct ebt_ip_info {
-	__be32 saddr;
-	__be32 daddr;
-	__be32 smsk;
-	__be32 dmsk;
-	__u8  tos;
-	__u8  protocol;
-	__u8  bitmask;
-	__u8  invflags;
-	union {
-		__u16 sport[2];
-		__u8 icmp_type[2];
-		__u8 igmp_type[2];
-	};
-	union {
-		__u16 dport[2];
-		__u8 icmp_code[2];
-	};
-};
-
 #define IP_SOURCE	'1'
 #define IP_DEST		'2'
 #define IP_EBT_TOS	'3' /* include/bits/in.h seems to already define IP_TOS */
diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
index c4bbc41b0ea47..ae5d4d1084188 100644
--- a/include/linux/netfilter_bridge/ebt_ip.h
+++ b/include/linux/netfilter_bridge/ebt_ip.h
@@ -23,8 +23,10 @@
 #define EBT_IP_PROTO 0x08
 #define EBT_IP_SPORT 0x10
 #define EBT_IP_DPORT 0x20
+#define EBT_IP_ICMP 0x40
+#define EBT_IP_IGMP 0x80
 #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
- EBT_IP_SPORT | EBT_IP_DPORT )
+		     EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
 #define EBT_IP_MATCH "ip"
 
 /* the same values are used for the invflags */
@@ -37,8 +39,15 @@ struct ebt_ip_info {
 	__u8  protocol;
 	__u8  bitmask;
 	__u8  invflags;
-	__u16 sport[2];
-	__u16 dport[2];
+	union {
+		__u16 sport[2];
+		__u8 icmp_type[2];
+		__u8 igmp_type[2];
+	};
+	union {
+		__u16 dport[2];
+		__u8 icmp_code[2];
+	};
 };
 
 #endif
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 5/7] extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any()
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
                   ` (3 preceding siblings ...)
  2022-11-12  0:20 ` [iptables PATCH 4/7] extensions: libebt_ip: Include kernel header Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 6/7] extensions: Collate ICMP types/codes in libxt_icmp.h Phil Sutter
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

The libxtables function covers all formerly supported inputs (and more).
The extended libebt_arp.t passes before and after this patch.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libebt_arp.c | 89 ++++-------------------------------------
 extensions/libebt_arp.t |  3 ++
 extensions/libebt_ip.c  | 86 +++++----------------------------------
 3 files changed, 21 insertions(+), 157 deletions(-)

diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index d5035b956cc15..63a953d4637da 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -87,91 +87,17 @@ static void brarp_print_help(void)
 #define OPT_MAC_D  0x40
 #define OPT_GRAT   0x80
 
-static int undot_ip(char *ip, unsigned char *ip2)
-{
-	char *p, *q, *end;
-	long int onebyte;
-	int i;
-	char buf[20];
-
-	strncpy(buf, ip, sizeof(buf) - 1);
-
-	p = buf;
-	for (i = 0; i < 3; i++) {
-		if ((q = strchr(p, '.')) == NULL)
-			return -1;
-		*q = '\0';
-		onebyte = strtol(p, &end, 10);
-		if (*end != '\0' || onebyte > 255 || onebyte < 0)
-			return -1;
-		ip2[i] = (unsigned char)onebyte;
-		p = q + 1;
-	}
-
-	onebyte = strtol(p, &end, 10);
-	if (*end != '\0' || onebyte > 255 || onebyte < 0)
-		return -1;
-	ip2[3] = (unsigned char)onebyte;
-
-	return 0;
-}
-
-static int ip_mask(char *mask, unsigned char *mask2)
-{
-	char *end;
-	long int bits;
-	uint32_t mask22;
-
-	if (undot_ip(mask, mask2)) {
-		/* not the /a.b.c.e format, maybe the /x format */
-		bits = strtol(mask, &end, 10);
-		if (*end != '\0' || bits > 32 || bits < 0)
-			return -1;
-		if (bits != 0) {
-			mask22 = htonl(0xFFFFFFFF << (32 - bits));
-			memcpy(mask2, &mask22, 4);
-		} else {
-			mask22 = 0xFFFFFFFF;
-			memcpy(mask2, &mask22, 4);
-		}
-	}
-	return 0;
-}
-
-static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
-{
-	char *p;
-
-	/* first the mask */
-	if ((p = strrchr(address, '/')) != NULL) {
-		*p = '\0';
-		if (ip_mask(p + 1, (unsigned char *)msk)) {
-			xtables_error(PARAMETER_PROBLEM,
-				      "Problem with the IP mask '%s'", p + 1);
-			return;
-		}
-	} else
-		*msk = 0xFFFFFFFF;
-
-	if (undot_ip(address, (unsigned char *)addr)) {
-		xtables_error(PARAMETER_PROBLEM,
-			      "Problem with the IP address '%s'", address);
-		return;
-	}
-	*addr = *addr & *msk;
-}
-
 static int
 brarp_parse(int c, char **argv, int invert, unsigned int *flags,
 	    const void *entry, struct xt_entry_match **match)
 {
 	struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
+	struct in_addr *ipaddr, ipmask;
 	long int i;
 	char *end;
-	uint32_t *addr;
-	uint32_t *mask;
 	unsigned char *maddr;
 	unsigned char *mmask;
+	unsigned int ipnr;
 
 	switch (c) {
 	case ARP_OPCODE:
@@ -231,24 +157,25 @@ brarp_parse(int c, char **argv, int invert, unsigned int *flags,
 
 	case ARP_IP_S:
 	case ARP_IP_D:
+		xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
 		if (c == ARP_IP_S) {
 			EBT_CHECK_OPTION(flags, OPT_IP_S);
-			addr = &arpinfo->saddr;
-			mask = &arpinfo->smsk;
+			arpinfo->saddr = ipaddr->s_addr;
+			arpinfo->smsk = ipmask.s_addr;
 			arpinfo->bitmask |= EBT_ARP_SRC_IP;
 		} else {
 			EBT_CHECK_OPTION(flags, OPT_IP_D);
-			addr = &arpinfo->daddr;
-			mask = &arpinfo->dmsk;
+			arpinfo->daddr = ipaddr->s_addr;
+			arpinfo->dmsk = ipmask.s_addr;
 			arpinfo->bitmask |= EBT_ARP_DST_IP;
 		}
+		free(ipaddr);
 		if (invert) {
 			if (c == ARP_IP_S)
 				arpinfo->invflags |= EBT_ARP_SRC_IP;
 			else
 				arpinfo->invflags |= EBT_ARP_DST_IP;
 		}
-		ebt_parse_ip_address(optarg, addr, mask);
 		break;
 	case ARP_MAC_S:
 	case ARP_MAC_D:
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
index 14ff0f097cfd8..96fbce906107c 100644
--- a/extensions/libebt_arp.t
+++ b/extensions/libebt_arp.t
@@ -6,6 +6,9 @@
 -p ARP ! --arp-ip-dst 1.2.3.4;-p ARP --arp-ip-dst ! 1.2.3.4 -j CONTINUE;OK
 -p ARP --arp-ip-src ! 0.0.0.0;=;OK
 -p ARP --arp-ip-dst ! 0.0.0.0/8;=;OK
+-p ARP --arp-ip-src ! 1.2.3.4/32;-p ARP --arp-ip-src ! 1.2.3.4;OK
+-p ARP --arp-ip-src ! 1.2.3.4/255.255.255.0;-p ARP --arp-ip-src ! 1.2.3.0/24;OK
+-p ARP --arp-ip-src ! 1.2.3.4/255.0.255.255;-p ARP --arp-ip-src ! 1.0.3.4/255.0.255.255;OK
 -p ARP --arp-mac-src 00:de:ad:be:ef:00;=;OK
 -p ARP --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
 -p ARP --arp-gratuitous;=;OK
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 8413a5aa8dd57..d13e83c06895d 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -164,80 +164,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
 }
 
 /* original code from ebtables: useful_functions.c */
-static int undot_ip(char *ip, unsigned char *ip2)
-{
-	char *p, *q, *end;
-	long int onebyte;
-	int i;
-	char buf[20];
-
-	strncpy(buf, ip, sizeof(buf) - 1);
-
-	p = buf;
-	for (i = 0; i < 3; i++) {
-		if ((q = strchr(p, '.')) == NULL)
-			return -1;
-		*q = '\0';
-		onebyte = strtol(p, &end, 10);
-		if (*end != '\0' || onebyte > 255 || onebyte < 0)
-			return -1;
-		ip2[i] = (unsigned char)onebyte;
-		p = q + 1;
-	}
-
-	onebyte = strtol(p, &end, 10);
-	if (*end != '\0' || onebyte > 255 || onebyte < 0)
-		return -1;
-	ip2[3] = (unsigned char)onebyte;
-
-	return 0;
-}
-
-static int ip_mask(char *mask, unsigned char *mask2)
-{
-	char *end;
-	long int bits;
-	uint32_t mask22;
-
-	if (undot_ip(mask, mask2)) {
-		/* not the /a.b.c.e format, maybe the /x format */
-		bits = strtol(mask, &end, 10);
-		if (*end != '\0' || bits > 32 || bits < 0)
-			return -1;
-		if (bits != 0) {
-			mask22 = htonl(0xFFFFFFFF << (32 - bits));
-			memcpy(mask2, &mask22, 4);
-		} else {
-			mask22 = 0xFFFFFFFF;
-			memcpy(mask2, &mask22, 4);
-		}
-	}
-	return 0;
-}
-
-static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
-{
-	char *p;
-
-	/* first the mask */
-	if ((p = strrchr(address, '/')) != NULL) {
-		*p = '\0';
-		if (ip_mask(p + 1, (unsigned char *)msk)) {
-			xtables_error(PARAMETER_PROBLEM,
-				      "Problem with the IP mask '%s'", p + 1);
-			return;
-		}
-	} else
-		*msk = 0xFFFFFFFF;
-
-	if (undot_ip(address, (unsigned char *)addr)) {
-		xtables_error(PARAMETER_PROBLEM,
-			      "Problem with the IP address '%s'", address);
-		return;
-	}
-	*addr = *addr & *msk;
-}
-
 static char *parse_range(const char *str, unsigned int res[])
 {
 	char *next;
@@ -355,18 +281,26 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
 	   const void *entry, struct xt_entry_match **match)
 {
 	struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
+	struct in_addr *ipaddr, ipmask;
+	unsigned int ipnr;
 
 	switch (c) {
 	case IP_SOURCE:
 		if (invert)
 			info->invflags |= EBT_IP_SOURCE;
-		ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
+		xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
+		info->saddr = ipaddr->s_addr;
+		info->smsk = ipmask.s_addr;
+		free(ipaddr);
 		info->bitmask |= EBT_IP_SOURCE;
 		break;
 	case IP_DEST:
 		if (invert)
 			info->invflags |= EBT_IP_DEST;
-		ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
+		xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
+		info->daddr = ipaddr->s_addr;
+		info->dmsk = ipmask.s_addr;
+		free(ipaddr);
 		info->bitmask |= EBT_IP_DEST;
 		break;
 	case IP_SPORT:
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 6/7] extensions: Collate ICMP types/codes in libxt_icmp.h
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
                   ` (4 preceding siblings ...)
  2022-11-12  0:20 ` [iptables PATCH 5/7] extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any() Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-12  0:20 ` [iptables PATCH 7/7] extensions: Unify ICMP parser into libxt_icmp.h Phil Sutter
  2022-11-15 16:33 ` [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

Put the most extensive version of icmp_codes, icmpv6_codes and
igmp_codes into the header. Have to rename the function
xt_print_icmp_types's parameter to avoid a compiler warning.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libebt_ip.c     |  62 --------------------
 extensions/libebt_ip6.c    |  38 ------------
 extensions/libip6t_icmp6.c |  42 --------------
 extensions/libipt_icmp.c   |  55 ------------------
 extensions/libxt_icmp.h    | 116 ++++++++++++++++++++++++++++++++++---
 5 files changed, 107 insertions(+), 206 deletions(-)

diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index d13e83c06895d..27ae84e9470d8 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -50,68 +50,6 @@ static const struct option brip_opts[] = {
 	XT_GETOPT_TABLEEND,
 };
 
-static const struct xt_icmp_names icmp_codes[] = {
-	{ "echo-reply", 0, 0, 0xFF },
-	/* Alias */ { "pong", 0, 0, 0xFF },
-
-	{ "destination-unreachable", 3, 0, 0xFF },
-	{   "network-unreachable", 3, 0, 0 },
-	{   "host-unreachable", 3, 1, 1 },
-	{   "protocol-unreachable", 3, 2, 2 },
-	{   "port-unreachable", 3, 3, 3 },
-	{   "fragmentation-needed", 3, 4, 4 },
-	{   "source-route-failed", 3, 5, 5 },
-	{   "network-unknown", 3, 6, 6 },
-	{   "host-unknown", 3, 7, 7 },
-	{   "network-prohibited", 3, 9, 9 },
-	{   "host-prohibited", 3, 10, 10 },
-	{   "TOS-network-unreachable", 3, 11, 11 },
-	{   "TOS-host-unreachable", 3, 12, 12 },
-	{   "communication-prohibited", 3, 13, 13 },
-	{   "host-precedence-violation", 3, 14, 14 },
-	{   "precedence-cutoff", 3, 15, 15 },
-
-	{ "source-quench", 4, 0, 0xFF },
-
-	{ "redirect", 5, 0, 0xFF },
-	{   "network-redirect", 5, 0, 0 },
-	{   "host-redirect", 5, 1, 1 },
-	{   "TOS-network-redirect", 5, 2, 2 },
-	{   "TOS-host-redirect", 5, 3, 3 },
-
-	{ "echo-request", 8, 0, 0xFF },
-	/* Alias */ { "ping", 8, 0, 0xFF },
-
-	{ "router-advertisement", 9, 0, 0xFF },
-
-	{ "router-solicitation", 10, 0, 0xFF },
-
-	{ "time-exceeded", 11, 0, 0xFF },
-	/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
-	{   "ttl-zero-during-transit", 11, 0, 0 },
-	{   "ttl-zero-during-reassembly", 11, 1, 1 },
-
-	{ "parameter-problem", 12, 0, 0xFF },
-	{   "ip-header-bad", 12, 0, 0 },
-	{   "required-option-missing", 12, 1, 1 },
-
-	{ "timestamp-request", 13, 0, 0xFF },
-
-	{ "timestamp-reply", 14, 0, 0xFF },
-
-	{ "address-mask-request", 17, 0, 0xFF },
-
-	{ "address-mask-reply", 18, 0, 0xFF }
-};
-
-static const struct xt_icmp_names igmp_types[] = {
-	{ "membership-query", 0x11 },
-	{ "membership-report-v1", 0x12 },
-	{ "membership-report-v2", 0x16 },
-	{ "leave-group", 0x17 },
-	{ "membership-report-v3", 0x22 },
-};
-
 static void brip_print_help(void)
 {
 	printf(
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index a686a285c3cb8..ac20666af5ba3 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -49,44 +49,6 @@ static const struct option brip6_opts[] = {
 	XT_GETOPT_TABLEEND,
 };
 
-static const struct xt_icmp_names icmpv6_codes[] = {
-	{ "destination-unreachable", 1, 0, 0xFF },
-	{ "no-route", 1, 0, 0 },
-	{ "communication-prohibited", 1, 1, 1 },
-	{ "address-unreachable", 1, 3, 3 },
-	{ "port-unreachable", 1, 4, 4 },
-
-	{ "packet-too-big", 2, 0, 0xFF },
-
-	{ "time-exceeded", 3, 0, 0xFF },
-	/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
-	{ "ttl-zero-during-transit", 3, 0, 0 },
-	{ "ttl-zero-during-reassembly", 3, 1, 1 },
-
-	{ "parameter-problem", 4, 0, 0xFF },
-	{ "bad-header", 4, 0, 0 },
-	{ "unknown-header-type", 4, 1, 1 },
-	{ "unknown-option", 4, 2, 2 },
-
-	{ "echo-request", 128, 0, 0xFF },
-	/* Alias */ { "ping", 128, 0, 0xFF },
-
-	{ "echo-reply", 129, 0, 0xFF },
-	/* Alias */ { "pong", 129, 0, 0xFF },
-
-	{ "router-solicitation", 133, 0, 0xFF },
-
-	{ "router-advertisement", 134, 0, 0xFF },
-
-	{ "neighbour-solicitation", 135, 0, 0xFF },
-	/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
-
-	{ "neighbour-advertisement", 136, 0, 0xFF },
-	/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
-
-	{ "redirect", 137, 0, 0xFF },
-};
-
 static void
 parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
 {
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index cc7bfaeb72fd7..44f7109528166 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -12,48 +12,6 @@ enum {
 	O_ICMPV6_TYPE = 0,
 };
 
-static const struct xt_icmp_names icmpv6_codes[] = {
-	{ "destination-unreachable", 1, 0, 0xFF },
-	{   "no-route", 1, 0, 0 },
-	{   "communication-prohibited", 1, 1, 1 },
-	{   "beyond-scope", 1, 2, 2 },
-	{   "address-unreachable", 1, 3, 3 },
-	{   "port-unreachable", 1, 4, 4 },
-	{   "failed-policy", 1, 5, 5 },
-	{   "reject-route", 1, 6, 6 },
-
-	{ "packet-too-big", 2, 0, 0xFF },
-
-	{ "time-exceeded", 3, 0, 0xFF },
-	/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
-	{   "ttl-zero-during-transit", 3, 0, 0 },
-	{   "ttl-zero-during-reassembly", 3, 1, 1 },
-
-	{ "parameter-problem", 4, 0, 0xFF },
-	{   "bad-header", 4, 0, 0 },
-	{   "unknown-header-type", 4, 1, 1 },
-	{   "unknown-option", 4, 2, 2 },
-
-	{ "echo-request", 128, 0, 0xFF },
-	/* Alias */ { "ping", 128, 0, 0xFF },
-
-	{ "echo-reply", 129, 0, 0xFF },
-	/* Alias */ { "pong", 129, 0, 0xFF },
-
-	{ "router-solicitation", 133, 0, 0xFF },
-
-	{ "router-advertisement", 134, 0, 0xFF },
-
-	{ "neighbour-solicitation", 135, 0, 0xFF },
-	/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
-
-	{ "neighbour-advertisement", 136, 0, 0xFF },
-	/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
-
-	{ "redirect", 137, 0, 0xFF },
-
-};
-
 static void icmp6_help(void)
 {
 	printf(
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index e5e236613f39f..f0e838874286b 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -19,61 +19,6 @@ enum {
 	O_ICMP_TYPE = 0,
 };
 
-static const struct xt_icmp_names icmp_codes[] = {
-	{ "any", 0xFF, 0, 0xFF },
-	{ "echo-reply", 0, 0, 0xFF },
-	/* Alias */ { "pong", 0, 0, 0xFF },
-
-	{ "destination-unreachable", 3, 0, 0xFF },
-	{   "network-unreachable", 3, 0, 0 },
-	{   "host-unreachable", 3, 1, 1 },
-	{   "protocol-unreachable", 3, 2, 2 },
-	{   "port-unreachable", 3, 3, 3 },
-	{   "fragmentation-needed", 3, 4, 4 },
-	{   "source-route-failed", 3, 5, 5 },
-	{   "network-unknown", 3, 6, 6 },
-	{   "host-unknown", 3, 7, 7 },
-	{   "network-prohibited", 3, 9, 9 },
-	{   "host-prohibited", 3, 10, 10 },
-	{   "TOS-network-unreachable", 3, 11, 11 },
-	{   "TOS-host-unreachable", 3, 12, 12 },
-	{   "communication-prohibited", 3, 13, 13 },
-	{   "host-precedence-violation", 3, 14, 14 },
-	{   "precedence-cutoff", 3, 15, 15 },
-
-	{ "source-quench", 4, 0, 0xFF },
-
-	{ "redirect", 5, 0, 0xFF },
-	{   "network-redirect", 5, 0, 0 },
-	{   "host-redirect", 5, 1, 1 },
-	{   "TOS-network-redirect", 5, 2, 2 },
-	{   "TOS-host-redirect", 5, 3, 3 },
-
-	{ "echo-request", 8, 0, 0xFF },
-	/* Alias */ { "ping", 8, 0, 0xFF },
-
-	{ "router-advertisement", 9, 0, 0xFF },
-
-	{ "router-solicitation", 10, 0, 0xFF },
-
-	{ "time-exceeded", 11, 0, 0xFF },
-	/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
-	{   "ttl-zero-during-transit", 11, 0, 0 },
-	{   "ttl-zero-during-reassembly", 11, 1, 1 },
-
-	{ "parameter-problem", 12, 0, 0xFF },
-	{   "ip-header-bad", 12, 0, 0 },
-	{   "required-option-missing", 12, 1, 1 },
-
-	{ "timestamp-request", 13, 0, 0xFF },
-
-	{ "timestamp-reply", 14, 0, 0xFF },
-
-	{ "address-mask-request", 17, 0, 0xFF },
-
-	{ "address-mask-reply", 18, 0, 0xFF }
-};
-
 static void icmp_help(void)
 {
 	printf(
diff --git a/extensions/libxt_icmp.h b/extensions/libxt_icmp.h
index 5820206ef469e..d6d9f9b6ffc98 100644
--- a/extensions/libxt_icmp.h
+++ b/extensions/libxt_icmp.h
@@ -1,25 +1,123 @@
-struct xt_icmp_names {
+static const struct xt_icmp_names {
 	const char *name;
 	uint8_t type;
 	uint8_t code_min, code_max;
+} icmp_codes[] = {
+	{ "any", 0xFF, 0, 0xFF },
+	{ "echo-reply", 0, 0, 0xFF },
+	/* Alias */ { "pong", 0, 0, 0xFF },
+
+	{ "destination-unreachable", 3, 0, 0xFF },
+	{   "network-unreachable", 3, 0, 0 },
+	{   "host-unreachable", 3, 1, 1 },
+	{   "protocol-unreachable", 3, 2, 2 },
+	{   "port-unreachable", 3, 3, 3 },
+	{   "fragmentation-needed", 3, 4, 4 },
+	{   "source-route-failed", 3, 5, 5 },
+	{   "network-unknown", 3, 6, 6 },
+	{   "host-unknown", 3, 7, 7 },
+	{   "network-prohibited", 3, 9, 9 },
+	{   "host-prohibited", 3, 10, 10 },
+	{   "TOS-network-unreachable", 3, 11, 11 },
+	{   "TOS-host-unreachable", 3, 12, 12 },
+	{   "communication-prohibited", 3, 13, 13 },
+	{   "host-precedence-violation", 3, 14, 14 },
+	{   "precedence-cutoff", 3, 15, 15 },
+
+	{ "source-quench", 4, 0, 0xFF },
+
+	{ "redirect", 5, 0, 0xFF },
+	{   "network-redirect", 5, 0, 0 },
+	{   "host-redirect", 5, 1, 1 },
+	{   "TOS-network-redirect", 5, 2, 2 },
+	{   "TOS-host-redirect", 5, 3, 3 },
+
+	{ "echo-request", 8, 0, 0xFF },
+	/* Alias */ { "ping", 8, 0, 0xFF },
+
+	{ "router-advertisement", 9, 0, 0xFF },
+
+	{ "router-solicitation", 10, 0, 0xFF },
+
+	{ "time-exceeded", 11, 0, 0xFF },
+	/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
+	{   "ttl-zero-during-transit", 11, 0, 0 },
+	{   "ttl-zero-during-reassembly", 11, 1, 1 },
+
+	{ "parameter-problem", 12, 0, 0xFF },
+	{   "ip-header-bad", 12, 0, 0 },
+	{   "required-option-missing", 12, 1, 1 },
+
+	{ "timestamp-request", 13, 0, 0xFF },
+
+	{ "timestamp-reply", 14, 0, 0xFF },
+
+	{ "address-mask-request", 17, 0, 0xFF },
+
+	{ "address-mask-reply", 18, 0, 0xFF }
+}, icmpv6_codes[] = {
+	{ "destination-unreachable", 1, 0, 0xFF },
+	{   "no-route", 1, 0, 0 },
+	{   "communication-prohibited", 1, 1, 1 },
+	{   "beyond-scope", 1, 2, 2 },
+	{   "address-unreachable", 1, 3, 3 },
+	{   "port-unreachable", 1, 4, 4 },
+	{   "failed-policy", 1, 5, 5 },
+	{   "reject-route", 1, 6, 6 },
+
+	{ "packet-too-big", 2, 0, 0xFF },
+
+	{ "time-exceeded", 3, 0, 0xFF },
+	/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
+	{   "ttl-zero-during-transit", 3, 0, 0 },
+	{   "ttl-zero-during-reassembly", 3, 1, 1 },
+
+	{ "parameter-problem", 4, 0, 0xFF },
+	{   "bad-header", 4, 0, 0 },
+	{   "unknown-header-type", 4, 1, 1 },
+	{   "unknown-option", 4, 2, 2 },
+
+	{ "echo-request", 128, 0, 0xFF },
+	/* Alias */ { "ping", 128, 0, 0xFF },
+
+	{ "echo-reply", 129, 0, 0xFF },
+	/* Alias */ { "pong", 129, 0, 0xFF },
+
+	{ "router-solicitation", 133, 0, 0xFF },
+
+	{ "router-advertisement", 134, 0, 0xFF },
+
+	{ "neighbour-solicitation", 135, 0, 0xFF },
+	/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
+
+	{ "neighbour-advertisement", 136, 0, 0xFF },
+	/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
+
+	{ "redirect", 137, 0, 0xFF },
+}, igmp_types[] = {
+	{ "membership-query", 0x11 },
+	{ "membership-report-v1", 0x12 },
+	{ "membership-report-v2", 0x16 },
+	{ "leave-group", 0x17 },
+	{ "membership-report-v3", 0x22 },
 };
 
-static void xt_print_icmp_types(const struct xt_icmp_names *icmp_codes,
+static void xt_print_icmp_types(const struct xt_icmp_names *_icmp_codes,
 				unsigned int n_codes)
 {
 	unsigned int i;
 
 	for (i = 0; i < n_codes; ++i) {
-		if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
-			if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
-			    && (icmp_codes[i].code_max
-				== icmp_codes[i-1].code_max))
-				printf(" (%s)", icmp_codes[i].name);
+		if (i && _icmp_codes[i].type == _icmp_codes[i-1].type) {
+			if (_icmp_codes[i].code_min == _icmp_codes[i-1].code_min
+			    && (_icmp_codes[i].code_max
+				== _icmp_codes[i-1].code_max))
+				printf(" (%s)", _icmp_codes[i].name);
 			else
-				printf("\n   %s", icmp_codes[i].name);
+				printf("\n   %s", _icmp_codes[i].name);
 		}
 		else
-			printf("\n%s", icmp_codes[i].name);
+			printf("\n%s", _icmp_codes[i].name);
 	}
 	printf("\n");
 }
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [iptables PATCH 7/7] extensions: Unify ICMP parser into libxt_icmp.h
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
                   ` (5 preceding siblings ...)
  2022-11-12  0:20 ` [iptables PATCH 6/7] extensions: Collate ICMP types/codes in libxt_icmp.h Phil Sutter
@ 2022-11-12  0:20 ` Phil Sutter
  2022-11-15 16:33 ` [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-12  0:20 UTC (permalink / raw)
  To: netfilter-devel

Merge all four copies of the ICMP/ICMPv6/IGMP parameter parsing code.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libebt_ip.c     |  82 +-----------------------
 extensions/libebt_ip6.c    |  73 +--------------------
 extensions/libip6t_icmp6.c |  55 +---------------
 extensions/libipt_icmp.c   |  55 +---------------
 extensions/libxt_icmp.h    | 126 +++++++++++++++++++++++++++++++++++++
 5 files changed, 131 insertions(+), 260 deletions(-)

diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 27ae84e9470d8..fd87dae7e2c62 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -102,82 +102,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
 }
 
 /* original code from ebtables: useful_functions.c */
-static char *parse_range(const char *str, unsigned int res[])
-{
-	char *next;
-
-	if (!xtables_strtoui(str, &next, &res[0], 0, 255))
-		return NULL;
-
-	res[1] = res[0];
-	if (*next == ':') {
-		str = next + 1;
-		if (!xtables_strtoui(str, &next, &res[1], 0, 255))
-			return NULL;
-	}
-
-	return next;
-}
-
-static int ebt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
-			  const char *icmptype, uint8_t type[], uint8_t code[])
-{
-	unsigned int match = n_codes;
-	unsigned int i, number[2];
-
-	for (i = 0; i < n_codes; i++) {
-		if (strncasecmp(codes[i].name, icmptype, strlen(icmptype)))
-			continue;
-		if (match != n_codes)
-			xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMP type `%s':"
-					" `%s' or `%s'?",
-					icmptype, codes[match].name,
-					codes[i].name);
-		match = i;
-	}
-
-	if (match < n_codes) {
-		type[0] = type[1] = codes[match].type;
-		if (code) {
-			code[0] = codes[match].code_min;
-			code[1] = codes[match].code_max;
-		}
-	} else {
-		char *next = parse_range(icmptype, number);
-		if (!next) {
-			xtables_error(PARAMETER_PROBLEM, "Unknown ICMP type `%s'",
-							icmptype);
-			return -1;
-		}
-
-		type[0] = (uint8_t) number[0];
-		type[1] = (uint8_t) number[1];
-		switch (*next) {
-		case 0:
-			if (code) {
-				code[0] = 0;
-				code[1] = 255;
-			}
-			return 0;
-		case '/':
-			if (code) {
-				next = parse_range(next+1, number);
-				code[0] = (uint8_t) number[0];
-				code[1] = (uint8_t) number[1];
-				if (next == NULL)
-					return -1;
-				if (next && *next == 0)
-					return 0;
-			}
-		/* fallthrough */
-		default:
-			xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
-			return -1;
-		}
-	}
-	return 0;
-}
-
 static void print_icmp_code(uint8_t *code)
 {
 	if (!code)
@@ -256,15 +180,13 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
 	case IP_EBT_ICMP:
 		if (invert)
 			info->invflags |= EBT_IP_ICMP;
-		ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
-			      info->icmp_type, info->icmp_code);
+		ebt_parse_icmp(optarg, info->icmp_type, info->icmp_code);
 		info->bitmask |= EBT_IP_ICMP;
 		break;
 	case IP_EBT_IGMP:
 		if (invert)
 			info->invflags |= EBT_IP_IGMP;
-		ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg,
-			       info->igmp_type, NULL);
+		ebt_parse_igmp(optarg, info->igmp_type);
 		info->bitmask |= EBT_IP_IGMP;
 		break;
 	case IP_EBT_TOS: {
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index ac20666af5ba3..18bb2720ccbec 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -72,76 +72,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
 	free(buffer);
 }
 
-static char *parse_range(const char *str, unsigned int res[])
-{
-	char *next;
-
-	if (!xtables_strtoui(str, &next, &res[0], 0, 255))
-		return NULL;
-
-	res[1] = res[0];
-	if (*next == ':') {
-		str = next + 1;
-		if (!xtables_strtoui(str, &next, &res[1], 0, 255))
-			return NULL;
-	}
-
-	return next;
-}
-
-static int
-parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
-{
-	static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
-	unsigned int match = limit;
-	unsigned int i, number[2];
-
-	for (i = 0; i < limit; i++) {
-		if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
-			continue;
-		if (match != limit)
-			xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMPv6 type `%s':"
-					" `%s' or `%s'?",
-					icmpv6type, icmpv6_codes[match].name,
-					icmpv6_codes[i].name);
-		match = i;
-	}
-
-	if (match < limit) {
-		type[0] = type[1] = icmpv6_codes[match].type;
-		code[0] = icmpv6_codes[match].code_min;
-		code[1] = icmpv6_codes[match].code_max;
-	} else {
-		char *next = parse_range(icmpv6type, number);
-		if (!next) {
-			xtables_error(PARAMETER_PROBLEM, "Unknown ICMPv6 type `%s'",
-							icmpv6type);
-			return -1;
-		}
-		type[0] = (uint8_t) number[0];
-		type[1] = (uint8_t) number[1];
-		switch (*next) {
-		case 0:
-			code[0] = 0;
-			code[1] = 255;
-			return 0;
-		case '/':
-			next = parse_range(next+1, number);
-			code[0] = (uint8_t) number[0];
-			code[1] = (uint8_t) number[1];
-			if (next == NULL)
-				return -1;
-			if (next && *next == 0)
-				return 0;
-		/* fallthrough */
-		default:
-			xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
-			return -1;
-		}
-	}
-	return 0;
-}
-
 static void print_port_range(uint16_t *ports)
 {
 	if (ports[0] == ports[1])
@@ -266,8 +196,7 @@ brip6_parse(int c, char **argv, int invert, unsigned int *flags,
 	case IP_ICMP6:
 		if (invert)
 			info->invflags |= EBT_IP6_ICMP6;
-		if (parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code))
-			return 0;
+		ebt_parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code);
 		info->bitmask |= EBT_IP6_ICMP6;
 		break;
 	case IP_TCLASS:
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index 44f7109528166..439291eaaaca5 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -28,59 +28,6 @@ static const struct xt_option_entry icmp6_opts[] = {
 	XTOPT_TABLEEND,
 };
 
-static void
-parse_icmpv6(const char *icmpv6type, uint8_t *type, uint8_t code[])
-{
-	static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
-	unsigned int match = limit;
-	unsigned int i;
-
-	for (i = 0; i < limit; i++) {
-		if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))
-		    == 0) {
-			if (match != limit)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Ambiguous ICMPv6 type `%s':"
-					   " `%s' or `%s'?",
-					   icmpv6type,
-					   icmpv6_codes[match].name,
-					   icmpv6_codes[i].name);
-			match = i;
-		}
-	}
-
-	if (match != limit) {
-		*type = icmpv6_codes[match].type;
-		code[0] = icmpv6_codes[match].code_min;
-		code[1] = icmpv6_codes[match].code_max;
-	} else {
-		char *slash;
-		char buffer[strlen(icmpv6type) + 1];
-		unsigned int number;
-
-		strcpy(buffer, icmpv6type);
-		slash = strchr(buffer, '/');
-
-		if (slash)
-			*slash = '\0';
-
-		if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				   "Invalid ICMPv6 type `%s'\n", buffer);
-		*type = number;
-		if (slash) {
-			if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
-				xtables_error(PARAMETER_PROBLEM,
-					   "Invalid ICMPv6 code `%s'\n",
-					   slash+1);
-			code[0] = code[1] = number;
-		} else {
-			code[0] = 0;
-			code[1] = 0xFF;
-		}
-	}
-}
-
 static void icmp6_init(struct xt_entry_match *m)
 {
 	struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)m->data;
@@ -93,7 +40,7 @@ static void icmp6_parse(struct xt_option_call *cb)
 	struct ip6t_icmp *icmpv6info = cb->data;
 
 	xtables_option_parse(cb);
-	parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
+	ipt_parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
 	if (cb->invert)
 		icmpv6info->invflags |= IP6T_ICMP_INV;
 }
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index f0e838874286b..b0318aebc2c57 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -35,59 +35,6 @@ static const struct xt_option_entry icmp_opts[] = {
 	XTOPT_TABLEEND,
 };
 
-static void 
-parse_icmp(const char *icmptype, uint8_t *type, uint8_t code[])
-{
-	static const unsigned int limit = ARRAY_SIZE(icmp_codes);
-	unsigned int match = limit;
-	unsigned int i;
-
-	for (i = 0; i < limit; i++) {
-		if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))
-		    == 0) {
-			if (match != limit)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Ambiguous ICMP type `%s':"
-					   " `%s' or `%s'?",
-					   icmptype,
-					   icmp_codes[match].name,
-					   icmp_codes[i].name);
-			match = i;
-		}
-	}
-
-	if (match != limit) {
-		*type = icmp_codes[match].type;
-		code[0] = icmp_codes[match].code_min;
-		code[1] = icmp_codes[match].code_max;
-	} else {
-		char *slash;
-		char buffer[strlen(icmptype) + 1];
-		unsigned int number;
-
-		strcpy(buffer, icmptype);
-		slash = strchr(buffer, '/');
-
-		if (slash)
-			*slash = '\0';
-
-		if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				   "Invalid ICMP type `%s'\n", buffer);
-		*type = number;
-		if (slash) {
-			if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
-				xtables_error(PARAMETER_PROBLEM,
-					   "Invalid ICMP code `%s'\n",
-					   slash+1);
-			code[0] = code[1] = number;
-		} else {
-			code[0] = 0;
-			code[1] = 0xFF;
-		}
-	}
-}
-
 static void icmp_init(struct xt_entry_match *m)
 {
 	struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data;
@@ -101,7 +48,7 @@ static void icmp_parse(struct xt_option_call *cb)
 	struct ipt_icmp *icmpinfo = cb->data;
 
 	xtables_option_parse(cb);
-	parse_icmp(cb->arg, &icmpinfo->type, icmpinfo->code);
+	ipt_parse_icmp(cb->arg, &icmpinfo->type, icmpinfo->code);
 	if (cb->invert)
 		icmpinfo->invflags |= IPT_ICMP_INV;
 }
diff --git a/extensions/libxt_icmp.h b/extensions/libxt_icmp.h
index d6d9f9b6ffc98..a763e50c1de32 100644
--- a/extensions/libxt_icmp.h
+++ b/extensions/libxt_icmp.h
@@ -102,6 +102,132 @@ static const struct xt_icmp_names {
 	{ "membership-report-v3", 0x22 },
 };
 
+static inline char *parse_range(const char *str, unsigned int res[])
+{
+	char *next;
+
+	if (!xtables_strtoui(str, &next, &res[0], 0, 255))
+		return NULL;
+
+	res[1] = res[0];
+	if (*next == ':') {
+		str = next + 1;
+		if (!xtables_strtoui(str, &next, &res[1], 0, 255))
+			return NULL;
+	}
+
+	return next;
+}
+
+static void
+__parse_icmp(const struct xt_icmp_names codes[], size_t n_codes,
+	     const char *codes_name, const char *fmtstring,
+	     uint8_t type[], uint8_t code[])
+{
+	unsigned int match = n_codes;
+	unsigned int i, number[2];
+
+	for (i = 0; i < n_codes; i++) {
+		if (strncasecmp(codes[i].name, fmtstring, strlen(fmtstring)))
+			continue;
+		if (match != n_codes)
+			xtables_error(PARAMETER_PROBLEM,
+				      "Ambiguous %s type `%s': `%s' or `%s'?",
+				      codes_name, fmtstring, codes[match].name,
+				      codes[i].name);
+		match = i;
+	}
+
+	if (match < n_codes) {
+		type[0] = type[1] = codes[match].type;
+		if (code) {
+			code[0] = codes[match].code_min;
+			code[1] = codes[match].code_max;
+		}
+	} else {
+		char *next = parse_range(fmtstring, number);
+		if (!next)
+			xtables_error(PARAMETER_PROBLEM, "Unknown %s type `%s'",
+				      codes_name, fmtstring);
+		type[0] = (uint8_t) number[0];
+		type[1] = (uint8_t) number[1];
+		switch (*next) {
+		case 0:
+			if (code) {
+				code[0] = 0;
+				code[1] = 255;
+			}
+			return;
+		case '/':
+			if (!code)
+				break;
+
+			next = parse_range(next + 1, number);
+			if (!next)
+				xtables_error(PARAMETER_PROBLEM,
+					      "Unknown %s code `%s'",
+					      codes_name, fmtstring);
+			code[0] = (uint8_t) number[0];
+			code[1] = (uint8_t) number[1];
+			if (!*next)
+				break;
+		/* fallthrough */
+		default:
+			xtables_error(PARAMETER_PROBLEM,
+				      "unknown character %c", *next);
+		}
+	}
+}
+
+static inline void
+__ipt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
+		 const char *codes_name, const char *fmtstr,
+		 uint8_t *type, uint8_t code[])
+{
+	uint8_t types[2];
+
+	__parse_icmp(codes, n_codes, codes_name, fmtstr, types, code);
+	if (types[1] != types[0])
+		xtables_error(PARAMETER_PROBLEM,
+			      "%s type range not supported", codes_name);
+	*type = types[0];
+}
+
+static inline void
+ipt_parse_icmp(const char *str, uint8_t *type, uint8_t code[])
+{
+	__ipt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
+			 "ICMP", str, type, code);
+}
+
+static inline void
+ipt_parse_icmpv6(const char *str, uint8_t *type, uint8_t code[])
+{
+	__ipt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
+			 "ICMPv6", str, type, code);
+}
+
+static inline void
+ebt_parse_icmp(const char *str, uint8_t type[], uint8_t code[])
+{
+	__parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
+		     "ICMP", str, type, code);
+}
+
+static inline void
+ebt_parse_icmpv6(const char *str, uint8_t type[], uint8_t code[])
+{
+	__parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
+		     "ICMPv6", str, type, code);
+}
+
+static inline void
+ebt_parse_igmp(const char *str, uint8_t type[])
+{
+	__parse_icmp(igmp_types, ARRAY_SIZE(igmp_types),
+		     "IGMP", str, type, NULL);
+}
+
 static void xt_print_icmp_types(const struct xt_icmp_names *_icmp_codes,
 				unsigned int n_codes)
 {
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [iptables PATCH 0/7] De-duplicate code here and there
  2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
                   ` (6 preceding siblings ...)
  2022-11-12  0:20 ` [iptables PATCH 7/7] extensions: Unify ICMP parser into libxt_icmp.h Phil Sutter
@ 2022-11-15 16:33 ` Phil Sutter
  7 siblings, 0 replies; 9+ messages in thread
From: Phil Sutter @ 2022-11-15 16:33 UTC (permalink / raw)
  To: netfilter-devel

On Sat, Nov 12, 2022 at 01:20:49AM +0100, Phil Sutter wrote:
> A series of unrelated patches reducing code size in different ways:
> 
> Patch 1 is a typical "move function to xshared.c for common use", patch
> 2 eliminates some c'n'p programming in nft-shared.c, patch 3 merges
> libipt_LOG.c and libip6t_LOG.c, patch 4 removes code from libebt_ip.c by
> including the right header, patch 5 drops some local IP address parsers
> in favor of the respective libxtables function and patches 6 and 7 move
> duplicate definitions and code into a header shared by multiple
> extensions.
> 
> Phil Sutter (7):
>   xshared: Share make_delete_mask() between ip{,6}tables
>   nft-shared: Introduce port_match_single_to_range()
>   extensions: libip*t_LOG: Merge extensions
>   extensions: libebt_ip: Include kernel header
>   extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any()
>   extensions: Collate ICMP types/codes in libxt_icmp.h
>   extensions: Unify ICMP parser into libxt_icmp.h

Series applied.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-11-15 16:34 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-12  0:20 [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 1/7] xshared: Share make_delete_mask() between ip{,6}tables Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 2/7] nft-shared: Introduce port_match_single_to_range() Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 3/7] extensions: libip*t_LOG: Merge extensions Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 4/7] extensions: libebt_ip: Include kernel header Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 5/7] extensions: libebt_arp, libebt_ip: Use xtables_ipparse_any() Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 6/7] extensions: Collate ICMP types/codes in libxt_icmp.h Phil Sutter
2022-11-12  0:20 ` [iptables PATCH 7/7] extensions: Unify ICMP parser into libxt_icmp.h Phil Sutter
2022-11-15 16:33 ` [iptables PATCH 0/7] De-duplicate code here and there Phil Sutter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).