libip6t_LOG.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
1/* Shared library add-on to ip6tables to add LOG support. */ 2#include <stdbool.h> 3#include <stdio.h> 4#include <netdb.h> 5#include <string.h> 6#include <stdlib.h> 7#include <syslog.h> 8#include <getopt.h> 9#include <xtables.h> 10#include <linux/netfilter_ipv6/ip6t_LOG.h> 11 12#ifndef IP6T_LOG_UID /* Old kernel */ 13#define IP6T_LOG_UID 0x08 14#undef IP6T_LOG_MASK 15#define IP6T_LOG_MASK 0x0f 16#endif 17 18#define LOG_DEFAULT_LEVEL LOG_WARNING 19 20static void LOG_help(void) 21{ 22 printf( 23"LOG target options:\n" 24" --log-level level Level of logging (numeric or see syslog.conf)\n" 25" --log-prefix prefix Prefix log messages with this prefix.\n" 26" --log-tcp-sequence Log TCP sequence numbers.\n" 27" --log-tcp-options Log TCP options.\n" 28" --log-ip-options Log IP options.\n" 29" --log-uid Log UID owning the local socket.\n" 30" --log-macdecode Decode MAC addresses and protocol.\n"); 31} 32 33static const struct option LOG_opts[] = { 34 {.name = "log-level", .has_arg = true, .val = '!'}, 35 {.name = "log-prefix", .has_arg = true, .val = '#'}, 36 {.name = "log-tcp-sequence", .has_arg = false, .val = '1'}, 37 {.name = "log-tcp-options", .has_arg = false, .val = '2'}, 38 {.name = "log-ip-options", .has_arg = false, .val = '3'}, 39 {.name = "log-uid", .has_arg = false, .val = '4'}, 40 {.name = "log-macdecode", .has_arg = false, .val = '5'}, 41 XT_GETOPT_TABLEEND, 42}; 43 44static void LOG_init(struct xt_entry_target *t) 45{ 46 struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data; 47 48 loginfo->level = LOG_DEFAULT_LEVEL; 49 50} 51 52struct ip6t_log_names { 53 const char *name; 54 unsigned int level; 55}; 56 57static const struct ip6t_log_names ip6t_log_names[] 58= { { .name = "alert", .level = LOG_ALERT }, 59 { .name = "crit", .level = LOG_CRIT }, 60 { .name = "debug", .level = LOG_DEBUG }, 61 { .name = "emerg", .level = LOG_EMERG }, 62 { .name = "error", .level = LOG_ERR }, /* DEPRECATED */ 63 { .name = "info", .level = LOG_INFO }, 64 { .name = "notice", .level = LOG_NOTICE }, 65 { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */ 66 { .name = "warning", .level = LOG_WARNING } 67}; 68 69static uint8_t 70parse_level(const char *level) 71{ 72 unsigned int lev = -1; 73 unsigned int set = 0; 74 75 if (!xtables_strtoui(level, NULL, &lev, 0, 7)) { 76 unsigned int i = 0; 77 78 for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i) 79 if (strncasecmp(level, ip6t_log_names[i].name, 80 strlen(level)) == 0) { 81 if (set++) 82 xtables_error(PARAMETER_PROBLEM, 83 "log-level `%s' ambiguous", 84 level); 85 lev = ip6t_log_names[i].level; 86 } 87 88 if (!set) 89 xtables_error(PARAMETER_PROBLEM, 90 "log-level `%s' unknown", level); 91 } 92 93 return lev; 94} 95 96#define IP6T_LOG_OPT_LEVEL 0x01 97#define IP6T_LOG_OPT_PREFIX 0x02 98#define IP6T_LOG_OPT_TCPSEQ 0x04 99#define IP6T_LOG_OPT_TCPOPT 0x08 100#define IP6T_LOG_OPT_IPOPT 0x10 101#define IP6T_LOG_OPT_UID 0x20 102#define IP6T_LOG_OPT_MACDECODE 0x40 103 104static int LOG_parse(int c, char **argv, int invert, unsigned int *flags, 105 const void *entry, struct xt_entry_target **target) 106{ 107 struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data; 108 109 switch (c) { 110 case '!': 111 if (*flags & IP6T_LOG_OPT_LEVEL) 112 xtables_error(PARAMETER_PROBLEM, 113 "Can't specify --log-level twice"); 114 115 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) 116 xtables_error(PARAMETER_PROBLEM, 117 "Unexpected `!' after --log-level"); 118 119 loginfo->level = parse_level(optarg); 120 *flags |= IP6T_LOG_OPT_LEVEL; 121 break; 122 123 case '#': 124 if (*flags & IP6T_LOG_OPT_PREFIX) 125 xtables_error(PARAMETER_PROBLEM, 126 "Can't specify --log-prefix twice"); 127 128 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) 129 xtables_error(PARAMETER_PROBLEM, 130 "Unexpected `!' after --log-prefix"); 131 132 if (strlen(optarg) > sizeof(loginfo->prefix) - 1) 133 xtables_error(PARAMETER_PROBLEM, 134 "Maximum prefix length %u for --log-prefix", 135 (unsigned int)sizeof(loginfo->prefix) - 1); 136 137 if (strlen(optarg) == 0) 138 xtables_error(PARAMETER_PROBLEM, 139 "No prefix specified for --log-prefix"); 140 141 if (strlen(optarg) != strlen(strtok(optarg, "\n"))) 142 xtables_error(PARAMETER_PROBLEM, 143 "Newlines not allowed in --log-prefix"); 144 145 strcpy(loginfo->prefix, optarg); 146 *flags |= IP6T_LOG_OPT_PREFIX; 147 break; 148 149 case '1': 150 if (*flags & IP6T_LOG_OPT_TCPSEQ) 151 xtables_error(PARAMETER_PROBLEM, 152 "Can't specify --log-tcp-sequence " 153 "twice"); 154 155 loginfo->logflags |= IP6T_LOG_TCPSEQ; 156 *flags |= IP6T_LOG_OPT_TCPSEQ; 157 break; 158 159 case '2': 160 if (*flags & IP6T_LOG_OPT_TCPOPT) 161 xtables_error(PARAMETER_PROBLEM, 162 "Can't specify --log-tcp-options twice"); 163 164 loginfo->logflags |= IP6T_LOG_TCPOPT; 165 *flags |= IP6T_LOG_OPT_TCPOPT; 166 break; 167 168 case '3': 169 if (*flags & IP6T_LOG_OPT_IPOPT) 170 xtables_error(PARAMETER_PROBLEM, 171 "Can't specify --log-ip-options twice"); 172 173 loginfo->logflags |= IP6T_LOG_IPOPT; 174 *flags |= IP6T_LOG_OPT_IPOPT; 175 break; 176 177 case '4': 178 if (*flags & IP6T_LOG_OPT_UID) 179 xtables_error(PARAMETER_PROBLEM, 180 "Can't specify --log-uid twice"); 181 182 loginfo->logflags |= IP6T_LOG_UID; 183 *flags |= IP6T_LOG_OPT_UID; 184 break; 185 186 case '5': 187 if (*flags & IP6T_LOG_OPT_MACDECODE) 188 xtables_error(PARAMETER_PROBLEM, 189 "Can't specify --log-macdecode twice"); 190 191 loginfo->logflags |= IP6T_LOG_MACDECODE; 192 *flags |= IP6T_LOG_OPT_MACDECODE; 193 break; 194 } 195 196 return 1; 197} 198 199static void LOG_print(const void *ip, const struct xt_entry_target *target, 200 int numeric) 201{ 202 const struct ip6t_log_info *loginfo 203 = (const struct ip6t_log_info *)target->data; 204 unsigned int i = 0; 205 206 printf(" LOG"); 207 if (numeric) 208 printf(" flags %u level %u", 209 loginfo->logflags, loginfo->level); 210 else { 211 for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i) 212 if (loginfo->level == ip6t_log_names[i].level) { 213 printf(" level %s", ip6t_log_names[i].name); 214 break; 215 } 216 if (i == ARRAY_SIZE(ip6t_log_names)) 217 printf(" UNKNOWN level %u", loginfo->level); 218 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 219 printf(" tcp-sequence"); 220 if (loginfo->logflags & IP6T_LOG_TCPOPT) 221 printf(" tcp-options"); 222 if (loginfo->logflags & IP6T_LOG_IPOPT) 223 printf(" ip-options"); 224 if (loginfo->logflags & IP6T_LOG_UID) 225 printf(" uid"); 226 if (loginfo->logflags & IP6T_LOG_MACDECODE) 227 printf(" macdecode"); 228 if (loginfo->logflags & ~(IP6T_LOG_MASK)) 229 printf(" unknown-flags"); 230 } 231 232 if (strcmp(loginfo->prefix, "") != 0) 233 printf(" prefix \"%s\"", loginfo->prefix); 234} 235 236static void LOG_save(const void *ip, const struct xt_entry_target *target) 237{ 238 const struct ip6t_log_info *loginfo 239 = (const struct ip6t_log_info *)target->data; 240 241 if (strcmp(loginfo->prefix, "") != 0) 242 printf(" --log-prefix \"%s\"", loginfo->prefix); 243 244 if (loginfo->level != LOG_DEFAULT_LEVEL) 245 printf(" --log-level %d", loginfo->level); 246 247 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 248 printf(" --log-tcp-sequence"); 249 if (loginfo->logflags & IP6T_LOG_TCPOPT) 250 printf(" --log-tcp-options"); 251 if (loginfo->logflags & IP6T_LOG_IPOPT) 252 printf(" --log-ip-options"); 253 if (loginfo->logflags & IP6T_LOG_UID) 254 printf(" --log-uid"); 255 if (loginfo->logflags & IP6T_LOG_MACDECODE) 256 printf(" --log-macdecode"); 257} 258 259static struct xtables_target log_tg6_reg = { 260 .name = "LOG", 261 .version = XTABLES_VERSION, 262 .family = NFPROTO_IPV6, 263 .size = XT_ALIGN(sizeof(struct ip6t_log_info)), 264 .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)), 265 .help = LOG_help, 266 .init = LOG_init, 267 .parse = LOG_parse, 268 .print = LOG_print, 269 .save = LOG_save, 270 .extra_opts = LOG_opts, 271}; 272 273void _init(void) 274{ 275 xtables_register_target(&log_tg6_reg); 276} 277