libipt_ULOG.c revision bf97128c7262f17a02fec41cdae75b472ba77f88
1/* Shared library add-on to iptables to add ULOG support.
2 *
3 * (C) 2000 by Harald Welte <laforge@gnumonks.org>
4 *
5 * multipart netlink support based on ideas by Sebastian Zander
6 * 						<zander@fokus.gmd.de>
7 *
8 * This software is released under the terms of GNU GPL
9 *
10 * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
11 */
12#include <stdio.h>
13#include <netdb.h>
14#include <string.h>
15#include <stdlib.h>
16#include <syslog.h>
17#include <getopt.h>
18#include <xtables.h>
19/* For 64bit kernel / 32bit userspace */
20#include <linux/netfilter_ipv4/ipt_ULOG.h>
21
22
23static void print_groups(unsigned int gmask)
24{
25	int b;
26	unsigned int test;
27
28	for (b = 31; b >= 0; b--) {
29		test = (1 << b);
30		if (gmask & test)
31			printf("%d ", b + 1);
32	}
33}
34
35static void ULOG_help(void)
36{
37	printf("ULOG target options:\n"
38	       " --ulog-nlgroup nlgroup		NETLINK group used for logging\n"
39	       " --ulog-cprange size		Bytes of each packet to be passed\n"
40	       " --ulog-qthreshold		Threshold of in-kernel queue\n"
41	       " --ulog-prefix prefix		Prefix log messages with this prefix.\n");
42}
43
44static const struct option ULOG_opts[] = {
45	{"ulog-nlgroup", 1, NULL, '!'},
46	{"ulog-prefix", 1, NULL, '#'},
47	{"ulog-cprange", 1, NULL, 'A'},
48	{"ulog-qthreshold", 1, NULL, 'B'},
49	{ .name = NULL }
50};
51
52static void ULOG_init(struct xt_entry_target *t)
53{
54	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
55
56	loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
57	loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD;
58
59}
60
61#define IPT_LOG_OPT_NLGROUP 0x01
62#define IPT_LOG_OPT_PREFIX 0x02
63#define IPT_LOG_OPT_CPRANGE 0x04
64#define IPT_LOG_OPT_QTHRESHOLD 0x08
65
66static int ULOG_parse(int c, char **argv, int invert, unsigned int *flags,
67                      const void *entry, struct xt_entry_target **target)
68{
69	struct ipt_ulog_info *loginfo =
70	    (struct ipt_ulog_info *) (*target)->data;
71	int group_d;
72
73	switch (c) {
74	case '!':
75		if (*flags & IPT_LOG_OPT_NLGROUP)
76			xtables_error(PARAMETER_PROBLEM,
77				   "Can't specify --ulog-nlgroup twice");
78
79		if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
80			xtables_error(PARAMETER_PROBLEM,
81				   "Unexpected `!' after --ulog-nlgroup");
82		group_d = atoi(optarg);
83		if (group_d > 32 || group_d < 1)
84			xtables_error(PARAMETER_PROBLEM,
85				   "--ulog-nlgroup has to be between 1 and 32");
86
87		loginfo->nl_group = (1 << (group_d - 1));
88
89		*flags |= IPT_LOG_OPT_NLGROUP;
90		break;
91
92	case '#':
93		if (*flags & IPT_LOG_OPT_PREFIX)
94			xtables_error(PARAMETER_PROBLEM,
95				   "Can't specify --ulog-prefix twice");
96
97		if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
98			xtables_error(PARAMETER_PROBLEM,
99				   "Unexpected `!' after --ulog-prefix");
100
101		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
102			xtables_error(PARAMETER_PROBLEM,
103				   "Maximum prefix length %u for --ulog-prefix",
104				   (unsigned int)sizeof(loginfo->prefix) - 1);
105
106		if (strlen(optarg) == 0)
107			xtables_error(PARAMETER_PROBLEM,
108				   "No prefix specified for --ulog-prefix");
109
110		if (strlen(optarg) != strlen(strtok(optarg, "\n")))
111			xtables_error(PARAMETER_PROBLEM,
112				   "Newlines not allowed in --ulog-prefix");
113
114		strcpy(loginfo->prefix, optarg);
115		*flags |= IPT_LOG_OPT_PREFIX;
116		break;
117	case 'A':
118		if (*flags & IPT_LOG_OPT_CPRANGE)
119			xtables_error(PARAMETER_PROBLEM,
120				   "Can't specify --ulog-cprange twice");
121		if (atoi(optarg) < 0)
122			xtables_error(PARAMETER_PROBLEM,
123				   "Negative copy range?");
124		loginfo->copy_range = atoi(optarg);
125		*flags |= IPT_LOG_OPT_CPRANGE;
126		break;
127	case 'B':
128		if (*flags & IPT_LOG_OPT_QTHRESHOLD)
129			xtables_error(PARAMETER_PROBLEM,
130				   "Can't specify --ulog-qthreshold twice");
131		if (atoi(optarg) < 1)
132			xtables_error(PARAMETER_PROBLEM,
133				   "Negative or zero queue threshold ?");
134		if (atoi(optarg) > ULOG_MAX_QLEN)
135			xtables_error(PARAMETER_PROBLEM,
136				   "Maximum queue length exceeded");
137		loginfo->qthreshold = atoi(optarg);
138		*flags |= IPT_LOG_OPT_QTHRESHOLD;
139		break;
140	default:
141		return 0;
142	}
143	return 1;
144}
145
146static void ULOG_save(const void *ip, const struct xt_entry_target *target)
147{
148	const struct ipt_ulog_info *loginfo
149	    = (const struct ipt_ulog_info *) target->data;
150
151	if (strcmp(loginfo->prefix, "") != 0) {
152		fputs("--ulog-prefix ", stdout);
153		xtables_save_string(loginfo->prefix);
154	}
155
156	if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
157		printf("--ulog-nlgroup ");
158		print_groups(loginfo->nl_group);
159	}
160	if (loginfo->copy_range)
161		printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
162
163	if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
164		printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
165}
166
167static void ULOG_print(const void *ip, const struct xt_entry_target *target,
168                       int numeric)
169{
170	const struct ipt_ulog_info *loginfo
171	    = (const struct ipt_ulog_info *) target->data;
172
173	printf("ULOG ");
174	printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
175	print_groups(loginfo->nl_group);
176	if (strcmp(loginfo->prefix, "") != 0)
177		printf("prefix `%s' ", loginfo->prefix);
178	printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
179}
180
181static struct xtables_target ulog_tg_reg = {
182	.name		= "ULOG",
183	.version	= XTABLES_VERSION,
184	.family		= NFPROTO_IPV4,
185	.size		= XT_ALIGN(sizeof(struct ipt_ulog_info)),
186	.userspacesize	= XT_ALIGN(sizeof(struct ipt_ulog_info)),
187	.help		= ULOG_help,
188	.init		= ULOG_init,
189	.parse		= ULOG_parse,
190	.print		= ULOG_print,
191	.save		= ULOG_save,
192	.extra_opts	= ULOG_opts,
193};
194
195void _init(void)
196{
197	xtables_register_target(&ulog_tg_reg);
198}
199