1 /* 2 * netlink/cache-api.h Caching 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-2006 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 #ifndef NETLINK_CACHE_API_H_ 13 #define NETLINK_CACHE_API_H_ 14 15 #include <netlink/netlink.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /** 22 * @ingroup cache 23 * @defgroup cache_api Cache Implementation 24 * @brief 25 * 26 * @par 1) Cache Definition 27 * @code 28 * struct nl_cache_ops my_cache_ops = { 29 * .co_name = "route/link", 30 * .co_protocol = NETLINK_ROUTE, 31 * .co_hdrsize = sizeof(struct ifinfomsg), 32 * .co_obj_ops = &my_obj_ops, 33 * }; 34 * @endcode 35 * 36 * @par 2) 37 * @code 38 * // The simplest way to fill a cache is by providing a request-update 39 * // function which must trigger a complete dump on the kernel-side of 40 * // whatever the cache covers. 41 * static int my_request_update(struct nl_cache *cache, 42 * struct nl_sock *socket) 43 * { 44 * // In this example, we request a full dump of the interface table 45 * return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP); 46 * } 47 * 48 * // The resulting netlink messages sent back will be fed into a message 49 * // parser one at a time. The message parser has to extract all relevant 50 * // information from the message and create an object reflecting the 51 * // contents of the message and pass it on to the parser callback function 52 * // provide which will add the object to the cache. 53 * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 54 * struct nlmsghdr *nlh, struct nl_parser_param *pp) 55 * { 56 * struct my_obj *obj; 57 * 58 * obj = my_obj_alloc(); 59 * obj->ce_msgtype = nlh->nlmsg_type; 60 * 61 * // Parse the netlink message and continue creating the object. 62 * 63 * err = pp->pp_cb((struct nl_object *) obj, pp); 64 * if (err < 0) 65 * goto errout; 66 * } 67 * 68 * struct nl_cache_ops my_cache_ops = { 69 * ... 70 * .co_request_update = my_request_update, 71 * .co_msg_parser = my_msg_parser, 72 * }; 73 * @endcode 74 * 75 * @par 3) Notification based Updates 76 * @code 77 * // Caches can be kept up-to-date based on notifications if the kernel 78 * // sends out notifications whenever an object is added/removed/changed. 79 * // 80 * // It is trivial to support this, first a list of groups needs to be 81 * // defined which are required to join in order to receive all necessary 82 * // notifications. The groups are separated by address family to support 83 * // the common situation where a separate group is used for each address 84 * // family. If there is only one group, simply specify AF_UNSPEC. 85 * static struct nl_af_group addr_groups[] = { 86 * { AF_INET, RTNLGRP_IPV4_IFADDR }, 87 * { AF_INET6, RTNLGRP_IPV6_IFADDR }, 88 * { END_OF_GROUP_LIST }, 89 * }; 90 * 91 * // In order for the caching system to know the meaning of each message 92 * // type it requires a table which maps each supported message type to 93 * // a cache action, e.g. RTM_NEWADDR means address has been added or 94 * // updated, RTM_DELADDR means address has been removed. 95 * static struct nl_cache_ops rtnl_addr_ops = { 96 * ... 97 * .co_msgtypes = { 98 * { RTM_NEWADDR, NL_ACT_NEW, "new" }, 99 * { RTM_DELADDR, NL_ACT_DEL, "del" }, 100 * { RTM_GETADDR, NL_ACT_GET, "get" }, 101 * END_OF_MSGTYPES_LIST, 102 * }, 103 * .co_groups = addr_groups, 104 * }; 105 * 106 * // It is now possible to keep the cache up-to-date using the cache manager. 107 * @endcode 108 * @{ 109 */ 110 111 enum { 112 NL_ACT_UNSPEC, 113 NL_ACT_NEW, 114 NL_ACT_DEL, 115 NL_ACT_GET, 116 NL_ACT_SET, 117 NL_ACT_CHANGE, 118 __NL_ACT_MAX, 119 }; 120 121 #define NL_ACT_MAX (__NL_ACT_MAX - 1) 122 123 #define END_OF_MSGTYPES_LIST { -1, -1, NULL } 124 125 /** 126 * Message type to cache action association 127 */ 128 struct nl_msgtype 129 { 130 /** Netlink message type */ 131 int mt_id; 132 133 /** Cache action to take */ 134 int mt_act; 135 136 /** Name of operation for human-readable printing */ 137 char * mt_name; 138 }; 139 140 /** 141 * Address family to netlink group association 142 */ 143 struct nl_af_group 144 { 145 /** Address family */ 146 int ag_family; 147 148 /** Netlink group identifier */ 149 int ag_group; 150 }; 151 152 #define END_OF_GROUP_LIST AF_UNSPEC, 0 153 154 struct nl_parser_param 155 { 156 int (*pp_cb)(struct nl_object *, struct nl_parser_param *); 157 void * pp_arg; 158 }; 159 160 /** 161 * Cache Operations 162 */ 163 struct nl_cache_ops 164 { 165 char * co_name; 166 167 int co_hdrsize; 168 int co_protocol; 169 struct nl_af_group * co_groups; 170 171 /** 172 * Called whenever an update of the cache is required. Must send 173 * a request message to the kernel requesting a complete dump. 174 */ 175 int (*co_request_update)(struct nl_cache *, struct nl_sock *); 176 177 /** 178 * Called whenever a message was received that needs to be parsed. 179 * Must parse the message and call the paser callback function 180 * (nl_parser_param) provided via the argument. 181 */ 182 int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, 183 struct nlmsghdr *, struct nl_parser_param *); 184 185 struct nl_object_ops * co_obj_ops; 186 187 struct nl_cache_ops *co_next; 188 struct nl_cache *co_major_cache; 189 struct genl_ops * co_genl; 190 struct nl_msgtype co_msgtypes[]; 191 }; 192 193 /** @} */ 194 195 #ifdef __cplusplus 196 } 197 #endif 198 199 #endif 200