libipt_LOG.c revision 127647892c7cac85baf8da62ed21232baa60f1c9
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" --log-macdecode Decode MAC addresses and protocol.\n\n"); 30} 31 32static const struct option LOG_opts[] = { 33 { .name = "log-level", .has_arg = 1, .val = '!' }, 34 { .name = "log-prefix", .has_arg = 1, .val = '#' }, 35 { .name = "log-tcp-sequence", .has_arg = 0, .val = '1' }, 36 { .name = "log-tcp-options", .has_arg = 0, .val = '2' }, 37 { .name = "log-ip-options", .has_arg = 0, .val = '3' }, 38 { .name = "log-uid", .has_arg = 0, .val = '4' }, 39 { .name = "log-macdecode", .has_arg = 0, .val = '5' }, 40 { .name = NULL } 41}; 42 43static void LOG_init(struct xt_entry_target *t) 44{ 45 struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data; 46 47 loginfo->level = LOG_DEFAULT_LEVEL; 48 49} 50 51struct ipt_log_names { 52 const char *name; 53 unsigned int level; 54}; 55 56static const struct ipt_log_names ipt_log_names[] 57= { { .name = "alert", .level = LOG_ALERT }, 58 { .name = "crit", .level = LOG_CRIT }, 59 { .name = "debug", .level = LOG_DEBUG }, 60 { .name = "emerg", .level = LOG_EMERG }, 61 { .name = "error", .level = LOG_ERR }, /* DEPRECATED */ 62 { .name = "info", .level = LOG_INFO }, 63 { .name = "notice", .level = LOG_NOTICE }, 64 { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */ 65 { .name = "warning", .level = LOG_WARNING } 66}; 67 68static u_int8_t 69parse_level(const char *level) 70{ 71 unsigned int lev = -1; 72 unsigned int set = 0; 73 74 if (!xtables_strtoui(level, NULL, &lev, 0, 7)) { 75 unsigned int i = 0; 76 77 for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++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 if (!set) 88 xtables_error(PARAMETER_PROBLEM, 89 "log-level `%s' unknown", level); 90 } 91 92 return 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#define IPT_LOG_OPT_UID 0x20 101#define IPT_LOG_OPT_MACDECODE 0x40 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, argv)) 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, argv)) 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 case '5': 186 if (*flags & IPT_LOG_OPT_MACDECODE) 187 xtables_error(PARAMETER_PROBLEM, 188 "Can't specifiy --log-macdecode twice"); 189 190 loginfo->logflags |= IPT_LOG_MACDECODE; 191 *flags |= IPT_LOG_OPT_MACDECODE; 192 break; 193 default: 194 return 0; 195 } 196 197 return 1; 198} 199 200static void LOG_print(const void *ip, const struct xt_entry_target *target, 201 int numeric) 202{ 203 const struct ipt_log_info *loginfo 204 = (const struct ipt_log_info *)target->data; 205 unsigned int i = 0; 206 207 printf("LOG "); 208 if (numeric) 209 printf("flags %u level %u ", 210 loginfo->logflags, loginfo->level); 211 else { 212 for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i) 213 if (loginfo->level == ipt_log_names[i].level) { 214 printf("level %s ", ipt_log_names[i].name); 215 break; 216 } 217 if (i == ARRAY_SIZE(ipt_log_names)) 218 printf("UNKNOWN level %u ", loginfo->level); 219 if (loginfo->logflags & IPT_LOG_TCPSEQ) 220 printf("tcp-sequence "); 221 if (loginfo->logflags & IPT_LOG_TCPOPT) 222 printf("tcp-options "); 223 if (loginfo->logflags & IPT_LOG_IPOPT) 224 printf("ip-options "); 225 if (loginfo->logflags & IPT_LOG_UID) 226 printf("uid "); 227 if (loginfo->logflags & IPT_LOG_MACDECODE) 228 printf("macdecode "); 229 if (loginfo->logflags & ~(IPT_LOG_MASK)) 230 printf("unknown-flags "); 231 } 232 233 if (strcmp(loginfo->prefix, "") != 0) 234 printf("prefix `%s' ", loginfo->prefix); 235} 236 237static void LOG_save(const void *ip, const struct xt_entry_target *target) 238{ 239 const struct ipt_log_info *loginfo 240 = (const struct ipt_log_info *)target->data; 241 242 if (strcmp(loginfo->prefix, "") != 0) { 243 printf("--log-prefix "); 244 xtables_save_string(loginfo->prefix); 245 } 246 247 if (loginfo->level != LOG_DEFAULT_LEVEL) 248 printf("--log-level %d ", loginfo->level); 249 250 if (loginfo->logflags & IPT_LOG_TCPSEQ) 251 printf("--log-tcp-sequence "); 252 if (loginfo->logflags & IPT_LOG_TCPOPT) 253 printf("--log-tcp-options "); 254 if (loginfo->logflags & IPT_LOG_IPOPT) 255 printf("--log-ip-options "); 256 if (loginfo->logflags & IPT_LOG_UID) 257 printf("--log-uid "); 258 if (loginfo->logflags & IPT_LOG_MACDECODE) 259 printf("--log-macdecode "); 260} 261 262static struct xtables_target log_tg_reg = { 263 .name = "LOG", 264 .version = XTABLES_VERSION, 265 .family = NFPROTO_IPV4, 266 .size = XT_ALIGN(sizeof(struct ipt_log_info)), 267 .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)), 268 .help = LOG_help, 269 .init = LOG_init, 270 .parse = LOG_parse, 271 .print = LOG_print, 272 .save = LOG_save, 273 .extra_opts = LOG_opts, 274}; 275 276void _init(void) 277{ 278 xtables_register_target(&log_tg_reg); 279} 280