/* * Bart De Schuymer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Giuseppe Longo adapted the original code to the * xtables-compat environment in 2015. * */ #include #include #include #include #include #include #include #define LOG_DEFAULT_LEVEL LOG_INFO #define LOG_PREFIX '1' #define LOG_LEVEL '2' #define LOG_ARP '3' #define LOG_IP '4' #define LOG_LOG '5' #define LOG_IP6 '6' struct code { char *c_name; int c_val; }; static struct 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 } }; static int name_to_loglevel(const char *arg) { int i; for (i = 0; i < 8; i++) if (!strcmp(arg, eight_priority[i].c_name)) return eight_priority[i].c_val; /* return bad loglevel */ return 9; } static const struct option brlog_opts[] = { { .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX }, { .name = "log-level", .has_arg = true, .val = LOG_LEVEL }, { .name = "log-arp", .has_arg = false, .val = LOG_ARP }, { .name = "log-ip", .has_arg = false, .val = LOG_IP }, { .name = "log", .has_arg = false, .val = LOG_LOG }, { .name = "log-ip6", .has_arg = false, .val = LOG_IP6 }, XT_GETOPT_TABLEEND, }; static void brlog_help(void) { 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" "--log-ip6 : put ip6 info. in the log for ip6 packets\n" , EBT_LOG_PREFIX_SIZE - 1); for (i = 0; i < 8; i++) printf("%d = %s\n", eight_priority[i].c_val, eight_priority[i].c_name); } static void brlog_init(struct xt_entry_target *t) { struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data; loginfo->bitmask = 0; loginfo->prefix[0] = '\0'; loginfo->loglevel = LOG_NOTICE; } static unsigned int log_chk_inv(int inv, unsigned int bit, const char *suffix) { if (inv) xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --log%s", suffix); return bit; } static int brlog_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data; long int i; char *end; switch (c) { case LOG_PREFIX: if (invert) xtables_error(PARAMETER_PROBLEM, "Unexpected `!` after --log-prefix"); if (strlen(optarg) > sizeof(loginfo->prefix) - 1) xtables_error(PARAMETER_PROBLEM, "Prefix too long"); if (strchr(optarg, '\"')) xtables_error(PARAMETER_PROBLEM, "Use of \\\" is not allowed" " in the prefix"); strcpy((char *)loginfo->prefix, (char *)optarg); break; case LOG_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) xtables_error(PARAMETER_PROBLEM, "Problem with the log-level"); break; case LOG_IP: loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP, "-ip"); break; case LOG_ARP: loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_ARP, "-arp"); break; case LOG_LOG: loginfo->bitmask |= log_chk_inv(invert, 0, ""); break; case LOG_IP6: loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP6, "-ip6"); break; default: return 0; } *flags |= loginfo->bitmask; return 1; } static void brlog_final_check(unsigned int flags) { } static void brlog_print(const void *ip, const struct xt_entry_target *target, int numeric) { struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data; printf("--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"); if (loginfo->bitmask & EBT_LOG_IP6) printf(" --log-ip6"); printf(" "); } static int brlog_xlate(struct xt_xlate *xl, const struct xt_xlate_tg_params *params) { const struct ebt_log_info *loginfo = (const void *)params->target->data; xt_xlate_add(xl, "log"); if (loginfo->prefix[0]) { if (params->escape_quotes) xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix); else xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix); } if (loginfo->loglevel != LOG_DEFAULT_LEVEL) xt_xlate_add(xl, " level %s", eight_priority[loginfo->loglevel].c_name); xt_xlate_add(xl, " flags ether "); return 1; } static struct xtables_target brlog_target = { .name = "log", .revision = 0, .version = XTABLES_VERSION, .family = NFPROTO_BRIDGE, .size = XT_ALIGN(sizeof(struct ebt_log_info)), .userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)), .init = brlog_init, .help = brlog_help, .parse = brlog_parse, .final_check = brlog_final_check, .print = brlog_print, .xlate = brlog_xlate, .extra_opts = brlog_opts, }; void _init(void) { xtables_register_target(&brlog_target); }