• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <string.h>
3 #include <syslog.h>
4 #include <xtables.h>
5 #include <linux/netfilter_ipv4/ipt_LOG.h>
6 
7 #define LOG_DEFAULT_LEVEL LOG_WARNING
8 
9 #ifndef IPT_LOG_UID /* Old kernel */
10 #define IPT_LOG_UID	0x08	/* Log UID owning local socket */
11 #undef  IPT_LOG_MASK
12 #define IPT_LOG_MASK	0x0f
13 #endif
14 
15 enum {
16 	O_LOG_LEVEL = 0,
17 	O_LOG_PREFIX,
18 	O_LOG_TCPSEQ,
19 	O_LOG_TCPOPTS,
20 	O_LOG_IPOPTS,
21 	O_LOG_UID,
22 	O_LOG_MAC,
23 };
24 
LOG_help(void)25 static void LOG_help(void)
26 {
27 	printf(
28 "LOG target options:\n"
29 " --log-level level		Level of logging (numeric or see syslog.conf)\n"
30 " --log-prefix prefix		Prefix log messages with this prefix.\n\n"
31 " --log-tcp-sequence		Log TCP sequence numbers.\n\n"
32 " --log-tcp-options		Log TCP options.\n\n"
33 " --log-ip-options		Log IP options.\n\n"
34 " --log-uid			Log UID owning the local socket.\n\n"
35 " --log-macdecode		Decode MAC addresses and protocol.\n\n");
36 }
37 
38 #define s struct ipt_log_info
39 static const struct xt_option_entry LOG_opts[] = {
40 	{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
41 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
42 	{.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
43 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
44 	{.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
45 	{.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
46 	{.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
47 	{.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
48 	{.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
49 	XTOPT_TABLEEND,
50 };
51 #undef s
52 
LOG_init(struct xt_entry_target * t)53 static void LOG_init(struct xt_entry_target *t)
54 {
55 	struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
56 
57 	loginfo->level = LOG_DEFAULT_LEVEL;
58 
59 }
60 
61 struct ipt_log_names {
62 	const char *name;
63 	unsigned int level;
64 };
65 
66 struct ipt_log_xlate {
67 	const char *name;
68 	unsigned int level;
69 };
70 
71 static const struct ipt_log_names ipt_log_names[]
72 = { { .name = "alert",   .level = LOG_ALERT },
73     { .name = "crit",    .level = LOG_CRIT },
74     { .name = "debug",   .level = LOG_DEBUG },
75     { .name = "emerg",   .level = LOG_EMERG },
76     { .name = "error",   .level = LOG_ERR },		/* DEPRECATED */
77     { .name = "info",    .level = LOG_INFO },
78     { .name = "notice",  .level = LOG_NOTICE },
79     { .name = "panic",   .level = LOG_EMERG },		/* DEPRECATED */
80     { .name = "warning", .level = LOG_WARNING }
81 };
82 
LOG_parse(struct xt_option_call * cb)83 static void LOG_parse(struct xt_option_call *cb)
84 {
85 	struct ipt_log_info *info = cb->data;
86 
87 	xtables_option_parse(cb);
88 	switch (cb->entry->id) {
89 	case O_LOG_PREFIX:
90 		if (strchr(cb->arg, '\n') != NULL)
91 			xtables_error(PARAMETER_PROBLEM,
92 				   "Newlines not allowed in --log-prefix");
93 		break;
94 	case O_LOG_TCPSEQ:
95 		info->logflags |= IPT_LOG_TCPSEQ;
96 		break;
97 	case O_LOG_TCPOPTS:
98 		info->logflags |= IPT_LOG_TCPOPT;
99 		break;
100 	case O_LOG_IPOPTS:
101 		info->logflags |= IPT_LOG_IPOPT;
102 		break;
103 	case O_LOG_UID:
104 		info->logflags |= IPT_LOG_UID;
105 		break;
106 	case O_LOG_MAC:
107 		info->logflags |= IPT_LOG_MACDECODE;
108 		break;
109 	}
110 }
111 
LOG_print(const void * ip,const struct xt_entry_target * target,int numeric)112 static void LOG_print(const void *ip, const struct xt_entry_target *target,
113                       int numeric)
114 {
115 	const struct ipt_log_info *loginfo
116 		= (const struct ipt_log_info *)target->data;
117 	unsigned int i = 0;
118 
119 	printf(" LOG");
120 	if (numeric)
121 		printf(" flags %u level %u",
122 		       loginfo->logflags, loginfo->level);
123 	else {
124 		for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
125 			if (loginfo->level == ipt_log_names[i].level) {
126 				printf(" level %s", ipt_log_names[i].name);
127 				break;
128 			}
129 		if (i == ARRAY_SIZE(ipt_log_names))
130 			printf(" UNKNOWN level %u", loginfo->level);
131 		if (loginfo->logflags & IPT_LOG_TCPSEQ)
132 			printf(" tcp-sequence");
133 		if (loginfo->logflags & IPT_LOG_TCPOPT)
134 			printf(" tcp-options");
135 		if (loginfo->logflags & IPT_LOG_IPOPT)
136 			printf(" ip-options");
137 		if (loginfo->logflags & IPT_LOG_UID)
138 			printf(" uid");
139 		if (loginfo->logflags & IPT_LOG_MACDECODE)
140 			printf(" macdecode");
141 		if (loginfo->logflags & ~(IPT_LOG_MASK))
142 			printf(" unknown-flags");
143 	}
144 
145 	if (strcmp(loginfo->prefix, "") != 0)
146 		printf(" prefix \"%s\"", loginfo->prefix);
147 }
148 
LOG_save(const void * ip,const struct xt_entry_target * target)149 static void LOG_save(const void *ip, const struct xt_entry_target *target)
150 {
151 	const struct ipt_log_info *loginfo
152 		= (const struct ipt_log_info *)target->data;
153 
154 	if (strcmp(loginfo->prefix, "") != 0) {
155 		printf(" --log-prefix");
156 		xtables_save_string(loginfo->prefix);
157 	}
158 
159 	if (loginfo->level != LOG_DEFAULT_LEVEL)
160 		printf(" --log-level %d", loginfo->level);
161 
162 	if (loginfo->logflags & IPT_LOG_TCPSEQ)
163 		printf(" --log-tcp-sequence");
164 	if (loginfo->logflags & IPT_LOG_TCPOPT)
165 		printf(" --log-tcp-options");
166 	if (loginfo->logflags & IPT_LOG_IPOPT)
167 		printf(" --log-ip-options");
168 	if (loginfo->logflags & IPT_LOG_UID)
169 		printf(" --log-uid");
170 	if (loginfo->logflags & IPT_LOG_MACDECODE)
171 		printf(" --log-macdecode");
172 }
173 
174 static const struct ipt_log_xlate ipt_log_xlate_names[] = {
175 	{"alert",	LOG_ALERT },
176 	{"crit",	LOG_CRIT },
177 	{"debug",	LOG_DEBUG },
178 	{"emerg",	LOG_EMERG },
179 	{"err",		LOG_ERR },
180 	{"info",	LOG_INFO },
181 	{"notice",	LOG_NOTICE },
182 	{"warn",	LOG_WARNING }
183 };
184 
LOG_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)185 static int LOG_xlate(struct xt_xlate *xl,
186 		     const struct xt_xlate_tg_params *params)
187 {
188 	const struct ipt_log_info *loginfo =
189 		(const struct ipt_log_info *)params->target->data;
190 	unsigned int i = 0;
191 
192 	xt_xlate_add(xl, "log");
193 	if (strcmp(loginfo->prefix, "") != 0) {
194 		if (params->escape_quotes)
195 			xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
196 		else
197 			xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
198 	}
199 
200 	for (i = 0; i < ARRAY_SIZE(ipt_log_xlate_names); ++i)
201 		if (loginfo->level != LOG_DEFAULT_LEVEL &&
202 		    loginfo->level == ipt_log_xlate_names[i].level) {
203 			xt_xlate_add(xl, " level %s",
204 				   ipt_log_xlate_names[i].name);
205 			break;
206 		}
207 
208 	if ((loginfo->logflags & IPT_LOG_MASK) == IPT_LOG_MASK) {
209 		xt_xlate_add(xl, " flags all");
210 	} else {
211 		if (loginfo->logflags & (IPT_LOG_TCPSEQ | IPT_LOG_TCPOPT)) {
212 			const char *delim = " ";
213 
214 			xt_xlate_add(xl, " flags tcp");
215 			if (loginfo->logflags & IPT_LOG_TCPSEQ) {
216 				xt_xlate_add(xl, " sequence");
217 				delim = ",";
218 			}
219 			if (loginfo->logflags & IPT_LOG_TCPOPT)
220 				xt_xlate_add(xl, "%soptions", delim);
221 		}
222 		if (loginfo->logflags & IPT_LOG_IPOPT)
223 			xt_xlate_add(xl, " flags ip options");
224 		if (loginfo->logflags & IPT_LOG_UID)
225 			xt_xlate_add(xl, " flags skuid");
226 		if (loginfo->logflags & IPT_LOG_MACDECODE)
227 			xt_xlate_add(xl, " flags ether");
228 	}
229 
230 	return 1;
231 }
232 static struct xtables_target log_tg_reg = {
233 	.name          = "LOG",
234 	.version       = XTABLES_VERSION,
235 	.family        = NFPROTO_IPV4,
236 	.size          = XT_ALIGN(sizeof(struct ipt_log_info)),
237 	.userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
238 	.help          = LOG_help,
239 	.init          = LOG_init,
240 	.print         = LOG_print,
241 	.save          = LOG_save,
242 	.x6_parse      = LOG_parse,
243 	.x6_options    = LOG_opts,
244 	.xlate	       = LOG_xlate,
245 };
246 
_init(void)247 void _init(void)
248 {
249 	xtables_register_target(&log_tg_reg);
250 }
251