1 /*
2  * Bart De Schuymer <bdschuym@pandora.be>
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 <giuseppelng@gmail.com> 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 typedef struct _code {
31 	char *c_name;
32 	int c_val;
33 } CODE;
34 
35 static 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 
brlog_parse(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)95 static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
96 		       const void *entry, struct xt_entry_target **target)
97 {
98 	struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
99 	long int i;
100 	char *end;
101 
102 	switch (c) {
103 	case LOG_PREFIX:
104 		if (invert)
105 			xtables_error(PARAMETER_PROBLEM,
106 				      "Unexpected `!` after --log-prefix");
107 		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
108 			xtables_error(PARAMETER_PROBLEM,
109 				      "Prefix too long");
110 		if (strchr(optarg, '\"'))
111 			xtables_error(PARAMETER_PROBLEM,
112 				      "Use of \\\" is not allowed"
113 				      " in the prefix");
114 		strcpy((char *)loginfo->prefix, (char *)optarg);
115 		break;
116 	case LOG_LEVEL:
117 		i = strtol(optarg, &end, 16);
118 		if (*end != '\0' || i < 0 || i > 7)
119 			loginfo->loglevel = name_to_loglevel(optarg);
120 		else
121 			loginfo->loglevel = i;
122 
123 		if (loginfo->loglevel == 9)
124 			xtables_error(PARAMETER_PROBLEM,
125 				      "Problem with the log-level");
126 		break;
127 	case LOG_IP:
128 		if (invert)
129 			xtables_error(PARAMETER_PROBLEM,
130 				      "Unexpected `!' after --log-ip");
131 		loginfo->bitmask |= EBT_LOG_IP;
132 		break;
133 	case LOG_ARP:
134 		if (invert)
135 			xtables_error(PARAMETER_PROBLEM,
136 				      "Unexpected `!' after --log-arp");
137 		loginfo->bitmask |= EBT_LOG_ARP;
138 	case LOG_LOG:
139 		if (invert)
140 			xtables_error(PARAMETER_PROBLEM,
141 				      "Unexpected `!' after --log");
142 		break;
143 	case LOG_IP6:
144 		if (invert)
145 			xtables_error(PARAMETER_PROBLEM,
146 				      "Unexpected `!' after --log-ip6");
147 		loginfo->bitmask |= EBT_LOG_IP6;
148 		break;
149 	default:
150 		return 0;
151 	}
152 
153 	*flags |= loginfo->bitmask;
154 	return 1;
155 }
156 
brlog_final_check(unsigned int flags)157 static void brlog_final_check(unsigned int flags)
158 {
159 }
160 
brlog_print(const void * ip,const struct xt_entry_target * target,int numeric)161 static void brlog_print(const void *ip, const struct xt_entry_target *target,
162 			int numeric)
163 {
164 	struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
165 
166 	printf("--log-level %s --log-prefix \"%s\"",
167 		eight_priority[loginfo->loglevel].c_name,
168 		loginfo->prefix);
169 
170 	if (loginfo->bitmask & EBT_LOG_IP)
171 		printf(" --log-ip");
172 	if (loginfo->bitmask & EBT_LOG_ARP)
173 		printf(" --log-arp");
174 	if (loginfo->bitmask & EBT_LOG_IP6)
175 		printf(" --log-ip6");
176 	printf(" ");
177 }
178 
179 static struct xtables_target brlog_target = {
180 	.name		= "log",
181 	.revision	= 0,
182 	.version	= XTABLES_VERSION,
183 	.family		= NFPROTO_BRIDGE,
184 	.size		= XT_ALIGN(sizeof(struct ebt_log_info)),
185 	.userspacesize	= XT_ALIGN(sizeof(struct ebt_log_info)),
186 	.init		= brlog_init,
187 	.help		= brlog_help,
188 	.parse		= brlog_parse,
189 	.final_check	= brlog_final_check,
190 	.print		= brlog_print,
191 	.extra_opts	= brlog_opts,
192 };
193 
_init(void)194 void _init(void)
195 {
196 	xtables_register_target(&brlog_target);
197 }
198