libipt_LOG.c revision edf14cf4b5edb148d7473f067d95e7bd1316900b
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 <iptables.h> 9#include <linux/netfilter_ipv4/ip_tables.h> 10#include <linux/netfilter_ipv4/ipt_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 ipt_entry_target *t, unsigned int *nfcache) 40{ 41 struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data; 42 43 loginfo->level = LOG_DEFAULT_LEVEL; 44 45 /* Can't cache this */ 46 *nfcache |= NFC_UNKNOWN; 47} 48 49struct ipt_log_names { 50 const char *name; 51 unsigned int level; 52}; 53 54static struct ipt_log_names ipt_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 int lev; 70 71 lev = string_to_number(level, 0, 7); 72 if (lev == -1) { 73 unsigned int i = 0; 74 75 for (i = 0; 76 i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names); 77 i++) { 78 if (strncasecmp(level, ipt_log_names[i].name, 79 strlen(level)) == 0) { 80 if (lev != -1) 81 exit_error(PARAMETER_PROBLEM, 82 "log-level `%s' ambiguous", 83 level); 84 lev = ipt_log_names[i].level; 85 } 86 } 87 88 if (lev == -1) 89 exit_error(PARAMETER_PROBLEM, 90 "log-level `%s' unknown", level); 91 } 92 93 return (u_int8_t)lev; 94} 95 96#define IPT_LOG_OPT_LEVEL 0x01 97#define IPT_LOG_OPT_PREFIX 0x02 98#define IPT_LOG_OPT_TCPSEQ 0x04 99#define IPT_LOG_OPT_TCPOPT 0x08 100#define IPT_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 ipt_entry *entry, 107 struct ipt_entry_target **target) 108{ 109 struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data; 110 111 switch (c) { 112 case '!': 113 if (*flags & IPT_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 |= IPT_LOG_OPT_LEVEL; 123 break; 124 125 case '#': 126 if (*flags & IPT_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 |= IPT_LOG_OPT_PREFIX; 141 break; 142 143 case '1': 144 if (*flags & IPT_LOG_OPT_TCPSEQ) 145 exit_error(PARAMETER_PROBLEM, 146 "Can't specify --log-tcp-sequence " 147 "twice"); 148 149 loginfo->logflags |= IPT_LOG_TCPSEQ; 150 *flags |= IPT_LOG_OPT_TCPSEQ; 151 break; 152 153 case '2': 154 if (*flags & IPT_LOG_OPT_TCPOPT) 155 exit_error(PARAMETER_PROBLEM, 156 "Can't specify --log-tcp-options twice"); 157 158 loginfo->logflags |= IPT_LOG_TCPOPT; 159 *flags |= IPT_LOG_OPT_TCPOPT; 160 break; 161 162 case '3': 163 if (*flags & IPT_LOG_OPT_IPOPT) 164 exit_error(PARAMETER_PROBLEM, 165 "Can't specify --log-ip-options twice"); 166 167 loginfo->logflags |= IPT_LOG_IPOPT; 168 *flags |= IPT_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 ipt_ip *ip, 186 const struct ipt_entry_target *target, 187 int numeric) 188{ 189 const struct ipt_log_info *loginfo 190 = (const struct ipt_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(ipt_log_names) / sizeof(struct ipt_log_names); 200 i++) { 201 if (loginfo->level == ipt_log_names[i].level) { 202 printf("level %s ", ipt_log_names[i].name); 203 break; 204 } 205 } 206 if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names)) 207 printf("UNKNOWN level %u ", loginfo->level); 208 if (loginfo->logflags & IPT_LOG_TCPSEQ) 209 printf("tcp-sequence "); 210 if (loginfo->logflags & IPT_LOG_TCPOPT) 211 printf("tcp-options "); 212 if (loginfo->logflags & IPT_LOG_IPOPT) 213 printf("ip-options "); 214 if (loginfo->logflags & ~(IPT_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 ipt_targinfo in parsable form to stdout. */ 223static void 224save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 225{ 226 const struct ipt_log_info *loginfo 227 = (const struct ipt_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 & IPT_LOG_TCPSEQ) 236 printf("--log-tcp-sequence "); 237 if (loginfo->logflags & IPT_LOG_TCPOPT) 238 printf("--log-tcp-options "); 239 if (loginfo->logflags & IPT_LOG_IPOPT) 240 printf("--log-ip-options "); 241} 242 243struct iptables_target log 244= { NULL, 245 "LOG", 246 NETFILTER_VERSION, 247 sizeof(struct ipt_log_info), 248 sizeof(struct ipt_log_info), 249 &help, 250 &init, 251 &parse, 252 &final_check, 253 &print, 254 &save, 255 opts 256}; 257 258void _init(void) 259{ 260 register_target(&log); 261} 262