Skip to content

Commit 50a896c

Browse files
jmberg-inteldavem330
authored andcommitted
genetlink: properly support per-op policy dumping
Add support for per-op policy dumping. The data is pretty much as before, except that now the assumption that the policy with index 0 is "the" policy no longer holds - you now need to look at the new CTRL_ATTR_OP_POLICY attribute which is a nested attr (indexed by op) containing attributes for do and dump policies. When a single op is requested, the CTRL_ATTR_OP_POLICY will be added in the same way, since do and dump policies may differ. v2: - conditionally advertise per-command policies only if there actually is a policy being used for the do/dump and it's present at all Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent aa85ee5 commit 50a896c

File tree

2 files changed

+102
-10
lines changed

2 files changed

+102
-10
lines changed

include/uapi/linux/genetlink.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ enum {
6464
CTRL_ATTR_OPS,
6565
CTRL_ATTR_MCAST_GROUPS,
6666
CTRL_ATTR_POLICY,
67+
CTRL_ATTR_OP_POLICY,
6768
__CTRL_ATTR_MAX,
6869
};
6970

@@ -85,6 +86,15 @@ enum {
8586
__CTRL_ATTR_MCAST_GRP_MAX,
8687
};
8788

89+
enum {
90+
CTRL_ATTR_POLICY_UNSPEC,
91+
CTRL_ATTR_POLICY_DO,
92+
CTRL_ATTR_POLICY_DUMP,
93+
94+
__CTRL_ATTR_POLICY_DUMP_MAX,
95+
CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1
96+
};
97+
8898
#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
8999

90100

net/netlink/genetlink.c

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,10 @@ static int genl_ctrl_event(int event, const struct genl_family *family,
11121112

11131113
struct ctrl_dump_policy_ctx {
11141114
struct netlink_policy_dump_state *state;
1115+
const struct genl_family *rt;
1116+
unsigned int opidx;
11151117
u16 fam_id;
1118+
u8 policies:1;
11161119
};
11171120

11181121
static const struct nla_policy ctrl_policy_policy[] = {
@@ -1127,6 +1130,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
11271130
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
11281131
struct nlattr **tb = info->attrs;
11291132
const struct genl_family *rt;
1133+
struct genl_ops op;
1134+
int err, i;
11301135

11311136
BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
11321137

@@ -1147,11 +1152,23 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
11471152
if (!rt)
11481153
return -ENOENT;
11491154

1150-
if (!rt->policy)
1151-
return -ENODATA;
1155+
ctx->rt = rt;
1156+
1157+
for (i = 0; i < genl_get_cmd_cnt(rt); i++) {
1158+
genl_get_cmd_by_index(i, rt, &op);
1159+
1160+
if (op.policy) {
1161+
err = netlink_policy_dump_add_policy(&ctx->state,
1162+
op.policy,
1163+
op.maxattr);
1164+
if (err)
1165+
return err;
1166+
}
1167+
}
11521168

1153-
return netlink_policy_dump_add_policy(&ctx->state, rt->policy,
1154-
rt->maxattr);
1169+
if (!ctx->state)
1170+
return -ENODATA;
1171+
return 0;
11551172
}
11561173

11571174
static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
@@ -1172,12 +1189,78 @@ static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
11721189
return hdr;
11731190
}
11741191

1192+
static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
1193+
struct netlink_callback *cb,
1194+
struct genl_ops *op)
1195+
{
1196+
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
1197+
struct nlattr *nest_pol, *nest_op;
1198+
void *hdr;
1199+
int idx;
1200+
1201+
/* skip if we have nothing to show */
1202+
if (!op->policy)
1203+
return 0;
1204+
if (!op->doit &&
1205+
(!op->dumpit || op->validate & GENL_DONT_VALIDATE_DUMP))
1206+
return 0;
1207+
1208+
hdr = ctrl_dumppolicy_prep(skb, cb);
1209+
if (!hdr)
1210+
return -ENOBUFS;
1211+
1212+
nest_pol = nla_nest_start(skb, CTRL_ATTR_OP_POLICY);
1213+
if (!nest_pol)
1214+
goto err;
1215+
1216+
nest_op = nla_nest_start(skb, op->cmd);
1217+
if (!nest_op)
1218+
goto err;
1219+
1220+
/* for now both do/dump are always the same */
1221+
idx = netlink_policy_dump_get_policy_idx(ctx->state,
1222+
op->policy,
1223+
op->maxattr);
1224+
1225+
if (op->doit && nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx))
1226+
goto err;
1227+
1228+
if (op->dumpit && !(op->validate & GENL_DONT_VALIDATE_DUMP) &&
1229+
nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx))
1230+
goto err;
1231+
1232+
nla_nest_end(skb, nest_op);
1233+
nla_nest_end(skb, nest_pol);
1234+
genlmsg_end(skb, hdr);
1235+
1236+
return 0;
1237+
err:
1238+
genlmsg_cancel(skb, hdr);
1239+
return -ENOBUFS;
1240+
}
1241+
11751242
static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
11761243
{
11771244
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
1245+
void *hdr;
1246+
1247+
if (!ctx->policies) {
1248+
while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) {
1249+
struct genl_ops op;
1250+
1251+
genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op);
1252+
1253+
if (ctrl_dumppolicy_put_op(skb, cb, &op))
1254+
return skb->len;
1255+
1256+
ctx->opidx++;
1257+
}
1258+
1259+
/* completed with the per-op policy index list */
1260+
ctx->policies = true;
1261+
}
11781262

11791263
while (netlink_policy_dump_loop(ctx->state)) {
1180-
void *hdr;
11811264
struct nlattr *nest;
11821265

11831266
hdr = ctrl_dumppolicy_prep(skb, cb);
@@ -1194,14 +1277,13 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
11941277
nla_nest_end(skb, nest);
11951278

11961279
genlmsg_end(skb, hdr);
1197-
continue;
1198-
1199-
nla_put_failure:
1200-
genlmsg_cancel(skb, hdr);
1201-
break;
12021280
}
12031281

12041282
return skb->len;
1283+
1284+
nla_put_failure:
1285+
genlmsg_cancel(skb, hdr);
1286+
return skb->len;
12051287
}
12061288

12071289
static int ctrl_dumppolicy_done(struct netlink_callback *cb)

0 commit comments

Comments
 (0)