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