libip6t_LOG.c revision 0942dd87902f4f7362245b593447790a8f8ef582
1/* Shared library add-on to iptables 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 <ip6tables.h> 9#include <linux/netfilter_ipv6/ip6_tables.h> 10#include <linux/netfilter_ipv6/ip6t_LOG.h> 11 12#define LOG_DEFAULT_LEVEL LOG_WARNING 13 14/* Function which prints out usage message. */ 15static void 16help(void) 17{ 18 printf( 19"LOG v%s options:\n" 20" --log-level level Level of logging (numeric or see syslog.conf)\n" 21" --log-prefix prefix Prefix log messages with this prefix.\n\n" 22" --log-tcp-sequence Log TCP sequence numbers.\n\n" 23" --log-tcp-options Log TCP options.\n\n" 24" --log-ip-options Log IP options.\n\n", 25NETFILTER_VERSION); 26} 27 28static struct option opts[] = { 29 { "log-level", 1, 0, '!' }, 30 { "log-prefix", 1, 0, '#' }, 31 { "log-tcp-sequence", 0, 0, '1' }, 32 { "log-tcp-options", 0, 0, '2' }, 33 { "log-ip-options", 0, 0, '3' }, 34 { 0 } 35}; 36 37/* Initialize the target. */ 38static void 39init(struct ip6t_entry_target *t, unsigned int *nfcache) 40{ 41 struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data; 42 43 loginfo->level = LOG_DEFAULT_LEVEL; 44 45 /* Can't cache this */ 46 *nfcache |= NFC_UNKNOWN; 47} 48 49struct ip6t_log_names { 50 const char *name; 51 unsigned int level; 52}; 53 54static struct ip6t_log_names ip6t_log_names[] 55= { { "alert", LOG_ALERT }, 56 { "crit", LOG_CRIT }, 57 { "debug", LOG_DEBUG }, 58 { "emerg", LOG_EMERG }, 59 { "error", LOG_ERR }, /* DEPRECATED */ 60 { "info", LOG_INFO }, 61 { "notice", LOG_NOTICE }, 62 { "panic", LOG_EMERG }, /* DEPRECATED */ 63 { "warning", 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 (string_to_number(level, 0, 7, &lev) == -1) { 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 exit_error(PARAMETER_PROBLEM, 82 "log-level `%s' ambiguous", 83 level); 84 lev = ip6t_log_names[i].level; 85 } 86 } 87 88 if (!set) 89 exit_error(PARAMETER_PROBLEM, 90 "log-level `%s' unknown", level); 91 } 92 93 return (u_int8_t)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 102/* Function which parses command options; returns true if it 103 ate an option */ 104static int 105parse(int c, char **argv, int invert, unsigned int *flags, 106 const struct ip6t_entry *entry, 107 struct ip6t_entry_target **target) 108{ 109 struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data; 110 111 switch (c) { 112 case '!': 113 if (*flags & IP6T_LOG_OPT_LEVEL) 114 exit_error(PARAMETER_PROBLEM, 115 "Can't specify --log-level twice"); 116 117 if (check_inverse(optarg, &invert)) 118 exit_error(PARAMETER_PROBLEM, 119 "Unexpected `!' after --log-level"); 120 121 loginfo->level = parse_level(optarg); 122 *flags |= IP6T_LOG_OPT_LEVEL; 123 break; 124 125 case '#': 126 if (*flags & IP6T_LOG_OPT_PREFIX) 127 exit_error(PARAMETER_PROBLEM, 128 "Can't specify --log-prefix twice"); 129 130 if (check_inverse(optarg, &invert)) 131 exit_error(PARAMETER_PROBLEM, 132 "Unexpected `!' after --log-prefix"); 133 134 if (strlen(optarg) > sizeof(loginfo->prefix) - 1) 135 exit_error(PARAMETER_PROBLEM, 136 "Maximum prefix length %u for --log-prefix", 137 sizeof(loginfo->prefix) - 1); 138 139 strcpy(loginfo->prefix, optarg); 140 *flags |= IP6T_LOG_OPT_PREFIX; 141 break; 142 143 case '1': 144 if (*flags & IP6T_LOG_OPT_TCPSEQ) 145 exit_error(PARAMETER_PROBLEM, 146 "Can't specify --log-tcp-sequence " 147 "twice"); 148 149 loginfo->logflags |= IP6T_LOG_TCPSEQ; 150 *flags |= IP6T_LOG_OPT_TCPSEQ; 151 break; 152 153 case '2': 154 if (*flags & IP6T_LOG_OPT_TCPOPT) 155 exit_error(PARAMETER_PROBLEM, 156 "Can't specify --log-tcp-options twice"); 157 158 loginfo->logflags |= IP6T_LOG_TCPOPT; 159 *flags |= IP6T_LOG_OPT_TCPOPT; 160 break; 161 162 case '3': 163 if (*flags & IP6T_LOG_OPT_IPOPT) 164 exit_error(PARAMETER_PROBLEM, 165 "Can't specify --log-ip-options twice"); 166 167 loginfo->logflags |= IP6T_LOG_IPOPT; 168 *flags |= IP6T_LOG_OPT_IPOPT; 169 break; 170 171 default: 172 return 0; 173 } 174 175 return 1; 176} 177 178/* Final check; nothing. */ 179static void final_check(unsigned int flags) 180{ 181} 182 183/* Prints out the targinfo. */ 184static void 185print(const struct ip6t_ip6 *ip, 186 const struct ip6t_entry_target *target, 187 int numeric) 188{ 189 const struct ip6t_log_info *loginfo 190 = (const struct ip6t_log_info *)target->data; 191 unsigned int i = 0; 192 193 printf("LOG "); 194 if (numeric) 195 printf("flags %u level %u ", 196 loginfo->logflags, loginfo->level); 197 else { 198 for (i = 0; 199 i < sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names); 200 i++) { 201 if (loginfo->level == ip6t_log_names[i].level) { 202 printf("level %s ", ip6t_log_names[i].name); 203 break; 204 } 205 } 206 if (i == sizeof(ip6t_log_names) / sizeof(struct 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_MASK)) 215 printf("unknown-flags "); 216 } 217 218 if (strcmp(loginfo->prefix, "") != 0) 219 printf("prefix `%s' ", loginfo->prefix); 220} 221 222/* Saves the union ip6t_targinfo in parsable form to stdout. */ 223static void 224save(const struct ip6t_ip6 *ip, const struct ip6t_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 %u ", 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} 242 243static 244struct ip6tables_target log 245= { NULL, 246 "LOG", 247 NETFILTER_VERSION, 248 IP6T_ALIGN(sizeof(struct ip6t_log_info)), 249 IP6T_ALIGN(sizeof(struct ip6t_log_info)), 250 &help, 251 &init, 252 &parse, 253 &final_check, 254 &print, 255 &save, 256 opts 257}; 258 259void _init(void) 260{ 261 register_target6(&log); 262} 263