@@ -3566,6 +3566,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
35663566 [NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
35673567 [NFTA_SET_HANDLE ] = { .type = NLA_U64 },
35683568 [NFTA_SET_EXPR ] = { .type = NLA_NESTED },
3569+ [NFTA_SET_EXPRESSIONS ] = { .type = NLA_NESTED },
35693570};
35703571
35713572static const struct nla_policy nft_set_desc_policy [NFTA_SET_DESC_MAX + 1 ] = {
@@ -3773,6 +3774,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
37733774 u32 portid = ctx -> portid ;
37743775 struct nlattr * nest ;
37753776 u32 seq = ctx -> seq ;
3777+ int i ;
37763778
37773779 event = nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event );
37783780 nlh = nlmsg_put (skb , portid , seq , event , sizeof (struct nfgenmsg ),
@@ -3847,6 +3849,17 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
38473849 goto nla_put_failure ;
38483850
38493851 nla_nest_end (skb , nest );
3852+ } else if (set -> num_exprs > 1 ) {
3853+ nest = nla_nest_start_noflag (skb , NFTA_SET_EXPRESSIONS );
3854+ if (nest == NULL )
3855+ goto nla_put_failure ;
3856+
3857+ for (i = 0 ; i < set -> num_exprs ; i ++ ) {
3858+ if (nft_expr_dump (skb , NFTA_LIST_ELEM ,
3859+ set -> exprs [i ]) < 0 )
3860+ goto nla_put_failure ;
3861+ }
3862+ nla_nest_end (skb , nest );
38503863 }
38513864
38523865 nlmsg_end (skb , nlh );
@@ -4215,7 +4228,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
42154228 return err ;
42164229 }
42174230
4218- if (nla [NFTA_SET_EXPR ])
4231+ if (nla [NFTA_SET_EXPR ] || nla [ NFTA_SET_EXPRESSIONS ] )
42194232 desc .expr = true;
42204233
42214234 table = nft_table_lookup (net , nla [NFTA_SET_TABLE ], family , genmask );
@@ -4281,6 +4294,29 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
42814294 }
42824295 set -> exprs [0 ] = expr ;
42834296 set -> num_exprs ++ ;
4297+ } else if (nla [NFTA_SET_EXPRESSIONS ]) {
4298+ struct nft_expr * expr ;
4299+ struct nlattr * tmp ;
4300+ int left ;
4301+
4302+ i = 0 ;
4303+ nla_for_each_nested (tmp , nla [NFTA_SET_EXPRESSIONS ], left ) {
4304+ if (i == NFT_SET_EXPR_MAX ) {
4305+ err = - E2BIG ;
4306+ goto err_set_init ;
4307+ }
4308+ if (nla_type (tmp ) != NFTA_LIST_ELEM ) {
4309+ err = - EINVAL ;
4310+ goto err_set_init ;
4311+ }
4312+ expr = nft_set_elem_expr_alloc (& ctx , set , tmp );
4313+ if (IS_ERR (expr )) {
4314+ err = PTR_ERR (expr );
4315+ goto err_set_init ;
4316+ }
4317+ set -> exprs [i ++ ] = expr ;
4318+ set -> num_exprs ++ ;
4319+ }
42844320 }
42854321
42864322 udata = NULL ;
@@ -4540,6 +4576,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
45404576 [NFTA_SET_ELEM_OBJREF ] = { .type = NLA_STRING ,
45414577 .len = NFT_OBJ_MAXNAMELEN - 1 },
45424578 [NFTA_SET_ELEM_KEY_END ] = { .type = NLA_NESTED },
4579+ [NFTA_SET_ELEM_EXPRESSIONS ] = { .type = NLA_NESTED },
45434580};
45444581
45454582static const struct nla_policy nft_set_elem_list_policy [NFTA_SET_ELEM_LIST_MAX + 1 ] = {
@@ -4580,6 +4617,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
45804617 struct nft_set_elem_expr * elem_expr ;
45814618 u32 size , num_exprs = 0 ;
45824619 struct nft_expr * expr ;
4620+ struct nlattr * nest ;
45834621
45844622 elem_expr = nft_set_ext_expr (ext );
45854623 nft_setelem_expr_foreach (expr , elem_expr , size )
@@ -4591,9 +4629,22 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
45914629 return -1 ;
45924630
45934631 return 0 ;
4594- }
4632+ } else if (num_exprs > 1 ) {
4633+ nest = nla_nest_start_noflag (skb , NFTA_SET_ELEM_EXPRESSIONS );
4634+ if (nest == NULL )
4635+ goto nla_put_failure ;
45954636
4637+ nft_setelem_expr_foreach (expr , elem_expr , size ) {
4638+ expr = nft_setelem_expr_at (elem_expr , size );
4639+ if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr ) < 0 )
4640+ goto nla_put_failure ;
4641+ }
4642+ nla_nest_end (skb , nest );
4643+ }
45964644 return 0 ;
4645+
4646+ nla_put_failure :
4647+ return -1 ;
45974648}
45984649
45994650static int nf_tables_fill_setelem (struct sk_buff * skb ,
@@ -5268,7 +5319,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
52685319 nla [NFTA_SET_ELEM_TIMEOUT ] ||
52695320 nla [NFTA_SET_ELEM_EXPIRATION ] ||
52705321 nla [NFTA_SET_ELEM_USERDATA ] ||
5271- nla [NFTA_SET_ELEM_EXPR ]))
5322+ nla [NFTA_SET_ELEM_EXPR ] ||
5323+ nla [NFTA_SET_ELEM_EXPRESSIONS ]))
52725324 return - EINVAL ;
52735325
52745326 timeout = 0 ;
@@ -5310,6 +5362,41 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
53105362 err = - EOPNOTSUPP ;
53115363 goto err_set_elem_expr ;
53125364 }
5365+ } else if (nla [NFTA_SET_ELEM_EXPRESSIONS ]) {
5366+ struct nft_expr * expr ;
5367+ struct nlattr * tmp ;
5368+ int left ;
5369+
5370+ if (set -> num_exprs == 0 )
5371+ return - EOPNOTSUPP ;
5372+
5373+ i = 0 ;
5374+ nla_for_each_nested (tmp , nla [NFTA_SET_ELEM_EXPRESSIONS ], left ) {
5375+ if (i == set -> num_exprs ) {
5376+ err = - E2BIG ;
5377+ goto err_set_elem_expr ;
5378+ }
5379+ if (nla_type (tmp ) != NFTA_LIST_ELEM ) {
5380+ err = - EINVAL ;
5381+ goto err_set_elem_expr ;
5382+ }
5383+ expr = nft_set_elem_expr_alloc (ctx , set , tmp );
5384+ if (IS_ERR (expr )) {
5385+ err = PTR_ERR (expr );
5386+ goto err_set_elem_expr ;
5387+ }
5388+ expr_array [i ] = expr ;
5389+
5390+ if (expr -> ops != set -> exprs [i ]-> ops ) {
5391+ err = - EOPNOTSUPP ;
5392+ goto err_set_elem_expr ;
5393+ }
5394+ i ++ ;
5395+ }
5396+ if (set -> num_exprs != i ) {
5397+ err = - EOPNOTSUPP ;
5398+ goto err_set_elem_expr ;
5399+ }
53135400 } else if (set -> num_exprs > 0 ) {
53145401 err = nft_set_elem_expr_clone (ctx , set , expr_array );
53155402 if (err < 0 )
0 commit comments