libmnl  1.0.3
callback.c
1 /*
2  * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include <errno.h>
11 #include <libmnl/libmnl.h>
12 #include "internal.h"
13 
14 static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
15 {
16  return MNL_CB_OK;
17 }
18 
19 static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
20 {
21  const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
22 
23  if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
24  errno = EBADMSG;
25  return MNL_CB_ERROR;
26  }
27  /* Netlink subsystems returns the errno value with different signess */
28  if (err->error < 0)
29  errno = -err->error;
30  else
31  errno = err->error;
32 
33  return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
34 }
35 
36 static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
37 {
38  return MNL_CB_STOP;
39 }
40 
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,
46 };
47 
48 static inline int
49 __mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
50  unsigned int portid, mnl_cb_t cb_data, void *data,
51  mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
52 {
53  int ret = MNL_CB_OK, len = numbytes;
54  const struct nlmsghdr *nlh = buf;
55 
56  while (mnl_nlmsg_ok(nlh, len)) {
57  /* check message source */
58  if (!mnl_nlmsg_portid_ok(nlh, portid)) {
59  errno = ESRCH;
60  return -1;
61  }
62  /* perform sequence tracking */
63  if (!mnl_nlmsg_seq_ok(nlh, seq)) {
64  errno = EPROTO;
65  return -1;
66  }
67 
68  /* netlink data message handling */
69  if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
70  if (cb_data){
71  ret = cb_data(nlh, data);
72  if (ret <= MNL_CB_STOP)
73  goto out;
74  }
75  } else if (nlh->nlmsg_type < cb_ctl_array_len) {
76  if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
77  ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
78  if (ret <= MNL_CB_STOP)
79  goto out;
80  }
81  } else if (default_cb_array[nlh->nlmsg_type]) {
82  ret = default_cb_array[nlh->nlmsg_type](nlh, data);
83  if (ret <= MNL_CB_STOP)
84  goto out;
85  }
86  nlh = mnl_nlmsg_next(nlh, &len);
87  }
88 out:
89  return ret;
90 }
91 
122 int
123 mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
124  unsigned int portid, mnl_cb_t cb_data, void *data,
125  mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
126 {
127  return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
128  cb_ctl_array, cb_ctl_array_len);
129 }
130 EXPORT_SYMBOL(mnl_cb_run2);
131 
151 int
152 mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
153  unsigned int portid, mnl_cb_t cb_data, void *data)
154 {
155  return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
156 }
157 EXPORT_SYMBOL(mnl_cb_run);
158 
struct nlmsghdr * mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
Definition: nlmsg.c:180
int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, unsigned int portid, mnl_cb_t cb_data, void *data)
Definition: callback.c:152
bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
Definition: nlmsg.c:158
bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
Definition: nlmsg.c:237
int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq, unsigned int portid, mnl_cb_t cb_data, void *data, mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
Definition: callback.c:123
size_t mnl_nlmsg_size(size_t len)
Definition: nlmsg.c:54
bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
Definition: nlmsg.c:216
void * mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
Definition: nlmsg.c:121