libipt_ULOG.c revision c5bdb40e2d78999e3bfed6256d0fd2df4bba784f
1c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Shared library add-on to iptables to add ULOG support. */
2c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdio.h>
3c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <netdb.h>
4c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <string.h>
5c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdlib.h>
6c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <syslog.h>
7c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <getopt.h>
8c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <iptables.h>
9c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <linux/netfilter_ipv4/ip_tables.h>
10c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <linux/netfilter_ipv4/ipt_ULOG.h>
11c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
12c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define ULOG_DEFAULT_NLGROUP 1
13c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
14c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
15c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltevoid print_groups(unsigned int gmask)
16c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
17c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	int b;
18c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	unsigned int test;
19c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
20c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	for (b = 31; b >= 0; b--)
21c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	{
22c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		test = (1 << b);
23c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (gmask & test)
24c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			printf("%d ", b + 1);
25c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
26c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
27c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
28c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Function which prints out usage message. */
29c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic void help(void)
30c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
31c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	printf(
32c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte"ULOG v%s options:\n"
33c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte" --ulog-nlgroup nlgroup		NETLINK grouo used for logging\n"
34c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte" --ulog-prefix prefix		Prefix log messages with this prefix.\n\n",
35c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald WelteNETFILTER_VERSION);
36c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
37c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
38c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic struct option opts[] = {
39c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	{ "ulog-nlgroup", 1, 0, '!' },
40c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	{ "ulog-prefix", 1, 0, '#' },
41c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	{ 0 }
42c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte};
43c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
44c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Initialize the target. */
45c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic void init(struct ipt_entry_target *t, unsigned int *nfcache)
46c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
47c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *)t->data;
48c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
49c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
50c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
51c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	/* Can't cache this */
52c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	*nfcache |= NFC_UNKNOWN;
53c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
54c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
55c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_NLGROUP 0x01
56c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_PREFIX 0x02
57c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
58c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Function which parses command options; returns true if it
59c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte   ate an option */
60c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic int parse(int c, char **argv, int invert, unsigned int *flags,
61c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte      const struct ipt_entry *entry,
62c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte      struct ipt_entry_target **target)
63c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
64c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *)(*target)->data;
65c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	int group_d;
66c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
67c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	switch (c) {
68c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	case '!':
69c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (*flags & IPT_LOG_OPT_NLGROUP)
70c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
71c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Can't specify --ulog-nlgroup twice");
72c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
73c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (check_inverse(optarg, &invert))
74c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
75c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Unexpected `!' after --ulog-nlgroup");
76c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		group_d = atoi(optarg);
77c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (group_d > 32 || group_d < 1)
78c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
79c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				"--ulog-nlgroup has to be between 1 and 32");
80c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
81c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		loginfo->nl_group = (1 << (group_d -1));
82c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
83c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		*flags |= IPT_LOG_OPT_NLGROUP;
84c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		break;
85c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
86c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	case '#':
87c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (*flags & IPT_LOG_OPT_PREFIX)
88c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
89c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Can't specify --ulog-prefix twice");
90c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
91c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (check_inverse(optarg, &invert))
92c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
93c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Unexpected `!' after --ulog-prefix");
94c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
95c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
96c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte			exit_error(PARAMETER_PROBLEM,
97c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   "Maximum prefix length %u for --ulog-prefix",
98c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte				   sizeof(loginfo->prefix) - 1);
99c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
100c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		strcpy(loginfo->prefix, optarg);
101c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		*flags |= IPT_LOG_OPT_PREFIX;
102c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		break;
103c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
104c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	return 1;
105c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
106c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
107c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Final check; nothing. */
108c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic void final_check(unsigned int flags)
109c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
110c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
111c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
112c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Saves the union ipt_targinfo in parsable form to stdout. */
113c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
114c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
115c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte        const struct ipt_ulog_info *loginfo
116c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte                = (const struct ipt_ulog_info *)target->data;
117c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
118c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte        if (strcmp(loginfo->prefix, "") != 0)
119c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte                printf("--ulog-prefix %s ", loginfo->prefix);
120c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
121c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte        if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP)
122c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	{
123c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte                printf("--ulog-nlgroup ");
124c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		print_groups(loginfo->nl_group);
125c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		printf("\n");
126c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	}
127c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
128c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
129c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte/* Prints out the targinfo. */
130c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestatic void
131c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welteprint(const struct ipt_ip *ip,
132c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte      const struct ipt_entry_target *target,
133c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte      int numeric)
134c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
135c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	const struct ipt_ulog_info *loginfo
136c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		= (const struct ipt_ulog_info *)target->data;
137c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
138c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	printf("ULOG ");
139c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	printf("nlgroup ");
140c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	print_groups(loginfo->nl_group);
141c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	if (strcmp(loginfo->prefix, "") != 0)
142c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte		printf("prefix `%s' ", loginfo->prefix);
143c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
144c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
145c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltestruct iptables_target ulog
146c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte= { NULL,
147c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    "ULOG",
148c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    NETFILTER_VERSION,
149c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    IPT_ALIGN(sizeof(struct ipt_ulog_info)),
150c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    IPT_ALIGN(sizeof(struct ipt_ulog_info)),
151c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &help,
152c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &init,
153c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &parse,
154c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &final_check,
155c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &print,
156c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    &save,
157c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte    opts
158c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte};
159c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte
160c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltevoid _init(void)
161c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{
162c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte	register_target(&ulog);
163c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}
164