Skip to content

Commit 04a351a

Browse files
jmberg-inteldavem330
authored andcommitted
netlink: rework policy dump to support multiple policies
Rework the policy dump code a bit to support adding multiple policies to a single dump, in order to e.g. support per-op policies in generic netlink. v2: - move kernel-doc to implementation [Jakub] - squash the first patch to not flip-flop on the prototype [Jakub] - merge netlink_policy_dump_get_policy_idx() with the old get_policy_idx() we already had - rebase without Jakub's patch to have per-op dump Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 899b07c commit 04a351a

File tree

3 files changed

+90
-24
lines changed

3 files changed

+90
-24
lines changed

include/net/netlink.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,9 +1937,12 @@ void nla_get_range_signed(const struct nla_policy *pt,
19371937

19381938
struct netlink_policy_dump_state;
19391939

1940-
int netlink_policy_dump_start(const struct nla_policy *policy,
1941-
unsigned int maxtype,
1942-
struct netlink_policy_dump_state **state);
1940+
int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate,
1941+
const struct nla_policy *policy,
1942+
unsigned int maxtype);
1943+
int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state,
1944+
const struct nla_policy *policy,
1945+
unsigned int maxtype);
19431946
bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state);
19441947
int netlink_policy_dump_write(struct sk_buff *skb,
19451948
struct netlink_policy_dump_state *state);

net/netlink/genetlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
11501150
if (!rt->policy)
11511151
return -ENODATA;
11521152

1153-
return netlink_policy_dump_start(rt->policy, rt->maxattr, &ctx->state);
1153+
return netlink_policy_dump_add_policy(&ctx->state, rt->policy,
1154+
rt->maxattr);
11541155
}
11551156

11561157
static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)

net/netlink/policy.c

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -63,44 +63,85 @@ static int add_policy(struct netlink_policy_dump_state **statep,
6363
return 0;
6464
}
6565

66-
static unsigned int get_policy_idx(struct netlink_policy_dump_state *state,
67-
const struct nla_policy *policy,
68-
unsigned int maxtype)
66+
/**
67+
* netlink_policy_dump_get_policy_idx - retrieve policy index
68+
* @state: the policy dump state
69+
* @policy: the policy to find
70+
* @maxtype: the policy's maxattr
71+
*
72+
* Returns: the index of the given policy in the dump state
73+
*
74+
* Call this to find a policy index when you've added multiple and e.g.
75+
* need to tell userspace which command has which policy (by index).
76+
*
77+
* Note: this will WARN and return 0 if the policy isn't found, which
78+
* means it wasn't added in the first place, which would be an
79+
* internal consistency bug.
80+
*/
81+
int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state,
82+
const struct nla_policy *policy,
83+
unsigned int maxtype)
6984
{
7085
unsigned int i;
7186

87+
if (WARN_ON(!policy || !maxtype))
88+
return 0;
89+
7290
for (i = 0; i < state->n_alloc; i++) {
7391
if (state->policies[i].policy == policy &&
7492
state->policies[i].maxtype == maxtype)
7593
return i;
7694
}
7795

78-
WARN_ON_ONCE(1);
79-
return -1;
96+
WARN_ON(1);
97+
return 0;
8098
}
8199

82-
int netlink_policy_dump_start(const struct nla_policy *policy,
83-
unsigned int maxtype,
84-
struct netlink_policy_dump_state **statep)
100+
static struct netlink_policy_dump_state *alloc_state(void)
85101
{
86102
struct netlink_policy_dump_state *state;
103+
104+
state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC),
105+
GFP_KERNEL);
106+
if (!state)
107+
return ERR_PTR(-ENOMEM);
108+
state->n_alloc = INITIAL_POLICIES_ALLOC;
109+
110+
return state;
111+
}
112+
113+
/**
114+
* netlink_policy_dump_add_policy - add a policy to the dump
115+
* @pstate: state to add to, may be reallocated, must be %NULL the first time
116+
* @policy: the new policy to add to the dump
117+
* @maxtype: the new policy's max attr type
118+
*
119+
* Returns: 0 on success, a negative error code otherwise.
120+
*
121+
* Call this to allocate a policy dump state, and to add policies to it. This
122+
* should be called from the dump start() callback.
123+
*
124+
* Note: on failures, any previously allocated state is freed.
125+
*/
126+
int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate,
127+
const struct nla_policy *policy,
128+
unsigned int maxtype)
129+
{
130+
struct netlink_policy_dump_state *state = *pstate;
87131
unsigned int policy_idx;
88132
int err;
89133

90-
if (*statep)
91-
return 0;
134+
if (!state) {
135+
state = alloc_state();
136+
if (IS_ERR(state))
137+
return PTR_ERR(state);
138+
}
92139

93140
/*
94141
* walk the policies and nested ones first, and build
95142
* a linear list of them.
96143
*/
97144

98-
state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC),
99-
GFP_KERNEL);
100-
if (!state)
101-
return -ENOMEM;
102-
state->n_alloc = INITIAL_POLICIES_ALLOC;
103-
104145
err = add_policy(&state, policy, maxtype);
105146
if (err)
106147
return err;
@@ -131,8 +172,7 @@ int netlink_policy_dump_start(const struct nla_policy *policy,
131172
}
132173
}
133174

134-
*statep = state;
135-
175+
*pstate = state;
136176
return 0;
137177
}
138178

@@ -143,11 +183,26 @@ netlink_policy_dump_finished(struct netlink_policy_dump_state *state)
143183
!state->policies[state->policy_idx].policy;
144184
}
145185

186+
/**
187+
* netlink_policy_dump_loop - dumping loop indicator
188+
* @state: the policy dump state
189+
*
190+
* Returns: %true if the dump continues, %false otherwise
191+
*
192+
* Note: this frees the dump state when finishing
193+
*/
146194
bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state)
147195
{
148196
return !netlink_policy_dump_finished(state);
149197
}
150198

199+
/**
200+
* netlink_policy_dump_write - write current policy dump attributes
201+
* @skb: the message skb to write to
202+
* @state: the policy dump state
203+
*
204+
* Returns: 0 on success, an error code otherwise
205+
*/
151206
int netlink_policy_dump_write(struct sk_buff *skb,
152207
struct netlink_policy_dump_state *state)
153208
{
@@ -185,8 +240,9 @@ int netlink_policy_dump_write(struct sk_buff *skb,
185240
type = NL_ATTR_TYPE_NESTED_ARRAY;
186241
if (pt->nested_policy && pt->len &&
187242
(nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX,
188-
get_policy_idx(state, pt->nested_policy,
189-
pt->len)) ||
243+
netlink_policy_dump_get_policy_idx(state,
244+
pt->nested_policy,
245+
pt->len)) ||
190246
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
191247
pt->len)))
192248
goto nla_put_failure;
@@ -309,6 +365,12 @@ int netlink_policy_dump_write(struct sk_buff *skb,
309365
return -ENOBUFS;
310366
}
311367

368+
/**
369+
* netlink_policy_dump_free - free policy dump state
370+
* @state: the policy dump state to free
371+
*
372+
* Call this from the done() method to ensure dump state is freed.
373+
*/
312374
void netlink_policy_dump_free(struct netlink_policy_dump_state *state)
313375
{
314376
kfree(state);

0 commit comments

Comments
 (0)