libnl  3.3.0
queue_msg.c
1 /*
2  * lib/netfilter/queue_msg.c Netfilter Queue Messages
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
10  * Copyright (c) 2010 Karl Hiramoto <karl@hiramoto.org>
11  */
12 
13 /**
14  * @ingroup nfnl
15  * @defgroup queue Queue
16  * @brief
17  * @{
18  */
19 
20 #include <sys/types.h>
21 #include <linux/netfilter/nfnetlink_queue.h>
22 
23 #include <netlink-private/netlink.h>
24 #include <netlink/attr.h>
25 #include <netlink/netfilter/nfnl.h>
26 #include <netlink/netfilter/queue_msg.h>
27 #include <netlink-private/utils.h>
28 
29 static struct nl_cache_ops nfnl_queue_msg_ops;
30 
31 static struct nla_policy queue_policy[NFQA_MAX+1] = {
32  [NFQA_PACKET_HDR] = {
33  .minlen = sizeof(struct nfqnl_msg_packet_hdr),
34  },
35  [NFQA_VERDICT_HDR] = {
36  .minlen = sizeof(struct nfqnl_msg_verdict_hdr),
37  },
38  [NFQA_MARK] = { .type = NLA_U32 },
39  [NFQA_TIMESTAMP] = {
40  .minlen = sizeof(struct nfqnl_msg_packet_timestamp),
41  },
42  [NFQA_IFINDEX_INDEV] = { .type = NLA_U32 },
43  [NFQA_IFINDEX_OUTDEV] = { .type = NLA_U32 },
44  [NFQA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 },
45  [NFQA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 },
46  [NFQA_HWADDR] = {
47  .minlen = sizeof(struct nfqnl_msg_packet_hw),
48  },
49 };
50 
51 int nfnlmsg_queue_msg_parse(struct nlmsghdr *nlh,
52  struct nfnl_queue_msg **result)
53 {
54  struct nfnl_queue_msg *msg;
55  struct nlattr *tb[NFQA_MAX+1];
56  struct nlattr *attr;
57  int err;
58 
59  msg = nfnl_queue_msg_alloc();
60  if (!msg)
61  return -NLE_NOMEM;
62 
63  msg->ce_msgtype = nlh->nlmsg_type;
64 
65  err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFQA_MAX,
66  queue_policy);
67  if (err < 0)
68  goto errout;
69 
70  nfnl_queue_msg_set_group(msg, nfnlmsg_res_id(nlh));
71  nfnl_queue_msg_set_family(msg, nfnlmsg_family(nlh));
72 
73  attr = tb[NFQA_PACKET_HDR];
74  if (attr) {
75  struct nfqnl_msg_packet_hdr *hdr = nla_data(attr);
76 
77  nfnl_queue_msg_set_packetid(msg, ntohl(hdr->packet_id));
78  if (hdr->hw_protocol)
79  nfnl_queue_msg_set_hwproto(msg, hdr->hw_protocol);
80  nfnl_queue_msg_set_hook(msg, hdr->hook);
81  }
82 
83  attr = tb[NFQA_MARK];
84  if (attr)
85  nfnl_queue_msg_set_mark(msg, ntohl(nla_get_u32(attr)));
86 
87  attr = tb[NFQA_TIMESTAMP];
88  if (attr) {
89  struct nfqnl_msg_packet_timestamp *timestamp = nla_data(attr);
90  struct timeval tv;
91 
92  tv.tv_sec = ntohll(timestamp->sec);
93  tv.tv_usec = ntohll(timestamp->usec);
94  nfnl_queue_msg_set_timestamp(msg, &tv);
95  }
96 
97  attr = tb[NFQA_IFINDEX_INDEV];
98  if (attr)
99  nfnl_queue_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
100 
101  attr = tb[NFQA_IFINDEX_OUTDEV];
102  if (attr)
103  nfnl_queue_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
104 
105  attr = tb[NFQA_IFINDEX_PHYSINDEV];
106  if (attr)
107  nfnl_queue_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
108 
109  attr = tb[NFQA_IFINDEX_PHYSOUTDEV];
110  if (attr)
111  nfnl_queue_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
112 
113  attr = tb[NFQA_HWADDR];
114  if (attr) {
115  struct nfqnl_msg_packet_hw *hw = nla_data(attr);
116 
117  nfnl_queue_msg_set_hwaddr(msg, hw->hw_addr,
118  ntohs(hw->hw_addrlen));
119  }
120 
121  attr = tb[NFQA_PAYLOAD];
122  if (attr) {
123  err = nfnl_queue_msg_set_payload(msg, nla_data(attr),
124  nla_len(attr));
125  if (err < 0)
126  goto errout;
127  }
128 
129  *result = msg;
130  return 0;
131 
132 errout:
133  nfnl_queue_msg_put(msg);
134  return err;
135 }
136 
137 static int queue_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
138  struct nlmsghdr *nlh, struct nl_parser_param *pp)
139 {
140  struct nfnl_queue_msg *msg;
141  int err;
142 
143  if ((err = nfnlmsg_queue_msg_parse(nlh, &msg)) < 0)
144  return err;
145 
146  err = pp->pp_cb((struct nl_object *) msg, pp);
147  nfnl_queue_msg_put(msg);
148  return err;
149 }
150 
151 /** @} */
152 
153 static struct nl_msg *
154 __nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg,
155  uint8_t type)
156 {
157  struct nl_msg *nlmsg;
158  struct nfqnl_msg_verdict_hdr verdict;
159 
160  nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, type, 0,
161  nfnl_queue_msg_get_family(msg),
162  nfnl_queue_msg_get_group(msg));
163  if (nlmsg == NULL)
164  return NULL;
165 
166  verdict.id = htonl(nfnl_queue_msg_get_packetid(msg));
167  verdict.verdict = htonl(nfnl_queue_msg_get_verdict(msg));
168  if (nla_put(nlmsg, NFQA_VERDICT_HDR, sizeof(verdict), &verdict) < 0)
169  goto nla_put_failure;
170 
171  if (nfnl_queue_msg_test_mark(msg) &&
172  nla_put_u32(nlmsg, NFQA_MARK,
173  ntohl(nfnl_queue_msg_get_mark(msg))) < 0)
174  goto nla_put_failure;
175 
176  return nlmsg;
177 
178 nla_put_failure:
179  nlmsg_free(nlmsg);
180  return NULL;
181 }
182 
183 struct nl_msg *
184 nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg)
185 {
186  return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT);
187 }
188 
189 struct nl_msg *
190 nfnl_queue_msg_build_verdict_batch(const struct nfnl_queue_msg *msg)
191 {
192  return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT_BATCH);
193 }
194 
195 /**
196 * Send a message verdict/mark
197 * @arg nlh netlink messsage header
198 * @arg msg queue msg
199 * @return 0 on OK or error code
200 */
201 int nfnl_queue_msg_send_verdict(struct nl_sock *nlh,
202  const struct nfnl_queue_msg *msg)
203 {
204  struct nl_msg *nlmsg;
205  int err;
206 
207  nlmsg = nfnl_queue_msg_build_verdict(msg);
208  if (nlmsg == NULL)
209  return -NLE_NOMEM;
210 
211  err = nl_send_auto_complete(nlh, nlmsg);
212  nlmsg_free(nlmsg);
213  if (err < 0)
214  return err;
215  return wait_for_ack(nlh);
216 }
217 
218 /**
219 * Send a message batched verdict/mark
220 * @arg nlh netlink messsage header
221 * @arg msg queue msg
222 * @return 0 on OK or error code
223 */
224 int nfnl_queue_msg_send_verdict_batch(struct nl_sock *nlh,
225  const struct nfnl_queue_msg *msg)
226 {
227  struct nl_msg *nlmsg;
228  int err;
229 
230  nlmsg = nfnl_queue_msg_build_verdict_batch(msg);
231  if (nlmsg == NULL)
232  return -NLE_NOMEM;
233 
234  err = nl_send_auto_complete(nlh, nlmsg);
235  nlmsg_free(nlmsg);
236  if (err < 0)
237  return err;
238  return wait_for_ack(nlh);
239 }
240 
241 /**
242 * Send a message verdict including the payload
243 * @arg nlh netlink messsage header
244 * @arg msg queue msg
245 * @arg payload_data packet payload data
246 * @arg payload_len payload length
247 * @return 0 on OK or error code
248 */
249 int nfnl_queue_msg_send_verdict_payload(struct nl_sock *nlh,
250  const struct nfnl_queue_msg *msg,
251  const void *payload_data, unsigned payload_len)
252 {
253  struct nl_msg *nlmsg;
254  int err;
255  struct iovec iov[3];
256  struct nlattr nla;
257 
258  nlmsg = nfnl_queue_msg_build_verdict(msg);
259  if (nlmsg == NULL)
260  return -NLE_NOMEM;
261 
262  memset(iov, 0, sizeof(iov));
263 
264  iov[0].iov_base = (void *) nlmsg_hdr(nlmsg);
265  iov[0].iov_len = nlmsg_hdr(nlmsg)->nlmsg_len;
266 
267  nla.nla_type = NFQA_PAYLOAD;
268  nla.nla_len = payload_len + sizeof(nla);
269  nlmsg_hdr(nlmsg)->nlmsg_len += nla.nla_len;
270 
271  iov[1].iov_base = (void *) &nla;
272  iov[1].iov_len = sizeof(nla);
273 
274  iov[2].iov_base = (void *) payload_data;
275  iov[2].iov_len = NLA_ALIGN(payload_len);
276 
277  nl_complete_msg(nlh, nlmsg);
278  err = nl_send_iovec(nlh, nlmsg, iov, 3);
279 
280  nlmsg_free(nlmsg);
281  if (err < 0)
282  return err;
283  return wait_for_ack(nlh);
284 }
285 
286 #define NFNLMSG_QUEUE_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_QUEUE, (type))
287 static struct nl_cache_ops nfnl_queue_msg_ops = {
288  .co_name = "netfilter/queue_msg",
289  .co_hdrsize = NFNL_HDRLEN,
290  .co_msgtypes = {
291  { NFNLMSG_QUEUE_TYPE(NFQNL_MSG_PACKET), NL_ACT_NEW, "new" },
292  END_OF_MSGTYPES_LIST,
293  },
294  .co_protocol = NETLINK_NETFILTER,
295  .co_msg_parser = queue_msg_parser,
296  .co_obj_ops = &queue_msg_obj_ops,
297 };
298 
299 static void __init nfnl_msg_queue_init(void)
300 {
301  nl_cache_mngt_register(&nfnl_queue_msg_ops);
302 }
303 
304 static void __exit nfnl_queue_msg_exit(void)
305 {
306  nl_cache_mngt_unregister(&nfnl_queue_msg_ops);
307 }
308 
309 /** @} */
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1247
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:562
void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg)
Finalize Netlink message.
Definition: nl.c:481
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:287
Attribute validation policy.
Definition: attr.h:69
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:214
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:252
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:540
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:120
int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen)
Transmit Netlink message (taking IO vector)
Definition: nl.c:373
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:131
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:152
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:74
int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
Add 32 bit integer attribute to netlink message.
Definition: attr.c:695
32 bit integer
Definition: attr.h:43
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.
Definition: attr.c:500
struct nl_msg * nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Allocate a new netfilter netlink message.
Definition: nfnl.c:203
uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
Get netfilter resource id from message.
Definition: nfnl.c:163