1 #include <stdio.h>
2 #include <string.h>
3 #define SYSLOG_NAMES
4 #include <syslog.h>
5 #include <xtables.h>
6 #include <linux/netfilter/xt_LOG.h>
7
8 #define LOG_DEFAULT_LEVEL LOG_WARNING
9
10 enum {
11 /* make sure the values correspond with XT_LOG_* bit positions */
12 O_LOG_TCPSEQ = 0,
13 O_LOG_TCPOPTS,
14 O_LOG_IPOPTS,
15 O_LOG_UID,
16 __O_LOG_NFLOG,
17 O_LOG_MAC,
18 O_LOG_LEVEL,
19 O_LOG_PREFIX,
20 };
21
LOG_help(void)22 static void LOG_help(void)
23 {
24 printf(
25 "LOG target options:\n"
26 " --log-level level Level of logging (numeric or see syslog.conf)\n"
27 " --log-prefix prefix Prefix log messages with this prefix.\n"
28 " --log-tcp-sequence Log TCP sequence numbers.\n"
29 " --log-tcp-options Log TCP options.\n"
30 " --log-ip-options Log IP options.\n"
31 " --log-uid Log UID owning the local socket.\n"
32 " --log-macdecode Decode MAC addresses and protocol.\n");
33 }
34
35 #define s struct xt_log_info
36 static const struct xt_option_entry LOG_opts[] = {
37 {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
38 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
39 {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
40 .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
41 {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
42 {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
43 {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
44 {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
45 {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
46 XTOPT_TABLEEND,
47 };
48 #undef s
49
LOG_init(struct xt_entry_target * t)50 static void LOG_init(struct xt_entry_target *t)
51 {
52 struct xt_log_info *loginfo = (void *)t->data;
53
54 loginfo->level = LOG_DEFAULT_LEVEL;
55 }
56
LOG_parse(struct xt_option_call * cb)57 static void LOG_parse(struct xt_option_call *cb)
58 {
59 struct xt_log_info *info = cb->data;
60
61 xtables_option_parse(cb);
62 switch (cb->entry->id) {
63 case O_LOG_PREFIX:
64 if (strchr(cb->arg, '\n') != NULL)
65 xtables_error(PARAMETER_PROBLEM,
66 "Newlines not allowed in --log-prefix");
67 break;
68 case O_LOG_TCPSEQ:
69 case O_LOG_TCPOPTS:
70 case O_LOG_IPOPTS:
71 case O_LOG_UID:
72 case O_LOG_MAC:
73 info->logflags |= 1 << cb->entry->id;
74 break;
75 }
76 }
77
priority2name(unsigned char level)78 static const char *priority2name(unsigned char level)
79 {
80 int i;
81
82 for (i = 0; prioritynames[i].c_name; ++i) {
83 if (level == prioritynames[i].c_val)
84 return prioritynames[i].c_name;
85 }
86 return NULL;
87 }
88
LOG_print(const void * ip,const struct xt_entry_target * target,int numeric)89 static void LOG_print(const void *ip, const struct xt_entry_target *target,
90 int numeric)
91 {
92 const struct xt_log_info *loginfo = (const void *)target->data;
93
94 printf(" LOG");
95 if (numeric)
96 printf(" flags %u level %u",
97 loginfo->logflags, loginfo->level);
98 else {
99 const char *pname = priority2name(loginfo->level);
100
101 if (pname)
102 printf(" level %s", pname);
103 else
104 printf(" UNKNOWN level %u", loginfo->level);
105 if (loginfo->logflags & XT_LOG_TCPSEQ)
106 printf(" tcp-sequence");
107 if (loginfo->logflags & XT_LOG_TCPOPT)
108 printf(" tcp-options");
109 if (loginfo->logflags & XT_LOG_IPOPT)
110 printf(" ip-options");
111 if (loginfo->logflags & XT_LOG_UID)
112 printf(" uid");
113 if (loginfo->logflags & XT_LOG_MACDECODE)
114 printf(" macdecode");
115 if (loginfo->logflags & ~(XT_LOG_MASK))
116 printf(" unknown-flags");
117 }
118
119 if (strcmp(loginfo->prefix, "") != 0)
120 printf(" prefix \"%s\"", loginfo->prefix);
121 }
122
LOG_save(const void * ip,const struct xt_entry_target * target)123 static void LOG_save(const void *ip, const struct xt_entry_target *target)
124 {
125 const struct xt_log_info *loginfo = (const void *)target->data;
126
127 if (strcmp(loginfo->prefix, "") != 0) {
128 printf(" --log-prefix");
129 xtables_save_string(loginfo->prefix);
130 }
131
132 if (loginfo->level != LOG_DEFAULT_LEVEL)
133 printf(" --log-level %d", loginfo->level);
134
135 if (loginfo->logflags & XT_LOG_TCPSEQ)
136 printf(" --log-tcp-sequence");
137 if (loginfo->logflags & XT_LOG_TCPOPT)
138 printf(" --log-tcp-options");
139 if (loginfo->logflags & XT_LOG_IPOPT)
140 printf(" --log-ip-options");
141 if (loginfo->logflags & XT_LOG_UID)
142 printf(" --log-uid");
143 if (loginfo->logflags & XT_LOG_MACDECODE)
144 printf(" --log-macdecode");
145 }
146
LOG_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)147 static int LOG_xlate(struct xt_xlate *xl,
148 const struct xt_xlate_tg_params *params)
149 {
150 const struct xt_log_info *loginfo = (const void *)params->target->data;
151 const char *pname = priority2name(loginfo->level);
152
153 xt_xlate_add(xl, "log");
154 if (strcmp(loginfo->prefix, "") != 0)
155 xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
156
157 if (loginfo->level != LOG_DEFAULT_LEVEL && pname)
158 xt_xlate_add(xl, " level %s", pname);
159 else if (!pname)
160 return 0;
161
162 if ((loginfo->logflags & XT_LOG_MASK) == XT_LOG_MASK) {
163 xt_xlate_add(xl, " flags all");
164 } else {
165 if (loginfo->logflags & (XT_LOG_TCPSEQ | XT_LOG_TCPOPT)) {
166 const char *delim = " ";
167
168 xt_xlate_add(xl, " flags tcp");
169 if (loginfo->logflags & XT_LOG_TCPSEQ) {
170 xt_xlate_add(xl, " sequence");
171 delim = ",";
172 }
173 if (loginfo->logflags & XT_LOG_TCPOPT)
174 xt_xlate_add(xl, "%soptions", delim);
175 }
176 if (loginfo->logflags & XT_LOG_IPOPT)
177 xt_xlate_add(xl, " flags ip options");
178 if (loginfo->logflags & XT_LOG_UID)
179 xt_xlate_add(xl, " flags skuid");
180 if (loginfo->logflags & XT_LOG_MACDECODE)
181 xt_xlate_add(xl, " flags ether");
182 }
183
184 return 1;
185 }
186 static struct xtables_target log_tg_reg = {
187 .name = "LOG",
188 .version = XTABLES_VERSION,
189 .family = NFPROTO_UNSPEC,
190 .size = XT_ALIGN(sizeof(struct xt_log_info)),
191 .userspacesize = XT_ALIGN(sizeof(struct xt_log_info)),
192 .help = LOG_help,
193 .init = LOG_init,
194 .print = LOG_print,
195 .save = LOG_save,
196 .x6_parse = LOG_parse,
197 .x6_options = LOG_opts,
198 .xlate = LOG_xlate,
199 };
200
_init(void)201 void _init(void)
202 {
203 xtables_register_target(&log_tg_reg);
204 }
205