20 #include <netlink-generic.h> 21 #include <netlink/netlink.h> 22 #include <netlink/genl/genl.h> 23 #include <netlink/genl/family.h> 24 #include <netlink/genl/mngt.h> 25 #include <netlink/genl/ctrl.h> 26 #include <netlink/utils.h> 29 #define CTRL_VERSION 0x0001 34 static int ctrl_request_update(
struct nl_cache *c,
struct nl_handle *h)
40 static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
42 [CTRL_ATTR_FAMILY_NAME] = { .type =
NLA_STRING,
43 .maxlen = GENL_NAMSIZ },
44 [CTRL_ATTR_VERSION] = { .type =
NLA_U32 },
45 [CTRL_ATTR_HDRSIZE] = { .type =
NLA_U32 },
46 [CTRL_ATTR_MAXATTR] = { .type =
NLA_U32 },
50 static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
52 [CTRL_ATTR_OP_FLAGS] = { .type =
NLA_U32 },
56 struct genl_info *info,
void *arg)
58 struct genl_family *family;
62 family = genl_family_alloc();
64 err = nl_errno(ENOMEM);
68 if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
69 err = nl_error(EINVAL,
"Missing family name TLV");
73 if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
74 err = nl_error(EINVAL,
"Missing family id TLV");
78 family->ce_msgtype = info->nlh->nlmsg_type;
79 genl_family_set_id(family,
81 genl_family_set_name(family,
84 if (info->attrs[CTRL_ATTR_VERSION]) {
85 uint32_t version =
nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
86 genl_family_set_version(family, version);
89 if (info->attrs[CTRL_ATTR_HDRSIZE]) {
90 uint32_t hdrsize =
nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
91 genl_family_set_hdrsize(family, hdrsize);
94 if (info->attrs[CTRL_ATTR_MAXATTR]) {
95 uint32_t maxattr =
nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
96 genl_family_set_maxattr(family, maxattr);
99 if (info->attrs[CTRL_ATTR_OPS]) {
100 struct nlattr *nla, *nla_ops;
103 nla_ops = info->attrs[CTRL_ATTR_OPS];
105 struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
113 if (tb[CTRL_ATTR_OP_ID] == NULL) {
114 err = nl_errno(EINVAL);
120 if (tb[CTRL_ATTR_OP_FLAGS])
123 err = genl_family_add_op(family,
id, flags);
130 err = pp->pp_cb((
struct nl_object *) family, pp);
137 genl_family_put(family);
146 struct nl_cache *genl_ctrl_alloc_cache(
struct nl_handle *handle)
148 struct nl_cache * cache;
176 struct genl_family *fam;
178 if (cache->c_ops != &genl_ctrl_ops)
181 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
182 if (fam->gf_id ==
id) {
211 struct genl_family *fam;
213 if (cache->c_ops != &genl_ctrl_ops)
216 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
217 if (!strcmp(name, fam->gf_name)) {
240 struct nl_cache *cache;
241 struct genl_family *family;
244 cache = genl_ctrl_alloc_cache(handle);
246 return nl_get_errno();
249 if (family == NULL) {
250 err = nl_error(ENOENT,
"Generic Netlink Family not found");
254 err = genl_family_get_id(family);
255 genl_family_put(family);
264 static struct genl_cmd genl_cmds[] = {
266 .
c_id = CTRL_CMD_NEWFAMILY,
267 .c_name =
"NEWFAMILY" ,
268 .c_maxattr = CTRL_ATTR_MAX,
269 .c_attr_policy = ctrl_policy,
270 .c_msg_parser = ctrl_msg_parser,
273 .c_id = CTRL_CMD_DELFAMILY,
274 .c_name =
"DELFAMILY" ,
277 .c_id = CTRL_CMD_GETFAMILY,
278 .c_name =
"GETFAMILY" ,
281 .c_id = CTRL_CMD_NEWOPS,
285 .c_id = CTRL_CMD_DELOPS,
292 .o_ncmds = ARRAY_SIZE(genl_cmds),
300 .co_name =
"genl/family",
301 .co_hdrsize = GENL_HDRSIZE(0),
302 .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL,
"nlctrl"),
304 .co_protocol = NETLINK_GENERIC,
305 .co_request_update = ctrl_request_update,
306 .co_obj_ops = &genl_family_ops,
309 static void __init ctrl_init(
void)
314 static void __exit ctrl_exit(
void)
uint16_t nla_get_u16(struct nlattr *nla)
Return payload of u16 attribute.
int genl_register(struct nl_cache_ops *ops)
Register generic netlink operations.
attribute validation policy
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
struct genl_family * genl_ctrl_search_by_name(struct nl_cache *cache, const char *name)
Look up generic netlink family by family name in the provided cache.
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
int genl_ctrl_resolve(struct nl_handle *handle, const char *name)
Resolve generic netlink family name to its identifier.
int c_id
Unique command identifier.
#define NLM_F_DUMP
Dump all entries.
void genl_unregister(struct nl_cache_ops *ops)
Unregister generic netlink operations.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
parse nested attributes
Generic Netlink Operations.
#define nla_for_each_nested(pos, nla, rem)
iterate over a stream of nested attributes
char * nla_get_string(struct nlattr *nla)
return payload of string attribute
int genl_send_simple(struct nl_handle *handle, int family, int cmd, int version, int flags)
Send trivial generic netlink message.
uint16_t type
Type of attribute or NLA_UNSPEC.
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
struct genl_family * genl_ctrl_search(struct nl_cache *cache, int id)
Look up generic netlink family by id in the provided cache.