blob: ba6af0441f12fb621fd717ee3a21b15bd001d6d8 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Shared library add-on to iptables to add LOG support. */
Jan Engelhardt32b8e612010-07-23 21:16:14 +02002#include <stdbool.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00003#include <stdio.h>
4#include <netdb.h>
5#include <string.h>
6#include <stdlib.h>
7#include <syslog.h>
8#include <getopt.h>
Jan Engelhardt5d9678a2008-11-20 10:15:35 +01009#include <xtables.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000010#include <linux/netfilter_ipv4/ipt_LOG.h>
11
12#define LOG_DEFAULT_LEVEL LOG_WARNING
13
Martin Josefsson2b9a5772005-01-05 15:21:15 +000014#ifndef IPT_LOG_UID /* Old kernel */
15#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
16#undef IPT_LOG_MASK
17#define IPT_LOG_MASK 0x0f
18#endif
19
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000020static void LOG_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000021{
22 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020023"LOG target options:\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000024" --log-level level Level of logging (numeric or see syslog.conf)\n"
25" --log-prefix prefix Prefix log messages with this prefix.\n\n"
26" --log-tcp-sequence Log TCP sequence numbers.\n\n"
27" --log-tcp-options Log TCP options.\n\n"
John Langef46e1af2005-01-02 23:33:12 +000028" --log-ip-options Log IP options.\n\n"
Patrick McHardy12764782010-06-28 14:51:35 +020029" --log-uid Log UID owning the local socket.\n\n"
30" --log-macdecode Decode MAC addresses and protocol.\n\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000031}
32
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000033static const struct option LOG_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020034 {.name = "log-level", .has_arg = true, .val = '!'},
35 {.name = "log-prefix", .has_arg = true, .val = '#'},
36 {.name = "log-tcp-sequence", .has_arg = false, .val = '1'},
37 {.name = "log-tcp-options", .has_arg = false, .val = '2'},
38 {.name = "log-ip-options", .has_arg = false, .val = '3'},
39 {.name = "log-uid", .has_arg = false, .val = '4'},
40 {.name = "log-macdecode", .has_arg = false, .val = '5'},
41 XT_GETOPT_TABLEEND,
Marc Bouchere6869a82000-03-20 06:03:29 +000042};
43
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000044static void LOG_init(struct xt_entry_target *t)
Marc Bouchere6869a82000-03-20 06:03:29 +000045{
46 struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
47
48 loginfo->level = LOG_DEFAULT_LEVEL;
49
Marc Bouchere6869a82000-03-20 06:03:29 +000050}
51
52struct ipt_log_names {
53 const char *name;
54 unsigned int level;
55};
56
Jan Engelhardt0e2abed2007-10-04 16:25:58 +000057static const struct ipt_log_names ipt_log_names[]
Stephane Ouellette2be28ab2003-08-11 19:58:56 +000058= { { .name = "alert", .level = LOG_ALERT },
59 { .name = "crit", .level = LOG_CRIT },
60 { .name = "debug", .level = LOG_DEBUG },
61 { .name = "emerg", .level = LOG_EMERG },
62 { .name = "error", .level = LOG_ERR }, /* DEPRECATED */
63 { .name = "info", .level = LOG_INFO },
64 { .name = "notice", .level = LOG_NOTICE },
65 { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */
66 { .name = "warning", .level = LOG_WARNING }
Marc Bouchere6869a82000-03-20 06:03:29 +000067};
68
Jan Engelhardt7ac40522011-01-07 12:34:04 +010069static uint8_t
Marc Bouchere6869a82000-03-20 06:03:29 +000070parse_level(const char *level)
71{
Marc Boucher459357f2001-09-08 02:16:51 +000072 unsigned int lev = -1;
Harald Welte3e44c502001-10-22 08:16:24 +000073 unsigned int set = 0;
Marc Bouchere6869a82000-03-20 06:03:29 +000074
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010075 if (!xtables_strtoui(level, NULL, &lev, 0, 7)) {
Marc Bouchere6869a82000-03-20 06:03:29 +000076 unsigned int i = 0;
77
Jan Engelhardt2c69b552009-04-30 19:32:02 +020078 for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
Marc Bouchere6869a82000-03-20 06:03:29 +000079 if (strncasecmp(level, ipt_log_names[i].name,
80 strlen(level)) == 0) {
Harald Welte3e44c502001-10-22 08:16:24 +000081 if (set++)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010082 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +000083 "log-level `%s' ambiguous",
84 level);
85 lev = ipt_log_names[i].level;
86 }
Marc Bouchere6869a82000-03-20 06:03:29 +000087
Harald Welte3e44c502001-10-22 08:16:24 +000088 if (!set)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010089 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +000090 "log-level `%s' unknown", level);
91 }
92
Jan Engelhardt213e1852009-01-27 17:24:34 +010093 return lev;
Marc Bouchere6869a82000-03-20 06:03:29 +000094}
95
96#define IPT_LOG_OPT_LEVEL 0x01
97#define IPT_LOG_OPT_PREFIX 0x02
98#define IPT_LOG_OPT_TCPSEQ 0x04
99#define IPT_LOG_OPT_TCPOPT 0x08
100#define IPT_LOG_OPT_IPOPT 0x10
John Langef46e1af2005-01-02 23:33:12 +0000101#define IPT_LOG_OPT_UID 0x20
Patrick McHardy12764782010-06-28 14:51:35 +0200102#define IPT_LOG_OPT_MACDECODE 0x40
Marc Bouchere6869a82000-03-20 06:03:29 +0000103
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000104static int LOG_parse(int c, char **argv, int invert, unsigned int *flags,
105 const void *entry, struct xt_entry_target **target)
Marc Bouchere6869a82000-03-20 06:03:29 +0000106{
107 struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data;
108
109 switch (c) {
110 case '!':
111 if (*flags & IPT_LOG_OPT_LEVEL)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100112 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000113 "Can't specify --log-level twice");
Rusty Russell7e53bf92000-03-20 07:03:28 +0000114
Jan Engelhardtbf971282009-11-03 19:55:11 +0100115 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100116 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000117 "Unexpected `!' after --log-level");
118
119 loginfo->level = parse_level(optarg);
120 *flags |= IPT_LOG_OPT_LEVEL;
121 break;
122
123 case '#':
124 if (*flags & IPT_LOG_OPT_PREFIX)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100125 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000126 "Can't specify --log-prefix twice");
Rusty Russell7e53bf92000-03-20 07:03:28 +0000127
Jan Engelhardtbf971282009-11-03 19:55:11 +0100128 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100129 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000130 "Unexpected `!' after --log-prefix");
131
132 if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100133 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000134 "Maximum prefix length %u for --log-prefix",
Martin Josefssona28d4952004-05-26 16:04:48 +0000135 (unsigned int)sizeof(loginfo->prefix) - 1);
Marc Bouchere6869a82000-03-20 06:03:29 +0000136
Mike Frysingered26b7b2006-10-10 06:18:40 +0000137 if (strlen(optarg) == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100138 xtables_error(PARAMETER_PROBLEM,
Mike Frysingered26b7b2006-10-10 06:18:40 +0000139 "No prefix specified for --log-prefix");
140
Phil Oester182f3f62005-04-01 07:07:00 +0000141 if (strlen(optarg) != strlen(strtok(optarg, "\n")))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100142 xtables_error(PARAMETER_PROBLEM,
Phil Oester182f3f62005-04-01 07:07:00 +0000143 "Newlines not allowed in --log-prefix");
144
Marc Bouchere6869a82000-03-20 06:03:29 +0000145 strcpy(loginfo->prefix, optarg);
146 *flags |= IPT_LOG_OPT_PREFIX;
147 break;
148
149 case '1':
150 if (*flags & IPT_LOG_OPT_TCPSEQ)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100151 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000152 "Can't specify --log-tcp-sequence "
153 "twice");
154
155 loginfo->logflags |= IPT_LOG_TCPSEQ;
156 *flags |= IPT_LOG_OPT_TCPSEQ;
157 break;
158
159 case '2':
160 if (*flags & IPT_LOG_OPT_TCPOPT)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100161 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000162 "Can't specify --log-tcp-options twice");
163
164 loginfo->logflags |= IPT_LOG_TCPOPT;
165 *flags |= IPT_LOG_OPT_TCPOPT;
166 break;
167
168 case '3':
169 if (*flags & IPT_LOG_OPT_IPOPT)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100170 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000171 "Can't specify --log-ip-options twice");
172
173 loginfo->logflags |= IPT_LOG_IPOPT;
174 *flags |= IPT_LOG_OPT_IPOPT;
175 break;
176
John Langef46e1af2005-01-02 23:33:12 +0000177 case '4':
178 if (*flags & IPT_LOG_OPT_UID)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100179 xtables_error(PARAMETER_PROBLEM,
John Langef46e1af2005-01-02 23:33:12 +0000180 "Can't specify --log-uid twice");
181
182 loginfo->logflags |= IPT_LOG_UID;
183 *flags |= IPT_LOG_OPT_UID;
184 break;
185
Patrick McHardy12764782010-06-28 14:51:35 +0200186 case '5':
187 if (*flags & IPT_LOG_OPT_MACDECODE)
188 xtables_error(PARAMETER_PROBLEM,
189 "Can't specifiy --log-macdecode twice");
190
191 loginfo->logflags |= IPT_LOG_MACDECODE;
192 *flags |= IPT_LOG_OPT_MACDECODE;
193 break;
Marc Bouchere6869a82000-03-20 06:03:29 +0000194 }
195
196 return 1;
197}
198
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000199static void LOG_print(const void *ip, const struct xt_entry_target *target,
200 int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000201{
202 const struct ipt_log_info *loginfo
203 = (const struct ipt_log_info *)target->data;
204 unsigned int i = 0;
205
Jan Engelhardt73866352010-12-18 02:04:59 +0100206 printf(" LOG");
Marc Bouchere6869a82000-03-20 06:03:29 +0000207 if (numeric)
Jan Engelhardt73866352010-12-18 02:04:59 +0100208 printf(" flags %u level %u",
Marc Bouchere6869a82000-03-20 06:03:29 +0000209 loginfo->logflags, loginfo->level);
210 else {
Jan Engelhardt2c69b552009-04-30 19:32:02 +0200211 for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
Marc Bouchere6869a82000-03-20 06:03:29 +0000212 if (loginfo->level == ipt_log_names[i].level) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100213 printf(" level %s", ipt_log_names[i].name);
Marc Bouchere6869a82000-03-20 06:03:29 +0000214 break;
215 }
Jan Engelhardt2c69b552009-04-30 19:32:02 +0200216 if (i == ARRAY_SIZE(ipt_log_names))
Jan Engelhardt73866352010-12-18 02:04:59 +0100217 printf(" UNKNOWN level %u", loginfo->level);
Marc Bouchere6869a82000-03-20 06:03:29 +0000218 if (loginfo->logflags & IPT_LOG_TCPSEQ)
Jan Engelhardt73866352010-12-18 02:04:59 +0100219 printf(" tcp-sequence");
Marc Bouchere6869a82000-03-20 06:03:29 +0000220 if (loginfo->logflags & IPT_LOG_TCPOPT)
Jan Engelhardt73866352010-12-18 02:04:59 +0100221 printf(" tcp-options");
Marc Bouchere6869a82000-03-20 06:03:29 +0000222 if (loginfo->logflags & IPT_LOG_IPOPT)
Jan Engelhardt73866352010-12-18 02:04:59 +0100223 printf(" ip-options");
John Langef46e1af2005-01-02 23:33:12 +0000224 if (loginfo->logflags & IPT_LOG_UID)
Jan Engelhardt73866352010-12-18 02:04:59 +0100225 printf(" uid");
Patrick McHardy12764782010-06-28 14:51:35 +0200226 if (loginfo->logflags & IPT_LOG_MACDECODE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100227 printf(" macdecode");
Marc Bouchere6869a82000-03-20 06:03:29 +0000228 if (loginfo->logflags & ~(IPT_LOG_MASK))
Jan Engelhardt73866352010-12-18 02:04:59 +0100229 printf(" unknown-flags");
Marc Bouchere6869a82000-03-20 06:03:29 +0000230 }
231
232 if (strcmp(loginfo->prefix, "") != 0)
Jan Engelhardt73866352010-12-18 02:04:59 +0100233 printf(" prefix \"%s\"", loginfo->prefix);
Marc Bouchere6869a82000-03-20 06:03:29 +0000234}
235
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000236static void LOG_save(const void *ip, const struct xt_entry_target *target)
Marc Bouchere6869a82000-03-20 06:03:29 +0000237{
238 const struct ipt_log_info *loginfo
239 = (const struct ipt_log_info *)target->data;
240
Max Kellermanna5d09942008-01-29 13:44:34 +0000241 if (strcmp(loginfo->prefix, "") != 0) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100242 printf(" --log-prefix");
Jan Engelhardta0baae82009-01-30 04:32:50 +0100243 xtables_save_string(loginfo->prefix);
Max Kellermanna5d09942008-01-29 13:44:34 +0000244 }
Marc Bouchere6869a82000-03-20 06:03:29 +0000245
Thomas Woerner01cbaa62003-07-14 20:01:29 +0000246 if (loginfo->level != LOG_DEFAULT_LEVEL)
Jan Engelhardt73866352010-12-18 02:04:59 +0100247 printf(" --log-level %d", loginfo->level);
Marc Bouchere6869a82000-03-20 06:03:29 +0000248
249 if (loginfo->logflags & IPT_LOG_TCPSEQ)
Jan Engelhardt73866352010-12-18 02:04:59 +0100250 printf(" --log-tcp-sequence");
Marc Bouchere6869a82000-03-20 06:03:29 +0000251 if (loginfo->logflags & IPT_LOG_TCPOPT)
Jan Engelhardt73866352010-12-18 02:04:59 +0100252 printf(" --log-tcp-options");
Marc Bouchere6869a82000-03-20 06:03:29 +0000253 if (loginfo->logflags & IPT_LOG_IPOPT)
Jan Engelhardt73866352010-12-18 02:04:59 +0100254 printf(" --log-ip-options");
John Langef46e1af2005-01-02 23:33:12 +0000255 if (loginfo->logflags & IPT_LOG_UID)
Jan Engelhardt73866352010-12-18 02:04:59 +0100256 printf(" --log-uid");
Patrick McHardy12764782010-06-28 14:51:35 +0200257 if (loginfo->logflags & IPT_LOG_MACDECODE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100258 printf(" --log-macdecode");
Marc Bouchere6869a82000-03-20 06:03:29 +0000259}
260
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200261static struct xtables_target log_tg_reg = {
Jan Engelhardte1df2212011-02-15 12:02:51 +0100262 .name = "LOG",
263 .version = XTABLES_VERSION,
264 .family = NFPROTO_IPV4,
265 .size = XT_ALIGN(sizeof(struct ipt_log_info)),
266 .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
267 .help = LOG_help,
268 .init = LOG_init,
269 .parse = LOG_parse,
270 .print = LOG_print,
271 .save = LOG_save,
272 .extra_opts = LOG_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000273};
274
275void _init(void)
276{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200277 xtables_register_target(&log_tg_reg);
Marc Bouchere6869a82000-03-20 06:03:29 +0000278}