libipt_LOG.c revision 459357fa4339716810009fea41209ea47460ae2f
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 unsigned int lev = -1; 70 71 if (string_to_number(level, 0, 7, &lev) == -1) { 72 unsigned int i = 0; 73 74 for (i = 0; 75 i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names); 76 i++) { 77 if (strncasecmp(level, ipt_log_names[i].name, 78 strlen(level)) == 0) { 79 if (lev != -1) 80 exit_error(PARAMETER_PROBLEM, 81 "log-level `%s' ambiguous", 82 level); 83 lev = ipt_log_names[i].level; 84 } 85 } 86 87 if (lev == -1) 88 exit_error(PARAMETER_PROBLEM, 89 "log-level `%s' unknown", level); 90 } 91 92 return (u_int8_t)lev; 93} 94 95#define IPT_LOG_OPT_LEVEL 0x01 96#define IPT_LOG_OPT_PREFIX 0x02 97#define IPT_LOG_OPT_TCPSEQ 0x04 98#define IPT_LOG_OPT_TCPOPT 0x08 99#define IPT_LOG_OPT_IPOPT 0x10 100 101/* Function which parses command options; returns true if it 102 ate an option */ 103static int 104parse(int c, char **argv, int invert, unsigned int *flags, 105 const struct ipt_entry *entry, 106 struct ipt_entry_target **target) 107{ 108 struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data; 109 110 switch (c) { 111 case '!': 112 if (*flags & IPT_LOG_OPT_LEVEL) 113 exit_error(PARAMETER_PROBLEM, 114 "Can't specify --log-level twice"); 115 116 if (check_inverse(optarg, &invert)) 117 exit_error(PARAMETER_PROBLEM, 118 "Unexpected `!' after --log-level"); 119 120 loginfo->level = parse_level(optarg); 121 *flags |= IPT_LOG_OPT_LEVEL; 122 break; 123 124 case '#': 125 if (*flags & IPT_LOG_OPT_PREFIX) 126 exit_error(PARAMETER_PROBLEM, 127 "Can't specify --log-prefix twice"); 128 129 if (check_inverse(optarg, &invert)) 130 exit_error(PARAMETER_PROBLEM, 131 "Unexpected `!' after --log-prefix"); 132 133 if (strlen(optarg) > sizeof(loginfo->prefix) - 1) 134 exit_error(PARAMETER_PROBLEM, 135 "Maximum prefix length %u for --log-prefix", 136 sizeof(loginfo->prefix) - 1); 137 138 strcpy(loginfo->prefix, optarg); 139 *flags |= IPT_LOG_OPT_PREFIX; 140 break; 141 142 case '1': 143 if (*flags & IPT_LOG_OPT_TCPSEQ) 144 exit_error(PARAMETER_PROBLEM, 145 "Can't specify --log-tcp-sequence " 146 "twice"); 147 148 loginfo->logflags |= IPT_LOG_TCPSEQ; 149 *flags |= IPT_LOG_OPT_TCPSEQ; 150 break; 151 152 case '2': 153 if (*flags & IPT_LOG_OPT_TCPOPT) 154 exit_error(PARAMETER_PROBLEM, 155 "Can't specify --log-tcp-options twice"); 156 157 loginfo->logflags |= IPT_LOG_TCPOPT; 158 *flags |= IPT_LOG_OPT_TCPOPT; 159 break; 160 161 case '3': 162 if (*flags & IPT_LOG_OPT_IPOPT) 163 exit_error(PARAMETER_PROBLEM, 164 "Can't specify --log-ip-options twice"); 165 166 loginfo->logflags |= IPT_LOG_IPOPT; 167 *flags |= IPT_LOG_OPT_IPOPT; 168 break; 169 170 default: 171 return 0; 172 } 173 174 return 1; 175} 176 177/* Final check; nothing. */ 178static void final_check(unsigned int flags) 179{ 180} 181 182/* Prints out the targinfo. */ 183static void 184print(const struct ipt_ip *ip, 185 const struct ipt_entry_target *target, 186 int numeric) 187{ 188 const struct ipt_log_info *loginfo 189 = (const struct ipt_log_info *)target->data; 190 unsigned int i = 0; 191 192 printf("LOG "); 193 if (numeric) 194 printf("flags %u level %u ", 195 loginfo->logflags, loginfo->level); 196 else { 197 for (i = 0; 198 i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names); 199 i++) { 200 if (loginfo->level == ipt_log_names[i].level) { 201 printf("level %s ", ipt_log_names[i].name); 202 break; 203 } 204 } 205 if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names)) 206 printf("UNKNOWN level %u ", loginfo->level); 207 if (loginfo->logflags & IPT_LOG_TCPSEQ) 208 printf("tcp-sequence "); 209 if (loginfo->logflags & IPT_LOG_TCPOPT) 210 printf("tcp-options "); 211 if (loginfo->logflags & IPT_LOG_IPOPT) 212 printf("ip-options "); 213 if (loginfo->logflags & ~(IPT_LOG_MASK)) 214 printf("unknown-flags "); 215 } 216 217 if (strcmp(loginfo->prefix, "") != 0) 218 printf("prefix `%s' ", loginfo->prefix); 219} 220 221/* Saves the union ipt_targinfo in parsable form to stdout. */ 222static void 223save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 224{ 225 const struct ipt_log_info *loginfo 226 = (const struct ipt_log_info *)target->data; 227 228 if (strcmp(loginfo->prefix, "") != 0) 229 printf("--log-prefix \"%s\" ", loginfo->prefix); 230 231 if (loginfo->level != LOG_DEFAULT_LEVEL) 232 printf("--log-level %u ", loginfo->level); 233 234 if (loginfo->logflags & IPT_LOG_TCPSEQ) 235 printf("--log-tcp-sequence "); 236 if (loginfo->logflags & IPT_LOG_TCPOPT) 237 printf("--log-tcp-options "); 238 if (loginfo->logflags & IPT_LOG_IPOPT) 239 printf("--log-ip-options "); 240} 241 242static 243struct iptables_target log 244= { NULL, 245 "LOG", 246 NETFILTER_VERSION, 247 IPT_ALIGN(sizeof(struct ipt_log_info)), 248 IPT_ALIGN(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