summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-03-01 23:05:29 +0100
committerPhil Sutter <phil@nwl.cc>2022-03-10 17:38:31 +0100
commitb6196c7504d4d41827cea86c167926125cdbf1f3 (patch)
tree73cc9c719e2f5650c3a960084c5e18034dfae835
parent07ee529f5a62838d68be59683be99bf6a7cda0f2 (diff)
xshared: Prefer xtables_chain_protos lookup over getprotoent
When dumping a large ruleset, common protocol matches such as for TCP port number significantly slow down rule printing due to repeated calls for getprotobynumber(). The latter does not involve any caching, so /etc/protocols is consulted over and over again. As a simple countermeasure, make functions converting between proto number and name prefer the built-in list of "well-known" protocols. This is not a perfect solution, repeated rules for protocol names libxtables does not cache (e.g. igmp or dccp) will still be slow. Implementing getprotoent() result caching could solve this. As a side-effect, explicit check for pseudo-protocol "all" may be dropped as it is contained in the built-in list and therefore immutable. Also update xtables_chain_protos entries a bit to align with typical /etc/protocols contents. The testsuite assumes those names, so the preferred ones prior to this patch are indeed uncommon nowadays. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
-rw-r--r--iptables/xshared.c8
-rw-r--r--libxtables/xtables.c19
2 files changed, 10 insertions, 17 deletions
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 50a1d48a..43321d3b 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -53,16 +53,16 @@ proto_to_name(uint16_t proto, int nolookup)
{
unsigned int i;
+ for (i = 0; xtables_chain_protos[i].name != NULL; ++i)
+ if (xtables_chain_protos[i].num == proto)
+ return xtables_chain_protos[i].name;
+
if (proto && !nolookup) {
struct protoent *pent = getprotobynumber(proto);
if (pent)
return pent->p_name;
}
- for (i = 0; xtables_chain_protos[i].name != NULL; ++i)
- if (xtables_chain_protos[i].num == proto)
- return xtables_chain_protos[i].name;
-
return NULL;
}
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 87424d04..094cbd87 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -2101,10 +2101,11 @@ const struct xtables_pprot xtables_chain_protos[] = {
{"udp", IPPROTO_UDP},
{"udplite", IPPROTO_UDPLITE},
{"icmp", IPPROTO_ICMP},
- {"icmpv6", IPPROTO_ICMPV6},
{"ipv6-icmp", IPPROTO_ICMPV6},
+ {"icmpv6", IPPROTO_ICMPV6},
{"esp", IPPROTO_ESP},
{"ah", IPPROTO_AH},
+ {"mobility-header", IPPROTO_MH},
{"ipv6-mh", IPPROTO_MH},
{"mh", IPPROTO_MH},
{"all", 0},
@@ -2120,23 +2121,15 @@ xtables_parse_protocol(const char *s)
if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
return proto;
- /* first deal with the special case of 'all' to prevent
- * people from being able to redefine 'all' in nsswitch
- * and/or provoke expensive [not working] ldap/nis/...
- * lookups */
- if (strcmp(s, "all") == 0)
- return 0;
+ for (i = 0; xtables_chain_protos[i].name != NULL; ++i) {
+ if (strcmp(s, xtables_chain_protos[i].name) == 0)
+ return xtables_chain_protos[i].num;
+ }
pent = getprotobyname(s);
if (pent != NULL)
return pent->p_proto;
- for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
- if (xtables_chain_protos[i].name == NULL)
- continue;
- if (strcmp(s, xtables_chain_protos[i].name) == 0)
- return xtables_chain_protos[i].num;
- }
xt_params->exit_err(PARAMETER_PROBLEM,
"unknown protocol \"%s\" specified", s);
return -1;