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