1/*
2 * lib/netfilter/queue_obj.c	Netfilter Queue
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) 2007, 2008 Patrick McHardy <kaber@trash.net>
10 */
11
12/**
13 * @ingroup nfnl
14 * @defgroup queue Queue
15 * @brief
16 * @{
17 */
18
19#include <netlink-local.h>
20#include <netlink/netfilter/nfnl.h>
21#include <netlink/netfilter/queue.h>
22
23/** @cond SKIP */
24#define QUEUE_ATTR_GROUP		(1UL << 0)
25#define QUEUE_ATTR_MAXLEN		(1UL << 1)
26#define QUEUE_ATTR_COPY_MODE		(1UL << 2)
27#define QUEUE_ATTR_COPY_RANGE		(1UL << 3)
28/** @endcond */
29
30
31static void nfnl_queue_dump(struct nl_object *a, struct nl_dump_params *p)
32{
33	struct nfnl_queue *queue = (struct nfnl_queue *) a;
34	char buf[64];
35
36	nl_new_line(p);
37
38	if (queue->ce_mask & QUEUE_ATTR_GROUP)
39		nl_dump(p, "group=%u ", queue->queue_group);
40
41	if (queue->ce_mask & QUEUE_ATTR_MAXLEN)
42		nl_dump(p, "maxlen=%u ", queue->queue_maxlen);
43
44	if (queue->ce_mask & QUEUE_ATTR_COPY_MODE)
45		nl_dump(p, "copy_mode=%s ",
46			nfnl_queue_copy_mode2str(queue->queue_copy_mode,
47						 buf, sizeof(buf)));
48
49	if (queue->ce_mask & QUEUE_ATTR_COPY_RANGE)
50		nl_dump(p, "copy_range=%u ", queue->queue_copy_range);
51
52	nl_dump(p, "\n");
53}
54
55static struct trans_tbl copy_modes[] = {
56	__ADD(NFNL_QUEUE_COPY_NONE,	none)
57	__ADD(NFNL_QUEUE_COPY_META,	meta)
58	__ADD(NFNL_QUEUE_COPY_PACKET,	packet)
59};
60
61char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf,
62			       size_t len)
63{
64	return __type2str(copy_mode, buf, len, copy_modes,
65			   ARRAY_SIZE(copy_modes));
66}
67
68enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *name)
69{
70	return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes));
71}
72
73/**
74 * @name Allocation/Freeing
75 * @{
76 */
77
78struct nfnl_queue *nfnl_queue_alloc(void)
79{
80	return (struct nfnl_queue *) nl_object_alloc(&queue_obj_ops);
81}
82
83void nfnl_queue_get(struct nfnl_queue *queue)
84{
85	nl_object_get((struct nl_object *) queue);
86}
87
88void nfnl_queue_put(struct nfnl_queue *queue)
89{
90	nl_object_put((struct nl_object *) queue);
91}
92
93/** @} */
94
95/**
96 * @name Attributes
97 * @{
98 */
99
100void nfnl_queue_set_group(struct nfnl_queue *queue, uint16_t group)
101{
102	queue->queue_group = group;
103	queue->ce_mask |= QUEUE_ATTR_GROUP;
104}
105
106int nfnl_queue_test_group(const struct nfnl_queue *queue)
107{
108	return !!(queue->ce_mask & QUEUE_ATTR_GROUP);
109}
110
111uint16_t nfnl_queue_get_group(const struct nfnl_queue *queue)
112{
113	return queue->queue_group;
114}
115
116void nfnl_queue_set_maxlen(struct nfnl_queue *queue, uint32_t maxlen)
117{
118	queue->queue_maxlen = maxlen;
119	queue->ce_mask |= QUEUE_ATTR_MAXLEN;
120}
121
122int nfnl_queue_test_maxlen(const struct nfnl_queue *queue)
123{
124	return !!(queue->ce_mask & QUEUE_ATTR_MAXLEN);
125}
126
127uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *queue)
128{
129	return queue->queue_maxlen;
130}
131
132void nfnl_queue_set_copy_mode(struct nfnl_queue *queue, enum nfnl_queue_copy_mode mode)
133{
134	queue->queue_copy_mode = mode;
135	queue->ce_mask |= QUEUE_ATTR_COPY_MODE;
136}
137
138int nfnl_queue_test_copy_mode(const struct nfnl_queue *queue)
139{
140	return !!(queue->ce_mask & QUEUE_ATTR_COPY_MODE);
141}
142
143enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *queue)
144{
145	return queue->queue_copy_mode;
146}
147
148void nfnl_queue_set_copy_range(struct nfnl_queue *queue, uint32_t copy_range)
149{
150	queue->queue_copy_range = copy_range;
151	queue->ce_mask |= QUEUE_ATTR_COPY_RANGE;
152}
153
154int nfnl_queue_test_copy_range(const struct nfnl_queue *queue)
155{
156	return !!(queue->ce_mask & QUEUE_ATTR_COPY_RANGE);
157}
158
159uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue)
160{
161	return queue->queue_copy_range;
162}
163
164static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
165			      uint32_t attrs, int flags)
166{
167	struct nfnl_queue *a = (struct nfnl_queue *) _a;
168	struct nfnl_queue *b = (struct nfnl_queue *) _b;
169	int diff = 0;
170
171#define NFNL_QUEUE_DIFF(ATTR, EXPR) \
172	ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
173#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \
174	NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD)
175
176	diff |= NFNL_QUEUE_DIFF_VAL(GROUP,	queue_group);
177	diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN,	queue_maxlen);
178	diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE,	queue_copy_mode);
179	diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE,	queue_copy_range);
180
181#undef NFNL_QUEUE_DIFF
182#undef NFNL_QUEUE_DIFF_VAL
183
184	return diff;
185}
186
187static struct trans_tbl nfnl_queue_attrs[] = {
188	__ADD(QUEUE_ATTR_GROUP,		group)
189	__ADD(QUEUE_ATTR_MAXLEN,	maxlen)
190	__ADD(QUEUE_ATTR_COPY_MODE,	copy_mode)
191	__ADD(QUEUE_ATTR_COPY_RANGE,	copy_range)
192};
193
194static char *nfnl_queue_attrs2str(int attrs, char *buf, size_t len)
195{
196	return __flags2str(attrs, buf, len, nfnl_queue_attrs,
197			   ARRAY_SIZE(nfnl_queue_attrs));
198}
199
200/** @} */
201
202struct nl_object_ops queue_obj_ops = {
203	.oo_name		= "netfilter/queue",
204	.oo_size		= sizeof(struct nfnl_queue),
205	.oo_dump = {
206	    [NL_DUMP_LINE]	= nfnl_queue_dump,
207	    [NL_DUMP_DETAILS]	= nfnl_queue_dump,
208	    [NL_DUMP_STATS]	= nfnl_queue_dump,
209	},
210	.oo_compare		= nfnl_queue_compare,
211	.oo_attrs2str		= nfnl_queue_attrs2str,
212	.oo_id_attrs		= QUEUE_ATTR_GROUP,
213};
214
215/** @} */
216