libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/link/api.c
00001 /*
00002  * lib/route/link/api.c         Link Info API
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup link
00014  * @defgroup link_API Link Modules API
00015  * @brief API for modules implementing specific link types/semantics.
00016  *
00017  * @par 1) Registering/Unregistering a new link info type
00018  * @code
00019  * static struct rtnl_link_info_ops vlan_info_ops = {
00020  *      .io_name                = "vlan",
00021  *      .io_alloc               = vlan_alloc,
00022  *      .io_parse               = vlan_parse,
00023  *      .io_dump[NL_DUMP_BRIEF] = vlan_dump_brief,
00024  *      .io_dump[NL_DUMP_FULL]  = vlan_dump_full,
00025  *      .io_free                = vlan_free,
00026  * };
00027  *
00028  * static void __init vlan_init(void)
00029  * {
00030  *      rtnl_link_register_info(&vlan_info_ops);
00031  * }
00032  *
00033  * static void __exit vlan_exit(void)
00034  * {
00035  *      rtnl_link_unregister_info(&vlan_info_ops);
00036  * }
00037  * @endcode
00038  *
00039  * @{
00040  */
00041 
00042 #include <netlink-local.h>
00043 #include <netlink/netlink.h>
00044 #include <netlink/utils.h>
00045 #include <netlink/route/link.h>
00046 #include <netlink/route/link/api.h>
00047 
00048 static NL_LIST_HEAD(info_ops);
00049 
00050 static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name)
00051 {
00052         struct rtnl_link_info_ops *ops;
00053 
00054         nl_list_for_each_entry(ops, &info_ops, io_list)
00055                 if (!strcmp(ops->io_name, name))
00056                         return ops;
00057 
00058         return NULL;
00059 }
00060 
00061 /**
00062  * @name Link Info Modules
00063  * @{
00064  */
00065 
00066 /**
00067  * Return operations of a specific link info type
00068  * @arg name            Name of link info type.
00069  *
00070  * @note The returned pointer must be given back using rtnl_link_info_ops_put()
00071  *
00072  * @return Pointer to operations or NULL if unavailable.
00073  */
00074 struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name)
00075 {
00076         struct rtnl_link_info_ops *ops;
00077 
00078         if ((ops = __rtnl_link_info_ops_lookup(name)))
00079                 ops->io_refcnt++;
00080 
00081         return ops;
00082 }
00083 
00084 /**
00085  * Give back reference to a set of operations.
00086  * @arg ops             Link info operations.
00087  */
00088 void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops)
00089 {
00090         if (ops)
00091                 ops->io_refcnt--;
00092 }
00093 
00094 /**
00095  * Register operations for a link info type
00096  * @arg ops             Link info operations
00097  *
00098  * This function must be called by modules implementing a specific link
00099  * info type. It will make the operations implemented by the module
00100  * available for everyone else.
00101  *
00102  * @return 0 on success or a negative error code.
00103  * @return -NLE_INVAL Link info name not specified.
00104  * @return -NLE_EXIST Operations for address family already registered.
00105  */
00106 int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
00107 {
00108         if (ops->io_name == NULL)
00109                 return -NLE_INVAL;
00110 
00111         if (__rtnl_link_info_ops_lookup(ops->io_name))
00112                 return -NLE_EXIST;
00113 
00114         NL_DBG(1, "Registered link info operations %s\n", ops->io_name);
00115 
00116         nl_list_add_tail(&ops->io_list, &info_ops);
00117 
00118         return 0;
00119 }
00120 
00121 /**
00122  * Unregister operations for a link info type
00123  * @arg ops             Link info operations
00124  *
00125  * This function must be called if a module implementing a specific link
00126  * info type is unloaded or becomes unavailable. It must provide a
00127  * set of operations which have previously been registered using
00128  * rtnl_link_register_info().
00129  *
00130  * @return 0 on success or a negative error code
00131  * @return _NLE_OPNOTSUPP Link info operations not registered.
00132  * @return -NLE_BUSY Link info operations still in use.
00133  */
00134 int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
00135 {
00136         struct rtnl_link_info_ops *t;
00137 
00138         nl_list_for_each_entry(t, &info_ops, io_list) {
00139                 if (t == ops) {
00140                         if (t->io_refcnt > 0)
00141                                 return -NLE_BUSY;
00142 
00143                         nl_list_del(&t->io_list);
00144 
00145                         NL_DBG(1, "Unregistered link info operations %s\n",
00146                                 ops->io_name);
00147 
00148                         return 0;
00149                 }
00150         }
00151 
00152         return -NLE_OPNOTSUPP;
00153 }
00154 
00155 /** @} */
00156 
00157 /**
00158  * @name Link Address Family Modules
00159  * @{
00160  */
00161 
00162 static struct rtnl_link_af_ops *af_ops[AF_MAX];
00163 
00164 /**
00165  * Return operations of a specific link address family
00166  * @arg family          Address family
00167  *
00168  * @note The returned pointer must be given back using rtnl_link_af_ops_put()
00169  *
00170  * @return Pointer to operations or NULL if unavailable.
00171  */
00172 struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family)
00173 {
00174         if (family == AF_UNSPEC || family >= AF_MAX)
00175                 return NULL;
00176 
00177         if (af_ops[family])
00178                 af_ops[family]->ao_refcnt++;
00179 
00180         return af_ops[family];
00181 }
00182 
00183 /**
00184  * Give back reference to a set of operations.
00185  * @arg ops             Address family operations.
00186  */
00187 void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops)
00188 {
00189         if (ops)
00190                 ops->ao_refcnt--;
00191 }
00192 
00193 /**
00194  * Allocate and return data buffer for link address family modules
00195  * @arg link            Link object
00196  * @arg ops             Address family operations
00197  *
00198  * This function must be called by link address family modules in all
00199  * cases where the API does not provide the data buffer as argument
00200  * already. This typically includes set functions the module provides.
00201  * Calling this function is strictly required to ensure proper allocation
00202  * of the buffer upon first use. Link objects will NOT proactively
00203  * allocate a data buffer for each registered link address family.
00204  *
00205  * @return Pointer to data buffer or NULL on error.
00206  */
00207 void *rtnl_link_af_alloc(struct rtnl_link *link,
00208                          const struct rtnl_link_af_ops *ops)
00209 {
00210         int family;
00211 
00212         if (!link || !ops)
00213                 BUG();
00214 
00215         family = ops->ao_family;
00216 
00217         if (!link->l_af_data[family]) {
00218                 if (!ops->ao_alloc)
00219                         BUG();
00220                 
00221                 link->l_af_data[family] = ops->ao_alloc(link);
00222                 if (!link->l_af_data[family])
00223                         return NULL;
00224         }
00225 
00226         return link->l_af_data[family];
00227 }
00228 
00229 /**
00230  * Return data buffer for link address family modules
00231  * @arg link            Link object
00232  * @arg ops             Address family operations
00233  *
00234  * This function returns a pointer to the data buffer for the specified link
00235  * address family module or NULL if the buffer was not allocated yet. This
00236  * function is typically used by get functions of modules which are not
00237  * interested in having the data buffer allocated if no values have been set
00238  * yet.
00239  *
00240  * @return Pointer to data buffer or NULL on error.
00241  */
00242 void *rtnl_link_af_data(const struct rtnl_link *link,
00243                         const struct rtnl_link_af_ops *ops)
00244 {
00245         if (!link || !ops)
00246                 BUG();
00247 
00248         return link->l_af_data[ops->ao_family];
00249 }
00250 
00251 /**
00252  * Register operations for a link address family
00253  * @arg ops             Address family operations
00254  *
00255  * This function must be called by modules implementing a specific link
00256  * address family. It will make the operations implemented by the module
00257  * available for everyone else.
00258  *
00259  * @return 0 on success or a negative error code.
00260  * @return -NLE_INVAL Address family is out of range (0..AF_MAX)
00261  * @return -NLE_EXIST Operations for address family already registered.
00262  */
00263 int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
00264 {
00265         if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX)
00266                 return -NLE_INVAL;
00267 
00268         if (af_ops[ops->ao_family])
00269                 return -NLE_EXIST;
00270 
00271         ops->ao_refcnt = 0;
00272         af_ops[ops->ao_family] = ops;
00273 
00274         NL_DBG(1, "Registered link address family operations %u\n",
00275                 ops->ao_family);
00276 
00277         return 0;
00278 }
00279 
00280 /**
00281  * Unregister operations for a link address family
00282  * @arg ops             Address family operations
00283  *
00284  * This function must be called if a module implementing a specific link
00285  * address family is unloaded or becomes unavailable. It must provide a
00286  * set of operations which have previously been registered using
00287  * rtnl_link_af_register().
00288  *
00289  * @return 0 on success or a negative error code
00290  * @return -NLE_INVAL ops is NULL
00291  * @return -NLE_OBJ_NOTFOUND Address family operations not registered.
00292  * @return -NLE_BUSY Address family operations still in use.
00293  */
00294 int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
00295 {
00296         if (!ops)
00297                 return -NLE_INVAL;
00298 
00299         if (!af_ops[ops->ao_family])
00300                 return -NLE_OBJ_NOTFOUND;
00301 
00302         if (ops->ao_refcnt > 0)
00303                 return -NLE_BUSY;
00304 
00305         af_ops[ops->ao_family] = NULL;
00306 
00307         NL_DBG(1, "Unregistered link address family operations %u\n",
00308                 ops->ao_family);
00309 
00310         return 0;
00311 }
00312 
00313 /** @} */
00314 
00315 /** @} */
00316