00001 /* 00002 * netlink/cache-api.h Caching 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-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 #ifndef NETLINK_CACHE_API_H_ 00013 #define NETLINK_CACHE_API_H_ 00014 00015 #include <netlink/netlink.h> 00016 00017 #ifdef __cplusplus 00018 extern "C" { 00019 #endif 00020 00021 /** 00022 * @ingroup cache 00023 * @defgroup cache_api Cache Implementation 00024 * @brief 00025 * 00026 * @par 1) Cache Definition 00027 * @code 00028 * struct nl_cache_ops my_cache_ops = { 00029 * .co_name = "route/link", 00030 * .co_protocol = NETLINK_ROUTE, 00031 * .co_hdrsize = sizeof(struct ifinfomsg), 00032 * .co_obj_ops = &my_obj_ops, 00033 * }; 00034 * @endcode 00035 * 00036 * @par 2) 00037 * @code 00038 * // The simplest way to fill a cache is by providing a request-update 00039 * // function which must trigger a complete dump on the kernel-side of 00040 * // whatever the cache covers. 00041 * static int my_request_update(struct nl_cache *cache, 00042 * struct nl_handle *socket) 00043 * { 00044 * // In this example, we request a full dump of the interface table 00045 * return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP); 00046 * } 00047 * 00048 * // The resulting netlink messages sent back will be fed into a message 00049 * // parser one at a time. The message parser has to extract all relevant 00050 * // information from the message and create an object reflecting the 00051 * // contents of the message and pass it on to the parser callback function 00052 * // provide which will add the object to the cache. 00053 * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00054 * struct nlmsghdr *nlh, struct nl_parser_param *pp) 00055 * { 00056 * struct my_obj *obj; 00057 * 00058 * obj = my_obj_alloc(); 00059 * obj->ce_msgtype = nlh->nlmsg_type; 00060 * 00061 * // Parse the netlink message and continue creating the object. 00062 * 00063 * err = pp->pp_cb((struct nl_object *) obj, pp); 00064 * if (err < 0) 00065 * goto errout; 00066 * } 00067 * 00068 * struct nl_cache_ops my_cache_ops = { 00069 * ... 00070 * .co_request_update = my_request_update, 00071 * .co_msg_parser = my_msg_parser, 00072 * }; 00073 * @endcode 00074 * 00075 * @par 3) Notification based Updates 00076 * @code 00077 * // Caches can be kept up-to-date based on notifications if the kernel 00078 * // sends out notifications whenever an object is added/removed/changed. 00079 * // 00080 * // It is trivial to support this, first a list of groups needs to be 00081 * // defined which are required to join in order to receive all necessary 00082 * // notifications. The groups are separated by address family to support 00083 * // the common situation where a separate group is used for each address 00084 * // family. If there is only one group, simply specify AF_UNSPEC. 00085 * static struct nl_af_group addr_groups[] = { 00086 * { AF_INET, RTNLGRP_IPV4_IFADDR }, 00087 * { AF_INET6, RTNLGRP_IPV6_IFADDR }, 00088 * { END_OF_GROUP_LIST }, 00089 * }; 00090 * 00091 * // In order for the caching system to know the meaning of each message 00092 * // type it requires a table which maps each supported message type to 00093 * // a cache action, e.g. RTM_NEWADDR means address has been added or 00094 * // updated, RTM_DELADDR means address has been removed. 00095 * static struct nl_cache_ops rtnl_addr_ops = { 00096 * ... 00097 * .co_msgtypes = { 00098 * { RTM_NEWADDR, NL_ACT_NEW, "new" }, 00099 * { RTM_DELADDR, NL_ACT_DEL, "del" }, 00100 * { RTM_GETADDR, NL_ACT_GET, "get" }, 00101 * END_OF_MSGTYPES_LIST, 00102 * }, 00103 * .co_groups = addr_groups, 00104 * }; 00105 * 00106 * // It is now possible to keep the cache up-to-date using the cache manager. 00107 * @endcode 00108 * @{ 00109 */ 00110 00111 enum { 00112 NL_ACT_UNSPEC, 00113 NL_ACT_NEW, 00114 NL_ACT_DEL, 00115 NL_ACT_GET, 00116 NL_ACT_SET, 00117 NL_ACT_CHANGE, 00118 __NL_ACT_MAX, 00119 }; 00120 00121 #define NL_ACT_MAX (__NL_ACT_MAX - 1) 00122 00123 #define END_OF_MSGTYPES_LIST { -1, -1, NULL } 00124 00125 /** 00126 * Message type to cache action association 00127 */ 00128 struct nl_msgtype 00129 { 00130 /** Netlink message type */ 00131 int mt_id; 00132 00133 /** Cache action to take */ 00134 int mt_act; 00135 00136 /** Name of operation for human-readable printing */ 00137 char * mt_name; 00138 }; 00139 00140 /** 00141 * Address family to netlink group association 00142 */ 00143 struct nl_af_group 00144 { 00145 /** Address family */ 00146 int ag_family; 00147 00148 /** Netlink group identifier */ 00149 int ag_group; 00150 }; 00151 00152 #define END_OF_GROUP_LIST AF_UNSPEC, 0 00153 00154 struct nl_parser_param 00155 { 00156 int (*pp_cb)(struct nl_object *, struct nl_parser_param *); 00157 void * pp_arg; 00158 }; 00159 00160 /** 00161 * Cache Operations 00162 */ 00163 struct nl_cache_ops 00164 { 00165 char * co_name; 00166 00167 int co_hdrsize; 00168 int co_protocol; 00169 struct nl_af_group * co_groups; 00170 00171 /** 00172 * Called whenever an update of the cache is required. Must send 00173 * a request message to the kernel requesting a complete dump. 00174 */ 00175 int (*co_request_update)(struct nl_cache *, struct nl_handle *); 00176 00177 /** 00178 * Called whenever a message was received that needs to be parsed. 00179 * Must parse the message and call the paser callback function 00180 * (nl_parser_param) provided via the argument. 00181 */ 00182 int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, 00183 struct nlmsghdr *, struct nl_parser_param *); 00184 00185 struct nl_object_ops * co_obj_ops; 00186 00187 struct nl_cache_ops *co_next; 00188 struct nl_cache *co_major_cache; 00189 struct genl_ops * co_genl; 00190 struct nl_msgtype co_msgtypes[]; 00191 }; 00192 00193 /** @} */ 00194 00195 #ifdef __cplusplus 00196 } 00197 #endif 00198 00199 #endif