144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/genl/ctrl.c Generic Netlink Controller 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup genl_mngt 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup ctrl Controller 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-generic.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/genl.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/family.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/mngt.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/ctrl.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CTRL_VERSION 0x0001 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf 3144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops genl_ctrl_ops; 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf 341155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int ctrl_request_update(struct nl_cache *c, struct nl_sock *h) 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf CTRL_VERSION, NLM_F_DUMP); 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf 4044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf .maxlen = GENL_NAMSIZ }, 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf 5044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_OP_ID] = { .type = NLA_U32 }, 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 }, 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf 5544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genl_info *info, void *arg) 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genl_family *family; 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_parser_param *pp = arg; 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf family = genl_family_alloc(); 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (family == NULL) { 648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) { 698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_MISSING_ATTR; 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) { 748a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_MISSING_ATTR; 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf family->ce_msgtype = info->nlh->nlmsg_type; 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_set_id(family, 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID])); 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_set_name(family, 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME])); 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_VERSION]) { 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]); 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_set_version(family, version); 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_HDRSIZE]) { 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]); 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_set_hdrsize(family, hdrsize); 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_MAXATTR]) { 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]); 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_set_maxattr(family, maxattr); 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (info->attrs[CTRL_ATTR_OPS]) { 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *nla, *nla_ops; 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf int remaining; 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_ops = info->attrs[CTRL_ATTR_OPS]; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_for_each_nested(nla, nla_ops, remaining) { 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTRL_ATTR_OP_MAX+1]; 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf int flags = 0, id; 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla, 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf family_op_policy); 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTRL_ATTR_OP_ID] == NULL) { 1148a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_MISSING_ATTR; 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf id = nla_get_u32(tb[CTRL_ATTR_OP_ID]); 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTRL_ATTR_OP_FLAGS]) 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]); 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf err = genl_family_add_op(family, id, flags); 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) family, pp); 13144d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_put(family); 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf 1411155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result) 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result); 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Look up generic netlink family by id in the provided cache. 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache Generic netlink family cache. 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg id Family identifier. 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Searches through the cache looking for a registered family 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf * matching the specified identifier. The caller will own a 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf * reference on the returned object which needs to be given 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf * back after usage using genl_family_put(). 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Generic netlink family object or NULL if no match was found. 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 15844d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct genl_family *genl_ctrl_search(struct nl_cache *cache, int id) 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genl_family *fam; 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cache->c_ops != &genl_ctrl_ops) 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_list_for_each_entry(fam, &cache->c_items, ce_list) { 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (fam->gf_id == id) { 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_get((struct nl_object *) fam); 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf return fam; 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Resolver 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Look up generic netlink family by family name in the provided cache. 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache Generic netlink family cache. 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name Family name. 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Searches through the cache looking for a registered family 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf * matching the specified name. The caller will own a reference 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf * on the returned object which needs to be given back after 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf * usage using genl_family_put(). 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Generic netlink family object or NULL if no match was found. 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 19244d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf const char *name) 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genl_family *fam; 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cache->c_ops != &genl_ctrl_ops) 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_list_for_each_entry(fam, &cache->c_items, ce_list) { 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!strcmp(name, fam->gf_name)) { 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_get((struct nl_object *) fam); 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf return fam; 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Resolve generic netlink family name to its identifier 2141155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name Name of generic netlink family 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Resolves the generic netlink family name to its identifer and returns 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf * it. 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return A positive identifier or a negative error code. 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2221155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_ctrl_resolve(struct nl_sock *sk, const char *name) 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache *cache; 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genl_family *family; 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf 2281155370f520cb64657e25153255cf7dc1424317fThomas Graf if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0) 2298a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf family = genl_ctrl_search_by_name(cache, name); 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (family == NULL) { 2338a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_OBJ_NOTFOUND; 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf err = genl_family_get_id(family); 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_family_put(family); 23944d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_free(cache); 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct genl_cmd genl_cmds[] = { 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf { 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_id = CTRL_CMD_NEWFAMILY, 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_name = "NEWFAMILY" , 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_maxattr = CTRL_ATTR_MAX, 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_attr_policy = ctrl_policy, 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_msg_parser = ctrl_msg_parser, 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf { 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_id = CTRL_CMD_DELFAMILY, 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_name = "DELFAMILY" , 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf { 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_id = CTRL_CMD_GETFAMILY, 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_name = "GETFAMILY" , 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf { 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_id = CTRL_CMD_NEWOPS, 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_name = "NEWOPS" , 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf { 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_id = CTRL_CMD_DELOPS, 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf .c_name = "DELOPS" , 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf 27344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct genl_ops genl_ops = { 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf .o_cmds = genl_cmds, 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf .o_ncmds = ARRAY_SIZE(genl_cmds), 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 27944d362409d5469aed47d19e7908d19bd194493aThomas Grafextern struct nl_object_ops genl_family_ops; 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf 28244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops genl_ctrl_ops = { 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "genl/family", 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_hdrsize = GENL_HDRSIZE(0), 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"), 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_genl = &genl_ops, 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_GENERIC, 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = ctrl_request_update, 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &genl_family_ops, 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf 29244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init ctrl_init(void) 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_register(&genl_ctrl_ops); 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf 29744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit ctrl_exit(void) 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf genl_unregister(&genl_ctrl_ops); 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 303