libnl 3.11.0
queue.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
4 */
5
6/**
7 * @ingroup nfnl
8 * @defgroup queue Queue
9 * @brief
10 * @{
11 */
12
13#include "nl-default.h"
14
15#include <sys/types.h>
16
17#include <linux/netfilter/nfnetlink_queue.h>
18
19#include <netlink/attr.h>
20#include <netlink/netfilter/nfnl.h>
21#include <netlink/netfilter/queue.h>
22
23#include "nl-priv-dynamic-core/nl-core.h"
24#include "nl-priv-dynamic-core/cache-api.h"
25
26struct nl_sock *nfnl_queue_socket_alloc(void)
27{
28 struct nl_sock *nlsk;
29
30 nlsk = nl_socket_alloc();
31 if (nlsk)
33 return nlsk;
34}
35
36static int send_queue_request(struct nl_sock *sk, struct nl_msg *msg)
37{
38 int err;
39
40 err = nl_send_auto_complete(sk, msg);
41 nlmsg_free(msg);
42 if (err < 0)
43 return err;
44
45 return wait_for_ack(sk);
46}
47
48/**
49 * @name Queue Commands
50 * @{
51 */
52
53static int build_queue_cmd_request(uint8_t family, uint16_t queuenum,
54 uint8_t command, struct nl_msg **result)
55{
56 struct nl_msg *msg;
57 struct nfqnl_msg_config_cmd cmd;
58
59 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0,
60 family, queuenum);
61 if (msg == NULL)
62 return -NLE_NOMEM;
63
64 cmd.pf = htons(family);
65 cmd._pad = 0;
66 cmd.command = command;
67 if (nla_put(msg, NFQA_CFG_CMD, sizeof(cmd), &cmd) < 0)
68 goto nla_put_failure;
69
70 *result = msg;
71 return 0;
72
73nla_put_failure:
74 nlmsg_free(msg);
75 return -NLE_MSGSIZE;
76}
77
78int nfnl_queue_build_pf_bind(uint8_t pf, struct nl_msg **result)
79{
80 return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_BIND, result);
81}
82
83int nfnl_queue_pf_bind(struct nl_sock *nlh, uint8_t pf)
84{
85 struct nl_msg *msg;
86 int err;
87
88 if ((err = nfnl_queue_build_pf_bind(pf, &msg)) < 0)
89 return err;
90
91 return send_queue_request(nlh, msg);
92}
93
94int nfnl_queue_build_pf_unbind(uint8_t pf, struct nl_msg **result)
95{
96 return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_UNBIND, result);
97}
98
99int nfnl_queue_pf_unbind(struct nl_sock *nlh, uint8_t pf)
100{
101 struct nl_msg *msg;
102 int err;
103
104 if ((err = nfnl_queue_build_pf_unbind(pf, &msg)) < 0)
105 return err;
106
107 return send_queue_request(nlh, msg);
108}
109
110static int nfnl_queue_build_request(const struct nfnl_queue *queue,
111 struct nl_msg **result)
112{
113 struct nl_msg *msg;
114
115 if (!nfnl_queue_test_group(queue))
116 return -NLE_MISSING_ATTR;
117
118 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0,
119 0, nfnl_queue_get_group(queue));
120 if (msg == NULL)
121 return -NLE_NOMEM;
122
123 if (nfnl_queue_test_maxlen(queue) &&
124 nla_put_u32(msg, NFQA_CFG_QUEUE_MAXLEN,
125 htonl(nfnl_queue_get_maxlen(queue))) < 0)
126 goto nla_put_failure;
127
128 /* This sucks, the nfnetlink_queue interface always expects both
129 * parameters to be present. Needs to be done properly.
130 */
131 if (nfnl_queue_test_copy_mode(queue)) {
132 struct nfqnl_msg_config_params params;
133
134 switch (nfnl_queue_get_copy_mode(queue)) {
135 case NFNL_QUEUE_COPY_NONE:
136 params.copy_mode = NFQNL_COPY_NONE;
137 break;
138 case NFNL_QUEUE_COPY_META:
139 params.copy_mode = NFQNL_COPY_META;
140 break;
141 case NFNL_QUEUE_COPY_PACKET:
142 params.copy_mode = NFQNL_COPY_PACKET;
143 break;
144 }
145 params.copy_range = htonl(nfnl_queue_get_copy_range(queue));
146
147 if (nla_put(msg, NFQA_CFG_PARAMS, sizeof(params), &params) < 0)
148 goto nla_put_failure;
149 }
150
151 *result = msg;
152 return 0;
153
154nla_put_failure:
155 nlmsg_free(msg);
156 return -NLE_MSGSIZE;
157}
158
159int nfnl_queue_build_create_request(const struct nfnl_queue *queue,
160 struct nl_msg **result)
161{
162 struct nfqnl_msg_config_cmd cmd;
163 int err;
164
165 if ((err = nfnl_queue_build_request(queue, result)) < 0)
166 return err;
167
168 cmd.pf = 0;
169 cmd._pad = 0;
170 cmd.command = NFQNL_CFG_CMD_BIND;
171
172 NLA_PUT(*result, NFQA_CFG_CMD, sizeof(cmd), &cmd);
173
174 return 0;
175
176nla_put_failure:
177 nlmsg_free(*result);
178 return -NLE_MSGSIZE;
179}
180
181int nfnl_queue_create(struct nl_sock *nlh, const struct nfnl_queue *queue)
182{
183 struct nl_msg *msg;
184 int err;
185
186 if ((err = nfnl_queue_build_create_request(queue, &msg)) < 0)
187 return err;
188
189 return send_queue_request(nlh, msg);
190}
191
192int nfnl_queue_build_change_request(const struct nfnl_queue *queue,
193 struct nl_msg **result)
194{
195 return nfnl_queue_build_request(queue, result);
196}
197
198int nfnl_queue_change(struct nl_sock *nlh, const struct nfnl_queue *queue)
199{
200 struct nl_msg *msg;
201 int err;
202
203 if ((err = nfnl_queue_build_change_request(queue, &msg)) < 0)
204 return err;
205
206 return send_queue_request(nlh, msg);
207}
208
209int nfnl_queue_build_delete_request(const struct nfnl_queue *queue,
210 struct nl_msg **result)
211{
212 if (!nfnl_queue_test_group(queue))
213 return -NLE_MISSING_ATTR;
214
215 return build_queue_cmd_request(0, nfnl_queue_get_group(queue),
216 NFQNL_CFG_CMD_UNBIND, result);
217}
218
219int nfnl_queue_delete(struct nl_sock *nlh, const struct nfnl_queue *queue)
220{
221 struct nl_msg *msg;
222 int err;
223
224 if ((err = nfnl_queue_build_delete_request(queue, &msg)) < 0)
225 return err;
226
227 return send_queue_request(nlh, msg);
228}
229
230/** @} */
231
232static struct nl_cache_ops nfnl_queue_ops = {
233 .co_name = "netfilter/queue",
234 .co_obj_ops = &queue_obj_ops,
235 .co_msgtypes = {
236 END_OF_MSGTYPES_LIST,
237 },
238};
239
240static void _nl_init nfnl_queue_init(void)
241{
242 nl_cache_mngt_register(&nfnl_queue_ops);
243}
244
245static void _nl_exit nfnl_queue_exit(void)
246{
247 nl_cache_mngt_unregister(&nfnl_queue_ops);
248}
249
250/** @} */
int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
Add 32 bit integer attribute to netlink message.
Definition attr.c:703
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:166
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.
Definition attr.c:505
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
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition msg.c:572
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_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition nl.c:1247
void nl_socket_disable_auto_ack(struct nl_sock *sk)
Disable automatic request for ACK.
Definition socket.c:339
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
Definition socket.c:226