1/*
2 * lib/netfilter/log_obj.c	Netfilter Log Object
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 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
13 */
14
15#include <netlink-local.h>
16#include <netlink/netfilter/nfnl.h>
17#include <netlink/netfilter/log.h>
18
19/** @cond SKIP */
20#define LOG_ATTR_GROUP			(1UL << 0)
21#define LOG_ATTR_COPY_MODE		(1UL << 1)
22#define LOG_ATTR_COPY_RANGE		(1UL << 3)
23#define LOG_ATTR_FLUSH_TIMEOUT		(1UL << 4)
24#define LOG_ATTR_ALLOC_SIZE		(1UL << 5)
25#define LOG_ATTR_QUEUE_THRESHOLD	(1UL << 6)
26
27/** @endcond */
28
29static void nfnl_log_dump(struct nl_object *a, struct nl_dump_params *p)
30{
31	struct nfnl_log *log = (struct nfnl_log *) a;
32	char buf[64];
33
34	nl_new_line(p);
35
36	if (log->ce_mask & LOG_ATTR_GROUP)
37		nl_dump(p, "group=%u ", log->log_group);
38
39	if (log->ce_mask & LOG_ATTR_COPY_MODE)
40		nl_dump(p, "copy_mode=%s ",
41			nfnl_log_copy_mode2str(log->log_copy_mode,
42					       buf, sizeof(buf)));
43
44	if (log->ce_mask & LOG_ATTR_COPY_RANGE)
45		nl_dump(p, "copy_range=%u ", log->log_copy_range);
46
47	if (log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT)
48		nl_dump(p, "flush_timeout=%u ", log->log_flush_timeout);
49
50	if (log->ce_mask & LOG_ATTR_ALLOC_SIZE)
51		nl_dump(p, "alloc_size=%u ", log->log_alloc_size);
52
53	if (log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD)
54		nl_dump(p, "queue_threshold=%u ", log->log_queue_threshold);
55
56	nl_dump(p, "\n");
57}
58
59static struct trans_tbl copy_modes[] = {
60	__ADD(NFNL_LOG_COPY_NONE,	none)
61	__ADD(NFNL_LOG_COPY_META,	meta)
62	__ADD(NFNL_LOG_COPY_PACKET,	packet)
63};
64
65char *nfnl_log_copy_mode2str(enum nfnl_log_copy_mode copy_mode, char *buf,
66			     size_t len)
67{
68	return __type2str(copy_mode, buf, len, copy_modes,
69			  ARRAY_SIZE(copy_modes));
70}
71
72enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *name)
73{
74	return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes));
75}
76
77/**
78 * @name Allocation/Freeing
79 * @{
80 */
81
82struct nfnl_log *nfnl_log_alloc(void)
83{
84	return (struct nfnl_log *) nl_object_alloc(&log_obj_ops);
85}
86
87void nfnl_log_get(struct nfnl_log *log)
88{
89	nl_object_get((struct nl_object *) log);
90}
91
92void nfnl_log_put(struct nfnl_log *log)
93{
94	nl_object_put((struct nl_object *) log);
95}
96
97/** @} */
98
99/**
100 * @name Attributes
101 * @{
102 */
103
104void nfnl_log_set_group(struct nfnl_log *log, uint16_t group)
105{
106	log->log_group = group;
107	log->ce_mask |= LOG_ATTR_GROUP;
108}
109
110int nfnl_log_test_group(const struct nfnl_log *log)
111{
112	return !!(log->ce_mask & LOG_ATTR_GROUP);
113}
114
115uint16_t nfnl_log_get_group(const struct nfnl_log *log)
116{
117	return log->log_group;
118}
119
120void nfnl_log_set_copy_mode(struct nfnl_log *log, enum nfnl_log_copy_mode mode)
121{
122	log->log_copy_mode = mode;
123	log->ce_mask |= LOG_ATTR_COPY_MODE;
124}
125
126int nfnl_log_test_copy_mode(const struct nfnl_log *log)
127{
128	return !!(log->ce_mask & LOG_ATTR_COPY_MODE);
129}
130
131enum nfnl_log_copy_mode nfnl_log_get_copy_mode(const struct nfnl_log *log)
132{
133	return log->log_copy_mode;
134}
135
136void nfnl_log_set_copy_range(struct nfnl_log *log, uint32_t copy_range)
137{
138	log->log_copy_range = copy_range;
139	log->ce_mask |= LOG_ATTR_COPY_RANGE;
140}
141
142int nfnl_log_test_copy_range(const struct nfnl_log *log)
143{
144	return !!(log->ce_mask & LOG_ATTR_COPY_RANGE);
145}
146
147uint32_t nfnl_log_get_copy_range(const struct nfnl_log *log)
148{
149	return log->log_copy_range;
150}
151
152void nfnl_log_set_flush_timeout(struct nfnl_log *log, uint32_t timeout)
153{
154	log->log_flush_timeout = timeout;
155	log->ce_mask |= LOG_ATTR_FLUSH_TIMEOUT;
156}
157
158int nfnl_log_test_flush_timeout(const struct nfnl_log *log)
159{
160	return !!(log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT);
161}
162
163uint32_t nfnl_log_get_flush_timeout(const struct nfnl_log *log)
164{
165	return log->log_flush_timeout;
166}
167
168void nfnl_log_set_alloc_size(struct nfnl_log *log, uint32_t alloc_size)
169{
170	log->log_alloc_size = alloc_size;
171	log->ce_mask |= LOG_ATTR_ALLOC_SIZE;
172}
173
174int nfnl_log_test_alloc_size(const struct nfnl_log *log)
175{
176	return !!(log->ce_mask & LOG_ATTR_ALLOC_SIZE);
177}
178
179uint32_t nfnl_log_get_alloc_size(const struct nfnl_log *log)
180{
181	return log->log_alloc_size;
182}
183
184void nfnl_log_set_queue_threshold(struct nfnl_log *log, uint32_t threshold)
185{
186	log->log_queue_threshold = threshold;
187	log->ce_mask |= LOG_ATTR_QUEUE_THRESHOLD;
188}
189
190int nfnl_log_test_queue_threshold(const struct nfnl_log *log)
191{
192	return !!(log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD);
193}
194
195uint32_t nfnl_log_get_queue_threshold(const struct nfnl_log *log)
196{
197	return log->log_queue_threshold;
198}
199
200/* We don't actually use the flags for anything yet since the
201 * nfnetlog_log interface truly sucks - it only contains the
202 * flag value, but not mask, so we would have to make assumptions
203 * about the supported flags.
204 */
205void nfnl_log_set_flags(struct nfnl_log *log, unsigned int flags)
206{
207	log->log_flags |= flags;
208	log->log_flag_mask |= flags;
209}
210
211void nfnl_log_unset_flags(struct nfnl_log *log, unsigned int flags)
212{
213	log->log_flags &= ~flags;
214	log->log_flag_mask |= flags;
215}
216
217static struct trans_tbl log_flags[] = {
218	__ADD(NFNL_LOG_FLAG_SEQ,	seq)
219	__ADD(NFNL_LOG_FLAG_SEQ_GLOBAL,	seq_global)
220};
221
222char *nfnl_log_flags2str(unsigned int flags, char *buf, size_t len)
223{
224	return __flags2str(flags, buf, len, log_flags, ARRAY_SIZE(log_flags));
225}
226
227unsigned int nfnl_log_str2flags(const char *name)
228{
229	return __str2flags(name, log_flags, ARRAY_SIZE(log_flags));
230}
231
232static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
233			    uint32_t attrs, int flags)
234{
235	struct nfnl_log *a = (struct nfnl_log *) _a;
236	struct nfnl_log *b = (struct nfnl_log *) _b;
237	int diff = 0;
238
239#define NFNL_LOG_DIFF(ATTR, EXPR) \
240	ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR)
241#define NFNL_LOG_DIFF_VAL(ATTR, FIELD) \
242	NFNL_LOG_DIFF(ATTR, a->FIELD != b->FIELD)
243
244	diff |= NFNL_LOG_DIFF_VAL(GROUP,		log_group);
245	diff |= NFNL_LOG_DIFF_VAL(COPY_MODE,		log_copy_mode);
246	diff |= NFNL_LOG_DIFF_VAL(COPY_RANGE,		log_copy_range);
247	diff |= NFNL_LOG_DIFF_VAL(FLUSH_TIMEOUT,	log_flush_timeout);
248	diff |= NFNL_LOG_DIFF_VAL(ALLOC_SIZE,		log_alloc_size);
249	diff |= NFNL_LOG_DIFF_VAL(QUEUE_THRESHOLD,	log_queue_threshold);
250
251#undef NFNL_LOG_DIFF
252#undef NFNL_LOG_DIFF_VAL
253
254	return diff;
255}
256
257static struct trans_tbl nfnl_log_attrs[] = {
258	__ADD(LOG_ATTR_GROUP,		group)
259	__ADD(LOG_ATTR_COPY_MODE,	copy_mode)
260	__ADD(LOG_ATTR_COPY_RANGE,	copy_range)
261	__ADD(LOG_ATTR_FLUSH_TIMEOUT,	flush_timeout)
262	__ADD(LOG_ATTR_ALLOC_SIZE,	alloc_size)
263	__ADD(LOG_ATTR_QUEUE_THRESHOLD, queue_threshold)
264};
265
266static char *nfnl_log_attrs2str(int attrs, char *buf, size_t len)
267{
268	return __flags2str(attrs, buf, len, nfnl_log_attrs,
269			   ARRAY_SIZE(nfnl_log_attrs));
270}
271
272/** @} */
273
274struct nl_object_ops log_obj_ops = {
275	.oo_name		= "netfilter/log",
276	.oo_size		= sizeof(struct nfnl_log),
277	.oo_dump = {
278	    [NL_DUMP_LINE]	= nfnl_log_dump,
279	    [NL_DUMP_DETAILS]	= nfnl_log_dump,
280	    [NL_DUMP_STATS]	= nfnl_log_dump,
281	},
282	.oo_compare		= nfnl_log_compare,
283	.oo_attrs2str		= nfnl_log_attrs2str,
284	.oo_id_attrs		= LOG_ATTR_GROUP,
285};
286
287/** @} */
288