1#include <stdio.h>
2#include <string.h>
3#include <syslog.h>
4#include <xtables.h>
5#include <linux/netfilter_ipv6/ip6t_LOG.h>
6
7#ifndef IP6T_LOG_UID	/* Old kernel */
8#define IP6T_LOG_UID	0x08
9#undef  IP6T_LOG_MASK
10#define IP6T_LOG_MASK	0x0f
11#endif
12
13#define LOG_DEFAULT_LEVEL LOG_WARNING
14
15enum {
16	O_LOG_LEVEL = 0,
17	O_LOG_PREFIX,
18	O_LOG_TCPSEQ,
19	O_LOG_TCPOPTS,
20	O_LOG_IPOPTS,
21	O_LOG_UID,
22	O_LOG_MAC,
23};
24
25static void LOG_help(void)
26{
27	printf(
28"LOG target options:\n"
29" --log-level level		Level of logging (numeric or see syslog.conf)\n"
30" --log-prefix prefix		Prefix log messages with this prefix.\n"
31" --log-tcp-sequence		Log TCP sequence numbers.\n"
32" --log-tcp-options		Log TCP options.\n"
33" --log-ip-options		Log IP options.\n"
34" --log-uid			Log UID owning the local socket.\n"
35" --log-macdecode		Decode MAC addresses and protocol.\n");
36}
37
38#define s struct ip6t_log_info
39static const struct xt_option_entry LOG_opts[] = {
40	{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
41	 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
42	{.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
43	 .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
44	{.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
45	{.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
46	{.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
47	{.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
48	{.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
49	XTOPT_TABLEEND,
50};
51#undef s
52
53static void LOG_init(struct xt_entry_target *t)
54{
55	struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
56
57	loginfo->level = LOG_DEFAULT_LEVEL;
58
59}
60
61struct ip6t_log_names {
62	const char *name;
63	unsigned int level;
64};
65
66static const struct ip6t_log_names ip6t_log_names[]
67= { { .name = "alert",   .level = LOG_ALERT },
68    { .name = "crit",    .level = LOG_CRIT },
69    { .name = "debug",   .level = LOG_DEBUG },
70    { .name = "emerg",   .level = LOG_EMERG },
71    { .name = "error",   .level = LOG_ERR },		/* DEPRECATED */
72    { .name = "info",    .level = LOG_INFO },
73    { .name = "notice",  .level = LOG_NOTICE },
74    { .name = "panic",   .level = LOG_EMERG },		/* DEPRECATED */
75    { .name = "warning", .level = LOG_WARNING }
76};
77
78static void LOG_parse(struct xt_option_call *cb)
79{
80	struct ip6t_log_info *info = cb->data;
81
82	xtables_option_parse(cb);
83	switch (cb->entry->id) {
84	case O_LOG_PREFIX:
85		if (strchr(cb->arg, '\n') != NULL)
86			xtables_error(PARAMETER_PROBLEM,
87				   "Newlines not allowed in --log-prefix");
88		break;
89	case O_LOG_TCPSEQ:
90		info->logflags |= IP6T_LOG_TCPSEQ;
91		break;
92	case O_LOG_TCPOPTS:
93		info->logflags |= IP6T_LOG_TCPOPT;
94		break;
95	case O_LOG_IPOPTS:
96		info->logflags |= IP6T_LOG_IPOPT;
97		break;
98	case O_LOG_UID:
99		info->logflags |= IP6T_LOG_UID;
100		break;
101	case O_LOG_MAC:
102		info->logflags |= IP6T_LOG_MACDECODE;
103		break;
104	}
105}
106
107static void LOG_print(const void *ip, const struct xt_entry_target *target,
108                      int numeric)
109{
110	const struct ip6t_log_info *loginfo
111		= (const struct ip6t_log_info *)target->data;
112	unsigned int i = 0;
113
114	printf(" LOG");
115	if (numeric)
116		printf(" flags %u level %u",
117		       loginfo->logflags, loginfo->level);
118	else {
119		for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
120			if (loginfo->level == ip6t_log_names[i].level) {
121				printf(" level %s", ip6t_log_names[i].name);
122				break;
123			}
124		if (i == ARRAY_SIZE(ip6t_log_names))
125			printf(" UNKNOWN level %u", loginfo->level);
126		if (loginfo->logflags & IP6T_LOG_TCPSEQ)
127			printf(" tcp-sequence");
128		if (loginfo->logflags & IP6T_LOG_TCPOPT)
129			printf(" tcp-options");
130		if (loginfo->logflags & IP6T_LOG_IPOPT)
131			printf(" ip-options");
132		if (loginfo->logflags & IP6T_LOG_UID)
133			printf(" uid");
134		if (loginfo->logflags & IP6T_LOG_MACDECODE)
135			printf(" macdecode");
136		if (loginfo->logflags & ~(IP6T_LOG_MASK))
137			printf(" unknown-flags");
138	}
139
140	if (strcmp(loginfo->prefix, "") != 0)
141		printf(" prefix \"%s\"", loginfo->prefix);
142}
143
144static void LOG_save(const void *ip, const struct xt_entry_target *target)
145{
146	const struct ip6t_log_info *loginfo
147		= (const struct ip6t_log_info *)target->data;
148
149	if (strcmp(loginfo->prefix, "") != 0) {
150		printf(" --log-prefix");
151		xtables_save_string(loginfo->prefix);
152	}
153
154	if (loginfo->level != LOG_DEFAULT_LEVEL)
155		printf(" --log-level %d", loginfo->level);
156
157	if (loginfo->logflags & IP6T_LOG_TCPSEQ)
158		printf(" --log-tcp-sequence");
159	if (loginfo->logflags & IP6T_LOG_TCPOPT)
160		printf(" --log-tcp-options");
161	if (loginfo->logflags & IP6T_LOG_IPOPT)
162		printf(" --log-ip-options");
163	if (loginfo->logflags & IP6T_LOG_UID)
164		printf(" --log-uid");
165	if (loginfo->logflags & IP6T_LOG_MACDECODE)
166		printf(" --log-macdecode");
167}
168
169static struct xtables_target log_tg6_reg = {
170	.name          = "LOG",
171	.version       = XTABLES_VERSION,
172	.family        = NFPROTO_IPV6,
173	.size          = XT_ALIGN(sizeof(struct ip6t_log_info)),
174	.userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
175	.help          = LOG_help,
176	.init          = LOG_init,
177	.print         = LOG_print,
178	.save          = LOG_save,
179	.x6_parse      = LOG_parse,
180	.x6_options    = LOG_opts,
181};
182
183void _init(void)
184{
185	xtables_register_target(&log_tg6_reg);
186}
187