libnl 1.1
|
Data Structures | |
struct | nl_msgtype |
Message type to cache action association. More... | |
struct | nl_af_group |
Address family to netlink group association. More... | |
struct | nl_parser_param |
struct | nl_cache_ops |
Cache Operations. More... | |
Defines | |
#define | NL_ACT_MAX (__NL_ACT_MAX - 1) |
#define | END_OF_MSGTYPES_LIST { -1, -1, NULL } |
#define | END_OF_GROUP_LIST AF_UNSPEC, 0 |
Enumerations | |
enum | { NL_ACT_UNSPEC, NL_ACT_NEW, NL_ACT_DEL, NL_ACT_GET, NL_ACT_SET, NL_ACT_CHANGE, __NL_ACT_MAX } |
struct nl_cache_ops my_cache_ops = { .co_name = "route/link", .co_protocol = NETLINK_ROUTE, .co_hdrsize = sizeof(struct ifinfomsg), .co_obj_ops = &my_obj_ops, };
// The simplest way to fill a cache is by providing a request-update // function which must trigger a complete dump on the kernel-side of // whatever the cache covers. static int my_request_update(struct nl_cache *cache, struct nl_handle *socket) { // In this example, we request a full dump of the interface table return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP); } // The resulting netlink messages sent back will be fed into a message // parser one at a time. The message parser has to extract all relevant // information from the message and create an object reflecting the // contents of the message and pass it on to the parser callback function // provide which will add the object to the cache. static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *nlh, struct nl_parser_param *pp) { struct my_obj *obj; obj = my_obj_alloc(); obj->ce_msgtype = nlh->nlmsg_type; // Parse the netlink message and continue creating the object. err = pp->pp_cb((struct nl_object *) obj, pp); if (err < 0) goto errout; } struct nl_cache_ops my_cache_ops = { ... .co_request_update = my_request_update, .co_msg_parser = my_msg_parser, };
// Caches can be kept up-to-date based on notifications if the kernel // sends out notifications whenever an object is added/removed/changed. // // It is trivial to support this, first a list of groups needs to be // defined which are required to join in order to receive all necessary // notifications. The groups are separated by address family to support // the common situation where a separate group is used for each address // family. If there is only one group, simply specify AF_UNSPEC. static struct nl_af_group addr_groups[] = { { AF_INET, RTNLGRP_IPV4_IFADDR }, { AF_INET6, RTNLGRP_IPV6_IFADDR }, { END_OF_GROUP_LIST }, }; // In order for the caching system to know the meaning of each message // type it requires a table which maps each supported message type to // a cache action, e.g. RTM_NEWADDR means address has been added or // updated, RTM_DELADDR means address has been removed. static struct nl_cache_ops rtnl_addr_ops = { ... .co_msgtypes = { { RTM_NEWADDR, NL_ACT_NEW, "new" }, { RTM_DELADDR, NL_ACT_DEL, "del" }, { RTM_GETADDR, NL_ACT_GET, "get" }, END_OF_MSGTYPES_LIST, }, .co_groups = addr_groups, }; // It is now possible to keep the cache up-to-date using the cache manager.