libipt_ULOG.c revision 03d99486d8283552705b58dc55b6085dffc38792
1015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte/* Shared library add-on to iptables to add ULOG support.
2015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte *
3d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * (C) 2000 by Harald Welte <laforge@gnumonks.org>
4d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte *
5d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * multipart netlink support based on ideas by Sebastian Zander
6d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * 						<zander@fokus.gmd.de>
7015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte *
8015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte * This software is released under the terms of GNU GPL
9015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte *
10d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
11015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte */
12c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdio.h>
13c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <netdb.h>
14c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <string.h>
15c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdlib.h>
16c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <syslog.h>
17c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <getopt.h>
18c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <iptables.h>
19c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <linux/netfilter_ipv4/ip_tables.h>
201eb0081027ee567e822b24377ea614e66c408ff2Martin Josefsson/* For 64bit kernel / 32bit userspace */
21a2a7f2b531cc582ab6cc3c2b73715ed1d58b9eabJan Engelhardt#include <linux/netfilter_ipv4/ipt_ULOG.h>
22c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
23c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
2433690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardtstatic void print_groups(unsigned int gmask)
25c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
26c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	int b;
27c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	unsigned int test;
28c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
29015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	for (b = 31; b >= 0; b--) {
30c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		test = (1 << b);
31c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (gmask & test)
32c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			printf("%d ", b + 1);
33c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
34c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
35c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
361d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_help(void)
37c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
388b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	printf("ULOG target options:\n"
3944540942fbd1f2a0f0dcd7247275a702bcf45a02Marc Boucher	       " --ulog-nlgroup nlgroup		NETLINK group used for logging\n"
40015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	       " --ulog-cprange size		Bytes of each packet to be passed\n"
41d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte	       " --ulog-qthreshold		Threshold of in-kernel queue\n"
428b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	       " --ulog-prefix prefix		Prefix log messages with this prefix.\n");
43c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
44c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
451d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic const struct option ULOG_opts[] = {
46500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{"ulog-nlgroup", 1, NULL, '!'},
47500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{"ulog-prefix", 1, NULL, '#'},
48500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{"ulog-cprange", 1, NULL, 'A'},
49500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{"ulog-qthreshold", 1, NULL, 'B'},
509ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann	{ .name = NULL }
51c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte};
52c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
531d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_init(struct xt_entry_target *t)
54c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
55015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
56c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
57c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
58d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte	loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD;
59c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
60c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
61c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
62c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_NLGROUP 0x01
63c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_PREFIX 0x02
64015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte#define IPT_LOG_OPT_CPRANGE 0x04
65d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte#define IPT_LOG_OPT_QTHRESHOLD 0x08
66c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
671d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic int ULOG_parse(int c, char **argv, int invert, unsigned int *flags,
681d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt                      const void *entry, struct xt_entry_target **target)
69c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
70015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	struct ipt_ulog_info *loginfo =
71015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	    (struct ipt_ulog_info *) (*target)->data;
72c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	int group_d;
73c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
74c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	switch (c) {
75c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	case '!':
76c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (*flags & IPT_LOG_OPT_NLGROUP)
77c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
78c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Can't specify --ulog-nlgroup twice");
79c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
80b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte		if (check_inverse(optarg, &invert, NULL, 0))
81c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
82c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Unexpected `!' after --ulog-nlgroup");
83c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		group_d = atoi(optarg);
84c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (group_d > 32 || group_d < 1)
85c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
86015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte				   "--ulog-nlgroup has to be between 1 and 32");
87c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
88015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		loginfo->nl_group = (1 << (group_d - 1));
89c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
90c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		*flags |= IPT_LOG_OPT_NLGROUP;
91c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		break;
92c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
93c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	case '#':
94c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (*flags & IPT_LOG_OPT_PREFIX)
95c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
96c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Can't specify --ulog-prefix twice");
97c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
98b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte		if (check_inverse(optarg, &invert, NULL, 0))
99c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
100c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Unexpected `!' after --ulog-prefix");
101c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
102c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
103c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
104c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Maximum prefix length %u for --ulog-prefix",
105a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson				   (unsigned int)sizeof(loginfo->prefix) - 1);
106c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
107ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger		if (strlen(optarg) == 0)
108ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger			exit_error(PARAMETER_PROBLEM,
109ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger				   "No prefix specified for --ulog-prefix");
110ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger
111ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger		if (strlen(optarg) != strlen(strtok(optarg, "\n")))
112ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger			exit_error(PARAMETER_PROBLEM,
113ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger				   "Newlines not allowed in --ulog-prefix");
114ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger
115c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		strcpy(loginfo->prefix, optarg);
116c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		*flags |= IPT_LOG_OPT_PREFIX;
117c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		break;
118015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	case 'A':
119015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		if (*flags & IPT_LOG_OPT_CPRANGE)
120015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte			exit_error(PARAMETER_PROBLEM,
121015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte				   "Can't specify --ulog-cprange twice");
122015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		if (atoi(optarg) < 0)
123015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte			exit_error(PARAMETER_PROBLEM,
124015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte				   "Negative copy range?");
125015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		loginfo->copy_range = atoi(optarg);
126015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		*flags |= IPT_LOG_OPT_CPRANGE;
127015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		break;
128d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte	case 'B':
129d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		if (*flags & IPT_LOG_OPT_QTHRESHOLD)
130d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte			exit_error(PARAMETER_PROBLEM,
131d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte				   "Can't specify --ulog-qthreshold twice");
132d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		if (atoi(optarg) < 1)
133d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte			exit_error(PARAMETER_PROBLEM,
134d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte				   "Negative or zero queue threshold ?");
135d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		if (atoi(optarg) > ULOG_MAX_QLEN)
136d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte			exit_error(PARAMETER_PROBLEM,
137d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte				   "Maximum queue length exceeded");
138d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		loginfo->qthreshold = atoi(optarg);
139d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		*flags |= IPT_LOG_OPT_QTHRESHOLD;
140d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte		break;
141e556800cf137e49a47cf1ac889c613f5d33cfe3bPatrick McHardy	default:
142e556800cf137e49a47cf1ac889c613f5d33cfe3bPatrick McHardy		return 0;
143c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
144c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	return 1;
145c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
146c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
1471d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_save(const void *ip, const struct xt_entry_target *target)
148c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
149015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	const struct ipt_ulog_info *loginfo
150015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	    = (const struct ipt_ulog_info *) target->data;
151c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
152a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (strcmp(loginfo->prefix, "") != 0) {
153a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs("--ulog-prefix ", stdout);
154a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		save_string(loginfo->prefix);
155a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
156c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
157015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
158015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte		printf("--ulog-nlgroup ");
159c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		print_groups(loginfo->nl_group);
160c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
161015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	if (loginfo->copy_range)
162a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson		printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
163d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte
164d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte	if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
165a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson		printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
166c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
167c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
1681d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_print(const void *ip, const struct xt_entry_target *target,
1691d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt                       int numeric)
170c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
171c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	const struct ipt_ulog_info *loginfo
172015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte	    = (const struct ipt_ulog_info *) target->data;
173c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
174c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	printf("ULOG ");
175a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson	printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
176c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	print_groups(loginfo->nl_group);
177c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	if (strcmp(loginfo->prefix, "") != 0)
178c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		printf("prefix `%s' ", loginfo->prefix);
179a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson	printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
180c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
181c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
1828b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_target ulog_tg_reg = {
1838caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira	.name		= "ULOG",
1848b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version	= XTABLES_VERSION,
18503d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt	.family		= NFPROTO_IPV4,
1868b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.size		= XT_ALIGN(sizeof(struct ipt_ulog_info)),
1878b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.userspacesize	= XT_ALIGN(sizeof(struct ipt_ulog_info)),
1881d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.help		= ULOG_help,
1891d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.init		= ULOG_init,
1901d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.parse		= ULOG_parse,
1911d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.print		= ULOG_print,
1921d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.save		= ULOG_save,
1931d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt	.extra_opts	= ULOG_opts,
194c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte};
195c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
196c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltevoid _init(void)
197c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
1988b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	xtables_register_target(&ulog_tg_reg);
199c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
200