libip6t_LOG.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
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 u_int8_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 default: 196 return 0; 197 } 198 199 return 1; 200} 201 202static void LOG_print(const void *ip, const struct xt_entry_target *target, 203 int numeric) 204{ 205 const struct ip6t_log_info *loginfo 206 = (const struct ip6t_log_info *)target->data; 207 unsigned int i = 0; 208 209 printf("LOG "); 210 if (numeric) 211 printf("flags %u level %u ", 212 loginfo->logflags, loginfo->level); 213 else { 214 for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i) 215 if (loginfo->level == ip6t_log_names[i].level) { 216 printf("level %s ", ip6t_log_names[i].name); 217 break; 218 } 219 if (i == ARRAY_SIZE(ip6t_log_names)) 220 printf("UNKNOWN level %u ", loginfo->level); 221 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 222 printf("tcp-sequence "); 223 if (loginfo->logflags & IP6T_LOG_TCPOPT) 224 printf("tcp-options "); 225 if (loginfo->logflags & IP6T_LOG_IPOPT) 226 printf("ip-options "); 227 if (loginfo->logflags & IP6T_LOG_UID) 228 printf("uid "); 229 if (loginfo->logflags & IP6T_LOG_MACDECODE) 230 printf("macdecode "); 231 if (loginfo->logflags & ~(IP6T_LOG_MASK)) 232 printf("unknown-flags "); 233 } 234 235 if (strcmp(loginfo->prefix, "") != 0) 236 printf("prefix `%s' ", loginfo->prefix); 237} 238 239static void LOG_save(const void *ip, const struct xt_entry_target *target) 240{ 241 const struct ip6t_log_info *loginfo 242 = (const struct ip6t_log_info *)target->data; 243 244 if (strcmp(loginfo->prefix, "") != 0) 245 printf("--log-prefix \"%s\" ", loginfo->prefix); 246 247 if (loginfo->level != LOG_DEFAULT_LEVEL) 248 printf("--log-level %d ", loginfo->level); 249 250 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 251 printf("--log-tcp-sequence "); 252 if (loginfo->logflags & IP6T_LOG_TCPOPT) 253 printf("--log-tcp-options "); 254 if (loginfo->logflags & IP6T_LOG_IPOPT) 255 printf("--log-ip-options "); 256 if (loginfo->logflags & IP6T_LOG_UID) 257 printf("--log-uid "); 258 if (loginfo->logflags & IP6T_LOG_MACDECODE) 259 printf("--log-macdecode "); 260} 261 262static struct xtables_target log_tg6_reg = { 263 .name = "LOG", 264 .version = XTABLES_VERSION, 265 .family = NFPROTO_IPV6, 266 .size = XT_ALIGN(sizeof(struct ip6t_log_info)), 267 .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)), 268 .help = LOG_help, 269 .init = LOG_init, 270 .parse = LOG_parse, 271 .print = LOG_print, 272 .save = LOG_save, 273 .extra_opts = LOG_opts, 274}; 275 276void _init(void) 277{ 278 xtables_register_target(&log_tg6_reg); 279} 280