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