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