1 #include <stdio.h> 2 #include <string.h> 3 #include <syslog.h> 4 #include <xtables.h> 5 #include <linux/netfilter_ipv6/ip6t_LOG.h> 6 7 #ifndef IP6T_LOG_UID /* Old kernel */ 8 #define IP6T_LOG_UID 0x08 9 #undef IP6T_LOG_MASK 10 #define IP6T_LOG_MASK 0x0f 11 #endif 12 13 #define LOG_DEFAULT_LEVEL LOG_WARNING 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" 31 " --log-tcp-sequence Log TCP sequence numbers.\n" 32 " --log-tcp-options Log TCP options.\n" 33 " --log-ip-options Log IP options.\n" 34 " --log-uid Log UID owning the local socket.\n" 35 " --log-macdecode Decode MAC addresses and protocol.\n"); 36 } 37 38 #define s struct ip6t_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 ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data; 56 57 loginfo->level = LOG_DEFAULT_LEVEL; 58 59 } 60 61 struct ip6t_log_names { 62 const char *name; 63 unsigned int level; 64 }; 65 66 struct ip6t_log_xlate { 67 const char *name; 68 unsigned int level; 69 }; 70 71 static const struct ip6t_log_names ip6t_log_names[] 72 = { { .name = "alert", .level = LOG_ALERT }, 73 { .name = "crit", .level = LOG_CRIT }, 74 { .name = "debug", .level = LOG_DEBUG }, 75 { .name = "emerg", .level = LOG_EMERG }, 76 { .name = "error", .level = LOG_ERR }, /* DEPRECATED */ 77 { .name = "info", .level = LOG_INFO }, 78 { .name = "notice", .level = LOG_NOTICE }, 79 { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */ 80 { .name = "warning", .level = LOG_WARNING } 81 }; 82 83 static void LOG_parse(struct xt_option_call *cb) 84 { 85 struct ip6t_log_info *info = cb->data; 86 87 xtables_option_parse(cb); 88 switch (cb->entry->id) { 89 case O_LOG_PREFIX: 90 if (strchr(cb->arg, '\n') != NULL) 91 xtables_error(PARAMETER_PROBLEM, 92 "Newlines not allowed in --log-prefix"); 93 break; 94 case O_LOG_TCPSEQ: 95 info->logflags |= IP6T_LOG_TCPSEQ; 96 break; 97 case O_LOG_TCPOPTS: 98 info->logflags |= IP6T_LOG_TCPOPT; 99 break; 100 case O_LOG_IPOPTS: 101 info->logflags |= IP6T_LOG_IPOPT; 102 break; 103 case O_LOG_UID: 104 info->logflags |= IP6T_LOG_UID; 105 break; 106 case O_LOG_MAC: 107 info->logflags |= IP6T_LOG_MACDECODE; 108 break; 109 } 110 } 111 112 static void LOG_print(const void *ip, const struct xt_entry_target *target, 113 int numeric) 114 { 115 const struct ip6t_log_info *loginfo 116 = (const struct ip6t_log_info *)target->data; 117 unsigned int i = 0; 118 119 printf(" LOG"); 120 if (numeric) 121 printf(" flags %u level %u", 122 loginfo->logflags, loginfo->level); 123 else { 124 for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i) 125 if (loginfo->level == ip6t_log_names[i].level) { 126 printf(" level %s", ip6t_log_names[i].name); 127 break; 128 } 129 if (i == ARRAY_SIZE(ip6t_log_names)) 130 printf(" UNKNOWN level %u", loginfo->level); 131 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 132 printf(" tcp-sequence"); 133 if (loginfo->logflags & IP6T_LOG_TCPOPT) 134 printf(" tcp-options"); 135 if (loginfo->logflags & IP6T_LOG_IPOPT) 136 printf(" ip-options"); 137 if (loginfo->logflags & IP6T_LOG_UID) 138 printf(" uid"); 139 if (loginfo->logflags & IP6T_LOG_MACDECODE) 140 printf(" macdecode"); 141 if (loginfo->logflags & ~(IP6T_LOG_MASK)) 142 printf(" unknown-flags"); 143 } 144 145 if (strcmp(loginfo->prefix, "") != 0) 146 printf(" prefix \"%s\"", loginfo->prefix); 147 } 148 149 static void LOG_save(const void *ip, const struct xt_entry_target *target) 150 { 151 const struct ip6t_log_info *loginfo 152 = (const struct ip6t_log_info *)target->data; 153 154 if (strcmp(loginfo->prefix, "") != 0) { 155 printf(" --log-prefix"); 156 xtables_save_string(loginfo->prefix); 157 } 158 159 if (loginfo->level != LOG_DEFAULT_LEVEL) 160 printf(" --log-level %d", loginfo->level); 161 162 if (loginfo->logflags & IP6T_LOG_TCPSEQ) 163 printf(" --log-tcp-sequence"); 164 if (loginfo->logflags & IP6T_LOG_TCPOPT) 165 printf(" --log-tcp-options"); 166 if (loginfo->logflags & IP6T_LOG_IPOPT) 167 printf(" --log-ip-options"); 168 if (loginfo->logflags & IP6T_LOG_UID) 169 printf(" --log-uid"); 170 if (loginfo->logflags & IP6T_LOG_MACDECODE) 171 printf(" --log-macdecode"); 172 } 173 174 static const struct ip6t_log_xlate ip6t_log_xlate_names[] = { 175 {"alert", LOG_ALERT }, 176 {"crit", LOG_CRIT }, 177 {"debug", LOG_DEBUG }, 178 {"emerg", LOG_EMERG }, 179 {"err", LOG_ERR }, 180 {"info", LOG_INFO }, 181 {"notice", LOG_NOTICE }, 182 {"warn", LOG_WARNING } 183 }; 184 185 static int LOG_xlate(struct xt_xlate *xl, 186 const struct xt_xlate_tg_params *params) 187 { 188 const struct ip6t_log_info *loginfo = 189 (const struct ip6t_log_info *)params->target->data; 190 unsigned int i = 0; 191 192 xt_xlate_add(xl, "log"); 193 if (strcmp(loginfo->prefix, "") != 0) { 194 if (params->escape_quotes) 195 xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix); 196 else 197 xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix); 198 } 199 200 for (i = 0; i < ARRAY_SIZE(ip6t_log_xlate_names); ++i) 201 if (loginfo->level == ip6t_log_xlate_names[i].level && 202 loginfo->level != LOG_DEFAULT_LEVEL) { 203 xt_xlate_add(xl, " level %s", 204 ip6t_log_xlate_names[i].name); 205 break; 206 } 207 208 if ((loginfo->logflags & IP6T_LOG_MASK) == IP6T_LOG_MASK) { 209 xt_xlate_add(xl, " flags all"); 210 } else { 211 if (loginfo->logflags & (IP6T_LOG_TCPSEQ | IP6T_LOG_TCPOPT)) { 212 const char *delim = " "; 213 214 xt_xlate_add(xl, " flags tcp"); 215 if (loginfo->logflags & IP6T_LOG_TCPSEQ) { 216 xt_xlate_add(xl, " sequence"); 217 delim = ","; 218 } 219 if (loginfo->logflags & IP6T_LOG_TCPOPT) 220 xt_xlate_add(xl, "%soptions", delim); 221 } 222 if (loginfo->logflags & IP6T_LOG_IPOPT) 223 xt_xlate_add(xl, " flags ip options"); 224 if (loginfo->logflags & IP6T_LOG_UID) 225 xt_xlate_add(xl, " flags skuid"); 226 if (loginfo->logflags & IP6T_LOG_MACDECODE) 227 xt_xlate_add(xl, " flags ether"); 228 } 229 230 return 1; 231 } 232 static struct xtables_target log_tg6_reg = { 233 .name = "LOG", 234 .version = XTABLES_VERSION, 235 .family = NFPROTO_IPV6, 236 .size = XT_ALIGN(sizeof(struct ip6t_log_info)), 237 .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)), 238 .help = LOG_help, 239 .init = LOG_init, 240 .print = LOG_print, 241 .save = LOG_save, 242 .x6_parse = LOG_parse, 243 .x6_options = LOG_opts, 244 .xlate = LOG_xlate, 245 }; 246 247 void _init(void) 248 { 249 xtables_register_target(&log_tg6_reg); 250 } 251