diff options
author | Thomas Graf <tgraf@suug.ch> | 2011-04-11 10:34:01 (GMT) |
---|---|---|
committer | Thomas Graf <tgraf@suug.ch> | 2011-04-11 10:34:01 (GMT) |
commit | 48d543cfdf49aef75b9898ebea379f2303d3935d (patch) | |
tree | ea0a9aa79176d18d5d94a4e28c7a5d55e6bafefe /lib/nl.c | |
parent | 41fb241b7bb88d10300145778e401ab34e3bf46b (diff) | |
download | libnl-48d543cfdf49aef75b9898ebea379f2303d3935d.zip libnl-48d543cfdf49aef75b9898ebea379f2303d3935d.tar.gz libnl-48d543cfdf49aef75b9898ebea379f2303d3935d.tar.bz2 |
API to issue direct GET requests to the kernel
Provide nl_pickup() to pick up an answer from a netlink request and parse
it using the supplied parser.
Add rtnl_link_get_kernel() which sends an RTM_GETLINK to the kernel to
fetch a single link directly from the kernel. This can be faster than
dumping the whole table, especially if lots of links are configured.
Diffstat (limited to 'lib/nl.c')
-rw-r--r-- | lib/nl.c | 70 |
1 files changed, 70 insertions, 0 deletions
@@ -799,6 +799,76 @@ int nl_wait_for_ack(struct nl_sock *sk) return err; } +/** @cond SKIP */ +struct pickup_param +{ + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + struct nl_object *result; +}; + +static int __store_answer(struct nl_object *obj, struct nl_parser_param *p) +{ + struct pickup_param *pp = p->pp_arg; + /* + * the parser will put() the object at the end, expecting the cache + * to take the reference. + */ + nl_object_get(obj); + pp->result = obj; + + return 0; +} + +static int __pickup_answer(struct nl_msg *msg, void *arg) +{ + struct pickup_param *pp = arg; + struct nl_parser_param parse_arg = { + .pp_cb = __store_answer, + .pp_arg = pp, + }; + + return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg); +} + +/** @endcond */ + +/** + * Pickup netlink answer, parse is and return object + * @arg sk Netlink socket + * @arg parser Parser function to parse answer + * @arg result Result pointer to return parsed object + * + * @return 0 on success or a negative error code. + */ +int nl_pickup(struct nl_sock *sk, + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result) +{ + struct nl_cb *cb; + int err; + struct pickup_param pp = { + .parser = parser, + }; + + cb = nl_cb_clone(sk->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp); + + err = nl_recvmsgs(sk, cb); + if (err < 0) + goto errout; + + *result = pp.result; +errout: + nl_cb_put(cb); + + return err; +} + /** @} */ /** @} */ |