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 
21 struct 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 
31 static 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 
48 static 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 
68 nla_put_failure:
69  nlmsg_free(msg);
70  return -NLE_MSGSIZE;
71 }
72 
73 int 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 
78 int 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 
89 int 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 
94 int 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 
105 static 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 
149 nla_put_failure:
150  nlmsg_free(msg);
151  return -NLE_MSGSIZE;
152 }
153 
154 int 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 
171 nla_put_failure:
172  nlmsg_free(*result);
173  return -NLE_MSGSIZE;
174 }
175 
176 int 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 
187 int 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 
193 int 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 
204 int 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 
214 int 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 
227 static 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 
235 static void __init nfnl_queue_init(void)
236 {
237  nl_cache_mngt_register(&nfnl_queue_ops);
238 }
239 
240 static 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:688
#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