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