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