libnl  3.5.0
log.c
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * lib/netfilter/log.c Netfilter Log
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) 2003-2008 Thomas Graf <tgraf@suug.ch>
11  * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
12  * Copyright (c) 2007 Secure Computing Corporation
13  */
14 
15 /**
16  * @ingroup nfnl
17  * @defgroup log Log
18  * @brief
19  * @{
20  */
21 
22 #include <sys/types.h>
23 #include <linux/netfilter/nfnetlink_log.h>
24 
25 #include <netlink-private/netlink.h>
26 #include <netlink/attr.h>
27 #include <netlink/netfilter/nfnl.h>
28 #include <netlink/netfilter/log.h>
29 
30 /**
31  * @name Log Commands
32  * @{
33  */
34 
35 static int build_log_cmd_request(uint8_t family, uint16_t queuenum,
36  uint8_t command, struct nl_msg **result)
37 {
38  struct nl_msg *msg;
39  struct nfulnl_msg_config_cmd cmd;
40 
41  msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
42  family, queuenum);
43  if (msg == NULL)
44  return -NLE_NOMEM;
45 
46  cmd.command = command;
47  if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
48  goto nla_put_failure;
49 
50  *result = msg;
51  return 0;
52 
53 nla_put_failure:
54  nlmsg_free(msg);
55  return -NLE_MSGSIZE;
56 }
57 
58 static int send_log_request(struct nl_sock *sk, struct nl_msg *msg)
59 {
60  int err;
61 
62  err = nl_send_auto_complete(sk, msg);
63  nlmsg_free(msg);
64  if (err < 0)
65  return err;
66 
67  return wait_for_ack(sk);
68 }
69 
70 int nfnl_log_build_pf_bind(uint8_t pf, struct nl_msg **result)
71 {
72  return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_BIND, result);
73 }
74 
75 int nfnl_log_pf_bind(struct nl_sock *nlh, uint8_t pf)
76 {
77  struct nl_msg *msg;
78  int err;
79 
80  if ((err = nfnl_log_build_pf_bind(pf, &msg)) < 0)
81  return err;
82 
83  return send_log_request(nlh, msg);
84 }
85 
86 int nfnl_log_build_pf_unbind(uint8_t pf, struct nl_msg **result)
87 {
88  return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_UNBIND, result);
89 }
90 
91 int nfnl_log_pf_unbind(struct nl_sock *nlh, uint8_t pf)
92 {
93  struct nl_msg *msg;
94  int err;
95 
96  if ((err = nfnl_log_build_pf_unbind(pf, &msg)) < 0)
97  return err;
98 
99  return send_log_request(nlh, msg);
100 }
101 
102 static int nfnl_log_build_request(const struct nfnl_log *log,
103  struct nl_msg **result)
104 {
105  struct nl_msg *msg;
106 
107  if (!nfnl_log_test_group(log))
108  return -NLE_MISSING_ATTR;
109 
110  msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
111  0, nfnl_log_get_group(log));
112  if (msg == NULL)
113  return -NLE_NOMEM;
114 
115  /* This sucks. The nfnetlink_log interface always expects both
116  * parameters to be present. Needs to be done properly.
117  */
118  if (nfnl_log_test_copy_mode(log)) {
119  struct nfulnl_msg_config_mode mode;
120 
121  switch (nfnl_log_get_copy_mode(log)) {
122  case NFNL_LOG_COPY_NONE:
123  mode.copy_mode = NFULNL_COPY_NONE;
124  break;
125  case NFNL_LOG_COPY_META:
126  mode.copy_mode = NFULNL_COPY_META;
127  break;
128  case NFNL_LOG_COPY_PACKET:
129  mode.copy_mode = NFULNL_COPY_PACKET;
130  break;
131  }
132  mode.copy_range = htonl(nfnl_log_get_copy_range(log));
133  mode._pad = 0;
134 
135  if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
136  goto nla_put_failure;
137  }
138 
139  if (nfnl_log_test_flush_timeout(log) &&
140  nla_put_u32(msg, NFULA_CFG_TIMEOUT,
141  htonl(nfnl_log_get_flush_timeout(log))) < 0)
142  goto nla_put_failure;
143 
144  if (nfnl_log_test_alloc_size(log) &&
145  nla_put_u32(msg, NFULA_CFG_NLBUFSIZ,
146  htonl(nfnl_log_get_alloc_size(log))) < 0)
147  goto nla_put_failure;
148 
149  if (nfnl_log_test_queue_threshold(log) &&
150  nla_put_u32(msg, NFULA_CFG_QTHRESH,
151  htonl(nfnl_log_get_queue_threshold(log))) < 0)
152  goto nla_put_failure;
153 
154  *result = msg;
155  return 0;
156 
157 nla_put_failure:
158  nlmsg_free(msg);
159  return -NLE_MSGSIZE;
160 }
161 
162 int nfnl_log_build_create_request(const struct nfnl_log *log,
163  struct nl_msg **result)
164 {
165  struct nfulnl_msg_config_cmd cmd;
166  int err;
167 
168  if ((err = nfnl_log_build_request(log, result)) < 0)
169  return err;
170 
171  cmd.command = NFULNL_CFG_CMD_BIND;
172 
173  if (nla_put(*result, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
174  goto nla_put_failure;
175 
176  return 0;
177 
178 nla_put_failure:
179  nlmsg_free(*result);
180  return -NLE_MSGSIZE;
181 }
182 
183 int nfnl_log_create(struct nl_sock *nlh, const struct nfnl_log *log)
184 {
185  struct nl_msg *msg;
186  int err;
187 
188  if ((err = nfnl_log_build_create_request(log, &msg)) < 0)
189  return err;
190 
191  return send_log_request(nlh, msg);
192 }
193 
194 int nfnl_log_build_change_request(const struct nfnl_log *log,
195  struct nl_msg **result)
196 {
197  return nfnl_log_build_request(log, result);
198 }
199 
200 int nfnl_log_change(struct nl_sock *nlh, const struct nfnl_log *log)
201 {
202  struct nl_msg *msg;
203  int err;
204 
205  if ((err = nfnl_log_build_change_request(log, &msg)) < 0)
206  return err;
207 
208  return send_log_request(nlh, msg);
209 }
210 
211 int nfnl_log_build_delete_request(const struct nfnl_log *log,
212  struct nl_msg **result)
213 {
214  if (!nfnl_log_test_group(log))
215  return -NLE_MISSING_ATTR;
216 
217  return build_log_cmd_request(0, nfnl_log_get_group(log),
218  NFULNL_CFG_CMD_UNBIND, result);
219 }
220 
221 int nfnl_log_delete(struct nl_sock *nlh, const struct nfnl_log *log)
222 {
223  struct nl_msg *msg;
224  int err;
225 
226  if ((err = nfnl_log_build_delete_request(log, &msg)) < 0)
227  return err;
228 
229  return send_log_request(nlh, msg);
230 }
231 
232 /** @} */
233 
234 static struct nl_cache_ops nfnl_log_ops = {
235  .co_name = "netfilter/log",
236  .co_obj_ops = &log_obj_ops,
237  .co_msgtypes = {
238  END_OF_MSGTYPES_LIST,
239  },
240 };
241 
242 static void __init log_init(void)
243 {
244  nl_cache_mngt_register(&nfnl_log_ops);
245 }
246 
247 static void __exit log_exit(void)
248 {
249  nl_cache_mngt_unregister(&nfnl_log_ops);
250 }
251 
252 /** @} */
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1248
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:565
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:288
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:253
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
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
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