api.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * lib/route/link/api.c Link Info API
  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 link
  13. * @defgroup link_API Link Modules API
  14. * @brief API for modules implementing specific link types/semantics.
  15. *
  16. * @par 1) Registering/Unregistering a new link info type
  17. * @code
  18. * static struct rtnl_link_info_ops vlan_info_ops = {
  19. * .io_name = "vlan",
  20. * .io_alloc = vlan_alloc,
  21. * .io_parse = vlan_parse,
  22. * .io_dump[NL_DUMP_BRIEF] = vlan_dump_brief,
  23. * .io_dump[NL_DUMP_FULL] = vlan_dump_full,
  24. * .io_free = vlan_free,
  25. * };
  26. *
  27. * static void __init vlan_init(void)
  28. * {
  29. * rtnl_link_register_info(&vlan_info_ops);
  30. * }
  31. *
  32. * static void __exit vlan_exit(void)
  33. * {
  34. * rtnl_link_unregister_info(&vlan_info_ops);
  35. * }
  36. * @endcode
  37. *
  38. * @{
  39. */
  40. #include <netlink-private/netlink.h>
  41. #include <netlink/netlink.h>
  42. #include <netlink/utils.h>
  43. #include <netlink/route/link.h>
  44. #include <netlink-private/route/link/api.h>
  45. static NL_LIST_HEAD(info_ops);
  46. /* lock protecting info_ops and af_ops */
  47. static NL_RW_LOCK(info_lock);
  48. static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name)
  49. {
  50. struct rtnl_link_info_ops *ops;
  51. nl_list_for_each_entry(ops, &info_ops, io_list)
  52. if (!strcmp(ops->io_name, name))
  53. return ops;
  54. return NULL;
  55. }
  56. /**
  57. * @name Link Info Modules
  58. * @{
  59. */
  60. /**
  61. * Return operations of a specific link info type
  62. * @arg name Name of link info type.
  63. *
  64. * @note The returned pointer must be given back using rtnl_link_info_ops_put()
  65. *
  66. * @return Pointer to operations or NULL if unavailable.
  67. */
  68. struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name)
  69. {
  70. struct rtnl_link_info_ops *ops;
  71. nl_write_lock(&info_lock);
  72. if ((ops = __rtnl_link_info_ops_lookup(name)))
  73. ops->io_refcnt++;
  74. nl_write_unlock(&info_lock);
  75. return ops;
  76. }
  77. /**
  78. * Give back reference to a set of operations.
  79. * @arg ops Link info operations.
  80. */
  81. void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops)
  82. {
  83. if (ops)
  84. ops->io_refcnt--;
  85. }
  86. /**
  87. * Register operations for a link info type
  88. * @arg ops Link info operations
  89. *
  90. * This function must be called by modules implementing a specific link
  91. * info type. It will make the operations implemented by the module
  92. * available for everyone else.
  93. *
  94. * @return 0 on success or a negative error code.
  95. * @return -NLE_INVAL Link info name not specified.
  96. * @return -NLE_EXIST Operations for address family already registered.
  97. */
  98. int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
  99. {
  100. int err = 0;
  101. if (ops->io_name == NULL)
  102. return -NLE_INVAL;
  103. nl_write_lock(&info_lock);
  104. if (__rtnl_link_info_ops_lookup(ops->io_name)) {
  105. err = -NLE_EXIST;
  106. goto errout;
  107. }
  108. NL_DBG(1, "Registered link info operations %s\n", ops->io_name);
  109. nl_list_add_tail(&ops->io_list, &info_ops);
  110. errout:
  111. nl_write_unlock(&info_lock);
  112. return err;
  113. }
  114. /**
  115. * Unregister operations for a link info type
  116. * @arg ops Link info operations
  117. *
  118. * This function must be called if a module implementing a specific link
  119. * info type is unloaded or becomes unavailable. It must provide a
  120. * set of operations which have previously been registered using
  121. * rtnl_link_register_info().
  122. *
  123. * @return 0 on success or a negative error code
  124. * @return _NLE_OPNOTSUPP Link info operations not registered.
  125. * @return -NLE_BUSY Link info operations still in use.
  126. */
  127. int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
  128. {
  129. struct rtnl_link_info_ops *t;
  130. int err = -NLE_OPNOTSUPP;
  131. nl_write_lock(&info_lock);
  132. nl_list_for_each_entry(t, &info_ops, io_list) {
  133. if (t == ops) {
  134. if (t->io_refcnt > 0) {
  135. err = -NLE_BUSY;
  136. goto errout;
  137. }
  138. nl_list_del(&t->io_list);
  139. NL_DBG(1, "Unregistered link info operations %s\n",
  140. ops->io_name);
  141. err = 0;
  142. goto errout;
  143. }
  144. }
  145. errout:
  146. nl_write_unlock(&info_lock);
  147. return err;
  148. }
  149. /** @} */
  150. /**
  151. * @name Link Address Family Modules
  152. * @{
  153. */
  154. static struct rtnl_link_af_ops *af_ops[AF_MAX];
  155. /**
  156. * Return operations of a specific link address family
  157. * @arg family Address family
  158. *
  159. * @note The returned pointer must be given back using rtnl_link_af_ops_put()
  160. *
  161. * @return Pointer to operations or NULL if unavailable.
  162. */
  163. struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family)
  164. {
  165. if (family == AF_UNSPEC || family >= AF_MAX)
  166. return NULL;
  167. nl_write_lock(&info_lock);
  168. if (af_ops[family])
  169. af_ops[family]->ao_refcnt++;
  170. nl_write_unlock(&info_lock);
  171. return af_ops[family];
  172. }
  173. /**
  174. * Give back reference to a set of operations.
  175. * @arg ops Address family operations.
  176. */
  177. void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops)
  178. {
  179. if (ops)
  180. ops->ao_refcnt--;
  181. }
  182. /**
  183. * Allocate and return data buffer for link address family modules
  184. * @arg link Link object
  185. * @arg ops Address family operations
  186. *
  187. * This function must be called by link address family modules in all
  188. * cases where the API does not provide the data buffer as argument
  189. * already. This typically includes set functions the module provides.
  190. * Calling this function is strictly required to ensure proper allocation
  191. * of the buffer upon first use. Link objects will NOT proactively
  192. * allocate a data buffer for each registered link address family.
  193. *
  194. * @return Pointer to data buffer or NULL on error.
  195. */
  196. void *rtnl_link_af_alloc(struct rtnl_link *link,
  197. const struct rtnl_link_af_ops *ops)
  198. {
  199. int family;
  200. if (!link || !ops)
  201. BUG();
  202. family = ops->ao_family;
  203. if (!link->l_af_data[family]) {
  204. if (!ops->ao_alloc)
  205. BUG();
  206. link->l_af_data[family] = ops->ao_alloc(link);
  207. if (!link->l_af_data[family])
  208. return NULL;
  209. }
  210. return link->l_af_data[family];
  211. }
  212. /**
  213. * Return data buffer for link address family modules
  214. * @arg link Link object
  215. * @arg ops Address family operations
  216. *
  217. * This function returns a pointer to the data buffer for the specified link
  218. * address family module or NULL if the buffer was not allocated yet. This
  219. * function is typically used by get functions of modules which are not
  220. * interested in having the data buffer allocated if no values have been set
  221. * yet.
  222. *
  223. * @return Pointer to data buffer or NULL on error.
  224. */
  225. void *rtnl_link_af_data(const struct rtnl_link *link,
  226. const struct rtnl_link_af_ops *ops)
  227. {
  228. if (!link || !ops)
  229. BUG();
  230. return link->l_af_data[ops->ao_family];
  231. }
  232. /**
  233. * Register operations for a link address family
  234. * @arg ops Address family operations
  235. *
  236. * This function must be called by modules implementing a specific link
  237. * address family. It will make the operations implemented by the module
  238. * available for everyone else.
  239. *
  240. * @return 0 on success or a negative error code.
  241. * @return -NLE_INVAL Address family is out of range (0..AF_MAX)
  242. * @return -NLE_EXIST Operations for address family already registered.
  243. */
  244. int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
  245. {
  246. int err = 0;
  247. if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX)
  248. return -NLE_INVAL;
  249. nl_write_lock(&info_lock);
  250. if (af_ops[ops->ao_family]) {
  251. err = -NLE_EXIST;
  252. goto errout;
  253. }
  254. ops->ao_refcnt = 0;
  255. af_ops[ops->ao_family] = ops;
  256. NL_DBG(1, "Registered link address family operations %u\n",
  257. ops->ao_family);
  258. errout:
  259. nl_write_unlock(&info_lock);
  260. return err;
  261. }
  262. /**
  263. * Unregister operations for a link address family
  264. * @arg ops Address family operations
  265. *
  266. * This function must be called if a module implementing a specific link
  267. * address family is unloaded or becomes unavailable. It must provide a
  268. * set of operations which have previously been registered using
  269. * rtnl_link_af_register().
  270. *
  271. * @return 0 on success or a negative error code
  272. * @return -NLE_INVAL ops is NULL
  273. * @return -NLE_OBJ_NOTFOUND Address family operations not registered.
  274. * @return -NLE_BUSY Address family operations still in use.
  275. */
  276. int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
  277. {
  278. int err = -NLE_INVAL;
  279. if (!ops)
  280. return err;
  281. nl_write_lock(&info_lock);
  282. if (!af_ops[ops->ao_family]) {
  283. err = -NLE_OBJ_NOTFOUND;
  284. goto errout;
  285. }
  286. if (ops->ao_refcnt > 0) {
  287. err = -NLE_BUSY;
  288. goto errout;
  289. }
  290. af_ops[ops->ao_family] = NULL;
  291. NL_DBG(1, "Unregistered link address family operations %u\n",
  292. ops->ao_family);
  293. errout:
  294. nl_write_unlock(&info_lock);
  295. return err;
  296. }
  297. /**
  298. * Compare af data for a link address family
  299. * @arg a Link object a
  300. * @arg b Link object b
  301. * @arg family af data family
  302. *
  303. * This function will compare af_data between two links
  304. * a and b of family given by arg family
  305. *
  306. * @return 0 if address family specific data matches or is not present
  307. * or != 0 if it mismatches.
  308. */
  309. int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b,
  310. int family)
  311. {
  312. struct rtnl_link_af_ops *af_ops;
  313. int ret = 0;
  314. if (!a->l_af_data[family] && !b->l_af_data[family])
  315. return 0;
  316. if (!a->l_af_data[family] || !b->l_af_data[family])
  317. return ~0;
  318. af_ops = rtnl_link_af_ops_lookup(family);
  319. if (!af_ops)
  320. return ~0;
  321. if (af_ops->ao_compare == NULL) {
  322. ret = ~0;
  323. goto out;
  324. }
  325. ret = af_ops->ao_compare(a, b, family, ~0, 0);
  326. out:
  327. rtnl_link_af_ops_put(af_ops);
  328. return ret;
  329. }
  330. /** @} */
  331. /** @} */