From 3488eecf1a5d9baa1808eaea7670a7aa2931e1ad Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 2 May 2013 16:44:50 +0200 Subject: [PATCH] Check whether ipset exists before referencing it in rules or redirects --- ipsets.c | 37 +++++++++++++++++++++++++++++++++++++ ipsets.h | 5 +++++ redirects.c | 8 ++++++++ rules.c | 8 ++++++++ 4 files changed, 58 insertions(+) diff --git a/ipsets.c b/ipsets.c index 713b343..9f43523 100644 --- a/ipsets.c +++ b/ipsets.c @@ -358,3 +358,40 @@ fw3_lookup_ipset(struct fw3_state *state, const char *name) return NULL; } + +bool +fw3_check_ipset(struct fw3_ipset *set) +{ + bool rv = false; + + socklen_t sz; + int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + struct ip_set_req_version req_ver; + struct ip_set_req_get_set req_name; + + if (s < 0 || fcntl(s, F_SETFD, FD_CLOEXEC)) + goto out; + + sz = sizeof(req_ver); + req_ver.op = IP_SET_OP_VERSION; + + if (getsockopt(s, SOL_IP, SO_IP_SET, &req_ver, &sz)) + goto out; + + sz = sizeof(req_name); + req_name.op = IP_SET_OP_GET_BYNAME; + req_name.version = req_ver.version; + snprintf(req_name.set.name, IPSET_MAXNAMELEN - 1, "%s", + (set->external && *set->external) ? set->external : set->name); + + if (getsockopt(s, SOL_IP, SO_IP_SET, &req_name, &sz)) + goto out; + + rv = ((sz == sizeof(req_name)) && (req_name.set.index != IPSET_INVALID_ID)); + +out: + if (s >= 0) + close(s); + + return rv; +} diff --git a/ipsets.h b/ipsets.h index 929f311..9704177 100644 --- a/ipsets.h +++ b/ipsets.h @@ -19,9 +19,12 @@ #ifndef __FW3_IPSETS_H #define __FW3_IPSETS_H +#include + #include "options.h" #include "utils.h" + extern const struct fw3_option fw3_ipset_opts[]; struct fw3_ipset * fw3_alloc_ipset(void); @@ -31,6 +34,8 @@ void fw3_destroy_ipsets(struct fw3_state *state); struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name); +bool fw3_check_ipset(struct fw3_ipset *set); + #define fw3_free_ipset(ipset) \ fw3_free_object(ipset, fw3_ipset_opts) diff --git a/redirects.c b/redirects.c index 6ea91b8..24d1356 100644 --- a/redirects.c +++ b/redirects.c @@ -372,6 +372,14 @@ print_redirect(struct fw3_state *state, enum fw3_family family, return; } + if (!fw3_check_ipset(redir->_ipset)) + { + info(" ! Skipping due to missing ipset '%s'", + (redir->_ipset->external && *redir->_ipset->external) ? + redir->_ipset->external : redir->_ipset->name); + return; + } + set(redir->_ipset->flags, family, family); } diff --git a/rules.c b/rules.c index 5a6ea00..785621f 100644 --- a/rules.c +++ b/rules.c @@ -365,6 +365,14 @@ expand_rule(struct fw3_state *state, enum fw3_family family, return; } + if (!fw3_check_ipset(rule->_ipset)) + { + info(" ! Skipping due to missing ipset '%s'", + (rule->_ipset->external && *rule->_ipset->external) ? + rule->_ipset->external : rule->_ipset->name); + return; + } + set(rule->_ipset->flags, family, family); } -- 2.25.1