xref: /aosp_15_r20/external/iptables/extensions/libebt_log.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
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