summaryrefslogtreecommitdiff
path: root/lib/netfilter/queue_obj.c
blob: 1ea461d840feccc63848ee58164b94cb13903486 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* SPDX-License-Identifier: LGPL-2.1-only */
/*
 * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
 */

/**
 * @ingroup nfnl
 * @defgroup queue Queue
 * @brief
 * @{
 */

#include <netlink-private/netlink.h>
#include <netlink/netfilter/nfnl.h>
#include <netlink/netfilter/queue.h>

/** @cond SKIP */
#define QUEUE_ATTR_GROUP		(1UL << 0)
#define QUEUE_ATTR_MAXLEN		(1UL << 1)
#define QUEUE_ATTR_COPY_MODE		(1UL << 2)
#define QUEUE_ATTR_COPY_RANGE		(1UL << 3)
/** @endcond */


static void nfnl_queue_dump(struct nl_object *a, struct nl_dump_params *p)
{
	struct nfnl_queue *queue = (struct nfnl_queue *) a;
	char buf[64];

	nl_new_line(p);

	if (queue->ce_mask & QUEUE_ATTR_GROUP)
		nl_dump(p, "group=%u ", queue->queue_group);

	if (queue->ce_mask & QUEUE_ATTR_MAXLEN)
		nl_dump(p, "maxlen=%u ", queue->queue_maxlen);

	if (queue->ce_mask & QUEUE_ATTR_COPY_MODE)
		nl_dump(p, "copy_mode=%s ",
			nfnl_queue_copy_mode2str(queue->queue_copy_mode,
						 buf, sizeof(buf)));

	if (queue->ce_mask & QUEUE_ATTR_COPY_RANGE)
		nl_dump(p, "copy_range=%u ", queue->queue_copy_range);

	nl_dump(p, "\n");
}

static const struct trans_tbl copy_modes[] = {
	__ADD(NFNL_QUEUE_COPY_NONE,	none),
	__ADD(NFNL_QUEUE_COPY_META,	meta),
	__ADD(NFNL_QUEUE_COPY_PACKET,	packet),
};

char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf,
			       size_t len)
{
	return __type2str(copy_mode, buf, len, copy_modes,
			   ARRAY_SIZE(copy_modes));
}

int nfnl_queue_str2copy_mode(const char *name)
{
	return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes));
}

/**
 * @name Allocation/Freeing
 * @{
 */

struct nfnl_queue *nfnl_queue_alloc(void)
{
	return (struct nfnl_queue *) nl_object_alloc(&queue_obj_ops);
}

void nfnl_queue_get(struct nfnl_queue *queue)
{
	nl_object_get((struct nl_object *) queue);
}

void nfnl_queue_put(struct nfnl_queue *queue)
{
	nl_object_put((struct nl_object *) queue);
}

/** @} */

/**
 * @name Attributes
 * @{
 */

void nfnl_queue_set_group(struct nfnl_queue *queue, uint16_t group)
{
	queue->queue_group = group;
	queue->ce_mask |= QUEUE_ATTR_GROUP;
}

int nfnl_queue_test_group(const struct nfnl_queue *queue)
{
	return !!(queue->ce_mask & QUEUE_ATTR_GROUP);
}

uint16_t nfnl_queue_get_group(const struct nfnl_queue *queue)
{
	return queue->queue_group;
}

void nfnl_queue_set_maxlen(struct nfnl_queue *queue, uint32_t maxlen)
{
	queue->queue_maxlen = maxlen;
	queue->ce_mask |= QUEUE_ATTR_MAXLEN;
}

int nfnl_queue_test_maxlen(const struct nfnl_queue *queue)
{
	return !!(queue->ce_mask & QUEUE_ATTR_MAXLEN);
}

uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *queue)
{
	return queue->queue_maxlen;
}

void nfnl_queue_set_copy_mode(struct nfnl_queue *queue, enum nfnl_queue_copy_mode mode)
{
	queue->queue_copy_mode = mode;
	queue->ce_mask |= QUEUE_ATTR_COPY_MODE;
}

int nfnl_queue_test_copy_mode(const struct nfnl_queue *queue)
{
	return !!(queue->ce_mask & QUEUE_ATTR_COPY_MODE);
}

enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *queue)
{
	return queue->queue_copy_mode;
}

void nfnl_queue_set_copy_range(struct nfnl_queue *queue, uint32_t copy_range)
{
	queue->queue_copy_range = copy_range;
	queue->ce_mask |= QUEUE_ATTR_COPY_RANGE;
}

int nfnl_queue_test_copy_range(const struct nfnl_queue *queue)
{
	return !!(queue->ce_mask & QUEUE_ATTR_COPY_RANGE);
}

uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue)
{
	return queue->queue_copy_range;
}

static uint64_t nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
				   uint64_t attrs, int flags)
{
	struct nfnl_queue *a = (struct nfnl_queue *) _a;
	struct nfnl_queue *b = (struct nfnl_queue *) _b;
	uint64_t diff = 0;

#define NFNL_QUEUE_DIFF(ATTR, EXPR) \
	ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \
	NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD)

	diff |= NFNL_QUEUE_DIFF_VAL(GROUP,	queue_group);
	diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN,	queue_maxlen);
	diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE,	queue_copy_mode);
	diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE,	queue_copy_range);

#undef NFNL_QUEUE_DIFF
#undef NFNL_QUEUE_DIFF_VAL

	return diff;
}

static const struct trans_tbl nfnl_queue_attrs[] = {
	__ADD(QUEUE_ATTR_GROUP,		group),
	__ADD(QUEUE_ATTR_MAXLEN,	maxlen),
	__ADD(QUEUE_ATTR_COPY_MODE,	copy_mode),
	__ADD(QUEUE_ATTR_COPY_RANGE,	copy_range),
};

static char *nfnl_queue_attrs2str(int attrs, char *buf, size_t len)
{
	return __flags2str(attrs, buf, len, nfnl_queue_attrs,
			   ARRAY_SIZE(nfnl_queue_attrs));
}

/** @} */

struct nl_object_ops queue_obj_ops = {
	.oo_name		= "netfilter/queue",
	.oo_size		= sizeof(struct nfnl_queue),
	.oo_dump = {
	    [NL_DUMP_LINE]	= nfnl_queue_dump,
	    [NL_DUMP_DETAILS]	= nfnl_queue_dump,
	    [NL_DUMP_STATS]	= nfnl_queue_dump,
	},
	.oo_compare		= nfnl_queue_compare,
	.oo_attrs2str		= nfnl_queue_attrs2str,
	.oo_id_attrs		= QUEUE_ATTR_GROUP,
};

/** @} */