1 /* SPDX-License-Identifier: LGPL-2.1-only */ 2 /* 3 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch> 4 */ 5 6 #ifndef NETLINK_CACHE_API_H_ 7 #define NETLINK_CACHE_API_H_ 8 9 #include <netlink/netlink.h> 10 #include <netlink/cache.h> 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif 15 16 /** 17 * @ingroup cache 18 * @defgroup cache_api Cache Implementation 19 * @brief 20 * 21 * @par 1) Cache Definition 22 * @code 23 * struct nl_cache_ops my_cache_ops = { 24 * .co_name = "route/link", 25 * .co_protocol = NETLINK_ROUTE, 26 * .co_hdrsize = sizeof(struct ifinfomsg), 27 * .co_obj_ops = &my_obj_ops, 28 * }; 29 * @endcode 30 * 31 * @par 2) 32 * @code 33 * // The simplest way to fill a cache is by providing a request-update 34 * // function which must trigger a complete dump on the kernel-side of 35 * // whatever the cache covers. 36 * static int my_request_update(struct nl_cache *cache, 37 * struct nl_sock *socket) 38 * { 39 * // In this example, we request a full dump of the interface table 40 * return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP); 41 * } 42 * 43 * // The resulting netlink messages sent back will be fed into a message 44 * // parser one at a time. The message parser has to extract all relevant 45 * // information from the message and create an object reflecting the 46 * // contents of the message and pass it on to the parser callback function 47 * // provide which will add the object to the cache. 48 * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 49 * struct nlmsghdr *nlh, struct nl_parser_param *pp) 50 * { 51 * struct my_obj *obj; 52 * 53 * obj = my_obj_alloc(); 54 * obj->ce_msgtype = nlh->nlmsg_type; 55 * 56 * // Parse the netlink message and continue creating the object. 57 * 58 * err = pp->pp_cb((struct nl_object *) obj, pp); 59 * if (err < 0) 60 * goto errout; 61 * } 62 * 63 * struct nl_cache_ops my_cache_ops = { 64 * ... 65 * .co_request_update = my_request_update, 66 * .co_msg_parser = my_msg_parser, 67 * }; 68 * @endcode 69 * 70 * @par 3) Notification based Updates 71 * @code 72 * // Caches can be kept up-to-date based on notifications if the kernel 73 * // sends out notifications whenever an object is added/removed/changed. 74 * // 75 * // It is trivial to support this, first a list of groups needs to be 76 * // defined which are required to join in order to receive all necessary 77 * // notifications. The groups are separated by address family to support 78 * // the common situation where a separate group is used for each address 79 * // family. If there is only one group, simply specify AF_UNSPEC. 80 * static struct nl_af_group addr_groups[] = { 81 * { AF_INET, RTNLGRP_IPV4_IFADDR }, 82 * { AF_INET6, RTNLGRP_IPV6_IFADDR }, 83 * { END_OF_GROUP_LIST }, 84 * }; 85 * 86 * // In order for the caching system to know the meaning of each message 87 * // type it requires a table which maps each supported message type to 88 * // a cache action, e.g. RTM_NEWADDR means address has been added or 89 * // updated, RTM_DELADDR means address has been removed. 90 * static struct nl_cache_ops rtnl_addr_ops = { 91 * ... 92 * .co_msgtypes = { 93 * { RTM_NEWADDR, NL_ACT_NEW, "new" }, 94 * { RTM_DELADDR, NL_ACT_DEL, "del" }, 95 * { RTM_GETADDR, NL_ACT_GET, "get" }, 96 * END_OF_MSGTYPES_LIST, 97 * }, 98 * .co_groups = addr_groups, 99 * }; 100 * 101 * // It is now possible to keep the cache up-to-date using the cache manager. 102 * @endcode 103 * @{ 104 */ 105 106 #define END_OF_MSGTYPES_LIST { -1, -1, NULL } 107 108 /** 109 * Message type to cache action association 110 */ 111 struct nl_msgtype 112 { 113 /** Netlink message type */ 114 int mt_id; 115 116 /** Cache action to take */ 117 int mt_act; 118 119 /** Name of operation for human-readable printing */ 120 char * mt_name; 121 }; 122 123 /** 124 * Address family to netlink group association 125 */ 126 struct nl_af_group 127 { 128 /** Address family */ 129 int ag_family; 130 131 /** Netlink group identifier */ 132 int ag_group; 133 }; 134 135 #define END_OF_GROUP_LIST AF_UNSPEC, 0 136 137 /** 138 * Parser parameters 139 * 140 * This structure is used to configure what kind of parser to use 141 * when parsing netlink messages to create objects. 142 */ 143 struct nl_parser_param 144 { 145 /** Function to parse netlink messages into objects */ 146 int (*pp_cb)(struct nl_object *, struct nl_parser_param *); 147 148 /** Arbitary argument to be passed to the parser */ 149 void * pp_arg; 150 }; 151 152 /** 153 * Cache Operations 154 * 155 * This structure defines the characterstics of a cache type. It contains 156 * pointers to functions which implement the specifics of the object type 157 * the cache can hold. 158 */ 159 struct nl_cache_ops 160 { 161 /** Name of cache type (must be unique) */ 162 char * co_name; 163 164 /** Size of family specific netlink header */ 165 int co_hdrsize; 166 167 /** Netlink protocol */ 168 int co_protocol; 169 170 /** cache object hash size **/ 171 int co_hash_size; 172 173 /** cache flags */ 174 unsigned int co_flags; 175 176 /** Reference counter */ 177 unsigned int co_refcnt; 178 179 /** Group definition */ 180 struct nl_af_group * co_groups; 181 182 /** 183 * Called whenever an update of the cache is required. Must send 184 * a request message to the kernel requesting a complete dump. 185 */ 186 int (*co_request_update)(struct nl_cache *, struct nl_sock *); 187 188 /** 189 * Called whenever a message was received that needs to be parsed. 190 * Must parse the message and call the paser callback function 191 * (nl_parser_param) provided via the argument. 192 */ 193 int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, 194 struct nlmsghdr *, struct nl_parser_param *); 195 196 /** 197 * The function registered under this callback is called after a 198 * netlink notification associated with this cache type has been 199 * parsed into an object and is being considered for inclusio into 200 * the specified cache. 201 * 202 * The purpose of this function is to filter out notifications 203 * which should be ignored when updating caches. 204 * 205 * The function must return NL_SKIP to prevent the object from 206 * being included, or NL_OK to include it. 207 * 208 * @code 209 * int my_filter(struct nl_cache *cache, struct nl_object *obj) 210 * { 211 * if (reason_to_not_include_obj(obj)) 212 * return NL_SKIP; 213 * 214 * return NL_OK; 215 * } 216 * @endcode 217 */ 218 int (*co_event_filter)(struct nl_cache *, struct nl_object *obj); 219 220 /** 221 * The function registered under this callback is called when an 222 * object formed from a notification event needs to be included in 223 * a cache. 224 * 225 * For each modified object, the change callback \c change_cb must 226 * be called with the \c data argument provided. 227 * 228 * If no function is registered, the function nl_cache_include() 229 * will be used for this purpose. 230 * 231 * @see nl_cache_include() 232 */ 233 int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, 234 change_func_t change_cb, change_func_v2_t change_cb_v2, 235 void *data); 236 237 void (*reserved_1)(void); 238 void (*reserved_2)(void); 239 void (*reserved_3)(void); 240 void (*reserved_4)(void); 241 void (*reserved_5)(void); 242 void (*reserved_6)(void); 243 void (*reserved_7)(void); 244 void (*reserved_8)(void); 245 246 /** Object operations */ 247 struct nl_object_ops * co_obj_ops; 248 249 /** Internal, do not touch! */ 250 struct nl_cache_ops *co_next; 251 252 struct nl_cache *co_major_cache; 253 struct genl_ops * co_genl; 254 255 /* Message type definition */ 256 struct nl_msgtype co_msgtypes[]; 257 }; 258 259 /** @} */ 260 261 #ifdef __cplusplus 262 } 263 #endif 264 265 #endif 266