diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2010-03-19 14:55:32 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2010-03-19 14:55:32 +0100 |
commit | 74e7bb8b033640f7c4692c4ea0d5c231e3137b7b (patch) | |
tree | 4cc2125d00b83b5ac1b076da2c8e3eff7b08ddc3 /src/callback.c | |
download | libmnl-74e7bb8b033640f7c4692c4ea0d5c231e3137b7b.tar.gz libmnl-74e7bb8b033640f7c4692c4ea0d5c231e3137b7b.zip |
initial libmnl import
Diffstat (limited to 'src/callback.c')
-rw-r--r-- | src/callback.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/callback.c b/src/callback.c new file mode 100644 index 0000000..3fc883e --- /dev/null +++ b/src/callback.c @@ -0,0 +1,119 @@ +/* + * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include <errno.h> +#include <libmnl/libmnl.h> + +static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data) +{ + return MNL_CB_OK; +} + +static int mnl_cb_error(const struct nlmsghdr *nlh, void *data) +{ + const struct nlmsgerr *err = mnl_nlmsg_get_data(nlh); + + if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) { + errno = EBADMSG; + return MNL_CB_ERROR; + } + /* Netlink subsystems returns the errno value with different signess */ + if (err->error < 0) + errno = -err->error; + else + errno = err->error; + + return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; +} + +static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data) +{ + return MNL_CB_STOP; +} + +static mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = { + [NLMSG_NOOP] = mnl_cb_noop, + [NLMSG_ERROR] = mnl_cb_error, + [NLMSG_DONE] = mnl_cb_stop, + [NLMSG_OVERRUN] = mnl_cb_noop, +}; + +/** + * mnl_cb_run2 - callback runqueue for netlink messages + * @buf: buffer that contains the netlink messages + * @numbytes: number of bytes stored in the buffer + * @seq: sequence number that we expect to receive (use zero to skip) + * @cb_data: callback handler for data messages + * @data: pointer to data that will be passed to the data callback handler + * @cb_ctl_array: array of custom callback handlers from control messages + * @cb_ctl_array_len: length of the array of custom control callback handlers + * + * You can set the cb_ctl_array to NULL if you want to use the default control + * callback handlers, in that case, the parameter cb_ctl_array_len is not + * checked. + * + * This function returns -1 in case of error, 0 if we have received a + * NLMSG_DONE message or the callback has explicitly returned MNL_CB_STOP. + */ +int mnl_cb_run2(const char *buf, int numbytes, unsigned int seq, + mnl_cb_t cb_data, void *data, + mnl_cb_t *cb_ctl_array, int cb_ctl_array_len) +{ + int ret = MNL_CB_OK; + struct nlmsghdr *nlh = (struct nlmsghdr *)buf; + + while (mnl_nlmsg_ok(nlh, numbytes)) { + /* perform sequence tracking */ + if (!mnl_nlmsg_seq_ok(nlh, seq)) { + errno = EILSEQ; + return -1; + } + + /* netlink data message handling */ + if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { + if (cb_data){ + ret = cb_data(nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + } else if (nlh->nlmsg_type < cb_ctl_array_len) { + if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) { + ret = cb_ctl_array[nlh->nlmsg_type](nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + } else if (default_cb_array[nlh->nlmsg_type]) { + ret = default_cb_array[nlh->nlmsg_type](nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + nlh = mnl_nlmsg_next(nlh, &numbytes); + } +out: + return ret <= MNL_CB_ERROR ? -1 : 0; +} + +/** + * mnl_cb_run - callback runqueue for netlink messages (simplified version) + * @buf: buffer that contains the netlink messages + * @numbytes: number of bytes stored in the buffer + * @seq: sequence number that we expect to receive (use zero to skip) + * @cb_data: callback handler for data messages + * @data: pointer to data that will be passed to the data callback handler + * + * This function is like mnl_cb_run2() but it does not allow you to set + * the control callback handlers. + * + * This function returns -1 in case of error, 0 if we have received a + * NLMSG_DONE message or the callback has explicitly returned MNL_CB_STOP. + */ + +int mnl_cb_run(const char *buf, int numbytes, unsigned int seq, + mnl_cb_t cb_data, void *data) +{ + return mnl_cb_run2(buf, numbytes, seq, cb_data, data, NULL, 0); +} |