libipt_LOG.c revision afe6b357db60c7d70379a27360c10a352bf55203
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 <xtables.h> 9#include <linux/netfilter_ipv4/ipt_LOG.h> 10 11#define LOG_DEFAULT_LEVEL LOG_WARNING 12 13#ifndef IPT_LOG_UID /* Old kernel */ 14#define IPT_LOG_UID 0x08 /* Log UID owning local socket */ 15#undef IPT_LOG_MASK 16#define IPT_LOG_MASK 0x0f 17#endif 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\n" 25" --log-tcp-sequence Log TCP sequence numbers.\n\n" 26" --log-tcp-options Log TCP options.\n\n" 27" --log-ip-options Log IP options.\n\n" 28" --log-uid Log UID owning the local socket.\n\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 ipt_log_info *loginfo = (struct ipt_log_info *)t->data; 44 45 loginfo->level = LOG_DEFAULT_LEVEL; 46 47} 48 49struct ipt_log_names { 50 const char *name; 51 unsigned int level; 52}; 53 54static const struct ipt_log_names ipt_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(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 (set++) 81 xtables_error(PARAMETER_PROBLEM, 82 "log-level `%s' ambiguous", 83 level); 84 lev = ipt_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 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#define IPT_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 ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data; 107 108 switch (c) { 109 case '!': 110 if (*flags & IPT_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 |= IPT_LOG_OPT_LEVEL; 120 break; 121 122 case '#': 123 if (*flags & IPT_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 |= IPT_LOG_OPT_PREFIX; 146 break; 147 148 case '1': 149 if (*flags & IPT_LOG_OPT_TCPSEQ) 150 xtables_error(PARAMETER_PROBLEM, 151 "Can't specify --log-tcp-sequence " 152 "twice"); 153 154 loginfo->logflags |= IPT_LOG_TCPSEQ; 155 *flags |= IPT_LOG_OPT_TCPSEQ; 156 break; 157 158 case '2': 159 if (*flags & IPT_LOG_OPT_TCPOPT) 160 xtables_error(PARAMETER_PROBLEM, 161 "Can't specify --log-tcp-options twice"); 162 163 loginfo->logflags |= IPT_LOG_TCPOPT; 164 *flags |= IPT_LOG_OPT_TCPOPT; 165 break; 166 167 case '3': 168 if (*flags & IPT_LOG_OPT_IPOPT) 169 xtables_error(PARAMETER_PROBLEM, 170 "Can't specify --log-ip-options twice"); 171 172 loginfo->logflags |= IPT_LOG_IPOPT; 173 *flags |= IPT_LOG_OPT_IPOPT; 174 break; 175 176 case '4': 177 if (*flags & IPT_LOG_OPT_UID) 178 xtables_error(PARAMETER_PROBLEM, 179 "Can't specify --log-uid twice"); 180 181 loginfo->logflags |= IPT_LOG_UID; 182 *flags |= IPT_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 ipt_log_info *loginfo 196 = (const struct ipt_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(ipt_log_names) / sizeof(struct ipt_log_names); 206 i++) { 207 if (loginfo->level == ipt_log_names[i].level) { 208 printf("level %s ", ipt_log_names[i].name); 209 break; 210 } 211 } 212 if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names)) 213 printf("UNKNOWN level %u ", loginfo->level); 214 if (loginfo->logflags & IPT_LOG_TCPSEQ) 215 printf("tcp-sequence "); 216 if (loginfo->logflags & IPT_LOG_TCPOPT) 217 printf("tcp-options "); 218 if (loginfo->logflags & IPT_LOG_IPOPT) 219 printf("ip-options "); 220 if (loginfo->logflags & IPT_LOG_UID) 221 printf("uid "); 222 if (loginfo->logflags & ~(IPT_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 ipt_log_info *loginfo 233 = (const struct ipt_log_info *)target->data; 234 235 if (strcmp(loginfo->prefix, "") != 0) { 236 printf("--log-prefix "); 237 xtables_save_string(loginfo->prefix); 238 } 239 240 if (loginfo->level != LOG_DEFAULT_LEVEL) 241 printf("--log-level %d ", loginfo->level); 242 243 if (loginfo->logflags & IPT_LOG_TCPSEQ) 244 printf("--log-tcp-sequence "); 245 if (loginfo->logflags & IPT_LOG_TCPOPT) 246 printf("--log-tcp-options "); 247 if (loginfo->logflags & IPT_LOG_IPOPT) 248 printf("--log-ip-options "); 249 if (loginfo->logflags & IPT_LOG_UID) 250 printf("--log-uid "); 251} 252 253static struct xtables_target log_tg_reg = { 254 .name = "LOG", 255 .version = XTABLES_VERSION, 256 .family = NFPROTO_IPV4, 257 .size = XT_ALIGN(sizeof(struct ipt_log_info)), 258 .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)), 259 .help = LOG_help, 260 .init = LOG_init, 261 .parse = LOG_parse, 262 .print = LOG_print, 263 .save = LOG_save, 264 .extra_opts = LOG_opts, 265}; 266 267void _init(void) 268{ 269 xtables_register_target(&log_tg_reg); 270} 271