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