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