11 #include <libmnl/libmnl.h>
14 static int mnl_cb_noop(
const struct nlmsghdr *nlh,
void *data)
19 static int mnl_cb_error(
const struct nlmsghdr *nlh,
void *data)
21 const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
23 if (nlh->nlmsg_len < mnl_nlmsg_size(
sizeof(
struct nlmsgerr))) {
33 return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
36 static int mnl_cb_stop(
const struct nlmsghdr *nlh,
void *data)
41 static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
42 [NLMSG_NOOP] = mnl_cb_noop,
43 [NLMSG_ERROR] = mnl_cb_error,
44 [NLMSG_DONE] = mnl_cb_stop,
45 [NLMSG_OVERRUN] = mnl_cb_noop,
48 static inline int __mnl_cb_run(
const void *buf,
size_t numbytes,
49 unsigned int seq,
unsigned int portid,
50 mnl_cb_t cb_data,
void *data,
51 const mnl_cb_t *cb_ctl_array,
52 unsigned int cb_ctl_array_len)
54 int ret = MNL_CB_OK, len = numbytes;
55 const struct nlmsghdr *nlh = buf;
57 while (mnl_nlmsg_ok(nlh, len)) {
59 if (!mnl_nlmsg_portid_ok(nlh, portid)) {
64 if (!mnl_nlmsg_seq_ok(nlh, seq)) {
70 if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
76 if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
78 ret = cb_data(nlh, data);
79 if (ret <= MNL_CB_STOP)
82 }
else if (nlh->nlmsg_type < cb_ctl_array_len) {
83 if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
84 ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
85 if (ret <= MNL_CB_STOP)
88 }
else if (default_cb_array[nlh->nlmsg_type]) {
89 ret = default_cb_array[nlh->nlmsg_type](nlh, data);
90 if (ret <= MNL_CB_STOP)
93 nlh = mnl_nlmsg_next(nlh, &len);
130 EXPORT_SYMBOL(mnl_cb_run2);
131 int mnl_cb_run2(
const void *buf,
size_t numbytes,
unsigned int seq,
132 unsigned int portid, mnl_cb_t cb_data,
void *data,
133 const mnl_cb_t *cb_ctl_array,
unsigned int cb_ctl_array_len)
135 return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
136 cb_ctl_array, cb_ctl_array_len);
158 EXPORT_SYMBOL(mnl_cb_run);
159 int mnl_cb_run(
const void *buf,
size_t numbytes,
unsigned int seq,
160 unsigned int portid, mnl_cb_t cb_data,
void *data)
162 return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);