summaryrefslogtreecommitdiffstats
path: root/userspace/ebtables2/extensions/ebt_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/ebtables2/extensions/ebt_log.c')
-rw-r--r--userspace/ebtables2/extensions/ebt_log.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/userspace/ebtables2/extensions/ebt_log.c b/userspace/ebtables2/extensions/ebt_log.c
new file mode 100644
index 0000000..6dff952
--- /dev/null
+++ b/userspace/ebtables2/extensions/ebt_log.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_log.h>
+
+// copied from syslog.h
+// used for the LOG target
+#define LOG_EMERG 0 // system is unusable
+#define LOG_ALERT 1 // action must be taken immediately
+#define LOG_CRIT 2 // critical conditions
+#define LOG_ERR 3 // error conditions
+#define LOG_WARNING 4 // warning conditions
+#define LOG_NOTICE 5 // normal but significant condition
+#define LOG_INFO 6 // informational
+#define LOG_DEBUG 7 // debug-level messages
+#define LOG_DEFAULT_LEVEL LOG_INFO
+
+typedef struct _code {
+ char *c_name;
+ int c_val;
+} CODE;
+
+static CODE eight_priority[] = {
+ { "emerg", LOG_EMERG },
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "error", LOG_ERR },
+ { "warning", LOG_WARNING },
+ { "notice", LOG_NOTICE },
+ { "info", LOG_INFO },
+ { "debug", LOG_DEBUG },
+ { NULL, -1 }
+};
+
+static int name_to_loglevel(char* arg)
+{
+ int i = 0, c_val = eight_priority[0].c_val;
+
+ while (c_val != -1) {
+ if (!strcmp(arg, eight_priority[i].c_name))
+ return c_val;
+ i++;
+ c_val = eight_priority[i].c_val;
+ }
+ // return bad loglevel
+ return 9;
+}
+
+#define LOG_PREFIX '1'
+#define LOG_LEVEL '2'
+#define LOG_ARP '3'
+#define LOG_IP '4'
+#define LOG_LOG '5'
+static struct option opts[] =
+{
+ { "log-prefix", required_argument, 0, LOG_PREFIX },
+ { "log-level" , required_argument, 0, LOG_LEVEL },
+ { "log-arp" , no_argument , 0, LOG_ARP },
+ { "log-ip" , no_argument , 0, LOG_IP },
+ { "log" , no_argument , 0, LOG_LOG },
+ { 0 }
+};
+
+static void print_help()
+{
+ int i;
+
+ printf(
+"log options:\n"
+"--log : use this if you're not specifying anything\n"
+"--log-level level : level = [1-8] or a string\n"
+"--log-prefix prefix : max. %d chars.\n"
+"--log-ip : put ip info. in the log for ip packets\n"
+"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
+ , EBT_LOG_PREFIX_SIZE - 1);
+ printf("levels:\n");
+ for (i = 0; i < 8; i++)
+ printf("%d = %s\n", eight_priority[i].c_val,
+ eight_priority[i].c_name);
+}
+
+static void init(struct ebt_entry_watcher *watcher)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)watcher->data;
+
+ loginfo->bitmask = 0;
+ loginfo->prefix[0] = '\0';
+ loginfo->loglevel = LOG_NOTICE;
+}
+
+#define OPT_PREFIX 0x01
+#define OPT_LEVEL 0x02
+#define OPT_ARP 0x04
+#define OPT_IP 0x08
+#define OPT_LOG 0x10
+static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
+ unsigned int *flags, struct ebt_entry_watcher **watcher)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)(*watcher)->data;
+ int i;
+ char *end;
+
+ switch (c) {
+ case LOG_PREFIX:
+ check_option(flags, OPT_PREFIX);
+ if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
+ print_error("Prefix too long");
+ strcpy(loginfo->prefix, optarg);
+ break;
+
+ case LOG_LEVEL:
+ check_option(flags, OPT_LEVEL);
+ i = strtol(optarg, &end, 16);
+ if (*end != '\0' || i < 0 || i > 7)
+ loginfo->loglevel = name_to_loglevel(optarg);
+ else
+ loginfo->loglevel = i;
+ if (loginfo->loglevel == 9)
+ print_error("Problem with the log-level");
+ break;
+
+ case LOG_IP:
+ check_option(flags, OPT_IP);
+ loginfo->bitmask |= EBT_LOG_IP;
+ break;
+
+ case LOG_ARP:
+ check_option(flags, OPT_ARP);
+ loginfo->bitmask |= EBT_LOG_ARP;
+ break;
+
+ case LOG_LOG:
+ check_option(flags, OPT_LOG);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+ const struct ebt_entry_watcher *watcher, const char *name, unsigned int hook)
+{
+ return;
+}
+
+static void print(const struct ebt_u_entry *entry,
+ const struct ebt_entry_watcher *watcher)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)watcher->data;
+
+ printf("log: log-level = %s - log-prefix = \"%s\"",
+ eight_priority[loginfo->loglevel].c_name,
+ loginfo->prefix);
+ if (loginfo->bitmask & EBT_LOG_IP)
+ printf(" - log-ip");
+ if (loginfo->bitmask & EBT_LOG_ARP)
+ printf(" - log-arp");
+ printf(" ");
+}
+
+static int compare(const struct ebt_entry_watcher *w1,
+ const struct ebt_entry_watcher *w2)
+{
+ struct ebt_log_info *loginfo1 = (struct ebt_log_info *)w1->data;
+ struct ebt_log_info *loginfo2 = (struct ebt_log_info *)w2->data;
+
+ if (loginfo1->loglevel != loginfo2->loglevel)
+ return 0;
+ if (loginfo1->bitmask != loginfo2->bitmask)
+ return 0;
+ return !strcmp(loginfo1->prefix, loginfo2->prefix);
+}
+
+static struct ebt_u_watcher log_watcher =
+{
+ EBT_LOG_WATCHER,
+ sizeof(struct ebt_log_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts,
+};
+
+#undef _init
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_watcher(&log_watcher);
+}