1 /* 2 * lib/genl/ctrl.c Generic Netlink Controller 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-2012 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 /** 13 * @ingroup genl 14 * @defgroup genl_ctrl Controller (Resolver) 15 * 16 * Resolves Generic Netlink family names to numeric identifiers. 17 * 18 * The controller is a component in the kernel that resolves Generic Netlink 19 * family names to their numeric identifiers. This module provides functions 20 * to query the controller to access the resolving functionality. 21 * @{ 22 */ 23 24 #include <netlink-private/genl.h> 25 #include <netlink/netlink.h> 26 #include <netlink/genl/genl.h> 27 #include <netlink/genl/family.h> 28 #include <netlink/genl/mngt.h> 29 #include <netlink/genl/ctrl.h> 30 #include <netlink/utils.h> 31 32 /** @cond SKIP */ 33 #define CTRL_VERSION 0x0001 34 35 static struct nl_cache_ops genl_ctrl_ops; 36 37 static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h) 38 { 39 return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 40 CTRL_VERSION, NLM_F_DUMP); 41 } 42 43 static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { 44 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, 45 [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, 46 .maxlen = GENL_NAMSIZ }, 47 [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, 48 [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, 49 [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, 50 [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, 51 [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED }, 52 }; 53 54 static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { 55 [CTRL_ATTR_OP_ID] = { .type = NLA_U32 }, 56 [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 }, 57 }; 58 59 static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = { 60 [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, 61 [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, 62 }; 63 64 static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr) 65 { 66 struct nlattr *nla; 67 int remaining, err; 68 69 if (!grp_attr) 70 BUG(); 71 72 nla_for_each_nested(nla, grp_attr, remaining) { 73 struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; 74 int id; 75 const char * name; 76 77 err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, 78 family_grp_policy); 79 if (err < 0) 80 goto errout; 81 82 if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { 83 err = -NLE_MISSING_ATTR; 84 goto errout; 85 } 86 id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); 87 88 if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { 89 err = -NLE_MISSING_ATTR; 90 goto errout; 91 } 92 name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); 93 94 err = genl_family_add_grp(family, id, name); 95 if (err < 0) 96 goto errout; 97 } 98 99 err = 0; 100 101 errout: 102 return err; 103 } 104 105 static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, 106 struct genl_info *info, void *arg) 107 { 108 struct genl_family *family; 109 struct nl_parser_param *pp = arg; 110 int err; 111 112 family = genl_family_alloc(); 113 if (family == NULL) { 114 err = -NLE_NOMEM; 115 goto errout; 116 } 117 118 if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) { 119 err = -NLE_MISSING_ATTR; 120 goto errout; 121 } 122 123 if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) { 124 err = -NLE_MISSING_ATTR; 125 goto errout; 126 } 127 128 family->ce_msgtype = info->nlh->nlmsg_type; 129 genl_family_set_id(family, 130 nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID])); 131 genl_family_set_name(family, 132 nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME])); 133 134 if (info->attrs[CTRL_ATTR_VERSION]) { 135 uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]); 136 genl_family_set_version(family, version); 137 } 138 139 if (info->attrs[CTRL_ATTR_HDRSIZE]) { 140 uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]); 141 genl_family_set_hdrsize(family, hdrsize); 142 } 143 144 if (info->attrs[CTRL_ATTR_MAXATTR]) { 145 uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]); 146 genl_family_set_maxattr(family, maxattr); 147 } 148 149 if (info->attrs[CTRL_ATTR_OPS]) { 150 struct nlattr *nla, *nla_ops; 151 int remaining; 152 153 nla_ops = info->attrs[CTRL_ATTR_OPS]; 154 nla_for_each_nested(nla, nla_ops, remaining) { 155 struct nlattr *tb[CTRL_ATTR_OP_MAX+1]; 156 int flags = 0, id; 157 158 err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla, 159 family_op_policy); 160 if (err < 0) 161 goto errout; 162 163 if (tb[CTRL_ATTR_OP_ID] == NULL) { 164 err = -NLE_MISSING_ATTR; 165 goto errout; 166 } 167 168 id = nla_get_u32(tb[CTRL_ATTR_OP_ID]); 169 170 if (tb[CTRL_ATTR_OP_FLAGS]) 171 flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]); 172 173 err = genl_family_add_op(family, id, flags); 174 if (err < 0) 175 goto errout; 176 177 } 178 } 179 180 if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) { 181 err = parse_mcast_grps(family, info->attrs[CTRL_ATTR_MCAST_GROUPS]); 182 if (err < 0) 183 goto errout; 184 } 185 186 err = pp->pp_cb((struct nl_object *) family, pp); 187 errout: 188 genl_family_put(family); 189 return err; 190 } 191 192 /** 193 * process responses from from the query sent by genl_ctrl_probe_by_name 194 * @arg nl_msg Returned message. 195 * @arg name genl_family structure to fill out. 196 * 197 * Process returned messages, filling out the missing informatino in the 198 * genl_family structure 199 * 200 * @return Indicator to keep processing frames or not 201 * 202 */ 203 static int probe_response(struct nl_msg *msg, void *arg) 204 { 205 struct nlattr *tb[CTRL_ATTR_MAX+1]; 206 struct nlmsghdr *nlh = nlmsg_hdr(msg); 207 struct genl_family *ret = (struct genl_family *)arg; 208 209 if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy)) 210 return NL_SKIP; 211 212 if (tb[CTRL_ATTR_FAMILY_ID]) 213 genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID])); 214 215 if (tb[CTRL_ATTR_MCAST_GROUPS]) 216 if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0) 217 return NL_SKIP; 218 219 return NL_STOP; 220 } 221 222 /** 223 * Look up generic netlink family by family name querying the kernel directly 224 * @arg sk Socket. 225 * @arg name Family name. 226 * 227 * Directly query's the kernel for a given family name. The caller will own a 228 * reference on the returned object which needsd to be given back after usage 229 * using genl_family_put. 230 * 231 * Note: This API call differs from genl_ctrl_search_by_name in that it querys 232 * the kernel directly, alowing for module autoload to take place to resolve the 233 * family request. Using an nl_cache prevents that operation 234 * 235 * @return Generic netlink family object or NULL if no match was found. 236 */ 237 static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, 238 const char *name) 239 { 240 struct nl_msg *msg; 241 struct genl_family *ret; 242 struct nl_cb *cb, *orig; 243 int rc; 244 245 ret = genl_family_alloc(); 246 if (!ret) 247 goto out; 248 249 genl_family_set_name(ret, name); 250 251 msg = nlmsg_alloc(); 252 if (!msg) 253 goto out_fam_free; 254 255 if (!(orig = nl_socket_get_cb(sk))) 256 goto out_msg_free; 257 258 cb = nl_cb_clone(orig); 259 nl_cb_put(orig); 260 if (!cb) 261 goto out_msg_free; 262 263 if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 264 0, 0, CTRL_CMD_GETFAMILY, 1)) { 265 BUG(); 266 goto out_cb_free; 267 } 268 269 if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0) 270 goto out_cb_free; 271 272 rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, 273 (void *) ret); 274 if (rc < 0) 275 goto out_cb_free; 276 277 rc = nl_send_auto_complete(sk, msg); 278 if (rc < 0) 279 goto out_cb_free; 280 281 rc = nl_recvmsgs(sk, cb); 282 if (rc < 0) 283 goto out_cb_free; 284 285 /* If search was successful, request may be ACKed after data */ 286 rc = wait_for_ack(sk); 287 if (rc < 0) 288 goto out_cb_free; 289 290 if (genl_family_get_id(ret) != 0) { 291 nlmsg_free(msg); 292 nl_cb_put(cb); 293 return ret; 294 } 295 296 out_cb_free: 297 nl_cb_put(cb); 298 out_msg_free: 299 nlmsg_free(msg); 300 out_fam_free: 301 genl_family_put(ret); 302 ret = NULL; 303 out: 304 return ret; 305 } 306 307 308 /** @endcond */ 309 310 /** 311 * @name Controller Cache 312 * 313 * The controller cache allows to keep a local copy of the list of all 314 * kernel side registered Generic Netlink families to quickly resolve 315 * multiple Generic Netlink family names without requiring to communicate 316 * with the kernel for each resolving iteration. 317 * 318 * @{ 319 */ 320 321 /** 322 * Allocate a new controller cache 323 * @arg sk Generic Netlink socket 324 * @arg result Pointer to store resulting cache 325 * 326 * Allocates a new cache mirroring the state of the controller and stores it 327 * in \c *result. The allocated cache will contain a list of all currently 328 * registered kernel side Generic Netlink families. The cache is meant to be 329 * used to resolve family names locally. 330 * 331 * @return 0 on success or a negative error code. 332 */ 333 int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 334 { 335 return nl_cache_alloc_and_fill(&genl_ctrl_ops, sk, result); 336 } 337 338 /** 339 * Search controller cache for a numeric address match 340 * @arg cache Controller cache 341 * @arg id Numeric family identifier. 342 * 343 * Searches a previously allocated controller cache and looks for an entry 344 * that matches the specified numeric family identifier \c id. If a match 345 * is found successfully, the reference count of the matching object is 346 * increased by one before the objet is returned. 347 * 348 * @see genl_ctrl_alloc_cache() 349 * @see genl_ctrl_search_by_name() 350 * @see genl_family_put() 351 * 352 * @return Generic Netlink family object or NULL if no match was found. 353 */ 354 struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id) 355 { 356 struct genl_family *fam; 357 358 if (cache->c_ops != &genl_ctrl_ops) 359 BUG(); 360 361 nl_list_for_each_entry(fam, &cache->c_items, ce_list) { 362 if (fam->gf_id == id) { 363 nl_object_get((struct nl_object *) fam); 364 return fam; 365 } 366 } 367 368 return NULL; 369 } 370 371 /** 372 * Search controller cache for a family name match 373 * @arg cache Controller cache 374 * @arg name Name of Generic Netlink family 375 * 376 * Searches a previously allocated controller cache and looks for an entry 377 * that matches the specified family \c name. If a match is found successfully, 378 * the reference count of the matching object is increased by one before the 379 * objet is returned. 380 * 381 * @see genl_ctrl_alloc_cache() 382 * @see genl_ctrl_search() 383 * @see genl_family_put() 384 * 385 * @return Generic Netlink family object or NULL if no match was found. 386 */ 387 struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, 388 const char *name) 389 { 390 struct genl_family *fam; 391 392 if (cache->c_ops != &genl_ctrl_ops) 393 BUG(); 394 395 nl_list_for_each_entry(fam, &cache->c_items, ce_list) { 396 if (!strcmp(name, fam->gf_name)) { 397 nl_object_get((struct nl_object *) fam); 398 return fam; 399 } 400 } 401 402 return NULL; 403 } 404 405 /** @} */ 406 407 /** 408 * @name Direct Resolvers 409 * 410 * These functions communicate directly with the kernel and do not require 411 * a cache to be kept up to date. 412 * 413 * @{ 414 */ 415 416 /** 417 * Resolve Generic Netlink family name to numeric identifier 418 * @arg sk Generic Netlink socket. 419 * @arg name Name of Generic Netlink family 420 * 421 * Resolves the Generic Netlink family name to the corresponding numeric 422 * family identifier. This function queries the kernel directly, use 423 * genl_ctrl_search_by_name() if you need to resolve multiple names. 424 * 425 * @see genl_ctrl_search_by_name() 426 * 427 * @return The numeric family identifier or a negative error code. 428 */ 429 int genl_ctrl_resolve(struct nl_sock *sk, const char *name) 430 { 431 struct genl_family *family; 432 int err; 433 434 family = genl_ctrl_probe_by_name(sk, name); 435 if (family == NULL) { 436 err = -NLE_OBJ_NOTFOUND; 437 goto errout; 438 } 439 440 err = genl_family_get_id(family); 441 genl_family_put(family); 442 errout: 443 return err; 444 } 445 446 static int genl_ctrl_grp_by_name(const struct genl_family *family, 447 const char *grp_name) 448 { 449 struct genl_family_grp *grp; 450 451 nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { 452 if (!strcmp(grp->name, grp_name)) { 453 return grp->id; 454 } 455 } 456 457 return -NLE_OBJ_NOTFOUND; 458 } 459 460 /** 461 * Resolve Generic Netlink family group name 462 * @arg sk Generic Netlink socket 463 * @arg family_name Name of Generic Netlink family 464 * @arg grp_name Name of group to resolve 465 * 466 * Looks up the family object and resolves the group name to the numeric 467 * group identifier. 468 * 469 * @return Numeric group identifier or a negative error code. 470 */ 471 int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, 472 const char *grp_name) 473 { 474 475 struct genl_family *family; 476 int err; 477 478 family = genl_ctrl_probe_by_name(sk, family_name); 479 if (family == NULL) { 480 err = -NLE_OBJ_NOTFOUND; 481 goto errout; 482 } 483 484 err = genl_ctrl_grp_by_name(family, grp_name); 485 genl_family_put(family); 486 errout: 487 return err; 488 } 489 490 /** @} */ 491 492 /** @cond SKIP */ 493 static struct genl_cmd genl_cmds[] = { 494 { 495 .c_id = CTRL_CMD_NEWFAMILY, 496 .c_name = "NEWFAMILY" , 497 .c_maxattr = CTRL_ATTR_MAX, 498 .c_attr_policy = ctrl_policy, 499 .c_msg_parser = ctrl_msg_parser, 500 }, 501 { 502 .c_id = CTRL_CMD_DELFAMILY, 503 .c_name = "DELFAMILY" , 504 }, 505 { 506 .c_id = CTRL_CMD_GETFAMILY, 507 .c_name = "GETFAMILY" , 508 }, 509 { 510 .c_id = CTRL_CMD_NEWOPS, 511 .c_name = "NEWOPS" , 512 }, 513 { 514 .c_id = CTRL_CMD_DELOPS, 515 .c_name = "DELOPS" , 516 }, 517 }; 518 519 static struct genl_ops genl_ops = { 520 .o_cmds = genl_cmds, 521 .o_ncmds = ARRAY_SIZE(genl_cmds), 522 }; 523 524 extern struct nl_object_ops genl_family_ops; 525 526 static struct nl_cache_ops genl_ctrl_ops = { 527 .co_name = "genl/family", 528 .co_hdrsize = GENL_HDRSIZE(0), 529 .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"), 530 .co_genl = &genl_ops, 531 .co_protocol = NETLINK_GENERIC, 532 .co_request_update = ctrl_request_update, 533 .co_obj_ops = &genl_family_ops, 534 }; 535 536 static void __init ctrl_init(void) 537 { 538 genl_register(&genl_ctrl_ops); 539 } 540 541 static void __exit ctrl_exit(void) 542 { 543 genl_unregister(&genl_ctrl_ops); 544 } 545 /** @endcond */ 546 547 /** @} */ 548