Check whether ipset exists before referencing it in rules or redirects
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 2 May 2013 14:44:50 +0000 (16:44 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 2 May 2013 15:36:16 +0000 (17:36 +0200)
ipsets.c
ipsets.h
redirects.c
rules.c

index 713b34378dd0551c2a1860c120f10438610bd1cb..9f4352346944f45acbd0c4db502d39142c221a9e 100644 (file)
--- 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;
+}
index 929f31194627c7a20b9659fd2a7872f81a67d280..9704177725b57cf571da6e82970a02a51fb2fe13 100644 (file)
--- a/ipsets.h
+++ b/ipsets.h
 #ifndef __FW3_IPSETS_H
 #define __FW3_IPSETS_H
 
+#include <linux/netfilter/ipset/ip_set.h>
+
 #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)
 
index 6ea91b8123e099674a142266bf741ef41473a994..24d13569b4d1a4b94c6dd58732af046137e99c96 100644 (file)
@@ -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 5a6ea004bf42b33a68e9fd4bc8c705affe509c57..785621fedb735059b00acc3e64d2bb21a5426be6 100644 (file)
--- 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);
        }