diff options
-rw-r--r-- | include/libipset/args.h | 2 | ||||
-rw-r--r-- | include/libipset/data.h | 1 | ||||
-rw-r--r-- | include/libipset/linux_ip_set.h | 18 | ||||
-rw-r--r-- | include/libipset/linux_ip_set_bitmap.h | 1 | ||||
-rw-r--r-- | include/libipset/linux_ip_set_hash.h | 1 | ||||
-rw-r--r-- | include/libipset/linux_ip_set_list.h | 1 | ||||
-rw-r--r-- | kernel/include/linux/netfilter/ipset/ip_set.h | 2 | ||||
-rw-r--r-- | kernel/include/linux/netfilter/ipset/ip_set_compat.h.in | 2 | ||||
-rw-r--r-- | kernel/include/uapi/linux/netfilter/ipset/ip_set.h | 19 | ||||
-rw-r--r-- | kernel/net/netfilter/ipset/ip_set_core.c | 166 | ||||
-rw-r--r-- | lib/PROTOCOL | 17 | ||||
-rw-r--r-- | lib/args.c | 2 | ||||
-rw-r--r-- | lib/data.c | 7 | ||||
-rw-r--r-- | lib/session.c | 4 |
14 files changed, 209 insertions, 34 deletions
diff --git a/include/libipset/args.h b/include/libipset/args.h index dce4190..3a9929f 100644 --- a/include/libipset/args.h +++ b/include/libipset/args.h @@ -63,7 +63,7 @@ extern "C" { #endif extern const struct ipset_arg * ipset_keyword(enum ipset_keywords i); -extern const char * ipset_ignored_optname(int opt); +extern const char * ipset_ignored_optname(unsigned int opt); #ifdef __cplusplus } #endif diff --git a/include/libipset/data.h b/include/libipset/data.h index ca21890..744b010 100644 --- a/include/libipset/data.h +++ b/include/libipset/data.h @@ -74,6 +74,7 @@ enum ipset_opt { IPSET_OPT_LINENO, IPSET_OPT_REVISION, IPSET_OPT_REVISION_MIN, + IPSET_OPT_INDEX, IPSET_OPT_MAX, }; diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h index 2096611..68a2087 100644 --- a/include/libipset/linux_ip_set.h +++ b/include/libipset/linux_ip_set.h @@ -12,9 +12,9 @@ #include <linux/types.h> -/* The supported protocol versions */ -#define IPSET_PROTOCOL_MIN 6 +/* The protocol versions */ #define IPSET_PROTOCOL 7 +#define IPSET_PROTOCOL_MIN 6 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 @@ -38,17 +38,19 @@ enum ipset_cmd { IPSET_CMD_TEST, /* 11: Test an element in a set */ IPSET_CMD_HEADER, /* 12: Get set header data only */ IPSET_CMD_TYPE, /* 13: Get set type */ + IPSET_CMD_GET_BYNAME, /* 14: Get set index by name */ + IPSET_CMD_GET_BYINDEX, /* 15: Get set name by index */ IPSET_MSG_MAX, /* Netlink message commands */ /* Commands in userspace: */ - IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ - IPSET_CMD_HELP, /* 15: Get help */ - IPSET_CMD_VERSION, /* 16: Get program version */ - IPSET_CMD_QUIT, /* 17: Quit from interactive mode */ + IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 16: Enter restore mode */ + IPSET_CMD_HELP, /* 17: Get help */ + IPSET_CMD_VERSION, /* 18: Get program version */ + IPSET_CMD_QUIT, /* 19: Quit from interactive mode */ IPSET_CMD_MAX, - IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */ + IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 20: Commit buffered commands */ }; /* Attributes at command level */ @@ -66,6 +68,7 @@ enum { IPSET_ATTR_LINENO, /* 9: Restore lineno */ IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */ IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */ + IPSET_ATTR_INDEX, /* 11: Kernel index of set */ __IPSET_ATTR_CMD_MAX, }; #define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1) @@ -223,6 +226,7 @@ enum ipset_adt { /* Sets are identified by an index in kernel space. Tweak with ip_set_id_t * and IPSET_INVALID_ID if you want to increase the max number of sets. + * Also, IPSET_ATTR_INDEX must be changed. */ typedef __u16 ip_set_id_t; diff --git a/include/libipset/linux_ip_set_bitmap.h b/include/libipset/linux_ip_set_bitmap.h index c4b63d6..a3652c2 100644 --- a/include/libipset/linux_ip_set_bitmap.h +++ b/include/libipset/linux_ip_set_bitmap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __IP_SET_BITMAP_H #define __IP_SET_BITMAP_H diff --git a/include/libipset/linux_ip_set_hash.h b/include/libipset/linux_ip_set_hash.h index 73d40d7..3753952 100644 --- a/include/libipset/linux_ip_set_hash.h +++ b/include/libipset/linux_ip_set_hash.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __IP_SET_HASH_H #define __IP_SET_HASH_H diff --git a/include/libipset/linux_ip_set_list.h b/include/libipset/linux_ip_set_list.h index f8cb89e..650e308 100644 --- a/include/libipset/linux_ip_set_list.h +++ b/include/libipset/linux_ip_set_list.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __IP_SET_LIST_H #define __IP_SET_LIST_H diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h index 94f126c..f2b946f 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/linux/netfilter/ipset/ip_set.h @@ -304,11 +304,11 @@ ip_set_put_flags(struct sk_buff *skb, struct ip_set *set) /* Netlink CB args */ enum { IPSET_CB_NET = 0, /* net namespace */ + IPSET_CB_PROTO, /* ipset protocol */ IPSET_CB_DUMP, /* dump single set/all sets */ IPSET_CB_INDEX, /* set index */ IPSET_CB_PRIVATE, /* set private data */ IPSET_CB_ARG0, /* type specific */ - IPSET_CB_ARG1, }; /* register and unregister set references */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in index b93d662..1d536a3 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in +++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in @@ -134,11 +134,13 @@ do { \ __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) #endif +#if 0 #ifdef CHECK_KCONFIG #ifndef CONFIG_SPARSE_RCU_POINTER #error "CONFIG_SPARSE_RCU_POINTER must be enabled" #endif #endif +#endif #if defined(CONFIG_NETFILTER_NETLINK) || defined(CONFIG_NETFILTER_NETLINK_MODULE) #else diff --git a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h index 4a6776f..c83497f 100644 --- a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h @@ -12,8 +12,9 @@ #include <linux/types.h> -/* The protocol version */ -#define IPSET_PROTOCOL 6 +/* The protocol versions */ +#define IPSET_PROTOCOL 7 +#define IPSET_PROTOCOL_MIN 6 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 @@ -37,17 +38,19 @@ enum ipset_cmd { IPSET_CMD_TEST, /* 11: Test an element in a set */ IPSET_CMD_HEADER, /* 12: Get set header data only */ IPSET_CMD_TYPE, /* 13: Get set type */ + IPSET_CMD_GET_BYNAME, /* 14: Get set index by name */ + IPSET_CMD_GET_BYINDEX, /* 15: Get set name by index */ IPSET_MSG_MAX, /* Netlink message commands */ /* Commands in userspace: */ - IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ - IPSET_CMD_HELP, /* 15: Get help */ - IPSET_CMD_VERSION, /* 16: Get program version */ - IPSET_CMD_QUIT, /* 17: Quit from interactive mode */ + IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 16: Enter restore mode */ + IPSET_CMD_HELP, /* 17: Get help */ + IPSET_CMD_VERSION, /* 18: Get program version */ + IPSET_CMD_QUIT, /* 19: Quit from interactive mode */ IPSET_CMD_MAX, - IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */ + IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 20: Commit buffered commands */ }; /* Attributes at command level */ @@ -65,6 +68,7 @@ enum { IPSET_ATTR_LINENO, /* 9: Restore lineno */ IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */ IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */ + IPSET_ATTR_INDEX, /* 11: Kernel index of set */ __IPSET_ATTR_CMD_MAX, }; #define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1) @@ -222,6 +226,7 @@ enum ipset_adt { /* Sets are identified by an index in kernel space. Tweak with ip_set_id_t * and IPSET_INVALID_ID if you want to increase the max number of sets. + * Also, IPSET_ATTR_INDEX must be changed. */ typedef __u16 ip_set_id_t; diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c index 65628ae..e99dda9 100644 --- a/kernel/net/netfilter/ipset/ip_set_core.c +++ b/kernel/net/netfilter/ipset/ip_set_core.c @@ -782,11 +782,21 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put); * The commands are serialized by the nfnl mutex. */ +static inline u8 protocol(const struct nlattr * const tb[]) +{ + return nla_get_u8(tb[IPSET_ATTR_PROTOCOL]); +} + static inline bool protocol_failed(const struct nlattr * const tb[]) { - return !tb[IPSET_ATTR_PROTOCOL] || - nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL; + return !tb[IPSET_ATTR_PROTOCOL] || protocol(tb) != IPSET_PROTOCOL; +} + +static inline bool +protocol_min_failed(const struct nlattr * const tb[]) +{ + return !tb[IPSET_ATTR_PROTOCOL] || protocol(tb) < IPSET_PROTOCOL_MIN; } static inline u32 @@ -903,7 +913,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, u32 flags = flag_exist(nlh); int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !attr[IPSET_ATTR_TYPENAME] || !attr[IPSET_ATTR_REVISION] || @@ -1042,7 +1052,7 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, ip_set_id_t i; int ret = 0; - if (unlikely(protocol_failed(attr))) + if (unlikely(protocol_min_failed(attr))) return -IPSET_ERR_PROTOCOL; /* Must wait for flush to be really finished in list:set */ @@ -1121,7 +1131,7 @@ IPSET_CBFN(ip_set_flush, struct net *net, struct sock *ctnl, struct ip_set *s; ip_set_id_t i; - if (unlikely(protocol_failed(attr))) + if (unlikely(protocol_min_failed(attr))) return -IPSET_ERR_PROTOCOL; if (!attr[IPSET_ATTR_SETNAME]) { @@ -1164,7 +1174,7 @@ IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl, ip_set_id_t i; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !attr[IPSET_ATTR_SETNAME2])) return -IPSET_ERR_PROTOCOL; @@ -1214,7 +1224,7 @@ IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl, ip_set_id_t from_id, to_id; char from_name[IPSET_MAXNAMELEN]; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !attr[IPSET_ATTR_SETNAME2])) return -IPSET_ERR_PROTOCOL; @@ -1309,6 +1319,7 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst) NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, attr, nlh->nlmsg_len - min_len, ip_set_setname_policy, NULL); + cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]); if (cda[IPSET_ATTR_SETNAME]) { struct ip_set *set; @@ -1410,7 +1421,8 @@ dump_last: ret = -EMSGSIZE; goto release_refcount; } - if (nla_put_u8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + if (nla_put_u8(skb, IPSET_ATTR_PROTOCOL, + cb->args[IPSET_CB_PROTO]) || nla_put_string(skb, IPSET_ATTR_SETNAME, set->name)) goto nla_put_failure; if (dump_flags & IPSET_FLAG_LIST_SETNAME) @@ -1425,6 +1437,9 @@ dump_last: nla_put_u8(skb, IPSET_ATTR_REVISION, set->revision)) goto nla_put_failure; + if (cb->args[IPSET_CB_PROTO] > IPSET_PROTOCOL_MIN && + nla_put_net16(skb, IPSET_ATTR_INDEX, htons(index))) + goto nla_put_failure; ret = set->variant->head(set, skb); if (ret < 0) goto release_refcount; @@ -1485,7 +1500,7 @@ IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl, const struct nlattr * const attr[], struct netlink_ext_ack *extack) { - if (unlikely(protocol_failed(attr))) + if (unlikely(protocol_min_failed(attr))) return -IPSET_ERR_PROTOCOL; #if HAVE_NETLINK_DUMP_START_ARGS == 5 @@ -1590,7 +1605,7 @@ IPSET_CBFN(ip_set_uadd, struct net *net, struct sock *ctnl, bool use_lineno; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !((attr[IPSET_ATTR_DATA] != NULL) ^ (attr[IPSET_ATTR_ADT] != NULL)) || @@ -1646,7 +1661,7 @@ IPSET_CBFN(ip_set_udel, struct net *net, struct sock *ctnl, bool use_lineno; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !((attr[IPSET_ATTR_DATA] != NULL) ^ (attr[IPSET_ATTR_ADT] != NULL)) || @@ -1700,7 +1715,7 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl, struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME] || !attr[IPSET_ATTR_DATA] || !flag_nested(attr[IPSET_ATTR_DATA]))) @@ -1738,7 +1753,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, struct nlmsghdr *nlh2; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_SETNAME])) return -IPSET_ERR_PROTOCOL; @@ -1754,7 +1769,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, IPSET_CMD_HEADER); if (!nlh2) goto nlmsg_failure; - if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, protocol(attr)) || nla_put_string(skb2, IPSET_ATTR_SETNAME, set->name) || nla_put_string(skb2, IPSET_ATTR_TYPENAME, set->type->name) || nla_put_u8(skb2, IPSET_ATTR_FAMILY, set->family) || @@ -1796,7 +1811,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, const char *typename; int ret = 0; - if (unlikely(protocol_failed(attr) || + if (unlikely(protocol_min_failed(attr) || !attr[IPSET_ATTR_TYPENAME] || !attr[IPSET_ATTR_FAMILY])) return -IPSET_ERR_PROTOCOL; @@ -1815,7 +1830,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, IPSET_CMD_TYPE); if (!nlh2) goto nlmsg_failure; - if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) || + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, protocol(attr)) || nla_put_string(skb2, IPSET_ATTR_TYPENAME, typename) || nla_put_u8(skb2, IPSET_ATTR_FAMILY, family) || nla_put_u8(skb2, IPSET_ATTR_REVISION, max) || @@ -1867,6 +1882,113 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, goto nlmsg_failure; if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL)) goto nla_put_failure; + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL_MIN, IPSET_PROTOCOL_MIN)) + goto nla_put_failure; + nlmsg_end(skb2, nlh2); + + ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); + if (ret < 0) + return ret; + + return 0; + +nla_put_failure: + nlmsg_cancel(skb2, nlh2); +nlmsg_failure: + kfree_skb(skb2); + return -EMSGSIZE; +} + +/* Get set by name or index, from userspace */ + +static int +IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, + struct sk_buff *skb, const struct nlmsghdr *nlh, + const struct nlattr * const attr[], + struct netlink_ext_ack *extack) +{ + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct sk_buff *skb2; + struct nlmsghdr *nlh2; + ip_set_id_t id = IPSET_INVALID_ID; + const struct ip_set *set; + int ret = 0; + + if (unlikely(protocol_failed(attr) || + !attr[IPSET_ATTR_SETNAME])) + return -IPSET_ERR_PROTOCOL; + + set = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]), &id); + if (id == IPSET_INVALID_ID) + return -ENOENT; + + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb2) + return -ENOMEM; + + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + IPSET_CMD_GET_BYNAME); + if (!nlh2) + goto nlmsg_failure; + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, protocol(attr)) || + nla_put_u8(skb2, IPSET_ATTR_FAMILY, set->family) || + nla_put_net16(skb2, IPSET_ATTR_INDEX, htons(id))) + goto nla_put_failure; + nlmsg_end(skb2, nlh2); + + ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); + if (ret < 0) + return ret; + + return 0; + +nla_put_failure: + nlmsg_cancel(skb2, nlh2); +nlmsg_failure: + kfree_skb(skb2); + return -EMSGSIZE; +} + +static const struct nla_policy ip_set_index_policy[IPSET_ATTR_CMD_MAX + 1] = { + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, + [IPSET_ATTR_INDEX] = { .type = NLA_U16 }, +}; + +static int +IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, + struct sk_buff *skb, const struct nlmsghdr *nlh, + const struct nlattr * const attr[], + struct netlink_ext_ack *extack) +{ + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); + struct sk_buff *skb2; + struct nlmsghdr *nlh2; + ip_set_id_t id = IPSET_INVALID_ID; + const struct ip_set *set; + int ret = 0; + + if (unlikely(protocol_failed(attr) || + !attr[IPSET_ATTR_INDEX])) + return -IPSET_ERR_PROTOCOL; + + id = ip_set_get_h16(attr[IPSET_ATTR_INDEX]); + if (id >= inst->ip_set_max) + return -ENOENT; + set = ip_set(inst, id); + if (set == NULL) + return -ENOENT; + + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb2) + return -ENOMEM; + + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, + IPSET_CMD_GET_BYINDEX); + if (!nlh2) + goto nlmsg_failure; + if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, protocol(attr)) || + nla_put_string(skb, IPSET_ATTR_SETNAME, set->name)) + goto nla_put_failure; nlmsg_end(skb2, nlh2); ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); @@ -1952,6 +2074,16 @@ static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { .attr_count = IPSET_ATTR_CMD_MAX, .policy = ip_set_protocol_policy, }, + [IPSET_CMD_GET_BYNAME] = { + .call = ip_set_byname, + .attr_count = IPSET_ATTR_CMD_MAX, + .policy = ip_set_setname_policy, + }, + [IPSET_CMD_GET_BYINDEX] = { + .call = ip_set_byindex, + .attr_count = IPSET_ATTR_CMD_MAX, + .policy = ip_set_index_policy, + }, }; static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = { @@ -1997,7 +2129,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) goto done; } - if (req_version->version != IPSET_PROTOCOL) { + if (req_version->version < IPSET_PROTOCOL_MIN) { ret = -EPROTO; goto done; } diff --git a/lib/PROTOCOL b/lib/PROTOCOL index aa8fc64..97a6b7c 100644 --- a/lib/PROTOCOL +++ b/lib/PROTOCOL @@ -1,3 +1,5 @@ +PROTOCOL 6: + req: msg: IPSET_CMD_PROTOCOL attr: IPSET_ATTR_PROTOCOL @@ -88,3 +90,18 @@ resp: attr: IPSET_ATTR_TYPENAME IPSET_ATTR_FAMILY IPSET_ATTR_REVISION (version max) IPSET_ATTR_REVISION_MIN (version min, optional) + +PROTOCOL 7: PROTOCOL 6 + + +req: msg: IPSET_CMD_GET_BYNAME + attr: IPSET_ATTR_PROTOCOL + IPSET_ATTR_SETNAME + +resp: attr: IPSET_ATTR_INDEX + IPSET_ATTR_FAMILY + +req: msg: IPSET_CMD_GET_BYINDEX + attr: IPSET_ATTR_PROTOCOL + IPSET_ATTR_INDEX + +resp: attr: IPSET_ATTR_SETNAME @@ -286,7 +286,7 @@ ipset_keyword(enum ipset_keywords i) } const char * -ipset_ignored_optname(int opt) +ipset_ignored_optname(unsigned int opt) { enum ipset_keywords i; @@ -44,6 +44,7 @@ struct ipset_data { uint32_t mark; uint16_t port; uint16_t port_to; + uint16_t index; union { /* RENAME/SWAP */ char setname2[IPSET_MAXNAMELEN]; @@ -281,6 +282,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value) case IPSET_OPT_TIMEOUT: data->timeout = *(const uint32_t *) value; break; + case IPSET_OPT_INDEX: + data->index = *(const uint16_t *) value; + break; /* Create-specific options */ case IPSET_OPT_GC: data->create.gc = *(const uint32_t *) value; @@ -485,6 +489,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt) return &data->port_to; case IPSET_OPT_TIMEOUT: return &data->timeout; + case IPSET_OPT_INDEX: + return &data->index; /* Create-specific options */ case IPSET_OPT_GC: return &data->create.gc; @@ -588,6 +594,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_PORT: case IPSET_OPT_PORT_TO: case IPSET_OPT_SKBQUEUE: + case IPSET_OPT_INDEX: return sizeof(uint16_t); case IPSET_SETNAME: case IPSET_OPT_NAME: diff --git a/lib/session.c b/lib/session.c index c19191a..768cc05 100644 --- a/lib/session.c +++ b/lib/session.c @@ -365,6 +365,10 @@ static const struct ipset_attr_policy cmd_attrs[] = { .type = MNL_TYPE_U32, .opt = IPSET_OPT_LINENO, }, + [IPSET_ATTR_INDEX] = { + .type = MNL_TYPE_U16, + .opt = IPSET_OPT_INDEX, + }, }; static const struct ipset_attr_policy create_attrs[] = { |