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