PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/package/libs/libnl-tiny/src/genl_ctrl.c

https://gitlab.com/gl-xinshouyong/1407-mifi-customer-tmp
C | 302 lines | 187 code | 49 blank | 66 comment | 25 complexity | 6953e8a2a8961bfc950088a26ed44d19 MD5 | raw file
  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-2008 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup genl_mngt
  13. * @defgroup ctrl Controller
  14. * @brief
  15. *
  16. * @{
  17. */
  18. #include <netlink-generic.h>
  19. #include <netlink/netlink.h>
  20. #include <netlink/genl/genl.h>
  21. #include <netlink/genl/family.h>
  22. #include <netlink/genl/mngt.h>
  23. #include <netlink/genl/ctrl.h>
  24. #include <netlink/utils.h>
  25. /** @cond SKIP */
  26. #define CTRL_VERSION 0x0001
  27. static struct nl_cache_ops genl_ctrl_ops;
  28. /** @endcond */
  29. static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h)
  30. {
  31. return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
  32. CTRL_VERSION, NLM_F_DUMP);
  33. }
  34. static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
  35. [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
  36. [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
  37. .maxlen = GENL_NAMSIZ },
  38. [CTRL_ATTR_VERSION] = { .type = NLA_U32 },
  39. [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
  40. [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
  41. [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
  42. };
  43. static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
  44. [CTRL_ATTR_OP_ID] = { .type = NLA_U32 },
  45. [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 },
  46. };
  47. static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
  48. struct genl_info *info, void *arg)
  49. {
  50. struct genl_family *family;
  51. struct nl_parser_param *pp = arg;
  52. int err;
  53. family = genl_family_alloc();
  54. if (family == NULL) {
  55. err = -NLE_NOMEM;
  56. goto errout;
  57. }
  58. if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
  59. err = -NLE_MISSING_ATTR;
  60. goto errout;
  61. }
  62. if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
  63. err = -NLE_MISSING_ATTR;
  64. goto errout;
  65. }
  66. family->ce_msgtype = info->nlh->nlmsg_type;
  67. genl_family_set_id(family,
  68. nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
  69. genl_family_set_name(family,
  70. nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
  71. if (info->attrs[CTRL_ATTR_VERSION]) {
  72. uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
  73. genl_family_set_version(family, version);
  74. }
  75. if (info->attrs[CTRL_ATTR_HDRSIZE]) {
  76. uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
  77. genl_family_set_hdrsize(family, hdrsize);
  78. }
  79. if (info->attrs[CTRL_ATTR_MAXATTR]) {
  80. uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
  81. genl_family_set_maxattr(family, maxattr);
  82. }
  83. if (info->attrs[CTRL_ATTR_OPS]) {
  84. struct nlattr *nla, *nla_ops;
  85. int remaining;
  86. nla_ops = info->attrs[CTRL_ATTR_OPS];
  87. nla_for_each_nested(nla, nla_ops, remaining) {
  88. struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
  89. int flags = 0, id;
  90. err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
  91. family_op_policy);
  92. if (err < 0)
  93. goto errout;
  94. if (tb[CTRL_ATTR_OP_ID] == NULL) {
  95. err = -NLE_MISSING_ATTR;
  96. goto errout;
  97. }
  98. id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
  99. if (tb[CTRL_ATTR_OP_FLAGS])
  100. flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
  101. err = genl_family_add_op(family, id, flags);
  102. if (err < 0)
  103. goto errout;
  104. }
  105. }
  106. err = pp->pp_cb((struct nl_object *) family, pp);
  107. errout:
  108. genl_family_put(family);
  109. return err;
  110. }
  111. /**
  112. * @name Cache Management
  113. * @{
  114. */
  115. int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
  116. {
  117. return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result);
  118. }
  119. /**
  120. * Look up generic netlink family by id in the provided cache.
  121. * @arg cache Generic netlink family cache.
  122. * @arg id Family identifier.
  123. *
  124. * Searches through the cache looking for a registered family
  125. * matching the specified identifier. The caller will own a
  126. * reference on the returned object which needs to be given
  127. * back after usage using genl_family_put().
  128. *
  129. * @return Generic netlink family object or NULL if no match was found.
  130. */
  131. struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
  132. {
  133. struct genl_family *fam;
  134. if (cache->c_ops != &genl_ctrl_ops)
  135. BUG();
  136. nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
  137. if (fam->gf_id == id) {
  138. nl_object_get((struct nl_object *) fam);
  139. return fam;
  140. }
  141. }
  142. return NULL;
  143. }
  144. /**
  145. * @name Resolver
  146. * @{
  147. */
  148. /**
  149. * Look up generic netlink family by family name in the provided cache.
  150. * @arg cache Generic netlink family cache.
  151. * @arg name Family name.
  152. *
  153. * Searches through the cache looking for a registered family
  154. * matching the specified name. The caller will own a reference
  155. * on the returned object which needs to be given back after
  156. * usage using genl_family_put().
  157. *
  158. * @return Generic netlink family object or NULL if no match was found.
  159. */
  160. struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
  161. const char *name)
  162. {
  163. struct genl_family *fam;
  164. if (cache->c_ops != &genl_ctrl_ops)
  165. BUG();
  166. nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
  167. if (!strcmp(name, fam->gf_name)) {
  168. nl_object_get((struct nl_object *) fam);
  169. return fam;
  170. }
  171. }
  172. return NULL;
  173. }
  174. /** @} */
  175. /**
  176. * Resolve generic netlink family name to its identifier
  177. * @arg sk Netlink socket.
  178. * @arg name Name of generic netlink family
  179. *
  180. * Resolves the generic netlink family name to its identifer and returns
  181. * it.
  182. *
  183. * @return A positive identifier or a negative error code.
  184. */
  185. int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
  186. {
  187. struct nl_cache *cache;
  188. struct genl_family *family;
  189. int err;
  190. if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0)
  191. return err;
  192. family = genl_ctrl_search_by_name(cache, name);
  193. if (family == NULL) {
  194. err = -NLE_OBJ_NOTFOUND;
  195. goto errout;
  196. }
  197. err = genl_family_get_id(family);
  198. genl_family_put(family);
  199. errout:
  200. nl_cache_free(cache);
  201. return err;
  202. }
  203. /** @} */
  204. static struct genl_cmd genl_cmds[] = {
  205. {
  206. .c_id = CTRL_CMD_NEWFAMILY,
  207. .c_name = "NEWFAMILY" ,
  208. .c_maxattr = CTRL_ATTR_MAX,
  209. .c_attr_policy = ctrl_policy,
  210. .c_msg_parser = ctrl_msg_parser,
  211. },
  212. {
  213. .c_id = CTRL_CMD_DELFAMILY,
  214. .c_name = "DELFAMILY" ,
  215. },
  216. {
  217. .c_id = CTRL_CMD_GETFAMILY,
  218. .c_name = "GETFAMILY" ,
  219. },
  220. {
  221. .c_id = CTRL_CMD_NEWOPS,
  222. .c_name = "NEWOPS" ,
  223. },
  224. {
  225. .c_id = CTRL_CMD_DELOPS,
  226. .c_name = "DELOPS" ,
  227. },
  228. };
  229. static struct genl_ops genl_ops = {
  230. .o_cmds = genl_cmds,
  231. .o_ncmds = ARRAY_SIZE(genl_cmds),
  232. };
  233. /** @cond SKIP */
  234. extern struct nl_object_ops genl_family_ops;
  235. /** @endcond */
  236. static struct nl_cache_ops genl_ctrl_ops = {
  237. .co_name = "genl/family",
  238. .co_hdrsize = GENL_HDRSIZE(0),
  239. .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
  240. .co_genl = &genl_ops,
  241. .co_protocol = NETLINK_GENERIC,
  242. .co_request_update = ctrl_request_update,
  243. .co_obj_ops = &genl_family_ops,
  244. };
  245. static void __init ctrl_init(void)
  246. {
  247. genl_register(&genl_ctrl_ops);
  248. }
  249. static void __exit ctrl_exit(void)
  250. {
  251. genl_unregister(&genl_ctrl_ops);
  252. }
  253. /** @} */