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