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