1 /* Shared library add-on to iptables to add LOG support. */
9 #include <linux/netfilter_ipv6/ip6_tables.h>
10 #include <linux/netfilter_ipv6/ip6t_LOG.h>
12 #ifndef IP6T_LOG_UID /* Old kernel */
13 #define IP6T_LOG_UID 0x08
15 #define IP6T_LOG_MASK 0x0f
18 #ifndef IPT_LOG_MACDECODE /* Old kernel */
19 #define IPT_LOG_MACDECODE 0x20
21 #define IPT_LOG_MASK 0x2f
24 #define LOG_DEFAULT_LEVEL LOG_WARNING
26 /* Function which prints out usage message. */
32 " --log-level level Level of logging (numeric or see syslog.conf)\n"
33 " --log-prefix prefix Prefix log messages with this prefix.\n\n"
34 " --log-tcp-sequence Log TCP sequence numbers.\n\n"
35 " --log-tcp-options Log TCP options.\n\n"
36 " --log-ip-options Log IP options.\n\n"
37 " --log-uid Log UID owning the local socket.\n\n"
38 " --log-macdecode Decode MAC addresses and protocol.\n\n",
42 static struct option opts
[] = {
43 { .name
= "log-level", .has_arg
= 1, .flag
= 0, .val
= '!' },
44 { .name
= "log-prefix", .has_arg
= 1, .flag
= 0, .val
= '#' },
45 { .name
= "log-tcp-sequence", .has_arg
= 0, .flag
= 0, .val
= '1' },
46 { .name
= "log-tcp-options", .has_arg
= 0, .flag
= 0, .val
= '2' },
47 { .name
= "log-ip-options", .has_arg
= 0, .flag
= 0, .val
= '3' },
48 { .name
= "log-uid", .has_arg
= 0, .flag
= 0, .val
= '4' },
49 { .name
= "log-macdecode", .has_arg
= 0, .flag
= 0, .val
= '5' },
53 /* Initialize the target. */
55 init(struct ip6t_entry_target
*t
, unsigned int *nfcache
)
57 struct ip6t_log_info
*loginfo
= (struct ip6t_log_info
*)t
->data
;
59 loginfo
->level
= LOG_DEFAULT_LEVEL
;
63 struct ip6t_log_names
{
68 static struct ip6t_log_names ip6t_log_names
[]
69 = { { .name
= "alert", .level
= LOG_ALERT
},
70 { .name
= "crit", .level
= LOG_CRIT
},
71 { .name
= "debug", .level
= LOG_DEBUG
},
72 { .name
= "emerg", .level
= LOG_EMERG
},
73 { .name
= "error", .level
= LOG_ERR
}, /* DEPRECATED */
74 { .name
= "info", .level
= LOG_INFO
},
75 { .name
= "notice", .level
= LOG_NOTICE
},
76 { .name
= "panic", .level
= LOG_EMERG
}, /* DEPRECATED */
77 { .name
= "warning", .level
= LOG_WARNING
}
81 parse_level(const char *level
)
83 unsigned int lev
= -1;
86 if (string_to_number(level
, 0, 7, &lev
) == -1) {
90 i
< sizeof(ip6t_log_names
) / sizeof(struct ip6t_log_names
);
92 if (strncasecmp(level
, ip6t_log_names
[i
].name
,
93 strlen(level
)) == 0) {
95 exit_error(PARAMETER_PROBLEM
,
96 "log-level `%s' ambiguous",
98 lev
= ip6t_log_names
[i
].level
;
103 exit_error(PARAMETER_PROBLEM
,
104 "log-level `%s' unknown", level
);
107 return (u_int8_t
)lev
;
110 #define IP6T_LOG_OPT_LEVEL 0x01
111 #define IP6T_LOG_OPT_PREFIX 0x02
112 #define IP6T_LOG_OPT_TCPSEQ 0x04
113 #define IP6T_LOG_OPT_TCPOPT 0x08
114 #define IP6T_LOG_OPT_IPOPT 0x10
115 #define IP6T_LOG_OPT_UID 0x20
116 #define IPT_LOG_OPT_MACDECODE 0x40
118 /* Function which parses command options; returns true if it
121 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
122 const struct ip6t_entry
*entry
,
123 struct ip6t_entry_target
**target
)
125 struct ip6t_log_info
*loginfo
= (struct ip6t_log_info
*)(*target
)->data
;
129 if (*flags
& IP6T_LOG_OPT_LEVEL
)
130 exit_error(PARAMETER_PROBLEM
,
131 "Can't specify --log-level twice");
133 if (check_inverse(optarg
, &invert
, NULL
, 0))
134 exit_error(PARAMETER_PROBLEM
,
135 "Unexpected `!' after --log-level");
137 loginfo
->level
= parse_level(optarg
);
138 *flags
|= IP6T_LOG_OPT_LEVEL
;
142 if (*flags
& IP6T_LOG_OPT_PREFIX
)
143 exit_error(PARAMETER_PROBLEM
,
144 "Can't specify --log-prefix twice");
146 if (check_inverse(optarg
, &invert
, NULL
, 0))
147 exit_error(PARAMETER_PROBLEM
,
148 "Unexpected `!' after --log-prefix");
150 if (strlen(optarg
) > sizeof(loginfo
->prefix
) - 1)
151 exit_error(PARAMETER_PROBLEM
,
152 "Maximum prefix length %u for --log-prefix",
153 (unsigned int)sizeof(loginfo
->prefix
) - 1);
155 if (strlen(optarg
) == 0)
156 exit_error(PARAMETER_PROBLEM
,
157 "No prefix specified for --log-prefix");
159 if (strlen(optarg
) != strlen(strtok(optarg
, "\n")))
160 exit_error(PARAMETER_PROBLEM
,
161 "Newlines not allowed in --log-prefix");
163 strcpy(loginfo
->prefix
, optarg
);
164 *flags
|= IP6T_LOG_OPT_PREFIX
;
168 if (*flags
& IP6T_LOG_OPT_TCPSEQ
)
169 exit_error(PARAMETER_PROBLEM
,
170 "Can't specify --log-tcp-sequence "
173 loginfo
->logflags
|= IP6T_LOG_TCPSEQ
;
174 *flags
|= IP6T_LOG_OPT_TCPSEQ
;
178 if (*flags
& IP6T_LOG_OPT_TCPOPT
)
179 exit_error(PARAMETER_PROBLEM
,
180 "Can't specify --log-tcp-options twice");
182 loginfo
->logflags
|= IP6T_LOG_TCPOPT
;
183 *flags
|= IP6T_LOG_OPT_TCPOPT
;
187 if (*flags
& IP6T_LOG_OPT_IPOPT
)
188 exit_error(PARAMETER_PROBLEM
,
189 "Can't specify --log-ip-options twice");
191 loginfo
->logflags
|= IP6T_LOG_IPOPT
;
192 *flags
|= IP6T_LOG_OPT_IPOPT
;
196 if (*flags
& IP6T_LOG_OPT_UID
)
197 exit_error(PARAMETER_PROBLEM
,
198 "Can't specify --log-uid twice");
200 loginfo
->logflags
|= IP6T_LOG_UID
;
201 *flags
|= IP6T_LOG_OPT_UID
;
205 if (*flags
& IPT_LOG_OPT_MACDECODE
)
206 exit_error(PARAMETER_PROBLEM
,
207 "Can't specify --log-macdecode twice");
209 loginfo
->logflags
|= IPT_LOG_MACDECODE
;
210 *flags
|= IPT_LOG_OPT_MACDECODE
;
220 /* Final check; nothing. */
221 static void final_check(unsigned int flags
)
225 /* Prints out the targinfo. */
227 print(const struct ip6t_ip6
*ip
,
228 const struct ip6t_entry_target
*target
,
231 const struct ip6t_log_info
*loginfo
232 = (const struct ip6t_log_info
*)target
->data
;
237 printf("flags %u level %u ",
238 loginfo
->logflags
, loginfo
->level
);
241 i
< sizeof(ip6t_log_names
) / sizeof(struct ip6t_log_names
);
243 if (loginfo
->level
== ip6t_log_names
[i
].level
) {
244 printf("level %s ", ip6t_log_names
[i
].name
);
248 if (i
== sizeof(ip6t_log_names
) / sizeof(struct ip6t_log_names
))
249 printf("UNKNOWN level %u ", loginfo
->level
);
250 if (loginfo
->logflags
& IP6T_LOG_TCPSEQ
)
251 printf("tcp-sequence ");
252 if (loginfo
->logflags
& IP6T_LOG_TCPOPT
)
253 printf("tcp-options ");
254 if (loginfo
->logflags
& IP6T_LOG_IPOPT
)
255 printf("ip-options ");
256 if (loginfo
->logflags
& IP6T_LOG_UID
)
258 if (loginfo
->logflags
& IPT_LOG_MACDECODE
)
259 printf("macdecode ");
260 if (loginfo
->logflags
& ~(IP6T_LOG_MASK
))
261 printf("unknown-flags ");
264 if (strcmp(loginfo
->prefix
, "") != 0)
265 printf("prefix `%s' ", loginfo
->prefix
);
268 /* Saves the union ip6t_targinfo in parsable form to stdout. */
270 save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_target
*target
)
273 const struct ip6t_log_info
*loginfo
274 = (const struct ip6t_log_info
*)target
->data
;
276 if (strcmp(loginfo
->prefix
, "") != 0)
277 printf("--log-prefix \"%s\" ", loginfo
->prefix
);
279 if (loginfo
->level
!= LOG_DEFAULT_LEVEL
)
280 printf("--log-level %d ", loginfo
->level
);
282 if (loginfo
->logflags
& IP6T_LOG_TCPSEQ
)
283 printf("--log-tcp-sequence ");
284 if (loginfo
->logflags
& IP6T_LOG_TCPOPT
)
285 printf("--log-tcp-options ");
286 if (loginfo
->logflags
& IP6T_LOG_IPOPT
)
287 printf("--log-ip-options ");
288 if (loginfo
->logflags
& IP6T_LOG_UID
)
289 printf("--log-uid ");
290 if (loginfo
->logflags
& IPT_LOG_MACDECODE
)
291 printf("--log-macdecode ");
296 struct ip6tables_target log
299 .version
= IPTABLES_VERSION
,
300 .size
= IP6T_ALIGN(sizeof(struct ip6t_log_info
)),
301 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_log_info
)),
305 .final_check
= &final_check
,
313 register_target6(&log
);