1 diff --git a/configure.ac b/configure.ac
2 index bd6116c..eb6c334 100644
5 @@ -7,6 +7,7 @@ AC_CONFIG_HEADER([config.h])
6 AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
7 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
12 LT_CONFIG_LTDL_DIR([libltdl])
13 @@ -786,6 +787,56 @@ else
14 AC_SUBST(HAVE_NLA_POLICY_EXACT_LEN, undef)
17 +AC_MSG_CHECKING([kernel source for nfnl_msg_put() in nfnetlink.h])
18 +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
19 + $GREP -q 'nfnl_msg_put' $ksourcedir/include/linux/netfilter/nfnetlink.h; then
21 + AC_SUBST(HAVE_NFNL_MSG_PUT, define)
24 + AC_SUBST(HAVE_NFNL_MSG_PUT, undef)
27 +AC_MSG_CHECKING([kernel source for struct nfnl_info in nfnl_callback function])
28 +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
29 + $AWK '/^struct nfnl_callback /,/^}/' $ksourcedir/include/linux/netfilter/nfnetlink.h | $GREP -q 'struct nfnl_info'; then
31 + AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, define)
34 + AC_SUBST(HAVE_NFNL_INFO_IN_NFNL_CALLBACK, undef)
37 +AC_MSG_CHECKING([kernel source for enum nfnl_callback_type])
38 +if test -f $ksourcedir/include/linux/netfilter/nfnetlink.h && \
39 + $GREP -q 'enum nfnl_callback_type ' $ksourcedir/include/linux/netfilter/nfnetlink.h; then
41 + AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, define)
44 + AC_SUBST(HAVE_NFNL_CALLBACK_TYPE, undef)
47 +AC_MSG_CHECKING([kernel source of handling -EAGAIN in nfnetlink_unicast])
48 +if test -f $ksourcedir/net/netfilter/nfnetlink.c && \
49 + $AWK '/nfnetlink_unicast\(/,/^}/' $ksourcedir/net/netfilter/nfnetlink.c | $GREP -q 'err == -EAGAIN'; then
51 + AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, define)
54 + AC_SUBST(HAVE_EAGAIN_IN_NFNETLINK_UNICAST, undef)
57 +AC_MSG_CHECKING([kernel source for nlmsg_unicast which returns zero in case of success])
58 +if test -f $ksourcedir/include/net/netlink.h && \
59 + $AWK '/static inline int nlmsg_unicast\(/,/^}/' $ksourcedir/include/net/netlink.h | $GREP -q 'err > 0'; then
61 + AC_SUBST(HAVE_NLMSG_UNICAST, define)
64 + AC_SUBST(HAVE_NLMSG_UNICAST, undef)
67 AC_MSG_CHECKING([kernel source for kvzalloc() in mm.h])
68 if test -f $ksourcedir/include/linux/mm.h && \
69 $GREP -q 'static inline void \*kvzalloc(' $ksourcedir/include/linux/mm.h; then
70 diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am
71 index c7f7b2b..2c04029 100644
72 --- a/include/libipset/Makefile.am
73 +++ b/include/libipset/Makefile.am
74 @@ -17,6 +17,7 @@ pkginclude_HEADERS = \
82 EXTRA_DIST = debug.h icmp.h icmpv6.h
83 diff --git a/include/libipset/xlate.h b/include/libipset/xlate.h
85 index 0000000..6569768
87 +++ b/include/libipset/xlate.h
89 +#ifndef LIBIPSET_XLATE_H
90 +#define LIBIPSET_XLATE_H
92 +int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]);
95 diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
96 index 96a4cf4..4d2c446 100644
97 --- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
98 +++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
100 #@HAVE_KVZALLOC@ HAVE_KVZALLOC
101 #@HAVE_GFP_KERNEL_ACCOUNT@ HAVE_GFP_KERNEL_ACCOUNT
102 #@HAVE_NLA_STRSCPY@ HAVE_NLA_STRSCPY
103 +#@HAVE_NFNL_MSG_PUT@ HAVE_NFNL_MSG_PUT
104 +#@HAVE_NFNL_INFO_IN_NFNL_CALLBACK@ HAVE_NFNL_INFO_IN_NFNL_CALLBACK
105 +#@HAVE_NFNL_CALLBACK_TYPE@ HAVE_NFNL_CALLBACK_TYPE
106 +#@HAVE_EAGAIN_IN_NFNETLINK_UNICAST@ HAVE_EAGAIN_IN_NFNETLINK_UNICAST
107 +#@HAVE_NLMSG_UNICAST@ HAVE_NLMSG_UNICAST
109 #ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H
110 #include <linux/module.h>
111 @@ -348,18 +353,44 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
115 -#ifdef HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS
116 -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda, e)
117 -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda, e)
118 -#define IPSET_SOCK_NET(net, ctnl) net
119 +#ifdef HAVE_NFNL_INFO_IN_NFNL_CALLBACK
120 +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(skb, i, cda)
121 +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, i)
122 +#define IPSET_SOCK_NET(n, ctnl, i) (i)->net
123 +#define INFO_NLH(i, n) (i)->nlh
124 +#define INFO_NET(i, n) (i)->net
125 +#define INFO_SK(i, n) (i)->sk
126 +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
127 +#elif defined(HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS)
128 +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda, e)
129 +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, e)
130 +#define IPSET_SOCK_NET(net, ctnl, i) net
131 +#define INFO_NLH(i, n) n
132 +#define INFO_NET(i, n) n
133 +#define INFO_SK(i, n) n
134 +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
135 #elif defined(HAVE_NET_IN_NFNL_CALLBACK_FN)
136 -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda)
137 -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda)
138 -#define IPSET_SOCK_NET(net, ctnl) net
139 +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda)
140 +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda)
141 +#define IPSET_SOCK_NET(net, ctnl, i) net
142 +#define INFO_NLH(i, n) n
143 +#define INFO_NET(i, n) n
144 +#define INFO_SK(i, n) n
145 +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l)
147 -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(nl, skb, nlh, cda)
148 -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(nl, skb, ad, nlh, cda)
149 -#define IPSET_SOCK_NET(net, ctnl) sock_net(ctnl)
150 +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(nl, skb, nlh, cda)
151 +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(nl, skb, ad, nlh, cda)
152 +#define IPSET_SOCK_NET(net, ctnl, i) sock_net(ctnl)
153 +#define INFO_NLH(i, n) n
154 +#define INFO_NET(i, n) n
155 +#define INFO_SK(i, n) n
156 +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(ctnl, skb, set, tb, adt, flags, l)
159 +#ifdef HAVE_NFNL_CALLBACK_TYPE
160 +#define SET_NFNL_CALLBACK_TYPE(t) .type = t,
162 +#define SET_NFNL_CALLBACK_TYPE(t)
165 #ifndef HAVE_TC_SKB_PROTOCOL
166 @@ -406,6 +437,36 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
170 +#ifndef HAVE_NFNL_MSG_PUT
171 +#include <linux/netfilter/nfnetlink.h>
172 +static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version,
175 + struct nfgenmsg *nfmsg;
177 + nfmsg = nlmsg_data(nlh);
178 + nfmsg->nfgen_family = family;
179 + nfmsg->version = version;
180 + nfmsg->res_id = res_id;
183 +static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid,
184 + u32 seq, int type, int flags,
185 + u8 family, u8 version,
188 + struct nlmsghdr *nlh;
190 + nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags);
194 + nfnl_fill_hdr(nlh, family, version, res_id);
200 #ifdef HAVE_NETLINK_EXTENDED_ACK
201 #define NETLINK_ACK(in_skb, nlh, err, extack) netlink_ack(in_skb, nlh, err, extack)
203 @@ -459,6 +520,23 @@ static inline ssize_t strscpy(char * dest, const char * src, size_t count)
204 #define nla_strscpy nla_strlcpy
207 +#if !defined(HAVE_EAGAIN_IN_NFNETLINK_UNICAST) || !defined(HAVE_NLMSG_UNICAST)
208 +#define NFNETLINK_UNICAST(cntl, skb, net, portid) ipset_nfnetlink_unicast(cntl, skb, portid)
209 +static inline int ipset_nfnetlink_unicast(struct sock *ctnl, struct sk_buff *skb, u32 portid)
211 + int err = netlink_unicast(ctnl, skb, portid, MSG_DONTWAIT);
215 + if (err == -EAGAIN)
221 +#define NFNETLINK_UNICAST(cntl, skb, net, portid) nfnetlink_unicast(skb, net, portid)
224 #ifndef smp_mb__before_atomic
225 #define smp_mb__before_atomic() smp_mb()
226 #define smp_mb__after_atomic() smp_mb()
227 diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c
228 index 63a7955..0fdafb7 100644
229 --- a/kernel/net/netfilter/ipset/ip_set_core.c
230 +++ b/kernel/net/netfilter/ipset/ip_set_core.c
231 @@ -964,20 +964,9 @@ static struct nlmsghdr *
232 start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags,
235 - struct nlmsghdr *nlh;
236 - struct nfgenmsg *nfmsg;
238 - nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd),
239 - sizeof(*nfmsg), flags);
243 - nfmsg = nlmsg_data(nlh);
244 - nfmsg->nfgen_family = NFPROTO_IPV4;
245 - nfmsg->version = NFNETLINK_V0;
249 + return nfnl_msg_put(skb, portid, seq,
250 + nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags,
251 + NFPROTO_IPV4, NFNETLINK_V0, 0);
255 @@ -1047,7 +1036,8 @@ static int
256 IPSET_CBFN(ip_set_none, struct net *net, struct sock *ctnl,
257 struct sk_buff *skb, const struct nlmsghdr *nlh,
258 const struct nlattr * const attr[],
259 - struct netlink_ext_ack *extack)
260 + struct netlink_ext_ack *extack,
261 + const struct nfnl_info *info)
265 @@ -1056,16 +1046,17 @@ static int
266 IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
267 struct sk_buff *skb, const struct nlmsghdr *nlh,
268 const struct nlattr * const attr[],
269 - struct netlink_ext_ack *extack)
270 + struct netlink_ext_ack *extack,
271 + const struct nfnl_info *info)
273 - struct net *net = IPSET_SOCK_NET(n, ctnl);
274 + struct net *net = IPSET_SOCK_NET(n, ctnl, info);
275 struct ip_set_net *inst = ip_set_pernet(net);
276 struct ip_set *set, *clash = NULL;
277 ip_set_id_t index = IPSET_INVALID_ID;
278 struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {};
279 const char *name, *typename;
281 - u32 flags = flag_exist(nlh);
282 + u32 flags = flag_exist(INFO_NLH(info, nlh));
285 if (unlikely(protocol_min_failed(attr) ||
286 @@ -1116,7 +1107,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
287 /* Set create flags depending on the type revision */
288 set->flags |= set->type->create_flags[revision];
290 - ret = set->type->create(net, set, tb, flags);
291 + ret = set->type->create(INFO_NET(info, net), set, tb, flags);
295 @@ -1202,9 +1193,10 @@ static int
296 IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
297 struct sk_buff *skb, const struct nlmsghdr *nlh,
298 const struct nlattr * const attr[],
299 - struct netlink_ext_ack *extack)
300 + struct netlink_ext_ack *extack,
301 + const struct nfnl_info *info)
303 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
304 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
308 @@ -1246,7 +1238,7 @@ IPSET_CBFN(ip_set_destroy, struct net *net, struct sock *ctnl,
309 /* Modified by ip_set_destroy() only, which is serialized */
310 inst->is_destroyed = false;
312 - u32 flags = flag_exist(nlh);
313 + u32 flags = flag_exist(INFO_NLH(info, nlh));
314 s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
317 @@ -1284,9 +1276,10 @@ static int
318 IPSET_CBFN(ip_set_flush, struct net *net, struct sock *ctnl,
319 struct sk_buff *skb, const struct nlmsghdr *nlh,
320 const struct nlattr * const attr[],
321 - struct netlink_ext_ack *extack)
322 + struct netlink_ext_ack *extack,
323 + const struct nfnl_info *info)
325 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
326 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
330 @@ -1325,9 +1318,10 @@ static int
331 IPSET_CBFN(ip_set_rename, struct net *net, struct sock *ctnl,
332 struct sk_buff *skb, const struct nlmsghdr *nlh,
333 const struct nlattr * const attr[],
334 - struct netlink_ext_ack *extack)
335 + struct netlink_ext_ack *extack,
336 + const struct nfnl_info *info)
338 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
339 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
340 struct ip_set *set, *s;
343 @@ -1376,9 +1370,10 @@ static int
344 IPSET_CBFN(ip_set_swap, struct net *net, struct sock *ctnl,
345 struct sk_buff *skb, const struct nlmsghdr *nlh,
346 const struct nlattr * const attr[],
347 - struct netlink_ext_ack *extack)
348 + struct netlink_ext_ack *extack,
349 + const struct nfnl_info *info)
351 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
352 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
353 struct ip_set *from, *to;
354 ip_set_id_t from_id, to_id;
355 char from_name[IPSET_MAXNAMELEN];
356 @@ -1706,7 +1701,8 @@ static int
357 IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl,
358 struct sk_buff *skb, const struct nlmsghdr *nlh,
359 const struct nlattr * const attr[],
360 - struct netlink_ext_ack *extack)
361 + struct netlink_ext_ack *extack,
362 + const struct nfnl_info *info)
364 if (unlikely(protocol_min_failed(attr)))
365 return -IPSET_ERR_PROTOCOL;
366 @@ -1728,7 +1724,7 @@ IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl,
367 .dump = ip_set_dump_do,
368 .done = ip_set_dump_done,
370 - return netlink_dump_start(ctnl, skb, nlh, &c);
371 + return netlink_dump_start(INFO_SK(info, ctnl), skb, INFO_NLH(info, nlh), &c);
375 @@ -1745,8 +1741,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
379 -call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
380 - struct nlattr *tb[], enum ipset_adt adt,
381 +CALL_AD(struct net *net, struct sock *ctnl, struct sk_buff *skb,
382 + struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt,
383 u32 flags, bool use_lineno)
386 @@ -1798,8 +1794,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
390 - netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb),
392 + NFNETLINK_UNICAST(ctnl, skb2, net, NETLINK_PORTID(skb));
393 /* Signal netlink not to send its ACK/errmsg. */
396 @@ -1807,19 +1802,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
401 -IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
402 - struct sk_buff *skb,
403 - enum ipset_adt adt,
404 - const struct nlmsghdr *nlh,
405 - const struct nlattr * const attr[],
406 - struct netlink_ext_ack *extack)
408 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
409 +static int IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
410 + struct sk_buff *skb,
411 + enum ipset_adt adt,
412 + const struct nlmsghdr *nlh,
413 + const struct nlattr * const attr[],
414 + struct netlink_ext_ack *extack, const struct nfnl_info *info)
416 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
418 struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
419 const struct nlattr *nla;
420 - u32 flags = flag_exist(nlh);
421 + u32 flags = flag_exist(INFO_NLH(info, nlh));
425 @@ -1844,7 +1838,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
426 attr[IPSET_ATTR_DATA],
427 set->type->adt_policy, NULL))
428 return -IPSET_ERR_PROTOCOL;
429 - ret = call_ad(ctnl, skb, set, tb, adt, flags,
430 + ret = CALL_AD(net, ctnl, skb, set, tb, adt, flags,
434 @@ -1855,7 +1849,7 @@ IPSET_CBFN_AD(ip_set_ad, struct net *net, struct sock *ctnl,
435 NLA_PARSE_NESTED(tb, IPSET_ATTR_ADT_MAX, nla,
436 set->type->adt_policy, NULL))
437 return -IPSET_ERR_PROTOCOL;
438 - ret = call_ad(ctnl, skb, set, tb, adt,
439 + ret = CALL_AD(net, ctnl, skb, set, tb, adt,
443 @@ -1868,20 +1862,22 @@ static int
444 IPSET_CBFN(ip_set_uadd, struct net *net, struct sock *ctnl,
445 struct sk_buff *skb, const struct nlmsghdr *nlh,
446 const struct nlattr * const attr[],
447 - struct netlink_ext_ack *extack)
448 + struct netlink_ext_ack *extack,
449 + const struct nfnl_info *info)
451 - return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb,
452 - IPSET_ADD, nlh, attr, extack);
453 + return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb,
454 + IPSET_ADD, INFO_NLH(info, nlh), attr, extack, info);
458 IPSET_CBFN(ip_set_udel, struct net *net, struct sock *ctnl,
459 struct sk_buff *skb, const struct nlmsghdr *nlh,
460 const struct nlattr * const attr[],
461 - struct netlink_ext_ack *extack)
462 + struct netlink_ext_ack *extack,
463 + const struct nfnl_info *info)
465 - return IPSET_CBFN_AD(ip_set_ad, net, ctnl, skb,
466 - IPSET_DEL, nlh, attr, extack);
467 + return IPSET_CBFN_AD(ip_set_ad, INFO_NET(info, net), INFO_SK(info, ctnl), skb,
468 + IPSET_DEL, INFO_NLH(info, nlh), attr, extack, info);
472 @@ -1889,9 +1885,10 @@ IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl,
474 const struct nlmsghdr *nlh,
475 const struct nlattr * const attr[],
476 - struct netlink_ext_ack *extack)
477 + struct netlink_ext_ack *extack,
478 + const struct nfnl_info *info)
480 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
481 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
483 struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
485 @@ -1927,13 +1924,13 @@ static int
486 IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
487 struct sk_buff *skb, const struct nlmsghdr *nlh,
488 const struct nlattr * const attr[],
489 - struct netlink_ext_ack *extack)
490 + struct netlink_ext_ack *extack,
491 + const struct nfnl_info *info)
493 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
494 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
495 const struct ip_set *set;
496 struct sk_buff *skb2;
497 struct nlmsghdr *nlh2;
500 if (unlikely(protocol_min_failed(attr) ||
501 !attr[IPSET_ATTR_SETNAME]))
502 @@ -1947,7 +1944,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
506 - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
507 + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
511 @@ -1959,11 +1956,7 @@ IPSET_CBFN(ip_set_header, struct net *net, struct sock *ctnl,
512 goto nla_put_failure;
513 nlmsg_end(skb2, nlh2);
515 - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
520 + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
523 nlmsg_cancel(skb2, nlh2);
524 @@ -1985,7 +1978,8 @@ static int
525 IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
526 struct sk_buff *skb, const struct nlmsghdr *nlh,
527 const struct nlattr * const attr[],
528 - struct netlink_ext_ack *extack)
529 + struct netlink_ext_ack *extack,
530 + const struct nfnl_info *info)
532 struct sk_buff *skb2;
533 struct nlmsghdr *nlh2;
534 @@ -2008,7 +2002,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
538 - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
539 + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
543 @@ -2021,11 +2015,7 @@ IPSET_CBFN(ip_set_type, struct net *net, struct sock *ctnl,
544 nlmsg_end(skb2, nlh2);
546 pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
547 - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
552 + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
555 nlmsg_cancel(skb2, nlh2);
556 @@ -2045,11 +2035,11 @@ static int
557 IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
558 struct sk_buff *skb, const struct nlmsghdr *nlh,
559 const struct nlattr * const attr[],
560 - struct netlink_ext_ack *extack)
561 + struct netlink_ext_ack *extack,
562 + const struct nfnl_info *info)
564 struct sk_buff *skb2;
565 struct nlmsghdr *nlh2;
568 if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
569 return -IPSET_ERR_PROTOCOL;
570 @@ -2058,7 +2048,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
574 - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
575 + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
579 @@ -2068,11 +2058,7 @@ IPSET_CBFN(ip_set_protocol, struct net *net, struct sock *ctnl,
580 goto nla_put_failure;
581 nlmsg_end(skb2, nlh2);
583 - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
588 + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
591 nlmsg_cancel(skb2, nlh2);
592 @@ -2087,14 +2073,14 @@ static int
593 IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
594 struct sk_buff *skb, const struct nlmsghdr *nlh,
595 const struct nlattr * const attr[],
596 - struct netlink_ext_ack *extack)
597 + struct netlink_ext_ack *extack,
598 + const struct nfnl_info *info)
600 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
601 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
602 struct sk_buff *skb2;
603 struct nlmsghdr *nlh2;
604 ip_set_id_t id = IPSET_INVALID_ID;
605 const struct ip_set *set;
608 if (unlikely(protocol_failed(attr) ||
609 !attr[IPSET_ATTR_SETNAME]))
610 @@ -2108,7 +2094,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
614 - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
615 + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
616 IPSET_CMD_GET_BYNAME);
619 @@ -2118,11 +2104,7 @@ IPSET_CBFN(ip_set_byname, struct net *net, struct sock *ctnl,
620 goto nla_put_failure;
621 nlmsg_end(skb2, nlh2);
623 - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
628 + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
631 nlmsg_cancel(skb2, nlh2);
632 @@ -2140,14 +2122,14 @@ static int
633 IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
634 struct sk_buff *skb, const struct nlmsghdr *nlh,
635 const struct nlattr * const attr[],
636 - struct netlink_ext_ack *extack)
637 + struct netlink_ext_ack *extack,
638 + const struct nfnl_info *info)
640 - struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl));
641 + struct ip_set_net *inst = ip_set_pernet(IPSET_SOCK_NET(net, ctnl, info));
642 struct sk_buff *skb2;
643 struct nlmsghdr *nlh2;
644 ip_set_id_t id = IPSET_INVALID_ID;
645 const struct ip_set *set;
648 if (unlikely(protocol_failed(attr) ||
649 !attr[IPSET_ATTR_INDEX]))
650 @@ -2164,7 +2146,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
654 - nlh2 = start_msg(skb2, NETLINK_PORTID(skb), nlh->nlmsg_seq, 0,
655 + nlh2 = start_msg(skb2, NETLINK_PORTID(skb), INFO_NLH(info, nlh)->nlmsg_seq, 0,
656 IPSET_CMD_GET_BYINDEX);
659 @@ -2173,11 +2155,7 @@ IPSET_CBFN(ip_set_byindex, struct net *net, struct sock *ctnl,
660 goto nla_put_failure;
661 nlmsg_end(skb2, nlh2);
663 - ret = netlink_unicast(ctnl, skb2, NETLINK_PORTID(skb), MSG_DONTWAIT);
668 + return NFNETLINK_UNICAST(INFO_SK(info, ctnl), skb2, INFO_NET(info, net), NETLINK_PORTID(skb));
671 nlmsg_cancel(skb2, nlh2);
672 @@ -2189,80 +2167,96 @@ nlmsg_failure:
673 static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
676 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
677 .attr_count = IPSET_ATTR_CMD_MAX,
679 [IPSET_CMD_CREATE] = {
680 .call = ip_set_create,
681 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
682 .attr_count = IPSET_ATTR_CMD_MAX,
683 .policy = ip_set_create_policy,
685 [IPSET_CMD_DESTROY] = {
686 .call = ip_set_destroy,
687 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
688 .attr_count = IPSET_ATTR_CMD_MAX,
689 .policy = ip_set_setname_policy,
691 [IPSET_CMD_FLUSH] = {
692 .call = ip_set_flush,
693 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
694 .attr_count = IPSET_ATTR_CMD_MAX,
695 .policy = ip_set_setname_policy,
697 [IPSET_CMD_RENAME] = {
698 .call = ip_set_rename,
699 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
700 .attr_count = IPSET_ATTR_CMD_MAX,
701 .policy = ip_set_setname2_policy,
705 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
706 .attr_count = IPSET_ATTR_CMD_MAX,
707 .policy = ip_set_setname2_policy,
711 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
712 .attr_count = IPSET_ATTR_CMD_MAX,
713 .policy = ip_set_dump_policy,
717 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
718 .attr_count = IPSET_ATTR_CMD_MAX,
719 .policy = ip_set_setname_policy,
723 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
724 .attr_count = IPSET_ATTR_CMD_MAX,
725 .policy = ip_set_adt_policy,
729 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
730 .attr_count = IPSET_ATTR_CMD_MAX,
731 .policy = ip_set_adt_policy,
734 .call = ip_set_utest,
735 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
736 .attr_count = IPSET_ATTR_CMD_MAX,
737 .policy = ip_set_adt_policy,
739 [IPSET_CMD_HEADER] = {
740 .call = ip_set_header,
741 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
742 .attr_count = IPSET_ATTR_CMD_MAX,
743 .policy = ip_set_setname_policy,
747 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
748 .attr_count = IPSET_ATTR_CMD_MAX,
749 .policy = ip_set_type_policy,
751 [IPSET_CMD_PROTOCOL] = {
752 .call = ip_set_protocol,
753 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
754 .attr_count = IPSET_ATTR_CMD_MAX,
755 .policy = ip_set_protocol_policy,
757 [IPSET_CMD_GET_BYNAME] = {
758 .call = ip_set_byname,
759 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
760 .attr_count = IPSET_ATTR_CMD_MAX,
761 .policy = ip_set_setname_policy,
763 [IPSET_CMD_GET_BYINDEX] = {
764 .call = ip_set_byindex,
765 + SET_NFNL_CALLBACK_TYPE(NFNL_CB_MUTEX)
766 .attr_count = IPSET_ATTR_CMD_MAX,
767 .policy = ip_set_index_policy,
769 diff --git a/lib/ipset.c b/lib/ipset.c
770 index 6729919..73e67db 100644
774 #include <stdio.h> /* printf */
775 #include <stdlib.h> /* exit */
776 #include <string.h> /* str* */
777 +#include <inttypes.h> /* PRIu64 */
782 #include <libipset/utils.h> /* STREQ */
783 #include <libipset/ipset.h> /* prototypes */
784 #include <libipset/ip_set_compiler.h> /* compiler attributes */
785 +#include <libipset/list_sort.h> /* lists */
787 static char program_name[] = PACKAGE;
788 static char program_version[] = PACKAGE_VERSION;
789 @@ -50,6 +52,17 @@ struct ipset {
790 char *newargv[MAX_ARGS];
792 const char *filename; /* Input/output filename */
794 + struct list_head xlate_sets;
797 +struct ipset_xlate_set {
798 + struct list_head list;
799 + char name[IPSET_MAXNAMELEN];
803 + const struct ipset_type *type;
806 /* Commands and environment options */
807 @@ -923,20 +936,33 @@ static const char *cmd_prefix[] = {
808 [IPSET_TEST] = "test SETNAME",
812 +static const struct ipset_xlate_set *
813 +ipset_xlate_set_get(struct ipset *ipset, const char *name)
815 + const struct ipset_xlate_set *set;
818 - * ipset_parse_argv - parse and argv array and execute the command
819 - * @ipset: ipset structure
820 - * @argc: length of the array
821 - * @argv: array of strings
823 - * Parse an array of strings and execute the ipset command.
825 - * Returns 0 on success or a negative error code.
828 -ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
829 + list_for_each_entry(set, &ipset->xlate_sets, list) {
830 + if (!strcmp(set->name, name))
837 +static const struct ipset_type *ipset_xlate_type_get(struct ipset *ipset,
840 + const struct ipset_xlate_set *set;
842 + set = ipset_xlate_set_get(ipset, name);
850 +ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
853 enum ipset_cmd cmd = IPSET_CMD_NONE;
854 @@ -1243,7 +1269,7 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
855 return ipset->custom_error(ipset,
856 p, IPSET_PARAMETER_PROBLEM,
857 "Unknown argument %s", argv[1]);
858 - return restore(ipset);
859 + return IPSET_CMD_RESTORE;
863 @@ -1253,7 +1279,12 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
865 return ipset->standard_error(ipset, p);
867 - type = ipset_type_get(session, cmd);
868 + if (!ipset->xlate) {
869 + type = ipset_type_get(session, cmd);
871 + type = ipset_xlate_type_get(ipset, arg0);
872 + ipset_session_data_set(session, IPSET_OPT_TYPE, type);
875 return ipset->standard_error(ipset, p);
877 @@ -1280,6 +1311,37 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
879 return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM,
880 "Unknown argument %s", argv[1]);
888 + * ipset_parse_argv - parse and argv array and execute the command
889 + * @ipset: ipset structure
890 + * @argc: length of the array
891 + * @argv: array of strings
893 + * Parse an array of strings and execute the ipset command.
895 + * Returns 0 on success or a negative error code.
898 +ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
900 + struct ipset_session *session = ipset->session;
901 + void *p = ipset_session_printf_private(session);
902 + enum ipset_cmd cmd;
905 + cmd = ipset_parser(ipset, oargc, oargv);
909 + if (cmd == IPSET_CMD_RESTORE)
910 + return restore(ipset);
912 ret = ipset_cmd(session, cmd, ipset->restore_line);
914 /* In the case of warning, the return code is success */
915 @@ -1455,6 +1517,9 @@ ipset_init(void)
918 ipset_custom_printf(ipset, NULL, NULL, NULL, NULL);
920 + INIT_LIST_HEAD(&ipset->xlate_sets);
925 @@ -1469,6 +1534,8 @@ ipset_init(void)
927 ipset_fini(struct ipset *ipset)
929 + struct ipset_xlate_set *xlate_set, *next;
934 @@ -1477,6 +1544,497 @@ ipset_fini(struct ipset *ipset)
935 if (ipset->newargv[0])
936 free(ipset->newargv[0]);
938 + list_for_each_entry_safe(xlate_set, next, &ipset->xlate_sets, list)
945 +/* Ignore the set family, use inet. */
946 +static const char *ipset_xlate_family(uint8_t family)
951 +enum ipset_xlate_set_type {
952 + IPSET_XLATE_TYPE_UNKNOWN = 0,
953 + IPSET_XLATE_TYPE_HASH_MAC,
954 + IPSET_XLATE_TYPE_HASH_IP,
955 + IPSET_XLATE_TYPE_HASH_IP_MAC,
956 + IPSET_XLATE_TYPE_HASH_NET_IFACE,
957 + IPSET_XLATE_TYPE_HASH_NET_PORT,
958 + IPSET_XLATE_TYPE_HASH_NET_PORT_NET,
959 + IPSET_XLATE_TYPE_HASH_NET_NET,
960 + IPSET_XLATE_TYPE_HASH_NET,
961 + IPSET_XLATE_TYPE_HASH_IP_PORT_NET,
962 + IPSET_XLATE_TYPE_HASH_IP_PORT_IP,
963 + IPSET_XLATE_TYPE_HASH_IP_MARK,
964 + IPSET_XLATE_TYPE_HASH_IP_PORT,
965 + IPSET_XLATE_TYPE_BITMAP_PORT,
966 + IPSET_XLATE_TYPE_BITMAP_IP_MAC,
967 + IPSET_XLATE_TYPE_BITMAP_IP,
970 +static enum ipset_xlate_set_type ipset_xlate_set_type(const char *typename)
972 + if (!strcmp(typename, "hash:mac"))
973 + return IPSET_XLATE_TYPE_HASH_MAC;
974 + else if (!strcmp(typename, "hash:ip"))
975 + return IPSET_XLATE_TYPE_HASH_IP;
976 + else if (!strcmp(typename, "hash:ip,mac"))
977 + return IPSET_XLATE_TYPE_HASH_IP_MAC;
978 + else if (!strcmp(typename, "hash:net,iface"))
979 + return IPSET_XLATE_TYPE_HASH_NET_IFACE;
980 + else if (!strcmp(typename, "hash:net,port"))
981 + return IPSET_XLATE_TYPE_HASH_NET_PORT;
982 + else if (!strcmp(typename, "hash:net,port,net"))
983 + return IPSET_XLATE_TYPE_HASH_NET_PORT_NET;
984 + else if (!strcmp(typename, "hash:net,net"))
985 + return IPSET_XLATE_TYPE_HASH_NET_NET;
986 + else if (!strcmp(typename, "hash:net"))
987 + return IPSET_XLATE_TYPE_HASH_NET;
988 + else if (!strcmp(typename, "hash:ip,port,net"))
989 + return IPSET_XLATE_TYPE_HASH_IP_PORT_NET;
990 + else if (!strcmp(typename, "hash:ip,port,ip"))
991 + return IPSET_XLATE_TYPE_HASH_IP_PORT_IP;
992 + else if (!strcmp(typename, "hash:ip,mark"))
993 + return IPSET_XLATE_TYPE_HASH_IP_MARK;
994 + else if (!strcmp(typename, "hash:ip,port"))
995 + return IPSET_XLATE_TYPE_HASH_IP_PORT;
996 + else if (!strcmp(typename, "hash:ip"))
997 + return IPSET_XLATE_TYPE_HASH_IP;
998 + else if (!strcmp(typename, "bitmap:port"))
999 + return IPSET_XLATE_TYPE_BITMAP_PORT;
1000 + else if (!strcmp(typename, "bitmap:ip,mac"))
1001 + return IPSET_XLATE_TYPE_BITMAP_IP_MAC;
1002 + else if (!strcmp(typename, "bitmap:ip"))
1003 + return IPSET_XLATE_TYPE_BITMAP_IP;
1005 + return IPSET_XLATE_TYPE_UNKNOWN;
1008 +#define NFT_SET_INTERVAL (1 << 0)
1010 +static const char *
1011 +ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type,
1015 + case IPSET_XLATE_TYPE_HASH_MAC:
1016 + return "ether_addr";
1017 + case IPSET_XLATE_TYPE_HASH_IP:
1018 + if (family == AF_INET)
1019 + return "ipv4_addr";
1020 + else if (family == AF_INET6)
1021 + return "ipv6_addr";
1023 + case IPSET_XLATE_TYPE_HASH_IP_MAC:
1024 + if (family == AF_INET)
1025 + return "ipv4_addr . ether_addr";
1026 + else if (family == AF_INET6)
1027 + return "ipv6_addr . ether_addr";
1029 + case IPSET_XLATE_TYPE_HASH_NET_IFACE:
1030 + *flags |= NFT_SET_INTERVAL;
1031 + if (family == AF_INET)
1032 + return "ipv4_addr . ifname";
1033 + else if (family == AF_INET6)
1034 + return "ipv6_addr . ifname";
1036 + case IPSET_XLATE_TYPE_HASH_NET_PORT:
1037 + *flags |= NFT_SET_INTERVAL;
1038 + if (family == AF_INET)
1039 + return "ipv4_addr . inet_proto . inet_service";
1040 + else if (family == AF_INET6)
1041 + return "ipv6_addr . inet_proto . inet_service";
1043 + case IPSET_XLATE_TYPE_HASH_NET_PORT_NET:
1044 + *flags |= NFT_SET_INTERVAL;
1045 + if (family == AF_INET)
1046 + return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
1047 + else if (family == AF_INET6)
1048 + return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
1050 + case IPSET_XLATE_TYPE_HASH_NET_NET:
1051 + *flags |= NFT_SET_INTERVAL;
1052 + if (family == AF_INET)
1053 + return "ipv4_addr . ipv4_addr";
1054 + else if (family == AF_INET6)
1055 + return "ipv6_addr . ipv6_addr";
1057 + case IPSET_XLATE_TYPE_HASH_NET:
1058 + *flags |= NFT_SET_INTERVAL;
1059 + if (family == AF_INET)
1060 + return "ipv4_addr";
1061 + else if (family == AF_INET6)
1062 + return "ipv6_addr";
1064 + case IPSET_XLATE_TYPE_HASH_IP_PORT_NET:
1065 + *flags |= NFT_SET_INTERVAL;
1066 + if (family == AF_INET)
1067 + return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
1068 + else if (family == AF_INET6)
1069 + return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
1071 + case IPSET_XLATE_TYPE_HASH_IP_PORT_IP:
1072 + if (family == AF_INET)
1073 + return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
1074 + else if (family == AF_INET6)
1075 + return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
1077 + case IPSET_XLATE_TYPE_HASH_IP_MARK:
1078 + if (family == AF_INET)
1079 + return "ipv4_addr . mark";
1080 + else if (family == AF_INET6)
1081 + return "ipv6_addr . mark";
1083 + case IPSET_XLATE_TYPE_HASH_IP_PORT:
1084 + if (family == AF_INET)
1085 + return "ipv4_addr . inet_proto . inet_service";
1086 + else if (family == AF_INET6)
1087 + return "ipv6_addr . inet_proto . inet_service";
1089 + case IPSET_XLATE_TYPE_BITMAP_PORT:
1090 + return "inet_service";
1091 + case IPSET_XLATE_TYPE_BITMAP_IP_MAC:
1092 + if (family == AF_INET)
1093 + return "ipv4_addr . ether_addr";
1094 + else if (family == AF_INET6)
1095 + return "ipv6_addr . ether_addr";
1097 + case IPSET_XLATE_TYPE_BITMAP_IP:
1098 + if (family == AF_INET)
1099 + return "ipv4_addr";
1100 + else if (family == AF_INET6)
1101 + return "ipv6_addr";
1104 + /* This should not ever happen. */
1108 +static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
1109 + const char *table)
1111 + const char *set, *typename, *nft_type;
1112 + const struct ipset_type *ipset_type;
1113 + struct ipset_xlate_set *xlate_set;
1114 + enum ipset_xlate_set_type type;
1115 + struct ipset_session *session;
1116 + const uint32_t *cadt_flags;
1117 + const uint32_t *timeout;
1118 + const uint32_t *maxelem;
1119 + struct ipset_data *data;
1120 + const uint8_t *netmask;
1121 + const char *comment;
1122 + uint32_t flags = 0;
1129 + session = ipset_session(ipset);
1130 + data = ipset_session_data(session);
1132 + set = ipset_data_get(data, IPSET_SETNAME);
1133 + family = ipset_data_family(data);
1136 + case IPSET_CMD_CREATE:
1137 + /* Not supported. */
1138 + if (ipset_data_test(data, IPSET_OPT_MARKMASK)) {
1139 + printf("# %s", ipset->cmdline);
1142 + cadt_flags = ipset_data_get(data, IPSET_OPT_CADT_FLAGS);
1145 + * - IPSET_FLAG_WITH_COMMENT
1146 + * - IPSET_FLAG_WITH_FORCEADD
1149 + (*cadt_flags & (IPSET_FLAG_BEFORE |
1150 + IPSET_FLAG_PHYSDEV |
1151 + IPSET_FLAG_NOMATCH |
1152 + IPSET_FLAG_WITH_SKBINFO |
1153 + IPSET_FLAG_IFACE_WILDCARD))) {
1154 + printf("# %s", ipset->cmdline);
1158 + typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
1159 + type = ipset_xlate_set_type(typename);
1160 + nft_type = ipset_xlate_type_to_nftables(family, type, &flags);
1162 + printf("add set %s %s %s { type %s; ",
1163 + ipset_xlate_family(family), table, set, nft_type);
1165 + if (*cadt_flags & IPSET_FLAG_WITH_COUNTERS)
1166 + printf("counter; ");
1168 + timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
1170 + printf("timeout %us; ", *timeout);
1171 + maxelem = ipset_data_get(data, IPSET_OPT_MAXELEM);
1173 + printf("size %u; ", *maxelem);
1175 + netmask = ipset_data_get(data, IPSET_OPT_NETMASK);
1177 + ((family == AF_INET && *netmask < 32) ||
1178 + (family == AF_INET6 && *netmask < 128)))
1179 + flags |= NFT_SET_INTERVAL;
1181 + if (flags & NFT_SET_INTERVAL)
1182 + printf("flags interval; ");
1184 + /* These create-specific options are safe to be ignored:
1186 + * - IPSET_OPT_HASHSIZE
1187 + * - IPSET_OPT_PROBES
1188 + * - IPSET_OPT_RESIZE
1189 + * - IPSET_OPT_SIZE
1190 + * - IPSET_OPT_FORCEADD
1192 + * Ranges and CIDR are safe to be ignored too:
1193 + * - IPSET_OPT_IP_FROM
1194 + * - IPSET_OPT_IP_TO
1195 + * - IPSET_OPT_PORT_FROM
1196 + * - IPSET_OPT_PORT_TO
1201 + xlate_set = calloc(1, sizeof(*xlate_set));
1205 + snprintf(xlate_set->name, sizeof(xlate_set->name), "%s", set);
1206 + ipset_type = ipset_types();
1207 + while (ipset_type) {
1208 + if (!strcmp(ipset_type->name, typename))
1210 + ipset_type = ipset_type->next;
1213 + xlate_set->family = family;
1214 + xlate_set->type = ipset_type;
1216 + xlate_set->netmask = *netmask;
1217 + xlate_set->interval = true;
1219 + list_add_tail(&xlate_set->list, &ipset->xlate_sets);
1221 + case IPSET_CMD_DESTROY:
1222 + printf("del set %s %s %s\n",
1223 + ipset_xlate_family(family), table, set);
1225 + case IPSET_CMD_FLUSH:
1227 + printf("# %s", ipset->cmdline);
1229 + printf("flush set %s %s %s\n",
1230 + ipset_xlate_family(family), table, set);
1233 + case IPSET_CMD_RENAME:
1234 + printf("# %s", ipset->cmdline);
1236 + case IPSET_CMD_SWAP:
1237 + printf("# %s", ipset->cmdline);
1239 + case IPSET_CMD_LIST:
1241 + printf("list sets %s\n",
1242 + ipset_xlate_family(family), table);
1244 + printf("list set %s %s %s\n",
1245 + ipset_xlate_family(family), table, set);
1248 + case IPSET_CMD_SAVE:
1249 + printf("# %s", ipset->cmdline);
1251 + case IPSET_CMD_ADD:
1252 + case IPSET_CMD_DEL:
1253 + case IPSET_CMD_TEST:
1254 + /* Not supported. */
1255 + if (ipset_data_test(data, IPSET_OPT_NOMATCH) ||
1256 + ipset_data_test(data, IPSET_OPT_SKBINFO) ||
1257 + ipset_data_test(data, IPSET_OPT_SKBMARK) ||
1258 + ipset_data_test(data, IPSET_OPT_SKBPRIO) ||
1259 + ipset_data_test(data, IPSET_OPT_SKBQUEUE) ||
1260 + ipset_data_test(data, IPSET_OPT_IFACE_WILDCARD)) {
1261 + printf("# %s", ipset->cmdline);
1264 + printf("%s element %s %s %s { ",
1265 + cmd == IPSET_CMD_ADD ? "add" :
1266 + cmd == IPSET_CMD_DEL ? "delete" : "get",
1267 + ipset_xlate_family(family), table, set);
1269 + typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
1270 + type = ipset_xlate_set_type(typename);
1272 + xlate_set = (struct ipset_xlate_set *)
1273 + ipset_xlate_set_get(ipset, set);
1274 + if (xlate_set && xlate_set->interval)
1275 + netmask = &xlate_set->netmask;
1280 + if (ipset_data_test(data, IPSET_OPT_IP)) {
1281 + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IP, 0);
1282 + printf("%s", buf);
1284 + printf("/%u ", *netmask);
1290 + if (ipset_data_test(data, IPSET_OPT_MARK)) {
1291 + ipset_print_mark(buf, sizeof(buf), data, IPSET_OPT_MARK, 0);
1292 + printf("%s%s ", concat ? ". " : "", buf);
1294 + if (ipset_data_test(data, IPSET_OPT_IFACE)) {
1295 + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IFACE, 0);
1296 + printf("%s%s ", concat ? ". " : "", buf);
1298 + if (ipset_data_test(data, IPSET_OPT_ETHER)) {
1299 + ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0);
1300 + for (i = 0; i < strlen(buf); i++)
1301 + buf[i] = tolower(buf[i]);
1303 + printf("%s%s ", concat ? ". " : "", buf);
1306 + if (ipset_data_test(data, IPSET_OPT_PORT)) {
1307 + ipset_print_proto_port(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
1308 + term = strchr(buf, ':');
1311 + printf("%s%s ", concat ? ". " : "", buf);
1313 + ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
1314 + printf("%s%s ", concat ? ". " : "", buf);
1316 + if (ipset_data_test(data, IPSET_OPT_IP2)) {
1317 + ipset_print_ip(buf, sizeof(buf), data, IPSET_OPT_IP2, 0);
1318 + printf("%s%s", concat ? ". " : "", buf);
1320 + printf("/%u ", *netmask);
1324 + if (ipset_data_test(data, IPSET_OPT_PACKETS) &&
1325 + ipset_data_test(data, IPSET_OPT_BYTES)) {
1326 + const uint64_t *pkts, *bytes;
1328 + pkts = ipset_data_get(data, IPSET_OPT_PACKETS);
1329 + bytes = ipset_data_get(data, IPSET_OPT_BYTES);
1331 + printf("counter packets %" PRIu64 " bytes %" PRIu64 " ",
1334 + timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
1336 + printf("timeout %us ", *timeout);
1338 + comment = ipset_data_get(data, IPSET_OPT_ADT_COMMENT);
1340 + printf("comment \"%s\" ", comment);
1344 + case IPSET_CMD_GET_BYNAME:
1345 + printf("# %s", ipset->cmdline);
1347 + case IPSET_CMD_GET_BYINDEX:
1348 + printf("# %s", ipset->cmdline);
1357 +static int ipset_xlate_restore(struct ipset *ipset)
1359 + struct ipset_session *session = ipset_session(ipset);
1360 + struct ipset_data *data = ipset_session_data(session);
1361 + void *p = ipset_session_printf_private(session);
1362 + const char *filename;
1363 + enum ipset_cmd cmd;
1368 + if (ipset->filename) {
1369 + f = fopen(ipset->filename, "r");
1371 + fprintf(stderr, "cannot open file `%s'\n", filename);
1376 + /* TODO: Allow to specify the table name other than 'global'. */
1377 + printf("add table inet global\n");
1379 + while (fgets(ipset->cmdline, sizeof(ipset->cmdline), f)) {
1380 + ipset->restore_line++;
1381 + c = ipset->cmdline;
1382 + while (isspace(c[0]))
1384 + if (c[0] == '\0' || c[0] == '#')
1386 + else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n"))
1389 + ret = build_argv(ipset, c);
1393 + cmd = ipset_parser(ipset, ipset->newargc, ipset->newargv);
1395 + ipset->standard_error(ipset, p);
1397 + /* TODO: Allow to specify the table name other than 'global'. */
1398 + ret = ipset_xlate(ipset, cmd, "global");
1402 + ipset_data_reset(data);
1411 +int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[])
1413 + enum ipset_cmd cmd;
1416 + ipset->xlate = true;
1418 + cmd = ipset_parser(ipset, argc, argv);
1422 + if (cmd == IPSET_CMD_RESTORE) {
1423 + ret = ipset_xlate_restore(ipset);
1425 + fprintf(stderr, "This command is not supported, "
1426 + "use `ipset-translate restore < file'\n");
1432 diff --git a/lib/parse.c b/lib/parse.c
1433 index f3f2d11..9cba252 100644
1437 #define syntax_err(fmt, args...) \
1438 ipset_err(session, "Syntax error: " fmt , ## args)
1440 +#define syntax_err_ll(errtype, fmt, args...) \
1441 + ipset_session_report(session, errtype, "Syntax error: " fmt , ## args)
1444 ipset_strchr(const char *str, const char *sep)
1446 @@ -87,7 +90,8 @@ string_to_number_ll(struct ipset_session *session,
1448 unsigned long long min,
1449 unsigned long long max,
1450 - unsigned long long *ret)
1451 + unsigned long long *ret,
1452 + enum ipset_err_type errtype)
1454 unsigned long long number = 0;
1456 @@ -104,13 +108,13 @@ string_to_number_ll(struct ipset_session *session,
1459 if (errno == ERANGE && max)
1460 - return syntax_err("'%s' is out of range %llu-%llu",
1462 + return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu",
1464 else if (errno == ERANGE)
1465 - return syntax_err("'%s' is out of range %llu-%llu",
1466 - str, min, ULLONG_MAX);
1467 + return syntax_err_ll(errtype, "'%s' is out of range %llu-%llu",
1468 + str, min, ULLONG_MAX);
1470 - return syntax_err("'%s' is invalid as number", str);
1471 + return syntax_err_ll(errtype, "'%s' is invalid as number", str);
1475 @@ -120,7 +124,7 @@ string_to_u8(struct ipset_session *session,
1477 unsigned long long num = 0;
1479 - err = string_to_number_ll(session, str, 0, 255, &num);
1480 + err = string_to_number_ll(session, str, 0, 255, &num, IPSET_ERROR);
1484 @@ -141,12 +145,13 @@ string_to_cidr(struct ipset_session *session,
1487 string_to_u16(struct ipset_session *session,
1488 - const char *str, uint16_t *ret)
1489 + const char *str, uint16_t *ret,
1490 + enum ipset_err_type errtype)
1493 unsigned long long num = 0;
1495 - err = string_to_number_ll(session, str, 0, USHRT_MAX, &num);
1496 + err = string_to_number_ll(session, str, 0, USHRT_MAX, &num, errtype);
1500 @@ -159,7 +164,8 @@ string_to_u32(struct ipset_session *session,
1502 unsigned long long num = 0;
1504 - err = string_to_number_ll(session, str, 0, UINT_MAX, &num);
1505 + err = string_to_number_ll(session, str, 0, UINT_MAX, &num,
1510 @@ -319,7 +325,7 @@ ipset_parse_port(struct ipset_session *session,
1511 assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO);
1514 - if (string_to_u16(session, str, &port) == 0) {
1515 + if (string_to_u16(session, str, &port, IPSET_WARNING) == 0) {
1516 return ipset_session_data_set(session, opt, &port);
1518 /* Error is stored as warning in session report */
1519 @@ -1335,7 +1341,8 @@ ipset_parse_timeout(struct ipset_session *session,
1520 assert(opt == IPSET_OPT_TIMEOUT);
1523 - err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum);
1524 + err = string_to_number_ll(session, str, 0, (UINT_MAX>>1)/1000, &llnum,
1527 /* Timeout is expected to be 32bits wide, so we have
1528 to convert it here */
1529 @@ -1579,7 +1586,8 @@ ipset_parse_uint64(struct ipset_session *session,
1533 - err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value);
1534 + err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value,
1539 @@ -1623,7 +1631,7 @@ ipset_parse_uint16(struct ipset_session *session,
1543 - err = string_to_u16(session, str, &value);
1544 + err = string_to_u16(session, str, &value, IPSET_ERROR);
1546 return ipset_session_data_set(session, opt, &value);
1548 diff --git a/src/Makefile.am b/src/Makefile.am
1549 index 438fcec..95dea07 100644
1550 --- a/src/Makefile.am
1551 +++ b/src/Makefile.am
1552 @@ -12,10 +12,16 @@ AM_LDFLAGS = -static
1556 -dist_man_MANS = ipset.8
1557 +dist_man_MANS = ipset.8 ipset-translate.8
1559 sparse-check: $(ipset_SOURCES:.c=.d)
1562 $(IPSET_AM_V_CHECK)\
1563 $(SPARSE) -I.. $(SPARSE_FLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) $< || :
1566 + ${LN_S} -f "${sbindir}/ipset" "${DESTDIR}${sbindir}/ipset-translate";
1569 + rm -f ${DESTDIR}${sbindir}/ipset-translate
1570 diff --git a/src/ipset-translate.8 b/src/ipset-translate.8
1571 new file mode 100644
1572 index 0000000..bb4e737
1574 +++ b/src/ipset-translate.8
1577 +.\" (C) Copyright 2021, Pablo Neira Ayuso <pablo@netfilter.org>
1579 +.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
1580 +.\" This is free documentation; you can redistribute it and/or
1581 +.\" modify it under the terms of the GNU General Public License as
1582 +.\" published by the Free Software Foundation; either version 2 of
1583 +.\" the License, or (at your option) any later version.
1585 +.\" The GNU General Public License's references to "object code"
1586 +.\" and "executables" are to be interpreted as the output of any
1587 +.\" document formatting or typesetting system, including
1588 +.\" intermediate and printed output.
1590 +.\" This manual is distributed in the hope that it will be useful,
1591 +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
1592 +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1593 +.\" GNU General Public License for more details.
1595 +.\" You should have received a copy of the GNU General Public
1596 +.\" License along with this manual; if not, see
1597 +.\" <http://www.gnu.org/licenses/>.
1600 +.TH IPSET-TRANSLATE 8 "May 31, 2021"
1603 +ipset-translate \(em translation tool to migrate from ipset to nftables
1605 +This tool allows system administrators to translate a given IP sets file
1606 +to \fBnftables(8)\fP.
1608 +The only available command is:
1611 +ipset-translate restores < file.ipt
1614 +The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by
1615 +\fBipset(8)\fP save. No set modifications occur, this tool is a text converter.
1618 +Basic operation examples.
1620 +Single command translation, assuming the original file:
1623 +create test1 hash:ip,port family inet counters timeout 300 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
1624 +add test1 1.1.1.1,udp:20
1625 +add test1 1.1.1.1,21
1626 +create test2 hash:ip,port family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
1629 +which results in the following translation:
1632 +root@machine:~# ipset-translate restore < file.ipt
1633 +add set inet global test1 { type ipv4_addr . inet_proto . inet_service; counter; timeout 300s; size 65536; }
1634 +add element inet global test1 { 1.1.1.1 . udp . 20 }
1635 +add element inet global test1 { 1.1.1.1 . tcp . 21 }
1636 +add set inet global test2 { type ipv4_addr . inet_proto . inet_service; size 65536; }
1640 +A few IP sets options may be not supported because they are not yet implemented
1641 +in \fBnftables(8)\fP.
1643 +Contrary to \fBnftables(8)\fP, IP sets are not attached to a specific table.
1644 +The translation utility assumes that sets are created in a table whose name
1645 +is \fBglobal\fP and family is \fBinet\fP. You might want to update the
1646 +resulting translation to use a different table name and family for your sets.
1648 +To get up-to-date information about this, please head to
1649 +\fBhttps://wiki.nftables.org/\fP.
1652 +\fBnft(8)\fP, \fBipset(8)\fP
1655 +The nftables framework has been written by the Netfilter Project
1656 +(https://www.netfilter.org).
1658 +This manual page was written by Pablo Neira Ayuso
1659 +<pablo@netfilter.org>.
1661 +This documentation is free/libre under the terms of the GPLv2+.
1663 +This tool was funded through the NGI0 PET Fund, a fund established by NLnet with
1664 +financial support from the European Commission's Next Generation Internet
1665 +programme, under the aegis of DG Communications Networks, Content and Technology
1666 +under grant agreement No 825310.
1667 diff --git a/src/ipset.8 b/src/ipset.8
1668 index 97cece9..269b9b5 100644
1671 @@ -333,7 +333,7 @@ are hex without 0x prefix.
1673 ipset create foo hash:ip skbinfo
1675 -ipset add foo skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10
1676 +ipset add foo 192.168.0.1 skbmark 0x1111/0xff00ffff skbprio 1:10 skbqueue 10
1679 This parameter is valid for the \fBcreate\fR command of all \fBhash\fR type sets.
1680 diff --git a/src/ipset.c b/src/ipset.c
1681 index ee36a06..6d42b60 100644
1685 #include <assert.h> /* assert */
1686 #include <stdio.h> /* fprintf */
1687 #include <stdlib.h> /* exit */
1688 +#include <string.h> /* strcmp */
1691 #include <libipset/ipset.h> /* ipset library */
1692 +#include <libipset/xlate.h> /* translate to nftables */
1695 main(int argc, char *argv[])
1696 @@ -29,7 +31,11 @@ main(int argc, char *argv[])
1700 - ret = ipset_parse_argv(ipset, argc, argv);
1701 + if (!strcmp(argv[0], "ipset-translate")) {
1702 + ret = ipset_xlate_argv(ipset, argc, argv);
1704 + ret = ipset_parse_argv(ipset, argc, argv);
1709 diff --git a/tests/xlate/runtest.sh b/tests/xlate/runtest.sh
1710 new file mode 100755
1711 index 0000000..a2a02c0
1713 +++ b/tests/xlate/runtest.sh
1718 +if [ ! -x "$DIFF" ] ; then
1719 + echo "ERROR: missing diff"
1723 +IPSET_XLATE=$(which ipset-translate)
1724 +if [ ! -x "$IPSET_XLATE" ] ; then
1725 + echo "ERROR: ipset-translate is not installed yet"
1730 +ipset-translate restore < xlate.t &> $TMP
1734 + echo -e "[\033[0;31mERROR\033[0m] failed to run ipset-translate"
1737 +${DIFF} -u xlate.t.nft $TMP
1740 + echo -e "[\033[0;32mOK\033[0m] tests are fine!"
1742 + echo -e "[\033[0;31mERROR\033[0m] unexpected ipset to nftables translation"
1744 diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t
1745 new file mode 100644
1746 index 0000000..b1e7d28
1748 +++ b/tests/xlate/xlate.t
1750 +create hip1 hash:ip
1751 +add hip1 192.168.10.2
1752 +add hip1 192.168.10.3
1753 +create hip2 hash:ip hashsize 128 bucketsize 255 timeout 4
1754 +add hip2 192.168.10.3
1755 +add hip2 192.168.10.4 timeout 10
1756 +create hip3 hash:ip counters
1757 +add hip3 192.168.10.3 packets 5 bytes 3456
1758 +create hip4 hash:ip netmask 24
1759 +add hip4 192.168.10.0
1760 +create hip5 hash:ip maxelem 24
1761 +add hip5 192.168.10.0
1762 +create hip6 hash:ip comment
1763 +add hip5 192.168.10.1
1764 +add hip5 192.168.10.2 comment "this is a comment"
1765 +create ipp1 hash:ip,port
1766 +add ipp1 192.168.10.1,0
1767 +add ipp1 192.168.10.2,5
1768 +create ipp2 hash:ip,port timeout 4
1769 +add ipp2 192.168.10.1,0 timeout 12
1770 +add ipp2 192.168.10.2,5
1771 +create ipp3 hash:ip,port counters
1772 +add ipp3 192.168.10.3,20 packets 5 bytes 3456
1773 +create ipp4 hash:ip,port timeout 4 counters
1774 +add ipp4 192.168.10.3,20 packets 5 bytes 3456
1775 +create bip1 bitmap:ip range 2.0.0.1-2.1.0.1 timeout 5
1776 +create bip2 bitmap:ip range 10.0.0.0/8 netmask 24 timeout 5
1777 +add bip2 10.10.10.0
1778 +add bip2 10.10.20.0 timeout 12
1779 +create net1 hash:net
1780 +add net1 192.168.10.0/24
1781 +create net2 hash:net,net
1782 +add net2 192.168.10.0/24,192.168.20.0/24
1783 +create hm1 hash:mac
1784 +add hm1 aa:bb:cc:dd:ee:ff
1785 +create him1 hash:ip,mac
1786 +add him1 1.1.1.1,aa:bb:cc:dd:ee:ff
1787 +create ni1 hash:net,iface
1788 +add ni1 1.1.1.0/24,eth0
1789 +create nip1 hash:net,port
1790 +add nip1 1.1.1.0/24,22
1791 +create npn1 hash:net,port,net
1792 +add npn1 1.1.1.0/24,22,2.2.2.0/24
1793 +create nn1 hash:net,net
1794 +add nn1 1.1.1.0/24,2.2.2.0/24
1795 +create ipn1 hash:ip,port,net
1796 +add ipn1 1.1.1.1,22,2.2.2.0/24
1797 +create ipi1 hash:ip,port,ip
1798 +add ipi1 1.1.1.1,22,2.2.2.2
1799 +create im1 hash:ip,mark
1800 +add im1 1.1.1.1,0x123456
1801 +create bp1 bitmap:port range 1-1024
1803 +create bim1 bitmap:ip,mac range 1.1.1.0/24
1804 +add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff
1805 diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft
1806 new file mode 100644
1807 index 0000000..96eba3b
1809 +++ b/tests/xlate/xlate.t.nft
1811 +add table inet global
1812 +add set inet global hip1 { type ipv4_addr; }
1813 +add element inet global hip1 { 192.168.10.2 }
1814 +add element inet global hip1 { 192.168.10.3 }
1815 +add set inet global hip2 { type ipv4_addr; timeout 4s; }
1816 +add element inet global hip2 { 192.168.10.3 }
1817 +add element inet global hip2 { 192.168.10.4 timeout 10s }
1818 +add set inet global hip3 { type ipv4_addr; counter; }
1819 +add element inet global hip3 { 192.168.10.3 counter packets 5 bytes 3456 }
1820 +add set inet global hip4 { type ipv4_addr; flags interval; }
1821 +add element inet global hip4 { 192.168.10.0/24 }
1822 +add set inet global hip5 { type ipv4_addr; size 24; }
1823 +add element inet global hip5 { 192.168.10.0 }
1824 +add set inet global hip6 { type ipv4_addr; }
1825 +add element inet global hip5 { 192.168.10.1 }
1826 +add element inet global hip5 { 192.168.10.2 comment "this is a comment" }
1827 +add set inet global ipp1 { type ipv4_addr . inet_proto . inet_service; }
1828 +add element inet global ipp1 { 192.168.10.1 . tcp . 0 }
1829 +add element inet global ipp1 { 192.168.10.2 . tcp . 5 }
1830 +add set inet global ipp2 { type ipv4_addr . inet_proto . inet_service; timeout 4s; }
1831 +add element inet global ipp2 { 192.168.10.1 . tcp . 0 timeout 12s }
1832 +add element inet global ipp2 { 192.168.10.2 . tcp . 5 }
1833 +add set inet global ipp3 { type ipv4_addr . inet_proto . inet_service; counter; }
1834 +add element inet global ipp3 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
1835 +add set inet global ipp4 { type ipv4_addr . inet_proto . inet_service; counter; timeout 4s; }
1836 +add element inet global ipp4 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
1837 +add set inet global bip1 { type ipv4_addr; timeout 5s; }
1838 +add set inet global bip2 { type ipv4_addr; timeout 5s; flags interval; }
1839 +add element inet global bip2 { 10.10.10.0/24 }
1840 +add element inet global bip2 { 10.10.20.0/24 timeout 12s }
1841 +add set inet global net1 { type ipv4_addr; flags interval; }
1842 +add element inet global net1 { 192.168.10.0/24 }
1843 +add set inet global net2 { type ipv4_addr . ipv4_addr; flags interval; }
1844 +add element inet global net2 { 192.168.10.0/24 . 192.168.20.0/24 }
1845 +add set inet global hm1 { type ether_addr; }
1846 +add element inet global hm1 { aa:bb:cc:dd:ee:ff }
1847 +add set inet global him1 { type ipv4_addr . ether_addr; }
1848 +add element inet global him1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
1849 +add set inet global ni1 { type ipv4_addr . ifname; flags interval; }
1850 +add element inet global ni1 { 1.1.1.0/24 . eth0 }
1851 +add set inet global nip1 { type ipv4_addr . inet_proto . inet_service; flags interval; }
1852 +add element inet global nip1 { 1.1.1.0/24 . tcp . 22 }
1853 +add set inet global npn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
1854 +add element inet global npn1 { 1.1.1.0/24 . tcp . 22 . 2.2.2.0/24 }
1855 +add set inet global nn1 { type ipv4_addr . ipv4_addr; flags interval; }
1856 +add element inet global nn1 { 1.1.1.0/24 . 2.2.2.0/24 }
1857 +add set inet global ipn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
1858 +add element inet global ipn1 { 1.1.1.1 . tcp . 22 . 2.2.2.0/24 }
1859 +add set inet global ipi1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; }
1860 +add element inet global ipi1 { 1.1.1.1 . tcp . 22 . 2.2.2.2 }
1861 +add set inet global im1 { type ipv4_addr . mark; }
1862 +add element inet global im1 { 1.1.1.1 . 0x00123456 }
1863 +add set inet global bp1 { type inet_service; }
1864 +add element inet global bp1 { 22 }
1865 +add set inet global bim1 { type ipv4_addr . ether_addr; }
1866 +add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }