From cf1f03f8f3cf2db577a9ddee254cc7f886129d18 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 4 Sep 2013 17:43:49 +0200 Subject: extensions: libxt_set, libxt_SET: check the set family too Do not accept silently sets with wrong protocol family but reject them with an error message. It makes straightforward to catch user errors. [ Use afinfo instead to avoid a binary interface update --pablo ] Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_set.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'extensions') diff --git a/extensions/libxt_set.h b/extensions/libxt_set.h index 47c3f5b6..5a1bdcf7 100644 --- a/extensions/libxt_set.h +++ b/extensions/libxt_set.h @@ -6,6 +6,7 @@ #include #include #include +#include "../iptables/xshared.h" #ifdef DEBUG #define DEBUGP(x, args...) fprintf(stderr, x , ## args) @@ -71,13 +72,13 @@ get_set_byid(char *setname, ip_set_id_t idx) } static void -get_set_byname(const char *setname, struct xt_set_info *info) +get_set_byname_only(const char *setname, struct xt_set_info *info, + int sockfd, unsigned int version) { - struct ip_set_req_get_set req; + struct ip_set_req_get_set req = { .version = version }; socklen_t size = sizeof(struct ip_set_req_get_set); - int res, sockfd; + int res; - sockfd = get_version(&req.version); req.op = IP_SET_OP_GET_BYNAME; strncpy(req.set.name, setname, IPSET_MAXNAMELEN); req.set.name[IPSET_MAXNAMELEN - 1] = '\0'; @@ -100,6 +101,49 @@ get_set_byname(const char *setname, struct xt_set_info *info) info->index = req.set.index; } +static void +get_set_byname(const char *setname, struct xt_set_info *info) +{ + struct ip_set_req_get_set_family req; + socklen_t size = sizeof(struct ip_set_req_get_set_family); + int res, sockfd, version; + + sockfd = get_version(&req.version); + version = req.version; + req.op = IP_SET_OP_GET_FNAME; + strncpy(req.set.name, setname, IPSET_MAXNAMELEN); + req.set.name[IPSET_MAXNAMELEN - 1] = '\0'; + res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size); + + if (res != 0 && errno == EBADMSG) + /* Backward compatibility */ + return get_set_byname_only(setname, info, sockfd, version); + + close(sockfd); + if (res != 0) + xtables_error(OTHER_PROBLEM, + "Problem when communicating with ipset, errno=%d.\n", + errno); + if (size != sizeof(struct ip_set_req_get_set_family)) + xtables_error(OTHER_PROBLEM, + "Incorrect return size from kernel during ipset lookup, " + "(want %zu, got %zu)\n", + sizeof(struct ip_set_req_get_set_family), + (size_t)size); + if (req.set.index == IPSET_INVALID_ID) + xtables_error(PARAMETER_PROBLEM, + "Set %s doesn't exist.\n", setname); + if (!(req.family == afinfo->family || + req.family == NFPROTO_UNSPEC)) + xtables_error(PARAMETER_PROBLEM, + "The protocol family of set %s is %s, " + "which is not applicable.\n", + setname, + req.family == NFPROTO_IPV4 ? "IPv4" : "IPv6"); + + info->index = req.set.index; +} + static void parse_dirs_v0(const char *opt_arg, struct xt_set_info_v0 *info) { -- cgit v1.2.3