libnl 3.5.0

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