From: Adam Gołębiowski Date: Wed, 28 Jul 2021 21:47:36 +0000 (+0200) Subject: - updated to 7.14 X-Git-Tag: auto/th/ipset-7.14-1 X-Git-Url: http://git.pld-linux.org/gitweb.cgi?a=commitdiff_plain;h=819319f418f8e80d5f762bbd8b79aa173e189f79;p=packages%2Fipset.git - updated to 7.14 --- diff --git a/git.patch b/git.patch deleted file mode 100644 index ddd3326..0000000 --- a/git.patch +++ /dev/null @@ -1,1866 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index bd6116c..eb6c334 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -7,6 +7,7 @@ AC_CONFIG_HEADER([config.h]) - AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax]) - m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -+AC_PROG_LN_S - AC_ENABLE_STATIC - LT_INIT([dlopen]) - LT_CONFIG_LTDL_DIR([libltdl]) -@@ -786,6 +787,56 @@ else - AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, undef) - fi - -+AC_MSG_CHECKING([kernel source for nfnl_msg_put() in nfnetlink.h]) -+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ -+ $GREP -q 'nfnl_msg_put' $ksourcedir/include/linux/netfilter/nfnetlink.h; then -+ AC_MSG_RESULT(yes) -+ AC_SUBST(HAVE_NFNL_MSG_PUT, define) -+else -+ AC_MSG_RESULT(no) -+ AC_SUBST(HAVE_NFNL_MSG_PUT, undef) -+fi -+ -+AC_MSG_CHECKING([kernel source for struct nfnl_info in nfnl_callback function]) -+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ -+ $AWK '/^struct nfnl_callback /,/^}/' $ksourcedir/include/linux/netfilter/nfnetlink.h | $GREP -q 'struct nfnl_info'; then -+ AC_MSG_RESULT(yes) -+ AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, define) -+else -+ AC_MSG_RESULT(no) -+ AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, undef) -+fi -+ -+AC_MSG_CHECKING([kernel source for enum nfnl_callback_type]) -+if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \ -+ $GREP -q 'enum nfnl_callback_type ' $ksourcedir/include/linux/netfilter/nfnetlink.h; then -+ AC_MSG_RESULT(yes) -+ AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, define) -+else -+ AC_MSG_RESULT(no) -+ AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, undef) -+fi -+ -+AC_MSG_CHECKING([kernel source of handling -EAGAIN in nfnetlink_unicast]) -+if test -f $ksourcedir/net/netfilter/nfnetlink.c && \ -+ $AWK '/nfnetlink_unicast\(/,/^}/' $ksourcedir/net/netfilter/nfnetlink.c | $GREP -q 'err == -EAGAIN'; then -+ AC_MSG_RESULT(yes) -+ AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, define) -+else -+ AC_MSG_RESULT(no) -+ AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, undef) -+fi -+ -+AC_MSG_CHECKING([kernel source for nlmsg_unicast which returns zero in case of success]) -+if test -f $ksourcedir/include/net/netlink.h && \ -+ $AWK '/static inline int nlmsg_unicast\(/,/^}/' $ksourcedir/include/net/netlink.h | $GREP -q 'err > 0'; then -+ AC_MSG_RESULT(yes) -+ AC_SUBST(HAVE_NLMSG_UNICAST, define) -+else -+ AC_MSG_RESULT(no) -+ AC_SUBST(HAVE_NLMSG_UNICAST, undef) -+fi -+ - AC_MSG_CHECKING([kernel source for kvzalloc() in mm.h]) - if test -f $ksourcedir/include/linux/mm.h && \ - $GREP -q 'static inline void \*kvzalloc(' $ksourcedir/include/linux/mm.h; then -diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am -index c7f7b2b..2c04029 100644 ---- a/include/libipset/Makefile.am -+++ b/include/libipset/Makefile.am -@@ -17,6 +17,7 @@ pkginclude_HEADERS = \ - transport.h \ - types.h \ - ipset.h \ -- utils.h -+ utils.h \ -+ xlate.h - - EXTRA_DIST = debug.h icmp.h icmpv6.h -diff --git a/include/libipset/xlate.h b/include/libipset/xlate.h -new file mode 100644 -index 0000000..6569768 ---- /dev/null -+++ b/include/libipset/xlate.h -@@ -0,0 +1,6 @@ -+#ifndef LIBIPSET_XLATE_H -+#define LIBIPSET_XLATE_H -+ -+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]); -+ -+#endif -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 96a4cf4..4d2c446 100644 ---- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in -+++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in -@@ -62,6 +62,11 @@ - #@HAVE_KVZALLOC@ HAVE_KVZALLOC - #@HAVE_GFP_KERNEL_ACCOUNT@ HAVE_GFP_KERNEL_ACCOUNT - #@HAVE_NLA_STRSCPY@ HAVE_NLA_STRSCPY -+#@HAVE_NFNL_MSG_PUT@ HAVE_NFNL_MSG_PUT -+#@HAVE_NFNL_INFO_IN_NFNL_CALLBACK@ HAVE_NFNL_INFO_IN_NFNL_CALLBACK -+#@HAVE_NFNL_CALLBACK_TYPE@ HAVE_NFNL_CALLBACK_TYPE -+#@HAVE_EAGAIN_IN_NFNETLINK_UNICAST@ HAVE_EAGAIN_IN_NFNETLINK_UNICAST -+#@HAVE_NLMSG_UNICAST@ HAVE_NLMSG_UNICAST - - #ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H - #include -@@ -348,18 +353,44 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, - } - #endif - --#ifdef HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS --#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda, e) --#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda, e) --#define IPSET_SOCK_NET(net, ctnl) net -+#ifdef HAVE_NFNL_INFO_IN_NFNL_CALLBACK -+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(skb, i, cda) -+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, i) -+#define IPSET_SOCK_NET(n, ctnl, i) (i)->net -+#define INFO_NLH(i, n) (i)->nlh -+#define INFO_NET(i, n) (i)->net -+#define INFO_SK(i, n) (i)->sk -+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) -+#elif defined(HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS) -+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda, e) -+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, e) -+#define IPSET_SOCK_NET(net, ctnl, i) net -+#define INFO_NLH(i, n) n -+#define INFO_NET(i, n) n -+#define INFO_SK(i, n) n -+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) - #elif defined(HAVE_NET_IN_NFNL_CALLBACK_FN) --#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda) --#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda) --#define IPSET_SOCK_NET(net, ctnl) net -+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda) -+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda) -+#define IPSET_SOCK_NET(net, ctnl, i) net -+#define INFO_NLH(i, n) n -+#define INFO_NET(i, n) n -+#define INFO_SK(i, n) n -+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) - #else --#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(nl, skb, nlh, cda) --#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(nl, skb, ad, nlh, cda) --#define IPSET_SOCK_NET(net, ctnl) sock_net(ctnl) -+#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(nl, skb, nlh, cda) -+#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(nl, skb, ad, nlh, cda) -+#define IPSET_SOCK_NET(net, ctnl, i) sock_net(ctnl) -+#define INFO_NLH(i, n) n -+#define INFO_NET(i, n) n -+#define INFO_SK(i, n) n -+#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(ctnl, skb, set, tb, adt, flags, l) -+#endif -+ -+#ifdef HAVE_NFNL_CALLBACK_TYPE -+#define SET_NFNL_CALLBACK_TYPE(t) .type = t, -+#else -+#define SET_NFNL_CALLBACK_TYPE(t) - #endif - - #ifndef HAVE_TC_SKB_PROTOCOL -@@ -406,6 +437,36 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) - } - #endif - -+#ifndef HAVE_NFNL_MSG_PUT -+#include -+static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version, -+ __be16 res_id) -+{ -+ struct nfgenmsg *nfmsg; -+ -+ nfmsg = nlmsg_data(nlh); -+ nfmsg->nfgen_family = family; -+ nfmsg->version = version; -+ nfmsg->res_id = res_id; -+} -+ -+static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid, -+ u32 seq, int type, int flags, -+ u8 family, u8 version, -+ __be16 res_id) -+{ -+ struct nlmsghdr *nlh; -+ -+ nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags); -+ if (!nlh) -+ return NULL; -+ -+ nfnl_fill_hdr(nlh, family, version, res_id); -+ -+ return nlh; -+} -+#endif -+ - #ifdef HAVE_NETLINK_EXTENDED_ACK - #define NETLINK_ACK(in_skb, nlh, err, extack) netlink_ack(in_skb, nlh, err, extack) - #else -@@ -459,6 +520,23 @@ static inline ssize_t strscpy(char * dest, const char * src, size_t count) - #define nla_strscpy nla_strlcpy - #endif - -+#if !defined(HAVE_EAGAIN_IN_NFNETLINK_UNICAST) || !defined(HAVE_NLMSG_UNICAST) -+#define NFNETLINK_UNICAST(cntl, skb, net, portid) ipset_nfnetlink_unicast(cntl, skb, portid) -+static inline int ipset_nfnetlink_unicast(struct sock *ctnl, struct sk_buff *skb, u32 portid) -+{ -+ int err = netlink_unicast(ctnl, skb, portid, MSG_DONTWAIT); -+ -+ if (err > 0) -+ err = 0; -+ if (err == -EAGAIN) -+ err = -ENOBUFS; -+ -+ return err; -+} -+#else -+#define NFNETLINK_UNICAST(cntl, skb, net, portid) nfnetlink_unicast(skb, net, portid) -+#endif -+ - #ifndef smp_mb__before_atomic - #define smp_mb__before_atomic() smp_mb() - #define smp_mb__after_atomic() smp_mb() -diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c -index 63a7955..0fdafb7 100644 ---- a/kernel/net/netfilter/ipset/ip_set_core.c -+++ b/kernel/net/netfilter/ipset/ip_set_core.c -@@ -964,20 +964,9 @@ static struct nlmsghdr * - start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags, - enum ipset_cmd cmd) - { -- struct nlmsghdr *nlh; -- struct nfgenmsg *nfmsg; -- -- nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), -- sizeof(*nfmsg), flags); -- if (!nlh) -- return NULL; -- -- nfmsg = nlmsg_data(nlh); -- nfmsg->nfgen_family = NFPROTO_IPV4; -- nfmsg->version = NFNETLINK_V0; -- nfmsg->res_id = 0; -- -- return nlh; -+ return nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags, -+ NFPROTO_IPV4, NFNETLINK_V0, 0); - } - - /* Create a set */ -@@ -1047,7 +1036,8 @@ static int - IPSET_CBFN(ip_set_none, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { - return -EOPNOTSUPP; - } -@@ -1056,16 +1046,17 @@ static int - IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, - struct sk_buff *skb, const struct nlmsghdr *nlh, - const struct nlattr * const attr[], -- struct netlink_ext_ack *extack) -+ struct netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct net *net = IPSET_SOCK_NET(n, ctnl); -+ struct net *net = IPSET_SOCK_NET(n, ctnl, info); - struct ip_set_net *inst = ip_set_pernet(net); - struct ip_set *set, *clash = NULL; - ip_set_id_t index = IPSET_INVALID_ID; - struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {}; - const char *name, *typename; - u8 family, revision; -- u32 flags = flag_exist(nlh); -+ u32 flags = flag_exist(INFO_NLH(info, nlh)); - int ret = 0; - - if (unlikely(protocol_min_failed(attr) || -@@ -1116,7 +1107,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl, - /* Set create flags depending on the type revision */ - set->flags |= set->type->create_flags[revision]; - -- ret = set->type->create(net, set, tb, flags); -+ ret = set->type->create(INFO_NET(info, net), set, tb, flags); - if (ret != 0) - goto put_out; - -@@ -1202,9 +1193,10 @@ static int - IPSET_CBFN(ip_set_destroy, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *s; - ip_set_id_t i; - int ret = 0; -@@ -1246,7 +1238,7 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl, - /* Modified by ip_set_destroy() only, which is serialized */ - inst->is_destroyed = false; - } else { -- u32 flags = flag_exist(nlh); -+ u32 flags = flag_exist(INFO_NLH(info, nlh)); - s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]), - &i); - if (!s) { -@@ -1284,9 +1276,10 @@ static int - IPSET_CBFN(ip_set_flush, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *s; - ip_set_id_t i; - -@@ -1325,9 +1318,10 @@ static int - IPSET_CBFN(ip_set_rename, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *set, *s; - const char *name2; - ip_set_id_t i; -@@ -1376,9 +1370,10 @@ static int - IPSET_CBFN(ip_set_swap, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *from, *to; - ip_set_id_t from_id, to_id; - char from_name[IPSET_MAXNAMELEN]; -@@ -1706,7 +1701,8 @@ static int - IPSET_CBFN(ip_set_dump, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { - if (unlikely(protocol_min_failed(attr))) - return -IPSET_ERR_PROTOCOL; -@@ -1728,7 +1724,7 @@ IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl, - .dump = ip_set_dump_do, - .done = ip_set_dump_done, - }; -- return netlink_dump_start(ctnl, skb, nlh, &c); -+ return netlink_dump_start(INFO_SK(info, ctnl), skb, INFO_NLH(info, nlh), &c); - } - #endif - } -@@ -1745,8 +1741,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = { - }; - - static int --call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, -- struct nlattr *tb[], enum ipset_adt adt, -+CALL_AD(struct net *net, struct sock *ctnl, struct sk_buff *skb, -+ struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, - u32 flags, bool use_lineno) - { - int ret; -@@ -1798,8 +1794,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, - - *errline = lineno; - -- netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), -- MSG_DONTWAIT); -+ NFNETLINK_UNICAST(ctnl, skb2, net, NETLINK_PORTID(skb)); - /* Signal netlink not to send its ACK/errmsg. */ - return -EINTR; - } -@@ -1807,19 +1802,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, - return ret; - } - --static int --IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, -- struct sk_buff *skb, -- enum ipset_adt adt, -- 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)); -+static int IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, -+ struct sk_buff *skb, -+ enum ipset_adt adt, -+ const struct nlmsghdr *nlh, -+ const struct nlattr * const attr[], -+ struct netlink_ext_ack *extack, const struct nfnl_info *info) -+{ -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *set; - struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; - const struct nlattr *nla; -- u32 flags = flag_exist(nlh); -+ u32 flags = flag_exist(INFO_NLH(info, nlh)); - bool use_lineno; - int ret = 0; - -@@ -1844,7 +1838,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, - attr[IPSET_ATTR_DATA], - set->type->adt_policy, NULL)) - return -IPSET_ERR_PROTOCOL; -- ret = call_ad(ctnl, skb, set, tb, adt, flags, -+ ret = CALL_AD(net, ctnl, skb, set, tb, adt, flags, - use_lineno); - } else { - int nla_rem; -@@ -1855,7 +1849,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl, - NLA_PARSE_NESTED(tb, IPSET_ATTR_ADT_MAX, nla, - set->type->adt_policy, NULL)) - return -IPSET_ERR_PROTOCOL; -- ret = call_ad(ctnl, skb, set, tb, adt, -+ ret = CALL_AD(net, ctnl, skb, set, tb, adt, - flags, use_lineno); - if (ret < 0) - return ret; -@@ -1868,20 +1862,22 @@ static int - IPSET_CBFN(ip_set_uadd, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb, -- IPSET_ADD, nlh, attr, extack); -+ return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb, -+ IPSET_ADD, INFO_NLH(info, nlh), attr, extack, info); - } - - static int - IPSET_CBFN(ip_set_udel, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb, -- IPSET_DEL, nlh, attr, extack); -+ return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb, -+ IPSET_DEL, INFO_NLH(info, nlh), attr, extack, info); - } - - static int -@@ -1889,9 +1885,10 @@ IPSET_CBFN(ip_set_utest, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - struct ip_set *set; - struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; - int ret = 0; -@@ -1927,13 +1924,13 @@ static int - IPSET_CBFN(ip_set_header, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - const struct ip_set *set; - struct sk_buff *skb2; - struct nlmsghdr *nlh2; -- int ret = 0; - - if (unlikely(protocol_min_failed(attr) || - !attr[IPSET_ATTR_SETNAME])) -@@ -1947,7 +1944,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, - if (!skb2) - return -ENOMEM; - -- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, -+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, - IPSET_CMD_HEADER); - if (!nlh2) - goto nlmsg_failure; -@@ -1959,11 +1956,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl, - 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; -+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); - - nla_put_failure: - nlmsg_cancel(skb2, nlh2); -@@ -1985,7 +1978,8 @@ static int - IPSET_CBFN(ip_set_type, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { - struct sk_buff *skb2; - struct nlmsghdr *nlh2; -@@ -2008,7 +2002,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, - if (!skb2) - return -ENOMEM; - -- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, -+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, - IPSET_CMD_TYPE); - if (!nlh2) - goto nlmsg_failure; -@@ -2021,11 +2015,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl, - nlmsg_end(skb2, nlh2); - - pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len); -- ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT); -- if (ret < 0) -- return ret; -- -- return 0; -+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); - - nla_put_failure: - nlmsg_cancel(skb2, nlh2); -@@ -2045,11 +2035,11 @@ static int - IPSET_CBFN(ip_set_protocol, 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { - struct sk_buff *skb2; - struct nlmsghdr *nlh2; -- int ret = 0; - - if (unlikely(!attr[IPSET_ATTR_PROTOCOL])) - return -IPSET_ERR_PROTOCOL; -@@ -2058,7 +2048,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, - if (!skb2) - return -ENOMEM; - -- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, -+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, - IPSET_CMD_PROTOCOL); - if (!nlh2) - goto nlmsg_failure; -@@ -2068,11 +2058,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl, - 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; -+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); - - nla_put_failure: - nlmsg_cancel(skb2, nlh2); -@@ -2087,14 +2073,14 @@ 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - 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])) -@@ -2108,7 +2094,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, - if (!skb2) - return -ENOMEM; - -- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, -+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, - IPSET_CMD_GET_BYNAME); - if (!nlh2) - goto nlmsg_failure; -@@ -2118,11 +2104,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl, - 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; -+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); - - nla_put_failure: - nlmsg_cancel(skb2, nlh2); -@@ -2140,14 +2122,14 @@ 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 netlink_ext_ack *extack, -+ const struct nfnl_info *info) - { -- struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl)); -+ struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info)); - 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])) -@@ -2164,7 +2146,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, - if (!skb2) - return -ENOMEM; - -- nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0, -+ nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0, - IPSET_CMD_GET_BYINDEX); - if (!nlh2) - goto nlmsg_failure; -@@ -2173,11 +2155,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl, - 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; -+ return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb)); - - nla_put_failure: - nlmsg_cancel(skb2, nlh2); -@@ -2189,80 +2167,96 @@ nlmsg_failure: - static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { - [IPSET_CMD_NONE] = { - .call = ip_set_none, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - }, - [IPSET_CMD_CREATE] = { - .call = ip_set_create, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_create_policy, - }, - [IPSET_CMD_DESTROY] = { - .call = ip_set_destroy, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname_policy, - }, - [IPSET_CMD_FLUSH] = { - .call = ip_set_flush, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname_policy, - }, - [IPSET_CMD_RENAME] = { - .call = ip_set_rename, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname2_policy, - }, - [IPSET_CMD_SWAP] = { - .call = ip_set_swap, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname2_policy, - }, - [IPSET_CMD_LIST] = { - .call = ip_set_dump, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_dump_policy, - }, - [IPSET_CMD_SAVE] = { - .call = ip_set_dump, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname_policy, - }, - [IPSET_CMD_ADD] = { - .call = ip_set_uadd, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_adt_policy, - }, - [IPSET_CMD_DEL] = { - .call = ip_set_udel, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_adt_policy, - }, - [IPSET_CMD_TEST] = { - .call = ip_set_utest, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_adt_policy, - }, - [IPSET_CMD_HEADER] = { - .call = ip_set_header, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname_policy, - }, - [IPSET_CMD_TYPE] = { - .call = ip_set_type, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_type_policy, - }, - [IPSET_CMD_PROTOCOL] = { - .call = ip_set_protocol, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_protocol_policy, - }, - [IPSET_CMD_GET_BYNAME] = { - .call = ip_set_byname, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_setname_policy, - }, - [IPSET_CMD_GET_BYINDEX] = { - .call = ip_set_byindex, -+ SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX) - .attr_count = IPSET_ATTR_CMD_MAX, - .policy = ip_set_index_policy, - }, -diff --git a/lib/ipset.c b/lib/ipset.c -index 6729919..73e67db 100644 ---- a/lib/ipset.c -+++ b/lib/ipset.c -@@ -13,6 +13,7 @@ - #include /* printf */ - #include /* exit */ - #include /* str* */ -+#include /* PRIu64 */ - - #include - -@@ -28,6 +29,7 @@ - #include /* STREQ */ - #include /* prototypes */ - #include /* compiler attributes */ -+#include /* lists */ - - static char program_name[] = PACKAGE; - static char program_version[] = PACKAGE_VERSION; -@@ -50,6 +52,17 @@ struct ipset { - char *newargv[MAX_ARGS]; - int newargc; - const char *filename; /* Input/output filename */ -+ bool xlate; -+ struct list_head xlate_sets; -+}; -+ -+struct ipset_xlate_set { -+ struct list_head list; -+ char name[IPSET_MAXNAMELEN]; -+ uint8_t netmask; -+ uint8_t family; -+ bool interval; -+ const struct ipset_type *type; - }; - - /* Commands and environment options */ -@@ -923,20 +936,33 @@ static const char *cmd_prefix[] = { - [IPSET_TEST] = "test SETNAME", - }; - --/* Workhorses */ -+static const struct ipset_xlate_set * -+ipset_xlate_set_get(struct ipset *ipset, const char *name) -+{ -+ const struct ipset_xlate_set *set; - --/** -- * ipset_parse_argv - parse and argv array and execute the command -- * @ipset: ipset structure -- * @argc: length of the array -- * @argv: array of strings -- * -- * Parse an array of strings and execute the ipset command. -- * -- * Returns 0 on success or a negative error code. -- */ --int --ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) -+ list_for_each_entry(set, &ipset->xlate_sets, list) { -+ if (!strcmp(set->name, name)) -+ return set; -+ } -+ -+ return NULL; -+} -+ -+static const struct ipset_type *ipset_xlate_type_get(struct ipset *ipset, -+ const char *name) -+{ -+ const struct ipset_xlate_set *set; -+ -+ set = ipset_xlate_set_get(ipset, name); -+ if (!set) -+ return NULL; -+ -+ return set->type; -+} -+ -+static int -+ipset_parser(struct ipset *ipset, int oargc, char *oargv[]) - { - int ret = 0; - enum ipset_cmd cmd = IPSET_CMD_NONE; -@@ -1243,7 +1269,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) - return ipset->custom_error(ipset, - p, IPSET_PARAMETER_PROBLEM, - "Unknown argument %s", argv[1]); -- return restore(ipset); -+ return IPSET_CMD_RESTORE; - case IPSET_CMD_ADD: - case IPSET_CMD_DEL: - case IPSET_CMD_TEST: -@@ -1253,7 +1279,12 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) - if (ret < 0) - return ipset->standard_error(ipset, p); - -- type = ipset_type_get(session, cmd); -+ if (!ipset->xlate) { -+ type = ipset_type_get(session, cmd); -+ } else { -+ type = ipset_xlate_type_get(ipset, arg0); -+ ipset_session_data_set(session, IPSET_OPT_TYPE, type); -+ } - if (type == NULL) - return ipset->standard_error(ipset, p); - -@@ -1280,6 +1311,37 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) - if (argc > 1) - return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM, - "Unknown argument %s", argv[1]); -+ -+ return cmd; -+} -+ -+/* Workhorses */ -+ -+/** -+ * ipset_parse_argv - parse and argv array and execute the command -+ * @ipset: ipset structure -+ * @argc: length of the array -+ * @argv: array of strings -+ * -+ * Parse an array of strings and execute the ipset command. -+ * -+ * Returns 0 on success or a negative error code. -+ */ -+int -+ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[]) -+{ -+ struct ipset_session *session = ipset->session; -+ void *p = ipset_session_printf_private(session); -+ enum ipset_cmd cmd; -+ int ret; -+ -+ cmd = ipset_parser(ipset, oargc, oargv); -+ if (cmd < 0) -+ return cmd; -+ -+ if (cmd == IPSET_CMD_RESTORE) -+ return restore(ipset); -+ - ret = ipset_cmd(session, cmd, ipset->restore_line); - D("ret %d", ret); - /* In the case of warning, the return code is success */ -@@ -1455,6 +1517,9 @@ ipset_init(void) - return NULL; - } - ipset_custom_printf(ipset, NULL, NULL, NULL, NULL); -+ -+ INIT_LIST_HEAD(&ipset->xlate_sets); -+ - return ipset; - } - -@@ -1469,6 +1534,8 @@ ipset_init(void) - int - ipset_fini(struct ipset *ipset) - { -+ struct ipset_xlate_set *xlate_set, *next; -+ - assert(ipset); - - if (ipset->session) -@@ -1477,6 +1544,497 @@ ipset_fini(struct ipset *ipset) - if (ipset->newargv[0]) - free(ipset->newargv[0]); - -+ list_for_each_entry_safe(xlate_set, next, &ipset->xlate_sets, list) -+ free(xlate_set); -+ - free(ipset); - return 0; - } -+ -+/* Ignore the set family, use inet. */ -+static const char *ipset_xlate_family(uint8_t family) -+{ -+ return "inet"; -+} -+ -+enum ipset_xlate_set_type { -+ IPSET_XLATE_TYPE_UNKNOWN = 0, -+ IPSET_XLATE_TYPE_HASH_MAC, -+ IPSET_XLATE_TYPE_HASH_IP, -+ IPSET_XLATE_TYPE_HASH_IP_MAC, -+ IPSET_XLATE_TYPE_HASH_NET_IFACE, -+ IPSET_XLATE_TYPE_HASH_NET_PORT, -+ IPSET_XLATE_TYPE_HASH_NET_PORT_NET, -+ IPSET_XLATE_TYPE_HASH_NET_NET, -+ IPSET_XLATE_TYPE_HASH_NET, -+ IPSET_XLATE_TYPE_HASH_IP_PORT_NET, -+ IPSET_XLATE_TYPE_HASH_IP_PORT_IP, -+ IPSET_XLATE_TYPE_HASH_IP_MARK, -+ IPSET_XLATE_TYPE_HASH_IP_PORT, -+ IPSET_XLATE_TYPE_BITMAP_PORT, -+ IPSET_XLATE_TYPE_BITMAP_IP_MAC, -+ IPSET_XLATE_TYPE_BITMAP_IP, -+}; -+ -+static enum ipset_xlate_set_type ipset_xlate_set_type(const char *typename) -+{ -+ if (!strcmp(typename, "hash:mac")) -+ return IPSET_XLATE_TYPE_HASH_MAC; -+ else if (!strcmp(typename, "hash:ip")) -+ return IPSET_XLATE_TYPE_HASH_IP; -+ else if (!strcmp(typename, "hash:ip,mac")) -+ return IPSET_XLATE_TYPE_HASH_IP_MAC; -+ else if (!strcmp(typename, "hash:net,iface")) -+ return IPSET_XLATE_TYPE_HASH_NET_IFACE; -+ else if (!strcmp(typename, "hash:net,port")) -+ return IPSET_XLATE_TYPE_HASH_NET_PORT; -+ else if (!strcmp(typename, "hash:net,port,net")) -+ return IPSET_XLATE_TYPE_HASH_NET_PORT_NET; -+ else if (!strcmp(typename, "hash:net,net")) -+ return IPSET_XLATE_TYPE_HASH_NET_NET; -+ else if (!strcmp(typename, "hash:net")) -+ return IPSET_XLATE_TYPE_HASH_NET; -+ else if (!strcmp(typename, "hash:ip,port,net")) -+ return IPSET_XLATE_TYPE_HASH_IP_PORT_NET; -+ else if (!strcmp(typename, "hash:ip,port,ip")) -+ return IPSET_XLATE_TYPE_HASH_IP_PORT_IP; -+ else if (!strcmp(typename, "hash:ip,mark")) -+ return IPSET_XLATE_TYPE_HASH_IP_MARK; -+ else if (!strcmp(typename, "hash:ip,port")) -+ return IPSET_XLATE_TYPE_HASH_IP_PORT; -+ else if (!strcmp(typename, "hash:ip")) -+ return IPSET_XLATE_TYPE_HASH_IP; -+ else if (!strcmp(typename, "bitmap:port")) -+ return IPSET_XLATE_TYPE_BITMAP_PORT; -+ else if (!strcmp(typename, "bitmap:ip,mac")) -+ return IPSET_XLATE_TYPE_BITMAP_IP_MAC; -+ else if (!strcmp(typename, "bitmap:ip")) -+ return IPSET_XLATE_TYPE_BITMAP_IP; -+ -+ return IPSET_XLATE_TYPE_UNKNOWN; -+} -+ -+#define NFT_SET_INTERVAL (1 << 0) -+ -+static const char * -+ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type, -+ uint32_t *flags) -+{ -+ switch (type) { -+ case IPSET_XLATE_TYPE_HASH_MAC: -+ return "ether_addr"; -+ case IPSET_XLATE_TYPE_HASH_IP: -+ if (family == AF_INET) -+ return "ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_IP_MAC: -+ if (family == AF_INET) -+ return "ipv4_addr . ether_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . ether_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_NET_IFACE: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr . ifname"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . ifname"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_NET_PORT: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr . inet_proto . inet_service"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . inet_proto . inet_service"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_NET_PORT_NET: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_NET_NET: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr . ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_NET: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_IP_PORT_NET: -+ *flags |= NFT_SET_INTERVAL; -+ if (family == AF_INET) -+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_IP_PORT_IP: -+ if (family == AF_INET) -+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_IP_MARK: -+ if (family == AF_INET) -+ return "ipv4_addr . mark"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . mark"; -+ break; -+ case IPSET_XLATE_TYPE_HASH_IP_PORT: -+ if (family == AF_INET) -+ return "ipv4_addr . inet_proto . inet_service"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . inet_proto . inet_service"; -+ break; -+ case IPSET_XLATE_TYPE_BITMAP_PORT: -+ return "inet_service"; -+ case IPSET_XLATE_TYPE_BITMAP_IP_MAC: -+ if (family == AF_INET) -+ return "ipv4_addr . ether_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr . ether_addr"; -+ break; -+ case IPSET_XLATE_TYPE_BITMAP_IP: -+ if (family == AF_INET) -+ return "ipv4_addr"; -+ else if (family == AF_INET6) -+ return "ipv6_addr"; -+ break; -+ } -+ /* This should not ever happen. */ -+ return "unknown"; -+} -+ -+static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd, -+ const char *table) -+{ -+ const char *set, *typename, *nft_type; -+ const struct ipset_type *ipset_type; -+ struct ipset_xlate_set *xlate_set; -+ enum ipset_xlate_set_type type; -+ struct ipset_session *session; -+ const uint32_t *cadt_flags; -+ const uint32_t *timeout; -+ const uint32_t *maxelem; -+ struct ipset_data *data; -+ const uint8_t *netmask; -+ const char *comment; -+ uint32_t flags = 0; -+ uint8_t family; -+ char buf[64]; -+ bool concat; -+ char *term; -+ int i; -+ -+ session = ipset_session(ipset); -+ data = ipset_session_data(session); -+ -+ set = ipset_data_get(data, IPSET_SETNAME); -+ family = ipset_data_family(data); -+ -+ switch (cmd) { -+ case IPSET_CMD_CREATE: -+ /* Not supported. */ -+ if (ipset_data_test(data, IPSET_OPT_MARKMASK)) { -+ printf("# %s", ipset->cmdline); -+ break; -+ } -+ cadt_flags = ipset_data_get(data, IPSET_OPT_CADT_FLAGS); -+ -+ /* Ignore: -+ * - IPSET_FLAG_WITH_COMMENT -+ * - IPSET_FLAG_WITH_FORCEADD -+ */ -+ if (cadt_flags && -+ (*cadt_flags & (IPSET_FLAG_BEFORE | -+ IPSET_FLAG_PHYSDEV | -+ IPSET_FLAG_NOMATCH | -+ IPSET_FLAG_WITH_SKBINFO | -+ IPSET_FLAG_IFACE_WILDCARD))) { -+ printf("# %s", ipset->cmdline); -+ break; -+ } -+ -+ typename = ipset_data_get(data, IPSET_OPT_TYPENAME); -+ type = ipset_xlate_set_type(typename); -+ nft_type = ipset_xlate_type_to_nftables(family, type, &flags); -+ -+ printf("add set %s %s %s { type %s; ", -+ ipset_xlate_family(family), table, set, nft_type); -+ if (cadt_flags) { -+ if (*cadt_flags & IPSET_FLAG_WITH_COUNTERS) -+ printf("counter; "); -+ } -+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT); -+ if (timeout) -+ printf("timeout %us; ", *timeout); -+ maxelem = ipset_data_get(data, IPSET_OPT_MAXELEM); -+ if (maxelem) -+ printf("size %u; ", *maxelem); -+ -+ netmask = ipset_data_get(data, IPSET_OPT_NETMASK); -+ if (netmask && -+ ((family == AF_INET && *netmask < 32) || -+ (family == AF_INET6 && *netmask < 128))) -+ flags |= NFT_SET_INTERVAL; -+ -+ if (flags & NFT_SET_INTERVAL) -+ printf("flags interval; "); -+ -+ /* These create-specific options are safe to be ignored: -+ * - IPSET_OPT_GC -+ * - IPSET_OPT_HASHSIZE -+ * - IPSET_OPT_PROBES -+ * - IPSET_OPT_RESIZE -+ * - IPSET_OPT_SIZE -+ * - IPSET_OPT_FORCEADD -+ * -+ * Ranges and CIDR are safe to be ignored too: -+ * - IPSET_OPT_IP_FROM -+ * - IPSET_OPT_IP_TO -+ * - IPSET_OPT_PORT_FROM -+ * - IPSET_OPT_PORT_TO -+ */ -+ -+ printf("}\n"); -+ -+ xlate_set = calloc(1, sizeof(*xlate_set)); -+ if (!xlate_set) -+ return -1; -+ -+ snprintf(xlate_set->name, sizeof(xlate_set->name), "%s", set); -+ ipset_type = ipset_types(); -+ while (ipset_type) { -+ if (!strcmp(ipset_type->name, typename)) -+ break; -+ ipset_type = ipset_type->next; -+ } -+ -+ xlate_set->family = family; -+ xlate_set->type = ipset_type; -+ if (netmask) { -+ xlate_set->netmask = *netmask; -+ xlate_set->interval = true; -+ } -+ list_add_tail(&xlate_set->list, &ipset->xlate_sets); -+ break; -+ case IPSET_CMD_DESTROY: -+ printf("del set %s %s %s\n", -+ ipset_xlate_family(family), table, set); -+ break; -+ case IPSET_CMD_FLUSH: -+ if (!set) { -+ printf("# %s", ipset->cmdline); -+ } else { -+ printf("flush set %s %s %s\n", -+ ipset_xlate_family(family), table, set); -+ } -+ break; -+ case IPSET_CMD_RENAME: -+ printf("# %s", ipset->cmdline); -+ return -1; -+ case IPSET_CMD_SWAP: -+ printf("# %s", ipset->cmdline); -+ return -1; -+ case IPSET_CMD_LIST: -+ if (!set) { -+ printf("list sets %s\n", -+ ipset_xlate_family(family), table); -+ } else { -+ printf("list set %s %s %s\n", -+ ipset_xlate_family(family), table, set); -+ } -+ break; -+ case IPSET_CMD_SAVE: -+ printf("# %s", ipset->cmdline); -+ return -1; -+ case IPSET_CMD_ADD: -+ case IPSET_CMD_DEL: -+ case IPSET_CMD_TEST: -+ /* Not supported. */ -+ if (ipset_data_test(data, IPSET_OPT_NOMATCH) || -+ ipset_data_test(data, IPSET_OPT_SKBINFO) || -+ ipset_data_test(data, IPSET_OPT_SKBMARK) || -+ ipset_data_test(data, IPSET_OPT_SKBPRIO) || -+ ipset_data_test(data, IPSET_OPT_SKBQUEUE) || -+ ipset_data_test(data, IPSET_OPT_IFACE_WILDCARD)) { -+ printf("# %s", ipset->cmdline); -+ break; -+ } -+ printf("%s element %s %s %s { ", -+ cmd == IPSET_CMD_ADD ? "add" : -+ cmd == IPSET_CMD_DEL ? "delete" : "get", -+ ipset_xlate_family(family), table, set); -+ -+ typename = ipset_data_get(data, IPSET_OPT_TYPENAME); -+ type = ipset_xlate_set_type(typename); -+ -+ xlate_set = (struct ipset_xlate_set *) -+ ipset_xlate_set_get(ipset, set); -+ if (xlate_set && xlate_set->interval) -+ netmask = &xlate_set->netmask; -+ else -+ netmask = NULL; -+ -+ concat = false; -+ if (ipset_data_test(data, IPSET_OPT_IP)) { -+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IP, 0); -+ printf("%s", buf); -+ if (netmask) -+ printf("/%u ", *netmask); -+ else -+ printf(" "); -+ -+ concat = true; -+ } -+ if (ipset_data_test(data, IPSET_OPT_MARK)) { -+ ipset_print_mark(buf, sizeof(buf), data, IPSET_OPT_MARK, 0); -+ printf("%s%s ", concat ? ". " : "", buf); -+ } -+ if (ipset_data_test(data, IPSET_OPT_IFACE)) { -+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IFACE, 0); -+ printf("%s%s ", concat ? ". " : "", buf); -+ } -+ if (ipset_data_test(data, IPSET_OPT_ETHER)) { -+ ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0); -+ for (i = 0; i < strlen(buf); i++) -+ buf[i] = tolower(buf[i]); -+ -+ printf("%s%s ", concat ? ". " : "", buf); -+ concat = true; -+ } -+ if (ipset_data_test(data, IPSET_OPT_PORT)) { -+ ipset_print_proto_port(buf, sizeof(buf), data, IPSET_OPT_PORT, 0); -+ term = strchr(buf, ':'); -+ if (term) { -+ *term = '\0'; -+ printf("%s%s ", concat ? ". " : "", buf); -+ } -+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_PORT, 0); -+ printf("%s%s ", concat ? ". " : "", buf); -+ } -+ if (ipset_data_test(data, IPSET_OPT_IP2)) { -+ ipset_print_ip(buf, sizeof(buf), data, IPSET_OPT_IP2, 0); -+ printf("%s%s", concat ? ". " : "", buf); -+ if (netmask) -+ printf("/%u ", *netmask); -+ else -+ printf(" "); -+ } -+ if (ipset_data_test(data, IPSET_OPT_PACKETS) && -+ ipset_data_test(data, IPSET_OPT_BYTES)) { -+ const uint64_t *pkts, *bytes; -+ -+ pkts = ipset_data_get(data, IPSET_OPT_PACKETS); -+ bytes = ipset_data_get(data, IPSET_OPT_BYTES); -+ -+ printf("counter packets %" PRIu64 " bytes %" PRIu64 " ", -+ *pkts, *bytes); -+ } -+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT); -+ if (timeout) -+ printf("timeout %us ", *timeout); -+ -+ comment = ipset_data_get(data, IPSET_OPT_ADT_COMMENT); -+ if (comment) -+ printf("comment \"%s\" ", comment); -+ -+ printf("}\n"); -+ break; -+ case IPSET_CMD_GET_BYNAME: -+ printf("# %s", ipset->cmdline); -+ return -1; -+ case IPSET_CMD_GET_BYINDEX: -+ printf("# %s", ipset->cmdline); -+ return -1; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int ipset_xlate_restore(struct ipset *ipset) -+{ -+ struct ipset_session *session = ipset_session(ipset); -+ struct ipset_data *data = ipset_session_data(session); -+ void *p = ipset_session_printf_private(session); -+ const char *filename; -+ enum ipset_cmd cmd; -+ FILE *f = stdin; -+ int ret = 0; -+ char *c; -+ -+ if (ipset->filename) { -+ f = fopen(ipset->filename, "r"); -+ if (!f) { -+ fprintf(stderr, "cannot open file `%s'\n", filename); -+ return -1; -+ } -+ } -+ -+ /* TODO: Allow to specify the table name other than 'global'. */ -+ printf("add table inet global\n"); -+ -+ while (fgets(ipset->cmdline, sizeof(ipset->cmdline), f)) { -+ ipset->restore_line++; -+ c = ipset->cmdline; -+ while (isspace(c[0])) -+ c++; -+ if (c[0] == '\0' || c[0] == '#') -+ continue; -+ else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n")) -+ continue; -+ -+ ret = build_argv(ipset, c); -+ if (ret < 0) -+ return ret; -+ -+ cmd = ipset_parser(ipset, ipset->newargc, ipset->newargv); -+ if (cmd < 0) -+ ipset->standard_error(ipset, p); -+ -+ /* TODO: Allow to specify the table name other than 'global'. */ -+ ret = ipset_xlate(ipset, cmd, "global"); -+ if (ret < 0) -+ break; -+ -+ ipset_data_reset(data); -+ } -+ -+ if (filename) -+ fclose(f); -+ -+ return ret; -+} -+ -+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]) -+{ -+ enum ipset_cmd cmd; -+ int ret; -+ -+ ipset->xlate = true; -+ -+ cmd = ipset_parser(ipset, argc, argv); -+ if (cmd < 0) -+ return cmd; -+ -+ if (cmd == IPSET_CMD_RESTORE) { -+ ret = ipset_xlate_restore(ipset); -+ } else { -+ fprintf(stderr, "This command is not supported, " -+ "use `ipset-translate restore < file'\n"); -+ ret = -1; -+ } -+ -+ return ret; -+} -diff --git a/lib/parse.c b/lib/parse.c -index f3f2d11..9cba252 100644 ---- a/lib/parse.c -+++ b/lib/parse.c -@@ -41,6 +41,9 @@ - #define syntax_err(fmt, args...) \ - ipset_err(session, "Syntax error: " fmt , ## args) - -+#define syntax_err_ll(errtype, fmt, args...) \ -+ ipset_session_report(session, errtype, "Syntax error: " fmt , ## args) -+ - static char * - ipset_strchr(const char *str, const char *sep) - { -@@ -87,7 +90,8 @@ string_to_number_ll(struct ipset_session *session, - const char *str, - unsigned long long min, - unsigned long long max, -- unsigned long long *ret) -+ unsigned long long *ret, -+ enum ipset_err_type errtype) - { - unsigned long long number = 0; - char *end; -@@ -104,13 +108,13 @@ string_to_number_ll(struct ipset_session *session, - errno = ERANGE; - } - if (errno == ERANGE && max) -- return syntax_err("'%s' is out of range %llu-%llu", -- str, min, max); -+ return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu", -+ str, min, max); - else if (errno == ERANGE) -- return syntax_err("'%s' is out of range %llu-%llu", -- str, min, ULLONG_MAX); -+ return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu", -+ str, min, ULLONG_MAX); - else -- return syntax_err("'%s' is invalid as number", str); -+ return syntax_err_ll(errtype, "'%s' is invalid as number", str); - } - - static int -@@ -120,7 +124,7 @@ string_to_u8(struct ipset_session *session, - int err; - unsigned long long num = 0; - -- err = string_to_number_ll(session, str, 0, 255, &num); -+ err = string_to_number_ll(session, str, 0, 255, &num, IPSET_ERROR); - *ret = num; - - return err; -@@ -141,12 +145,13 @@ string_to_cidr(struct ipset_session *session, - - static int - string_to_u16(struct ipset_session *session, -- const char *str, uint16_t *ret) -+ const char *str, uint16_t *ret, -+ enum ipset_err_type errtype) - { - int err; - unsigned long long num = 0; - -- err = string_to_number_ll(session, str, 0, USHRT_MAX, &num); -+ err = string_to_number_ll(session, str, 0, USHRT_MAX, &num, errtype); - *ret = num; - - return err; -@@ -159,7 +164,8 @@ string_to_u32(struct ipset_session *session, - int err; - unsigned long long num = 0; - -- err = string_to_number_ll(session, str, 0, UINT_MAX, &num); -+ err = string_to_number_ll(session, str, 0, UINT_MAX, &num, -+ IPSET_ERROR); - *ret = num; - - return err; -@@ -319,7 +325,7 @@ ipset_parse_port(struct ipset_session *session, - assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO); - assert(str); - -- if (string_to_u16(session, str, &port) == 0) { -+ if (string_to_u16(session, str, &port, IPSET_WARNING) == 0) { - return ipset_session_data_set(session, opt, &port); - } - /* Error is stored as warning in session report */ -@@ -1335,7 +1341,8 @@ ipset_parse_timeout(struct ipset_session *session, - assert(opt == IPSET_OPT_TIMEOUT); - assert(str); - -- err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum); -+ err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum, -+ IPSET_ERROR); - if (err == 0) { - /* Timeout is expected to be 32bits wide, so we have - to convert it here */ -@@ -1579,7 +1586,8 @@ ipset_parse_uint64(struct ipset_session *session, - assert(session); - assert(str); - -- err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value); -+ err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value, -+ IPSET_ERROR); - if (err) - return err; - -@@ -1623,7 +1631,7 @@ ipset_parse_uint16(struct ipset_session *session, - assert(session); - assert(str); - -- err = string_to_u16(session, str, &value); -+ err = string_to_u16(session, str, &value, IPSET_ERROR); - if (err == 0) - return ipset_session_data_set(session, opt, &value); - -diff --git a/src/Makefile.am b/src/Makefile.am -index 438fcec..95dea07 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -12,10 +12,16 @@ AM_LDFLAGS = -static - endif - endif - --dist_man_MANS = ipset.8 -+dist_man_MANS = ipset.8 ipset-translate.8 - - sparse-check: $(ipset_SOURCES:.c=.d) - - %.d: %.c - $(IPSET_AM_V_CHECK)\ - $(SPARSE) -I.. $(SPARSE_FLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) $< || : -+ -+install-exec-hook: -+ ${LN_S} -f "${sbindir}/ipset" "${DESTDIR}${sbindir}/ipset-translate"; -+ -+uninstall-hook: -+ rm -f ${DESTDIR}${sbindir}/ipset-translate -diff --git a/src/ipset-translate.8 b/src/ipset-translate.8 -new file mode 100644 -index 0000000..bb4e737 ---- /dev/null -+++ b/src/ipset-translate.8 -@@ -0,0 +1,91 @@ -+.\" -+.\" (C) Copyright 2021, Pablo Neira Ayuso -+.\" -+.\" %%%LICENSE_START(GPLv2+_DOC_FULL) -+.\" This is free documentation; you can redistribute it and/or -+.\" modify it under the terms of the GNU General Public License as -+.\" published by the Free Software Foundation; either version 2 of -+.\" the License, or (at your option) any later version. -+.\" -+.\" The GNU General Public License's references to "object code" -+.\" and "executables" are to be interpreted as the output of any -+.\" document formatting or typesetting system, including -+.\" intermediate and printed output. -+.\" -+.\" This manual is distributed in the hope that it will be useful, -+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+.\" GNU General Public License for more details. -+.\" -+.\" You should have received a copy of the GNU General Public -+.\" License along with this manual; if not, see -+.\" . -+.\" %%%LICENSE_END -+.\" -+.TH IPSET-TRANSLATE 8 "May 31, 2021" -+ -+.SH NAME -+ipset-translate \(em translation tool to migrate from ipset to nftables -+.SH DESCRIPTION -+This tool allows system administrators to translate a given IP sets file -+to \fBnftables(8)\fP. -+ -+The only available command is: -+ -+.IP \[bu] 2 -+ipset-translate restores < file.ipt -+ -+.SH USAGE -+The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by -+\fBipset(8)\fP save. No set modifications occur, this tool is a text converter. -+ -+.SH EXAMPLES -+Basic operation examples. -+ -+Single command translation, assuming the original file: -+ -+.nf -+create test1 hash:ip,port family inet counters timeout 300 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d -+add test1 1.1.1.1,udp:20 -+add test1 1.1.1.1,21 -+create test2 hash:ip,port family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d -+.fi -+ -+which results in the following translation: -+ -+.nf -+root@machine:~# ipset-translate restore < file.ipt -+add set inet global test1 { type ipv4_addr . inet_proto . inet_service; counter; timeout 300s; size 65536; } -+add element inet global test1 { 1.1.1.1 . udp . 20 } -+add element inet global test1 { 1.1.1.1 . tcp . 21 } -+add set inet global test2 { type ipv4_addr . inet_proto . inet_service; size 65536; } -+.fi -+ -+.SH LIMITATIONS -+A few IP sets options may be not supported because they are not yet implemented -+in \fBnftables(8)\fP. -+ -+Contrary to \fBnftables(8)\fP, IP sets are not attached to a specific table. -+The translation utility assumes that sets are created in a table whose name -+is \fBglobal\fP and family is \fBinet\fP. You might want to update the -+resulting translation to use a different table name and family for your sets. -+ -+To get up-to-date information about this, please head to -+\fBhttps://wiki.nftables.org/\fP. -+ -+.SH SEE ALSO -+\fBnft(8)\fP, \fBipset(8)\fP -+ -+.SH AUTHORS -+The nftables framework has been written by the Netfilter Project -+(https://www.netfilter.org). -+ -+This manual page was written by Pablo Neira Ayuso -+. -+ -+This documentation is free/libre under the terms of the GPLv2+. -+ -+This tool was funded through the NGI0 PET Fund, a fund established by NLnet with -+financial support from the European Commission's Next Generation Internet -+programme, under the aegis of DG Communications Networks, Content and Technology -+under grant agreement No 825310. -diff --git a/src/ipset.8 b/src/ipset.8 -index 97cece9..269b9b5 100644 ---- a/src/ipset.8 -+++ b/src/ipset.8 -@@ -333,7 +333,7 @@ are hex without 0x prefix. - .IP - ipset create foo hash:ip skbinfo - .IP --ipset add foo skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10 -+ipset add foo 192.168.0.1 skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10 - .PP - .SS hashsize - This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets. -diff --git a/src/ipset.c b/src/ipset.c -index ee36a06..6d42b60 100644 ---- a/src/ipset.c -+++ b/src/ipset.c -@@ -9,9 +9,11 @@ - #include /* assert */ - #include /* fprintf */ - #include /* exit */ -+#include /* strcmp */ - - #include - #include /* ipset library */ -+#include /* translate to nftables */ - - int - main(int argc, char *argv[]) -@@ -29,7 +31,11 @@ main(int argc, char *argv[]) - exit(1); - } - -- ret = ipset_parse_argv(ipset, argc, argv); -+ if (!strcmp(argv[0], "ipset-translate")) { -+ ret = ipset_xlate_argv(ipset, argc, argv); -+ } else { -+ ret = ipset_parse_argv(ipset, argc, argv); -+ } - - ipset_fini(ipset); - -diff --git a/tests/xlate/runtest.sh b/tests/xlate/runtest.sh -new file mode 100755 -index 0000000..a2a02c0 ---- /dev/null -+++ b/tests/xlate/runtest.sh -@@ -0,0 +1,29 @@ -+#!/bin/bash -+ -+DIFF=$(which diff) -+if [ ! -x "$DIFF" ] ; then -+ echo "ERROR: missing diff" -+ exit 1 -+fi -+ -+IPSET_XLATE=$(which ipset-translate) -+if [ ! -x "$IPSET_XLATE" ] ; then -+ echo "ERROR: ipset-translate is not installed yet" -+ exit 1 -+fi -+ -+TMP=$(mktemp) -+ipset-translate restore < xlate.t &> $TMP -+if [ $? -ne 0 ] -+then -+ cat $TMP -+ echo -e "[\033[0;31mERROR\033[0m] failed to run ipset-translate" -+ exit 1 -+fi -+${DIFF} -u xlate.t.nft $TMP -+if [ $? -eq 0 ] -+then -+ echo -e "[\033[0;32mOK\033[0m] tests are fine!" -+else -+ echo -e "[\033[0;31mERROR\033[0m] unexpected ipset to nftables translation" -+fi -diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t -new file mode 100644 -index 0000000..b1e7d28 ---- /dev/null -+++ b/tests/xlate/xlate.t -@@ -0,0 +1,55 @@ -+create hip1 hash:ip -+add hip1 192.168.10.2 -+add hip1 192.168.10.3 -+create hip2 hash:ip hashsize 128 bucketsize 255 timeout 4 -+add hip2 192.168.10.3 -+add hip2 192.168.10.4 timeout 10 -+create hip3 hash:ip counters -+add hip3 192.168.10.3 packets 5 bytes 3456 -+create hip4 hash:ip netmask 24 -+add hip4 192.168.10.0 -+create hip5 hash:ip maxelem 24 -+add hip5 192.168.10.0 -+create hip6 hash:ip comment -+add hip5 192.168.10.1 -+add hip5 192.168.10.2 comment "this is a comment" -+create ipp1 hash:ip,port -+add ipp1 192.168.10.1,0 -+add ipp1 192.168.10.2,5 -+create ipp2 hash:ip,port timeout 4 -+add ipp2 192.168.10.1,0 timeout 12 -+add ipp2 192.168.10.2,5 -+create ipp3 hash:ip,port counters -+add ipp3 192.168.10.3,20 packets 5 bytes 3456 -+create ipp4 hash:ip,port timeout 4 counters -+add ipp4 192.168.10.3,20 packets 5 bytes 3456 -+create bip1 bitmap:ip range 2.0.0.1-2.1.0.1 timeout 5 -+create bip2 bitmap:ip range 10.0.0.0/8 netmask 24 timeout 5 -+add bip2 10.10.10.0 -+add bip2 10.10.20.0 timeout 12 -+create net1 hash:net -+add net1 192.168.10.0/24 -+create net2 hash:net,net -+add net2 192.168.10.0/24,192.168.20.0/24 -+create hm1 hash:mac -+add hm1 aa:bb:cc:dd:ee:ff -+create him1 hash:ip,mac -+add him1 1.1.1.1,aa:bb:cc:dd:ee:ff -+create ni1 hash:net,iface -+add ni1 1.1.1.0/24,eth0 -+create nip1 hash:net,port -+add nip1 1.1.1.0/24,22 -+create npn1 hash:net,port,net -+add npn1 1.1.1.0/24,22,2.2.2.0/24 -+create nn1 hash:net,net -+add nn1 1.1.1.0/24,2.2.2.0/24 -+create ipn1 hash:ip,port,net -+add ipn1 1.1.1.1,22,2.2.2.0/24 -+create ipi1 hash:ip,port,ip -+add ipi1 1.1.1.1,22,2.2.2.2 -+create im1 hash:ip,mark -+add im1 1.1.1.1,0x123456 -+create bp1 bitmap:port range 1-1024 -+add bp1 22 -+create bim1 bitmap:ip,mac range 1.1.1.0/24 -+add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff -diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft -new file mode 100644 -index 0000000..96eba3b ---- /dev/null -+++ b/tests/xlate/xlate.t.nft -@@ -0,0 +1,56 @@ -+add table inet global -+add set inet global hip1 { type ipv4_addr; } -+add element inet global hip1 { 192.168.10.2 } -+add element inet global hip1 { 192.168.10.3 } -+add set inet global hip2 { type ipv4_addr; timeout 4s; } -+add element inet global hip2 { 192.168.10.3 } -+add element inet global hip2 { 192.168.10.4 timeout 10s } -+add set inet global hip3 { type ipv4_addr; counter; } -+add element inet global hip3 { 192.168.10.3 counter packets 5 bytes 3456 } -+add set inet global hip4 { type ipv4_addr; flags interval; } -+add element inet global hip4 { 192.168.10.0/24 } -+add set inet global hip5 { type ipv4_addr; size 24; } -+add element inet global hip5 { 192.168.10.0 } -+add set inet global hip6 { type ipv4_addr; } -+add element inet global hip5 { 192.168.10.1 } -+add element inet global hip5 { 192.168.10.2 comment "this is a comment" } -+add set inet global ipp1 { type ipv4_addr . inet_proto . inet_service; } -+add element inet global ipp1 { 192.168.10.1 . tcp . 0 } -+add element inet global ipp1 { 192.168.10.2 . tcp . 5 } -+add set inet global ipp2 { type ipv4_addr . inet_proto . inet_service; timeout 4s; } -+add element inet global ipp2 { 192.168.10.1 . tcp . 0 timeout 12s } -+add element inet global ipp2 { 192.168.10.2 . tcp . 5 } -+add set inet global ipp3 { type ipv4_addr . inet_proto . inet_service; counter; } -+add element inet global ipp3 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 } -+add set inet global ipp4 { type ipv4_addr . inet_proto . inet_service; counter; timeout 4s; } -+add element inet global ipp4 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 } -+add set inet global bip1 { type ipv4_addr; timeout 5s; } -+add set inet global bip2 { type ipv4_addr; timeout 5s; flags interval; } -+add element inet global bip2 { 10.10.10.0/24 } -+add element inet global bip2 { 10.10.20.0/24 timeout 12s } -+add set inet global net1 { type ipv4_addr; flags interval; } -+add element inet global net1 { 192.168.10.0/24 } -+add set inet global net2 { type ipv4_addr . ipv4_addr; flags interval; } -+add element inet global net2 { 192.168.10.0/24 . 192.168.20.0/24 } -+add set inet global hm1 { type ether_addr; } -+add element inet global hm1 { aa:bb:cc:dd:ee:ff } -+add set inet global him1 { type ipv4_addr . ether_addr; } -+add element inet global him1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff } -+add set inet global ni1 { type ipv4_addr . ifname; flags interval; } -+add element inet global ni1 { 1.1.1.0/24 . eth0 } -+add set inet global nip1 { type ipv4_addr . inet_proto . inet_service; flags interval; } -+add element inet global nip1 { 1.1.1.0/24 . tcp . 22 } -+add set inet global npn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; } -+add element inet global npn1 { 1.1.1.0/24 . tcp . 22 . 2.2.2.0/24 } -+add set inet global nn1 { type ipv4_addr . ipv4_addr; flags interval; } -+add element inet global nn1 { 1.1.1.0/24 . 2.2.2.0/24 } -+add set inet global ipn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; } -+add element inet global ipn1 { 1.1.1.1 . tcp . 22 . 2.2.2.0/24 } -+add set inet global ipi1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; } -+add element inet global ipi1 { 1.1.1.1 . tcp . 22 . 2.2.2.2 } -+add set inet global im1 { type ipv4_addr . mark; } -+add element inet global im1 { 1.1.1.1 . 0x00123456 } -+add set inet global bp1 { type inet_service; } -+add element inet global bp1 { 22 } -+add set inet global bim1 { type ipv4_addr . ether_addr; } -+add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff } diff --git a/ipset.spec b/ipset.spec index 40dc9af..1c62603 100644 --- a/ipset.spec +++ b/ipset.spec @@ -22,20 +22,19 @@ exit 1 %define _enable_debug_packages 0 %endif -%define rel 2 +%define rel 1 %define pname ipset Summary: IP sets utility Summary(pl.UTF-8): Narzędzie do zarządzania zbiorami IP Name: %{pname}%{?_pld_builder:%{?with_kernel:-kernel}}%{_alt_kernel} -Version: 7.11 +Version: 7.14 Release: %{rel}%{?_pld_builder:%{?with_kernel:@%{_kernel_ver_str}}} License: GPL v2 Group: Networking/Admin #Source0Download: http://ipset.netfilter.org/install.html Source0: http://ipset.netfilter.org/%{pname}-%{version}.tar.bz2 -# Source0-md5: 7c17aca72bcf852f5bc95582aaa60408 +# Source0-md5: a624b3de000a14b9fd2518a9a806ef1c Source1: %{pname}.init -Patch0: git.patch URL: http://ipset.netfilter.org/ BuildRequires: autoconf >= 2.63 BuildRequires: automake @@ -185,7 +184,6 @@ done\ %prep %setup -q -n %{pname}-%{version} -%patch0 -p1 %build %{__aclocal}