1 /* 2 * lib/genl/mngt.c Generic Netlink Management 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12 /** 13 * @ingroup genl 14 * @defgroup genl_mngt Management 15 * 16 * @par 1) Registering a generic netlink module 17 * @code 18 * #include <netlink/genl/mngt.h> 19 * 20 * // First step is to define all the commands being used in 21 * // particular generic netlink family. The ID and name are 22 * // mandatory to be filled out. A callback function and 23 * // most the attribute policy that comes with it must be 24 * // defined for commands expected to be issued towards 25 * // userspace. 26 * static struct genl_cmd foo_cmds[] = { 27 * { 28 * .c_id = FOO_CMD_NEW, 29 * .c_name = "NEWFOO" , 30 * .c_maxattr = FOO_ATTR_MAX, 31 * .c_attr_policy = foo_policy, 32 * .c_msg_parser = foo_msg_parser, 33 * }, 34 * { 35 * .c_id = FOO_CMD_DEL, 36 * .c_name = "DELFOO" , 37 * }, 38 * }; 39 * 40 * // The list of commands must then be integrated into a 41 * // struct genl_ops serving as handle for this particular 42 * // family. 43 * static struct genl_ops my_genl_ops = { 44 * .o_cmds = foo_cmds, 45 * .o_ncmds = ARRAY_SIZE(foo_cmds), 46 * }; 47 * 48 * // Using the above struct genl_ops an arbitary number of 49 * // cache handles can be associated to it. 50 * // 51 * // The macro GENL_HDRSIZE() must be used to specify the 52 * // length of the header to automatically take headers on 53 * // generic layers into account. 54 * // 55 * // The macro GENL_FAMILY() is used to represent the generic 56 * // netlink family id. 57 * static struct nl_cache_ops genl_foo_ops = { 58 * .co_name = "genl/foo", 59 * .co_hdrsize = GENL_HDRSIZE(sizeof(struct my_hdr)), 60 * .co_msgtypes = GENL_FAMILY(GENL_ID_GENERATE, "foo"), 61 * .co_genl = &my_genl_ops, 62 * .co_protocol = NETLINK_GENERIC, 63 * .co_request_update = foo_request_update, 64 * .co_obj_ops = &genl_foo_ops, 65 * }; 66 * 67 * // Finally each cache handle for a generic netlink family 68 * // must be registered using genl_register(). 69 * static void __init foo_init(void) 70 * { 71 * genl_register(&genl_foo_ops); 72 * } 73 * 74 * // ... respectively unregsted again. 75 * static void __exit foo_exit(void) 76 * { 77 * genl_unregister(&genl_foo_ops); 78 * } 79 * @endcode 80 * @{ 81 */ 82 83 #include <netlink-generic.h> 84 #include <netlink/netlink.h> 85 #include <netlink/genl/genl.h> 86 #include <netlink/genl/mngt.h> 87 #include <netlink/genl/family.h> 88 #include <netlink/genl/ctrl.h> 89 #include <netlink/utils.h> 90 91 static NL_LIST_HEAD(genl_ops_list); 92 93 static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 94 struct nlmsghdr *nlh, struct nl_parser_param *pp) 95 { 96 int i, err; 97 struct genlmsghdr *ghdr; 98 struct genl_cmd *cmd; 99 100 ghdr = nlmsg_data(nlh); 101 102 if (ops->co_genl == NULL) 103 BUG(); 104 105 for (i = 0; i < ops->co_genl->o_ncmds; i++) { 106 cmd = &ops->co_genl->o_cmds[i]; 107 if (cmd->c_id == ghdr->cmd) 108 goto found; 109 } 110 111 err = -NLE_MSGTYPE_NOSUPPORT; 112 goto errout; 113 114 found: 115 if (cmd->c_msg_parser == NULL) 116 err = -NLE_OPNOTSUPP; 117 else { 118 struct nlattr *tb[cmd->c_maxattr + 1]; 119 struct genl_info info = { 120 .who = who, 121 .nlh = nlh, 122 .genlhdr = ghdr, 123 .userhdr = genlmsg_data(ghdr), 124 .attrs = tb, 125 }; 126 127 err = nlmsg_parse(nlh, ops->co_hdrsize, tb, cmd->c_maxattr, 128 cmd->c_attr_policy); 129 if (err < 0) 130 goto errout; 131 132 err = cmd->c_msg_parser(ops, cmd, &info, pp); 133 } 134 errout: 135 return err; 136 137 } 138 139 /** 140 * @name Register/Unregister 141 * @{ 142 */ 143 144 /** 145 * Register generic netlink operations 146 * @arg ops cache operations 147 */ 148 int genl_register(struct nl_cache_ops *ops) 149 { 150 int err; 151 152 if (ops->co_protocol != NETLINK_GENERIC) { 153 err = -NLE_PROTO_MISMATCH; 154 goto errout; 155 } 156 157 if ((size_t) ops->co_hdrsize < GENL_HDRSIZE(0)) { 158 err = -NLE_INVAL; 159 goto errout; 160 } 161 162 if (ops->co_genl == NULL) { 163 err = -NLE_INVAL; 164 goto errout; 165 } 166 167 ops->co_genl->o_cache_ops = ops; 168 ops->co_genl->o_name = ops->co_msgtypes[0].mt_name; 169 ops->co_genl->o_family = ops->co_msgtypes[0].mt_id; 170 ops->co_msg_parser = genl_msg_parser; 171 172 /* FIXME: check for dup */ 173 174 nl_list_add_tail(&ops->co_genl->o_list, &genl_ops_list); 175 176 err = nl_cache_mngt_register(ops); 177 errout: 178 return err; 179 } 180 181 /** 182 * Unregister generic netlink operations 183 * @arg ops cache operations 184 */ 185 void genl_unregister(struct nl_cache_ops *ops) 186 { 187 nl_cache_mngt_unregister(ops); 188 nl_list_del(&ops->co_genl->o_list); 189 } 190 191 /** @} */ 192 193 /** @} */ 194
This page was automatically generated by LXR 0.3.1. • OpenWrt