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