]> git.ipfire.org Git - thirdparty/xtables-addons.git/commitdiff
ipset; update to ipset-6.3 (genl)
authorJan Engelhardt <jengelh@medozas.de>
Mon, 11 Apr 2011 02:03:30 +0000 (04:03 +0200)
committerJan Engelhardt <jengelh@medozas.de>
Mon, 11 Apr 2011 02:11:30 +0000 (04:11 +0200)
* Handle EAGAIN from autoloading code.
* Turn one nfgenmsg site into genlmsg to avoid protocol mismatch

doc/changelog.txt
extensions/ipset-6/include/libipset/linux_ip_set.h
extensions/ipset-6/ip_set.h
extensions/ipset-6/ip_set_bitmap_ipmac.c
extensions/ipset-6/ip_set_core.c
extensions/ipset-6/ip_set_list_set.c
extensions/ipset-6/ipset.8
extensions/ipset-6/xt_set.c

index cf2f0ae467068ca05e0a7cbd0a9b84c7a21c526e..8fedf2c49502109d26a29d6028be9e914fe4c849 100644 (file)
@@ -21,6 +21,10 @@ Enhancements:
   * revision reporting fixes
 - update to ipset 6.2
   * list:set timeout variant fixes
+- update to ipset 6.3
+  * bitmap:ip,mac type requires "src" for MAC, enforce it
+- ipset-genl: handle EAGAIN return value emitted from autoloader
+- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort
 
 
 v1.33 (2011-02-02)
index d4b6308b82e2d185987657e3aa0feb0f6be2e8ec..d81a811cd0b5e53f3601305a163bc0601e74d5bc 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 /* The protocol version */
-#define IPSET_PROTOCOL         60
+#define IPSET_PROTOCOL         6
 
 /* The max length of strings including NUL: set and type identifiers */
 #define IPSET_MAXNAMELEN       32
index 8026f1b7732753bdb427735614226f93ad5474fd..08f59eb106cb90dbba66e58b575ecc09491fcca1 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/netlink.h>
 
 /* The protocol version */
-#define IPSET_PROTOCOL         60
+#define IPSET_PROTOCOL         6
 
 /* The max length of strings including NUL: set and type identifiers */
 #define IPSET_MAXNAMELEN       32
index 74bca4cb87b3f93cc1e8f6a2eabe8555f0f09e58..175d8719f6f750e564270fb4f7c8bd61d9042db9 100644 (file)
@@ -344,6 +344,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct ipmac data;
 
+       /* MAC can be src only */
+       if (!(flags & IPSET_DIM_TWO_SRC))
+               return 0;
+
        data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
        if (data.id < map->first_ip || data.id > map->last_ip)
                return -IPSET_ERR_BITMAP_RANGE;
index abf1c9024eadb5d38a373ceb711319d528b4227e..509a87cbdc323df843f372a15273193f83a07478 100644 (file)
@@ -26,6 +26,8 @@
 #include <net/genetlink.h>
 #define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
 
+struct genlmsg_buf;
+
 static LIST_HEAD(ip_set_type_list);            /* all registered set types */
 static DEFINE_MUTEX(ip_set_type_mutex);                /* protects ip_set_type_list */
 static DEFINE_RWLOCK(ip_set_ref_lock);         /* protects the set refs */
@@ -82,14 +84,14 @@ find_set_type(const char *name, u8 family, u8 revision)
 static int
 try_to_load_type(const char *name)
 {
-       nfnl_unlock();
+       genl_unlock();
        pr_debug("try to load ip_set_%s\n", name);
        if (request_module("ip_set_%s", name) < 0) {
                pr_warning("Can't find ip_set type %s\n", name);
-               nfnl_lock();
+               genl_lock();
                return -IPSET_ERR_FIND_TYPE;
        }
-       nfnl_lock();
+       genl_lock();
        return -EAGAIN;
 }
 
@@ -99,8 +101,10 @@ find_set_type_get(const char *name, u8 family, u8 revision,
                  struct ip_set_type **found)
 {
        struct ip_set_type *type;
+       unsigned int retry = 0;
        int err;
 
+retry:
        rcu_read_lock();
        *found = find_set_type(name, family, revision);
        if (*found) {
@@ -115,7 +119,10 @@ find_set_type_get(const char *name, u8 family, u8 revision,
                }
        rcu_read_unlock();
 
-       return try_to_load_type(name);
+       err = try_to_load_type(name);
+       if (err == -EAGAIN && retry++ == 0)
+               goto retry;
+       return err;
 
 unlock:
        rcu_read_unlock();
@@ -131,7 +138,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
 {
        struct ip_set_type *type;
        bool found = false;
+       unsigned int retry = 0;
+       int err;
 
+retry:
        *min = 255; *max = 0;
        rcu_read_lock();
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
@@ -147,7 +157,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
        if (found)
                return 0;
 
-       return try_to_load_type(name);
+       err = try_to_load_type(name);
+       if (err == -EAGAIN && retry++ == 0)
+               goto retry;
+       return err;
 }
 
 #define family_name(f) ((f) == AF_INET ? "inet" : \
@@ -482,9 +495,9 @@ ip_set_nfnl_get(const char *name)
        struct ip_set *s;
        ip_set_id_t index;
 
-       nfnl_lock();
+       genl_lock();
        index = ip_set_get_byname(name, &s);
-       nfnl_unlock();
+       genl_unlock();
 
        return index;
 }
@@ -502,12 +515,12 @@ ip_set_nfnl_get_byindex(ip_set_id_t index)
        if (index > ip_set_max)
                return IPSET_INVALID_ID;
 
-       nfnl_lock();
+       genl_lock();
        if (ip_set_list[index])
                __ip_set_get(index);
        else
                index = IPSET_INVALID_ID;
-       nfnl_unlock();
+       genl_unlock();
 
        return index;
 }
@@ -523,9 +536,9 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
 void
 ip_set_nfnl_put(ip_set_id_t index)
 {
-       nfnl_lock();
+       genl_lock();
        ip_set_put_byindex(index);
-       nfnl_unlock();
+       genl_unlock();
 }
 EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
 
@@ -548,11 +561,11 @@ flag_exist(const struct genlmsghdr *ghdr)
        return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
 }
 
-static struct nlmsghdr *
+static struct genlmsg_buf *
 start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
          enum ipset_cmd cmd)
 {
-       void *nlh;
+       struct genlmsg_buf *nlh;
 
        nlh = genlmsg_put(skb, pid, seq, &ip_set_netlink_subsys, flags, cmd);
        if (nlh == NULL)
@@ -950,10 +963,11 @@ ip_set_dump_done(struct netlink_callback *cb)
 }
 
 static inline void
-dump_attrs(void *phdr)
+dump_attrs(struct genlmsg_buf *phdr)
 {
        const struct nlattr *attr;
-       const struct nlmsghdr *nlh = phdr - GENL_HDRLEN - NLMSG_HDRLEN;
+       const struct nlmsghdr *nlh =
+               (const void *)phdr - GENL_HDRLEN - NLMSG_HDRLEN;
        int rem;
 
        pr_debug("dump nlmsg\n");
@@ -999,14 +1013,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
 {
        ip_set_id_t index = IPSET_INVALID_ID, max;
        struct ip_set *set = NULL;
-       struct nlmsghdr *nlh = NULL;
+       struct genlmsg_buf *nlh = NULL;
        unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
        int ret = 0;
 
        if (cb->args[0] == DUMP_INIT) {
                ret = dump_init(cb);
                if (ret < 0) {
-                       nlh = nlmsg_hdr(cb->skb);
+                       struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
                        /* We have to create and send the error message
                         * manually :-( */
                        if (nlh->nlmsg_flags & NLM_F_ACK)
@@ -1159,7 +1173,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
                struct sk_buff *skb2;
                struct nlmsgerr *errmsg;
                size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
-               int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+               int min_len = NLMSG_SPACE(sizeof(struct genlmsghdr));
                struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
                struct nlattr *cmdattr;
                u32 *errline;
@@ -1342,7 +1356,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
        struct nlattr *const *attr = info->attrs;
        const struct nlmsghdr *nlh = info->nlhdr;
        struct sk_buff *skb2;
-       struct nlmsghdr *nlh2;
+       struct genlmsg_buf *nlh2;
        ip_set_id_t index;
        int ret = 0;
 
@@ -1355,7 +1369,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
                return -ENOENT;
        set = ip_set_list[index];
 
-       skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       skb2 = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (skb2 == NULL)
                return -ENOMEM;
 
@@ -1377,7 +1391,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
        return 0;
 
 nla_put_failure:
-       nlmsg_cancel(skb2, nlh2);
+       genlmsg_cancel(skb2, nlh2);
 nlmsg_failure:
        kfree_skb(skb2);
        return -EMSGSIZE;
@@ -1399,7 +1413,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info)
        const struct nlmsghdr *nlh = info->nlhdr;
 
        struct sk_buff *skb2;
-       void *nlh2;
+       struct genlmsg_buf *nlh2;
        u8 family, min, max;
        const char *typename;
        int ret = 0;
@@ -1458,7 +1472,7 @@ ip_set_protocol(struct sk_buff *skb, struct genl_info *info)
        const struct nlmsghdr *nlh = info->nlhdr;
 
        struct sk_buff *skb2;
-       void *nlh2;
+       struct genlmsg_buf *nlh2;
        int ret = 0;
 
        if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
@@ -1633,9 +1647,9 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                        goto done;
                }
                req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
-               nfnl_lock();
+               genl_lock();
                req_get->set.index = find_set_id(req_get->set.name);
-               nfnl_unlock();
+               genl_unlock();
                goto copy;
        }
        case IP_SET_OP_GET_BYINDEX: {
@@ -1646,12 +1660,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                        ret = -EINVAL;
                        goto done;
                }
-               nfnl_lock();
+               genl_lock();
                strncpy(req_get->set.name,
                        ip_set_list[req_get->set.index]
                                ? ip_set_list[req_get->set.index]->name : "",
                        IPSET_MAXNAMELEN);
-               nfnl_unlock();
+               genl_unlock();
                goto copy;
        }
        default:
index c3643a0524293966a8c7ed05c43a31723d9910aa..e15f819049e5bebe687c3499b14355f51a8e0a90 100644 (file)
@@ -310,8 +310,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                                     !id_eq(map, i + 1, refid)) ||
                                    (before < 0 &&
                                     (i == 0 || !id_eq(map, i - 1, refid)))) {
-                                       ret = -IPSET_ERR_EXIST;
-                                       goto finish;
+                                       ret = -IPSET_ERR_EXIST;
+                                       goto finish;
                                }
                                e->timeout = ip_set_timeout_set(timeout);
                                ip_set_put_byindex(id);
index 9603ddc0d27e9f8d54040fd7624c0adabfcdbc51..d9e5ff8e902f8e4e2b722456101a2f71e2456e17 100644 (file)
@@ -302,9 +302,10 @@ matched by the kernel, it will automatically fill out the missing MAC address wi
 source MAC address from the packet. If the entry was specified with a timeout value,
 the timer starts off when the IP and MAC address pair is complete.
 .PP 
-Please note, the \fBset\fR match and \fBSET\fR target netfilter kernel modules
-\fBalways\fR use the source MAC address from the packet to match, add or delete
-entries from a \fBbitmap:ip,mac\fR type of set.
+The \fBbitmap:ip,mac\fR type of sets require two \fBsrc/dst\fR parameters of
+the \fBset\fR match and \fBSET\fR target netfilter kernel modules and the second
+one must be \fBsrc\fR to match, add or delete entries because the \fBset\fR match
+and \fBSET\fR target have access to the source MAC address only.
 .PP 
 Examples:
 .IP 
index f2a90880072738370145648c97f1c1ac360f86d4..93de81d2b97a382b7373e42b060da0c0563533bd 100644 (file)
@@ -115,6 +115,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return CHECK_FAIL(-ERANGE);     /* error */
        }
 
@@ -179,6 +180,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return CHECK_FAIL(-ENOENT);     /* error */
                }
        }
@@ -186,6 +189,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
            info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return CHECK_FAIL(-ERANGE);     /* error */
        }
 
@@ -246,6 +253,7 @@ set_match_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return CHECK_FAIL(-ERANGE);     /* error */
        }
 
@@ -278,7 +286,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par)
        if (info->del_set.index != IPSET_INVALID_ID)
                ip_set_del(info->del_set.index,
                           skb, par->family,
-                          info->add_set.dim,
+                          info->del_set.dim,
                           info->del_set.flags);
 
        return XT_CONTINUE;
@@ -309,13 +317,19 @@ set_target_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return CHECK_FAIL(-ENOENT);     /* error */
                }
        }
        if (info->add_set.dim > IPSET_DIM_MAX ||
-           info->del_set.flags > IPSET_DIM_MAX) {
+           info->del_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return CHECK_FAIL(-ERANGE);     /* error */
        }