summaryrefslogtreecommitdiffstats
path: root/extensions/ebt_ulog.c
blob: 673b4b43d1159b342b8d50ea39e514ff87b6bde5 (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
/* ebt_ulog
 *
 * Authors:
 * Bart De Schuymer <bdschuym@pandora.be>
 *
 * November, 2004
 */

#define __need_time_t
#define __need_suseconds_t
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "../include/ebtables_u.h"
#include <sys/time.h>
#include <linux/netfilter_bridge/ebt_ulog.h>

#define CP_NO_LIMIT_S "default_cprange"
#define CP_NO_LIMIT_N 0

#define ULOG_PREFIX     '1'
#define ULOG_NLGROUP    '2'
#define ULOG_CPRANGE    '3'
#define ULOG_QTHRESHOLD '4'
#define ULOG_ULOG       '5'
static struct option opts[] =
{
	{ "ulog-prefix"    , required_argument, 0, ULOG_PREFIX     },
	{ "ulog-nlgroup"   , required_argument, 0, ULOG_NLGROUP    },
	{ "ulog-cprange"   , required_argument, 0, ULOG_CPRANGE    },
	{ "ulog-qthreshold", required_argument, 0, ULOG_QTHRESHOLD },
	{ "ulog"           , no_argument      , 0, ULOG_ULOG       },
	{ 0 }
};

static void print_help()
{
	printf(
"ulog options:\n"
"--ulog                : use the default ulog parameters\n"
"--ulog-prefix prefix  : max %d characters (default is no prefix)\n"
"--ulog-nlgroup group  : 0 < group number < %d (default = %d)\n"
"--ulog-cprange range  : max copy range (default is " CP_NO_LIMIT_S ")\n"
"--ulog-qthreshold     : 0 < queueing threshold < %d (default = %d)\n",
	EBT_ULOG_PREFIX_LEN - 1, EBT_ULOG_MAXNLGROUPS + 1,
	EBT_ULOG_DEFAULT_NLGROUP + 1, EBT_ULOG_MAX_QLEN + 1,
	EBT_ULOG_DEFAULT_QTHRESHOLD);
}

static void init(struct ebt_entry_watcher *watcher)
{
	struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)watcher->data;

	uloginfo->prefix[0] = '\0';
	uloginfo->nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
	uloginfo->cprange = CP_NO_LIMIT_N; /* Use default netlink buffer size */
	uloginfo->qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
}

#define OPT_PREFIX     0x01
#define OPT_NLGROUP    0x02
#define OPT_CPRANGE    0x04
#define OPT_QTHRESHOLD 0x08
#define OPT_ULOG       0x10
static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
   unsigned int *flags, struct ebt_entry_watcher **watcher)
{
	struct ebt_ulog_info *uloginfo;
	unsigned int i;
	char *end;

	uloginfo = (struct ebt_ulog_info *)(*watcher)->data;
	switch (c) {
	case ULOG_PREFIX:
		if (ebt_check_inverse2(optarg))
			goto inverse_invalid;
		ebt_check_option2(flags, OPT_PREFIX);
		if (strlen(optarg) > EBT_ULOG_PREFIX_LEN - 1)
			ebt_print_error("Prefix too long for ulog-prefix");
		strcpy(uloginfo->prefix, optarg);
		break;

	case ULOG_NLGROUP:
		if (ebt_check_inverse2(optarg))
			goto inverse_invalid;
		ebt_check_option2(flags, OPT_NLGROUP);
		i = strtoul(optarg, &end, 10);
		if (*end != '\0')
			ebt_print_error2("Problem with ulog-nlgroup: %s", optarg);
		if (i < 1 || i > EBT_ULOG_MAXNLGROUPS)
			ebt_print_error2("the ulog-nlgroup number must be between 1 and 32");
		uloginfo->nlgroup = i - 1;
		break;

	case ULOG_CPRANGE:
		if (ebt_check_inverse2(optarg))
			goto inverse_invalid;
		ebt_check_option2(flags, OPT_CPRANGE);
		i = strtoul(optarg, &end, 10);
		if (*end != '\0') {
			if (strcasecmp(optarg, CP_NO_LIMIT_S))
				ebt_print_error2("Problem with ulog-cprange: %s", optarg);
			i = CP_NO_LIMIT_N;
		}
		uloginfo->cprange = i;
		break;

	case ULOG_QTHRESHOLD:
		if (ebt_check_inverse2(optarg))
			goto inverse_invalid;
		ebt_check_option2(flags, OPT_QTHRESHOLD);
		i = strtoul(optarg, &end, 10);
		if (*end != '\0')
			ebt_print_error2("Problem with ulog-qthreshold: %s", optarg);
		if (i > EBT_ULOG_MAX_QLEN)
			ebt_print_error2("ulog-qthreshold argument %d exceeds the maximum of %d", i, EBT_ULOG_MAX_QLEN);
		uloginfo->qthreshold = i;
		break;
	case ULOG_ULOG:
		if (ebt_check_inverse(optarg))
			goto inverse_invalid;
		ebt_check_option2(flags, OPT_ULOG);
		break;

	default:
		return 0;
	}
	return 1;

inverse_invalid:
	ebt_print_error("The use of '!' makes no sense for the ulog watcher");
	return 1;
}

static void final_check(const struct ebt_u_entry *entry,
   const struct ebt_entry_watcher *watcher, const char *name,
   unsigned int hookmask, unsigned int time)
{
}

static void print(const struct ebt_u_entry *entry,
   const struct ebt_entry_watcher *watcher)
{
	struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)watcher->data;

	printf("--ulog-prefix \"%s\" --ulog-nlgroup %d --ulog-cprange ",
	       uloginfo->prefix, uloginfo->nlgroup + 1);
	if (uloginfo->cprange == CP_NO_LIMIT_N)
		printf(CP_NO_LIMIT_S);
	else
		printf("%d", uloginfo->cprange);
	printf(" --ulog-qthreshold %d ", uloginfo->qthreshold);
}

static int compare(const struct ebt_entry_watcher *w1,
   const struct ebt_entry_watcher *w2)
{
	struct ebt_ulog_info *uloginfo1 = (struct ebt_ulog_info *)w1->data;
	struct ebt_ulog_info *uloginfo2 = (struct ebt_ulog_info *)w2->data;

	if (uloginfo1->nlgroup != uloginfo2->nlgroup ||
	    uloginfo1->cprange != uloginfo2->cprange ||
	    uloginfo1->qthreshold != uloginfo2->qthreshold ||
	    strcmp(uloginfo1->prefix, uloginfo2->prefix))
		return 0;
	return 1;
}

static struct ebt_u_watcher ulog_watcher =
{
	.name		= EBT_ULOG_WATCHER,
	.size		= sizeof(struct ebt_ulog_info),
	.help		= print_help,
	.init		= init,
	.parse		= parse,
	.final_check	= final_check,
	.print		= print,
	.compare	= compare,
	.extra_ops	= opts,
};

void _init(void)
{
	ebt_register_watcher(&ulog_watcher);
}