15#include <netlink-private/genl.h>
16#include <netlink/netlink.h>
17#include <netlink/genl/genl.h>
18#include <netlink/genl/mngt.h>
19#include <netlink/genl/family.h>
20#include <netlink/genl/ctrl.h>
21#include <netlink/utils.h>
23#include "netlink-private/utils.h"
27static NL_LIST_HEAD(genl_ops_list);
34 for (i = 0; i < ops->
o_ncmds; i++) {
36 if (cmd->
c_id == cmd_id)
43static int cmd_msg_parser(
struct sockaddr_nl *who,
struct nlmsghdr *nlh,
44 struct genl_ops *ops,
struct nl_cache_ops *cache_ops,
void *arg)
46 _nl_auto_free
struct nlattr **tb_free = NULL;
48 struct genlmsghdr *ghdr;
54 if (!(cmd = lookup_cmd(ops, ghdr->cmd)))
55 return -NLE_MSGTYPE_NOSUPPORT;
58 return -NLE_OPNOTSUPP;
60 tb = _nl_malloc_maybe_a (300, (((
size_t) cmd->
c_maxattr) + 1u) * sizeof (
struct nlattr *), &tb_free);
85static int genl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *
who,
86 struct nlmsghdr *
nlh,
struct nl_parser_param *pp)
88 if (ops->co_genl == NULL)
91 return cmd_msg_parser(
who,
nlh, ops->co_genl, ops, pp);
94static struct genl_ops *lookup_family(
int family)
98 nl_list_for_each_entry(ops, &genl_ops_list,
o_list) {
99 if (ops->
o_id == family)
106static struct genl_ops *lookup_family_by_name(
const char *name)
110 nl_list_for_each_entry(ops, &genl_ops_list,
o_list) {
111 if (!strcmp(ops->
o_name, name))
118char *genl_op2name(
int family,
int op,
char *buf,
size_t len)
123 if ((ops = lookup_family(family))) {
124 for (i = 0; i < ops->
o_ncmds; i++) {
128 if (cmd->
c_id == op) {
129 _nl_strncpy_trunc(buf, cmd->
c_name, len);
135 _nl_strncpy_trunc(buf,
"unknown", len);
172 if (ops->
o_id && lookup_family(ops->
o_id))
175 if (lookup_family_by_name(ops->
o_name))
178 nl_list_add_tail(&ops->
o_list, &genl_ops_list);
196 nl_list_del(&ops->
o_list);
216 if (!(ops = lookup_family(nlh->nlmsg_type)))
217 return -NLE_MSGTYPE_NOSUPPORT;
219 return cmd_msg_parser(nlmsg_get_src(msg), nlh, ops, NULL, arg);
245 if (ops->co_protocol != NETLINK_GENERIC) {
246 err = -NLE_PROTO_MISMATCH;
250 if (ops->co_hdrsize < GENL_HDRSIZE(0)) {
255 if (ops->co_genl == NULL) {
260 ops->co_genl->o_cache_ops = ops;
261 ops->co_genl->o_hdrsize = ops->co_hdrsize - GENL_HDRLEN;
262 ops->co_genl->o_name = ops->co_msgtypes[0].mt_name;
263 ops->co_genl->o_id = ops->co_msgtypes[0].mt_id;
264 ops->co_msg_parser = genl_msg_parser;
291static int __genl_ops_resolve(
struct nl_cache *ctrl,
struct genl_ops *ops)
293 struct genl_family *family;
296 if (family != NULL) {
307 return -NLE_OBJ_NOTFOUND;
310int genl_resolve_id(
struct genl_ops *ops)
353 struct nl_cache *ctrl;
359 err = __genl_ops_resolve(ctrl, ops);
381 struct nl_cache *ctrl;
388 nl_list_for_each_entry(ops, &genl_ops_list,
o_list) {
389 err = __genl_ops_resolve(ctrl, ops);
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Allocate a new controller cache.
struct genl_family * genl_ctrl_search_by_name(struct nl_cache *cache, const char *name)
Search controller cache for a family name match.
void genl_family_put(struct genl_family *family)
Release reference on Generic Netlink family object.
unsigned int genl_family_get_id(struct genl_family *family)
Return numeric identifier.
int genl_register(struct nl_cache_ops *ops)
Register Generic Netlink family backed cache.
int genl_mngt_resolve(struct nl_sock *sk)
Resolve all registered Generic Netlink families.
void genl_unregister(struct nl_cache_ops *ops)
Unregister cache based Generic Netlink family.
int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
Resolve a single Generic Netlink family.
int genl_unregister_family(struct genl_ops *ops)
Unregister Generic Netlink family.
int genl_register_family(struct genl_ops *ops)
Register Generic Netlink family and associated commands.
int genl_handle_msg(struct nl_msg *msg, void *arg)
Run a received message through the demultiplexer.
struct genlmsghdr * genlmsg_hdr(struct nlmsghdr *nlh)
Return pointer to Generic Netlink header.
void * genlmsg_user_hdr(const struct genlmsghdr *gnlh)
Return pointer to user header.
int genl_connect(struct nl_sock *sk)
Connect a Generic Netlink socket.
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
Validate Generic Netlink message headers.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
void nl_socket_free(struct nl_sock *sk)
Free a netlink socket.
Definition of a Generic Netlink command.
struct nla_policy * c_attr_policy
Attribute validation policy, enforced before the callback is called.
int c_id
Numeric command identifier (required)
char * c_name
Human readable name (required)
int(* c_msg_parser)(struct nl_cache_ops *, struct genl_cmd *, struct genl_info *, void *)
Called whenever a message for this command is received.
int c_maxattr
Maximum attribute identifier that the command is prepared to handle.
Informative structure passed on to message parser callbacks.
struct nlmsghdr * nlh
Pointer to Netlink message header.
struct sockaddr_nl * who
Socket address of sender.
Definition of a Generic Netlink family.
int o_ncmds
Number of elements in o_cmds array.
unsigned int o_hdrsize
Length of user header.
struct nl_list_head o_list
Used internally to link together all registered operations.
char * o_name
Human readable name, used by genl_ops_resolve() to resolve numeric id.
int o_id
Numeric identifier, automatically filled in by genl_ops_resolve()
struct genl_cmd * o_cmds
Optional array defining the available Generic Netlink commands.
struct nl_cache_ops * o_cache_ops
If registered via genl_register(), will point to the related cache operations.