Home | History | Annotate | Download | only in extensions
      1 /*
      2  * Bart De Schuymer <bdschuym (at) pandora.be>
      3  *
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License version 2 as
      6  * published by the Free Software Foundation.
      7  *
      8  * Giuseppe Longo <giuseppelng (at) gmail.com> adapted the original code to the
      9  * xtables-compat environment in 2015.
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <syslog.h>
     16 #include <string.h>
     17 #include <getopt.h>
     18 #include <xtables.h>
     19 #include <linux/netfilter_bridge/ebt_log.h>
     20 
     21 #define LOG_DEFAULT_LEVEL LOG_INFO
     22 
     23 #define LOG_PREFIX '1'
     24 #define LOG_LEVEL  '2'
     25 #define LOG_ARP    '3'
     26 #define LOG_IP     '4'
     27 #define LOG_LOG    '5'
     28 #define LOG_IP6    '6'
     29 
     30 typedef struct _code {
     31 	char *c_name;
     32 	int c_val;
     33 } CODE;
     34 
     35 static CODE eight_priority[] = {
     36 	{ "emerg", LOG_EMERG },
     37 	{ "alert", LOG_ALERT },
     38 	{ "crit", LOG_CRIT },
     39 	{ "error", LOG_ERR },
     40 	{ "warning", LOG_WARNING },
     41 	{ "notice", LOG_NOTICE },
     42 	{ "info", LOG_INFO },
     43 	{ "debug", LOG_DEBUG }
     44 };
     45 
     46 static int name_to_loglevel(const char *arg)
     47 {
     48 	int i;
     49 
     50 	for (i = 0; i < 8; i++)
     51 		if (!strcmp(arg, eight_priority[i].c_name))
     52 			return eight_priority[i].c_val;
     53 
     54 	/* return bad loglevel */
     55 	return 9;
     56 }
     57 
     58 static const struct option brlog_opts[] = {
     59 	{ .name = "log-prefix",		.has_arg = true,  .val = LOG_PREFIX },
     60 	{ .name = "log-level",		.has_arg = true,  .val = LOG_LEVEL  },
     61 	{ .name = "log-arp",		.has_arg = false, .val = LOG_ARP    },
     62 	{ .name = "log-ip",		.has_arg = false, .val = LOG_IP     },
     63 	{ .name = "log",		.has_arg = false, .val = LOG_LOG    },
     64 	{ .name = "log-ip6",		.has_arg = false, .val = LOG_IP6    },
     65 	XT_GETOPT_TABLEEND,
     66 };
     67 
     68 static void brlog_help(void)
     69 {
     70 	int i;
     71 
     72 	printf(
     73 "log options:\n"
     74 "--log               : use this if you're not specifying anything\n"
     75 "--log-level level   : level = [1-8] or a string\n"
     76 "--log-prefix prefix : max. %d chars.\n"
     77 "--log-ip            : put ip info. in the log for ip packets\n"
     78 "--log-arp           : put (r)arp info. in the log for (r)arp packets\n"
     79 "--log-ip6           : put ip6 info. in the log for ip6 packets\n"
     80 	, EBT_LOG_PREFIX_SIZE - 1);
     81 	for (i = 0; i < 8; i++)
     82 		printf("%d = %s\n", eight_priority[i].c_val,
     83 				    eight_priority[i].c_name);
     84 }
     85 
     86 static void brlog_init(struct xt_entry_target *t)
     87 {
     88 	struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
     89 
     90 	loginfo->bitmask = 0;
     91 	loginfo->prefix[0] = '\0';
     92 	loginfo->loglevel = LOG_NOTICE;
     93 }
     94 
     95 static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
     96 		       const void *entry, struct xt_entry_target **target)
     97 {
     98 	struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
     99 	long int i;
    100 	char *end;
    101 
    102 	switch (c) {
    103 	case LOG_PREFIX:
    104 		if (invert)
    105 			xtables_error(PARAMETER_PROBLEM,
    106 				      "Unexpected `!` after --log-prefix");
    107 		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
    108 			xtables_error(PARAMETER_PROBLEM,
    109 				      "Prefix too long");
    110 		if (strchr(optarg, '\"'))
    111 			xtables_error(PARAMETER_PROBLEM,
    112 				      "Use of \\\" is not allowed"
    113 				      " in the prefix");
    114 		strcpy((char *)loginfo->prefix, (char *)optarg);
    115 		break;
    116 	case LOG_LEVEL:
    117 		i = strtol(optarg, &end, 16);
    118 		if (*end != '\0' || i < 0 || i > 7)
    119 			loginfo->loglevel = name_to_loglevel(optarg);
    120 		else
    121 			loginfo->loglevel = i;
    122 
    123 		if (loginfo->loglevel == 9)
    124 			xtables_error(PARAMETER_PROBLEM,
    125 				      "Problem with the log-level");
    126 		break;
    127 	case LOG_IP:
    128 		if (invert)
    129 			xtables_error(PARAMETER_PROBLEM,
    130 				      "Unexpected `!' after --log-ip");
    131 		loginfo->bitmask |= EBT_LOG_IP;
    132 		break;
    133 	case LOG_ARP:
    134 		if (invert)
    135 			xtables_error(PARAMETER_PROBLEM,
    136 				      "Unexpected `!' after --log-arp");
    137 		loginfo->bitmask |= EBT_LOG_ARP;
    138 	case LOG_LOG:
    139 		if (invert)
    140 			xtables_error(PARAMETER_PROBLEM,
    141 				      "Unexpected `!' after --log");
    142 		break;
    143 	case LOG_IP6:
    144 		if (invert)
    145 			xtables_error(PARAMETER_PROBLEM,
    146 				      "Unexpected `!' after --log-ip6");
    147 		loginfo->bitmask |= EBT_LOG_IP6;
    148 		break;
    149 	default:
    150 		return 0;
    151 	}
    152 
    153 	*flags |= loginfo->bitmask;
    154 	return 1;
    155 }
    156 
    157 static void brlog_final_check(unsigned int flags)
    158 {
    159 }
    160 
    161 static void brlog_print(const void *ip, const struct xt_entry_target *target,
    162 			int numeric)
    163 {
    164 	struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
    165 
    166 	printf("--log-level %s --log-prefix \"%s\"",
    167 		eight_priority[loginfo->loglevel].c_name,
    168 		loginfo->prefix);
    169 
    170 	if (loginfo->bitmask & EBT_LOG_IP)
    171 		printf(" --log-ip");
    172 	if (loginfo->bitmask & EBT_LOG_ARP)
    173 		printf(" --log-arp");
    174 	if (loginfo->bitmask & EBT_LOG_IP6)
    175 		printf(" --log-ip6");
    176 	printf(" ");
    177 }
    178 
    179 static struct xtables_target brlog_target = {
    180 	.name		= "log",
    181 	.revision	= 0,
    182 	.version	= XTABLES_VERSION,
    183 	.family		= NFPROTO_BRIDGE,
    184 	.size		= XT_ALIGN(sizeof(struct ebt_log_info)),
    185 	.userspacesize	= XT_ALIGN(sizeof(struct ebt_log_info)),
    186 	.init		= brlog_init,
    187 	.help		= brlog_help,
    188 	.parse		= brlog_parse,
    189 	.final_check	= brlog_final_check,
    190 	.print		= brlog_print,
    191 	.extra_opts	= brlog_opts,
    192 };
    193 
    194 void _init(void)
    195 {
    196 	xtables_register_target(&brlog_target);
    197 }
    198