1 /*
2 * Bart De Schuymer <[email protected]>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Giuseppe Longo <[email protected]> adapted the original code to the
9 * xtables-compat environment in 2015.
10 *
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <syslog.h>
16 #include <string.h>
17 #include <getopt.h>
18 #include <xtables.h>
19 #include <linux/netfilter_bridge/ebt_log.h>
20
21 #define LOG_DEFAULT_LEVEL LOG_INFO
22
23 #define LOG_PREFIX '1'
24 #define LOG_LEVEL '2'
25 #define LOG_ARP '3'
26 #define LOG_IP '4'
27 #define LOG_LOG '5'
28 #define LOG_IP6 '6'
29
30 struct code {
31 char *c_name;
32 int c_val;
33 };
34
35 static struct code eight_priority[] = {
36 { "emerg", LOG_EMERG },
37 { "alert", LOG_ALERT },
38 { "crit", LOG_CRIT },
39 { "error", LOG_ERR },
40 { "warning", LOG_WARNING },
41 { "notice", LOG_NOTICE },
42 { "info", LOG_INFO },
43 { "debug", LOG_DEBUG }
44 };
45
name_to_loglevel(const char * arg)46 static int name_to_loglevel(const char *arg)
47 {
48 int i;
49
50 for (i = 0; i < 8; i++)
51 if (!strcmp(arg, eight_priority[i].c_name))
52 return eight_priority[i].c_val;
53
54 /* return bad loglevel */
55 return 9;
56 }
57
58 static const struct option brlog_opts[] = {
59 { .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX },
60 { .name = "log-level", .has_arg = true, .val = LOG_LEVEL },
61 { .name = "log-arp", .has_arg = false, .val = LOG_ARP },
62 { .name = "log-ip", .has_arg = false, .val = LOG_IP },
63 { .name = "log", .has_arg = false, .val = LOG_LOG },
64 { .name = "log-ip6", .has_arg = false, .val = LOG_IP6 },
65 XT_GETOPT_TABLEEND,
66 };
67
brlog_help(void)68 static void brlog_help(void)
69 {
70 int i;
71
72 printf(
73 "log options:\n"
74 "--log : use this if you're not specifying anything\n"
75 "--log-level level : level = [1-8] or a string\n"
76 "--log-prefix prefix : max. %d chars.\n"
77 "--log-ip : put ip info. in the log for ip packets\n"
78 "--log-arp : put (r)arp info. in the log for (r)arp packets\n"
79 "--log-ip6 : put ip6 info. in the log for ip6 packets\n"
80 , EBT_LOG_PREFIX_SIZE - 1);
81 for (i = 0; i < 8; i++)
82 printf("%d = %s\n", eight_priority[i].c_val,
83 eight_priority[i].c_name);
84 }
85
brlog_init(struct xt_entry_target * t)86 static void brlog_init(struct xt_entry_target *t)
87 {
88 struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
89
90 loginfo->bitmask = 0;
91 loginfo->prefix[0] = '\0';
92 loginfo->loglevel = LOG_NOTICE;
93 }
94
log_chk_inv(int inv,unsigned int bit,const char * suffix)95 static unsigned int log_chk_inv(int inv, unsigned int bit, const char *suffix)
96 {
97 if (inv)
98 xtables_error(PARAMETER_PROBLEM,
99 "Unexpected `!' after --log%s", suffix);
100 return bit;
101 }
102
brlog_parse(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)103 static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
104 const void *entry, struct xt_entry_target **target)
105 {
106 struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
107 long int i;
108 char *end;
109
110 switch (c) {
111 case LOG_PREFIX:
112 if (invert)
113 xtables_error(PARAMETER_PROBLEM,
114 "Unexpected `!` after --log-prefix");
115 if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
116 xtables_error(PARAMETER_PROBLEM,
117 "Prefix too long");
118 if (strchr(optarg, '\"'))
119 xtables_error(PARAMETER_PROBLEM,
120 "Use of \\\" is not allowed"
121 " in the prefix");
122 strcpy((char *)loginfo->prefix, (char *)optarg);
123 break;
124 case LOG_LEVEL:
125 i = strtol(optarg, &end, 16);
126 if (*end != '\0' || i < 0 || i > 7)
127 loginfo->loglevel = name_to_loglevel(optarg);
128 else
129 loginfo->loglevel = i;
130
131 if (loginfo->loglevel == 9)
132 xtables_error(PARAMETER_PROBLEM,
133 "Problem with the log-level");
134 break;
135 case LOG_IP:
136 loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP, "-ip");
137 break;
138 case LOG_ARP:
139 loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_ARP, "-arp");
140 break;
141 case LOG_LOG:
142 loginfo->bitmask |= log_chk_inv(invert, 0, "");
143 break;
144 case LOG_IP6:
145 loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP6, "-ip6");
146 break;
147 default:
148 return 0;
149 }
150
151 *flags |= loginfo->bitmask;
152 return 1;
153 }
154
brlog_final_check(unsigned int flags)155 static void brlog_final_check(unsigned int flags)
156 {
157 }
158
brlog_print(const void * ip,const struct xt_entry_target * target,int numeric)159 static void brlog_print(const void *ip, const struct xt_entry_target *target,
160 int numeric)
161 {
162 struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
163
164 printf("--log-level %s", eight_priority[loginfo->loglevel].c_name);
165
166 if (loginfo->prefix[0])
167 printf(" --log-prefix \"%s\"", loginfo->prefix);
168
169 if (loginfo->bitmask & EBT_LOG_IP)
170 printf(" --log-ip");
171 if (loginfo->bitmask & EBT_LOG_ARP)
172 printf(" --log-arp");
173 if (loginfo->bitmask & EBT_LOG_IP6)
174 printf(" --log-ip6");
175 printf(" ");
176 }
177
brlog_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)178 static int brlog_xlate(struct xt_xlate *xl,
179 const struct xt_xlate_tg_params *params)
180 {
181 const struct ebt_log_info *loginfo = (const void *)params->target->data;
182
183 xt_xlate_add(xl, "log");
184 if (loginfo->prefix[0])
185 xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
186
187 if (loginfo->loglevel != LOG_DEFAULT_LEVEL)
188 xt_xlate_add(xl, " level %s", eight_priority[loginfo->loglevel].c_name);
189
190 /* ebt_log always decodes MAC header, nft_log always decodes upper header -
191 * so set flags ether and ignore EBT_LOG_IP, EBT_LOG_ARP and EBT_LOG_IP6 */
192 xt_xlate_add(xl, " flags ether ");
193
194 return 1;
195 }
196
197 static struct xtables_target brlog_target = {
198 .name = "log",
199 .revision = 0,
200 .ext_flags = XTABLES_EXT_WATCHER,
201 .version = XTABLES_VERSION,
202 .family = NFPROTO_BRIDGE,
203 .size = XT_ALIGN(sizeof(struct ebt_log_info)),
204 .userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
205 .init = brlog_init,
206 .help = brlog_help,
207 .parse = brlog_parse,
208 .final_check = brlog_final_check,
209 .print = brlog_print,
210 .xlate = brlog_xlate,
211 .extra_opts = brlog_opts,
212 };
213
_init(void)214 void _init(void)
215 {
216 xtables_register_target(&brlog_target);
217 }
218