@@ -23,6 +23,7 @@ struct nft_ng_inc {
23
23
enum nft_registers dreg :8 ;
24
24
u32 modulus ;
25
25
atomic_t counter ;
26
+ u32 offset ;
26
27
};
27
28
28
29
static void nft_ng_inc_eval (const struct nft_expr * expr ,
@@ -37,13 +38,14 @@ static void nft_ng_inc_eval(const struct nft_expr *expr,
37
38
nval = (oval + 1 < priv -> modulus ) ? oval + 1 : 0 ;
38
39
} while (atomic_cmpxchg (& priv -> counter , oval , nval ) != oval );
39
40
40
- regs -> data [priv -> dreg ] = nval ;
41
+ regs -> data [priv -> dreg ] = nval + priv -> offset ;
41
42
}
42
43
43
44
static const struct nla_policy nft_ng_policy [NFTA_NG_MAX + 1 ] = {
44
45
[NFTA_NG_DREG ] = { .type = NLA_U32 },
45
46
[NFTA_NG_MODULUS ] = { .type = NLA_U32 },
46
47
[NFTA_NG_TYPE ] = { .type = NLA_U32 },
48
+ [NFTA_NG_OFFSET ] = { .type = NLA_U32 },
47
49
};
48
50
49
51
static int nft_ng_inc_init (const struct nft_ctx * ctx ,
@@ -52,10 +54,16 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
52
54
{
53
55
struct nft_ng_inc * priv = nft_expr_priv (expr );
54
56
57
+ if (tb [NFTA_NG_OFFSET ])
58
+ priv -> offset = ntohl (nla_get_be32 (tb [NFTA_NG_OFFSET ]));
59
+
55
60
priv -> modulus = ntohl (nla_get_be32 (tb [NFTA_NG_MODULUS ]));
56
61
if (priv -> modulus == 0 )
57
62
return - ERANGE ;
58
63
64
+ if (priv -> offset + priv -> modulus - 1 < priv -> offset )
65
+ return - EOVERFLOW ;
66
+
59
67
priv -> dreg = nft_parse_register (tb [NFTA_NG_DREG ]);
60
68
atomic_set (& priv -> counter , 0 );
61
69
@@ -64,14 +72,16 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
64
72
}
65
73
66
74
static int nft_ng_dump (struct sk_buff * skb , enum nft_registers dreg ,
67
- u32 modulus , enum nft_ng_types type )
75
+ u32 modulus , enum nft_ng_types type , u32 offset )
68
76
{
69
77
if (nft_dump_register (skb , NFTA_NG_DREG , dreg ))
70
78
goto nla_put_failure ;
71
79
if (nla_put_be32 (skb , NFTA_NG_MODULUS , htonl (modulus )))
72
80
goto nla_put_failure ;
73
81
if (nla_put_be32 (skb , NFTA_NG_TYPE , htonl (type )))
74
82
goto nla_put_failure ;
83
+ if (nla_put_be32 (skb , NFTA_NG_OFFSET , htonl (offset )))
84
+ goto nla_put_failure ;
75
85
76
86
return 0 ;
77
87
@@ -83,12 +93,14 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr)
83
93
{
84
94
const struct nft_ng_inc * priv = nft_expr_priv (expr );
85
95
86
- return nft_ng_dump (skb , priv -> dreg , priv -> modulus , NFT_NG_INCREMENTAL );
96
+ return nft_ng_dump (skb , priv -> dreg , priv -> modulus , NFT_NG_INCREMENTAL ,
97
+ priv -> offset );
87
98
}
88
99
89
100
struct nft_ng_random {
90
101
enum nft_registers dreg :8 ;
91
102
u32 modulus ;
103
+ u32 offset ;
92
104
};
93
105
94
106
static void nft_ng_random_eval (const struct nft_expr * expr ,
@@ -97,9 +109,10 @@ static void nft_ng_random_eval(const struct nft_expr *expr,
97
109
{
98
110
struct nft_ng_random * priv = nft_expr_priv (expr );
99
111
struct rnd_state * state = this_cpu_ptr (& nft_numgen_prandom_state );
112
+ u32 val ;
100
113
101
- regs -> data [ priv -> dreg ] = reciprocal_scale (prandom_u32_state (state ),
102
- priv -> modulus ) ;
114
+ val = reciprocal_scale (prandom_u32_state (state ), priv -> modulus );
115
+ regs -> data [ priv -> dreg ] = val + priv -> offset ;
103
116
}
104
117
105
118
static int nft_ng_random_init (const struct nft_ctx * ctx ,
@@ -108,10 +121,16 @@ static int nft_ng_random_init(const struct nft_ctx *ctx,
108
121
{
109
122
struct nft_ng_random * priv = nft_expr_priv (expr );
110
123
124
+ if (tb [NFTA_NG_OFFSET ])
125
+ priv -> offset = ntohl (nla_get_be32 (tb [NFTA_NG_OFFSET ]));
126
+
111
127
priv -> modulus = ntohl (nla_get_be32 (tb [NFTA_NG_MODULUS ]));
112
128
if (priv -> modulus == 0 )
113
129
return - ERANGE ;
114
130
131
+ if (priv -> offset + priv -> modulus - 1 < priv -> offset )
132
+ return - EOVERFLOW ;
133
+
115
134
prandom_init_once (& nft_numgen_prandom_state );
116
135
117
136
priv -> dreg = nft_parse_register (tb [NFTA_NG_DREG ]);
@@ -124,7 +143,8 @@ static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr)
124
143
{
125
144
const struct nft_ng_random * priv = nft_expr_priv (expr );
126
145
127
- return nft_ng_dump (skb , priv -> dreg , priv -> modulus , NFT_NG_RANDOM );
146
+ return nft_ng_dump (skb , priv -> dreg , priv -> modulus , NFT_NG_RANDOM ,
147
+ priv -> offset );
128
148
}
129
149
130
150
static struct nft_expr_type nft_ng_type ;
0 commit comments