• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
build_log_cmd_request(uint8_t family,uint16_t queuenum,uint8_t command,struct nl_msg ** result)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 
send_log_request(struct nl_sock * sk,struct nl_msg * msg)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 
nfnl_log_build_pf_bind(uint8_t pf,struct nl_msg ** result)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 
nfnl_log_pf_bind(struct nl_sock * nlh,uint8_t pf)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 
nfnl_log_build_pf_unbind(uint8_t pf,struct nl_msg ** result)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 
nfnl_log_pf_unbind(struct nl_sock * nlh,uint8_t pf)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 
nfnl_log_build_request(const struct nfnl_log * log,struct nl_msg ** result)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 
nfnl_log_build_create_request(const struct nfnl_log * log,struct nl_msg ** result)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 
nfnl_log_create(struct nl_sock * nlh,const struct nfnl_log * log)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 
nfnl_log_build_change_request(const struct nfnl_log * log,struct nl_msg ** result)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 
nfnl_log_change(struct nl_sock * nlh,const struct nfnl_log * log)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 
nfnl_log_build_delete_request(const struct nfnl_log * log,struct nl_msg ** result)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 
nfnl_log_delete(struct nl_sock * nlh,const struct nfnl_log * log)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 
log_init(void)242 static void __init log_init(void)
243 {
244 	nl_cache_mngt_register(&nfnl_log_ops);
245 }
246 
log_exit(void)247 static void __exit log_exit(void)
248 {
249 	nl_cache_mngt_unregister(&nfnl_log_ops);
250 }
251 
252 /** @} */
253