1 #include <stdio.h> 2 #include <string.h> 3 #include <syslog.h> 4 #include <xtables.h> 5 #include <linux/netfilter_ipv4/ipt_LOG.h> 6 7 #define LOG_DEFAULT_LEVEL LOG_WARNING 8 9 #ifndef IPT_LOG_UID /* Old kernel */ 10 #define IPT_LOG_UID 0x08 /* Log UID owning local socket */ 11 #undef IPT_LOG_MASK 12 #define IPT_LOG_MASK 0x0f 13 #endif 14 15 enum { 16 O_LOG_LEVEL = 0, 17 O_LOG_PREFIX, 18 O_LOG_TCPSEQ, 19 O_LOG_TCPOPTS, 20 O_LOG_IPOPTS, 21 O_LOG_UID, 22 O_LOG_MAC, 23 }; 24 25 static void LOG_help(void) 26 { 27 printf( 28 "LOG target options:\n" 29 " --log-level level Level of logging (numeric or see syslog.conf)\n" 30 " --log-prefix prefix Prefix log messages with this prefix.\n\n" 31 " --log-tcp-sequence Log TCP sequence numbers.\n\n" 32 " --log-tcp-options Log TCP options.\n\n" 33 " --log-ip-options Log IP options.\n\n" 34 " --log-uid Log UID owning the local socket.\n\n" 35 " --log-macdecode Decode MAC addresses and protocol.\n\n"); 36 } 37 38 #define s struct ipt_log_info 39 static const struct xt_option_entry LOG_opts[] = { 40 {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL, 41 .flags = XTOPT_PUT, XTOPT_POINTER(s, level)}, 42 {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING, 43 .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1}, 44 {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE}, 45 {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE}, 46 {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE}, 47 {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE}, 48 {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE}, 49 XTOPT_TABLEEND, 50 }; 51 #undef s 52 53 static void LOG_init(struct xt_entry_target *t) 54 { 55 struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data; 56 57 loginfo->level = LOG_DEFAULT_LEVEL; 58 59 } 60 61 struct ipt_log_names { 62 const char *name; 63 unsigned int level; 64 }; 65 66 static const struct ipt_log_names ipt_log_names[] 67 = { { .name = "alert", .level = LOG_ALERT }, 68 { .name = "crit", .level = LOG_CRIT }, 69 { .name = "debug", .level = LOG_DEBUG }, 70 { .name = "emerg", .level = LOG_EMERG }, 71 { .name = "error", .level = LOG_ERR }, /* DEPRECATED */ 72 { .name = "info", .level = LOG_INFO }, 73 { .name = "notice", .level = LOG_NOTICE }, 74 { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */ 75 { .name = "warning", .level = LOG_WARNING } 76 }; 77 78 static void LOG_parse(struct xt_option_call *cb) 79 { 80 struct ipt_log_info *info = cb->data; 81 82 xtables_option_parse(cb); 83 switch (cb->entry->id) { 84 case O_LOG_PREFIX: 85 if (strchr(cb->arg, '\n') != NULL) 86 xtables_error(PARAMETER_PROBLEM, 87 "Newlines not allowed in --log-prefix"); 88 break; 89 case O_LOG_TCPSEQ: 90 info->logflags = IPT_LOG_TCPSEQ; 91 break; 92 case O_LOG_TCPOPTS: 93 info->logflags = IPT_LOG_TCPOPT; 94 break; 95 case O_LOG_IPOPTS: 96 info->logflags = IPT_LOG_IPOPT; 97 break; 98 case O_LOG_UID: 99 info->logflags = IPT_LOG_UID; 100 break; 101 case O_LOG_MAC: 102 info->logflags = IPT_LOG_MACDECODE; 103 break; 104 } 105 } 106 107 static void LOG_print(const void *ip, const struct xt_entry_target *target, 108 int numeric) 109 { 110 const struct ipt_log_info *loginfo 111 = (const struct ipt_log_info *)target->data; 112 unsigned int i = 0; 113 114 printf(" LOG"); 115 if (numeric) 116 printf(" flags %u level %u", 117 loginfo->logflags, loginfo->level); 118 else { 119 for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i) 120 if (loginfo->level == ipt_log_names[i].level) { 121 printf(" level %s", ipt_log_names[i].name); 122 break; 123 } 124 if (i == ARRAY_SIZE(ipt_log_names)) 125 printf(" UNKNOWN level %u", loginfo->level); 126 if (loginfo->logflags & IPT_LOG_TCPSEQ) 127 printf(" tcp-sequence"); 128 if (loginfo->logflags & IPT_LOG_TCPOPT) 129 printf(" tcp-options"); 130 if (loginfo->logflags & IPT_LOG_IPOPT) 131 printf(" ip-options"); 132 if (loginfo->logflags & IPT_LOG_UID) 133 printf(" uid"); 134 if (loginfo->logflags & IPT_LOG_MACDECODE) 135 printf(" macdecode"); 136 if (loginfo->logflags & ~(IPT_LOG_MASK)) 137 printf(" unknown-flags"); 138 } 139 140 if (strcmp(loginfo->prefix, "") != 0) 141 printf(" prefix \"%s\"", loginfo->prefix); 142 } 143 144 static void LOG_save(const void *ip, const struct xt_entry_target *target) 145 { 146 const struct ipt_log_info *loginfo 147 = (const struct ipt_log_info *)target->data; 148 149 if (strcmp(loginfo->prefix, "") != 0) { 150 printf(" --log-prefix"); 151 xtables_save_string(loginfo->prefix); 152 } 153 154 if (loginfo->level != LOG_DEFAULT_LEVEL) 155 printf(" --log-level %d", loginfo->level); 156 157 if (loginfo->logflags & IPT_LOG_TCPSEQ) 158 printf(" --log-tcp-sequence"); 159 if (loginfo->logflags & IPT_LOG_TCPOPT) 160 printf(" --log-tcp-options"); 161 if (loginfo->logflags & IPT_LOG_IPOPT) 162 printf(" --log-ip-options"); 163 if (loginfo->logflags & IPT_LOG_UID) 164 printf(" --log-uid"); 165 if (loginfo->logflags & IPT_LOG_MACDECODE) 166 printf(" --log-macdecode"); 167 } 168 169 static struct xtables_target log_tg_reg = { 170 .name = "LOG", 171 .version = XTABLES_VERSION, 172 .family = NFPROTO_IPV4, 173 .size = XT_ALIGN(sizeof(struct ipt_log_info)), 174 .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)), 175 .help = LOG_help, 176 .init = LOG_init, 177 .print = LOG_print, 178 .save = LOG_save, 179 .x6_parse = LOG_parse, 180 .x6_options = LOG_opts, 181 }; 182 183 void _init(void) 184 { 185 xtables_register_target(&log_tg_reg); 186 } 187