Home | History | Annotate | Download | only in extensions
      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