rtnl_link: add basic IFLA_INFO_* handling

Dispatch for IFLA_INFO_* attributes should be performed based on the
string provided in a IFLA_INFO_KIND attribute.

* nlattr.h (struct ifla_linkinfo_ctx): New type definition.
* rtnl_link.c (decode_nla_linkinfo_kind): New function.
(ifla_linkinfo_nla_decoders) <IFLA_INFO_KIND>: Use
decode_nla_linkinfo_kind as decoder.
(decode_ifla_linkinfo): Add struct ifla_linkinfo_ctx context, pass it to
the decode_nlattr call as opaque data.
This commit is contained in:
Eugene Syromyatnikov 2018-05-18 17:42:18 +02:00 committed by Dmitry V. Levin
parent 97eb4367e4
commit 7503a0f9e4
2 changed files with 37 additions and 2 deletions

View File

@ -44,6 +44,16 @@ struct decode_nla_xlat_opts {
size_t size;
};
/*
* Used for IFLA_LINKINFO decoding. Since there are no other indicators
* regarding the nature of data except for previously provided string
* in an IFLA_LINKINFO_KIND attribute, we have to store it in order to pass
* between calls as an opaque data.
*/
struct ifla_linkinfo_ctx {
char kind[16];
};
typedef bool (*nla_decoder_t)(struct tcb *, kernel_ulong_t addr,
unsigned int len, const void *opaque_data);

View File

@ -206,8 +206,31 @@ decode_rtnl_link_ifmap(struct tcb *const tcp,
return true;
}
bool
decode_nla_linkinfo_kind(struct tcb *const tcp,
const kernel_ulong_t addr,
const unsigned int len,
const void *const opaque_data)
{
struct ifla_linkinfo_ctx *ctx = (void *) opaque_data;
memset(ctx->kind, '\0', sizeof(ctx->kind));
if (umovestr(tcp, addr, sizeof(ctx->kind), ctx->kind) <= 0) {
/*
* If we haven't seen NUL or an error occurred, set kind to
* an empty string.
*/
ctx->kind[0] = '\0';
}
printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
return true;
}
static const nla_decoder_t ifla_linkinfo_nla_decoders[] = {
[IFLA_INFO_KIND] = decode_nla_str,
[IFLA_INFO_KIND] = decode_nla_linkinfo_kind,
[IFLA_INFO_DATA] = NULL, /* unimplemented */
[IFLA_INFO_XSTATS] = NULL, /* unimplemented */
[IFLA_INFO_SLAVE_KIND] = decode_nla_str,
@ -220,9 +243,11 @@ decode_ifla_linkinfo(struct tcb *const tcp,
const unsigned int len,
const void *const opaque_data)
{
struct ifla_linkinfo_ctx ctx = { .kind = "", };
decode_nlattr(tcp, addr, len, rtnl_ifla_info_attrs,
"IFLA_INFO_???", ifla_linkinfo_nla_decoders,
ARRAY_SIZE(ifla_linkinfo_nla_decoders), opaque_data);
ARRAY_SIZE(ifla_linkinfo_nla_decoders), &ctx);
return true;
}