X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=extensions%2Flibipt_MARK.c;fp=extensions%2Flibipt_MARK.c;h=457f6ad393886bc5aed7f1afc4957ec95b88a863;hb=6afea0b41dfbc3824956d11d960ad80097218feb;hp=08630419ec9e42a451ac87d5edcd3ed757d0491c;hpb=f7b70cf9e00324b89b02de213bcd0dde7044d035;p=iptables.git diff --git a/extensions/libipt_MARK.c b/extensions/libipt_MARK.c index 0863041..457f6ad 100644 --- a/extensions/libipt_MARK.c +++ b/extensions/libipt_MARK.c @@ -6,12 +6,8 @@ #include #include -#include - -struct markinfo { - struct ipt_entry_target t; - struct ipt_mark_target_info mark; -}; +/* For 64bit kernel / 32bit userspace */ +#include "../include/linux/netfilter_ipv4/ipt_MARK.h" /* Function which prints out usage message. */ static void @@ -20,12 +16,16 @@ help(void) printf( "MARK target v%s options:\n" " --set-mark value Set nfmark value\n" +" --and-mark value Binary AND the nfmark with value\n" +" --or-mark value Binary OR the nfmark with value\n" "\n", IPTABLES_VERSION); } static struct option opts[] = { { "set-mark", 1, 0, '1' }, + { "and-mark", 1, 0, '2' }, + { "or-mark", 1, 0, '3' }, { 0 } }; @@ -38,24 +38,34 @@ init(struct ipt_entry_target *t, unsigned int *nfcache) /* Function which parses command options; returns true if it ate an option */ static int -parse(int c, char **argv, int invert, unsigned int *flags, - const struct ipt_entry *entry, - struct ipt_entry_target **target) +parse_v0(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + struct ipt_entry_target **target) { struct ipt_mark_target_info *markinfo = (struct ipt_mark_target_info *)(*target)->data; switch (c) { case '1': - if (string_to_number(optarg, 0, 0xffffffff, - (unsigned int *)&markinfo->mark)) +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, + &markinfo->mark)) +#else + if (string_to_number_l(optarg, 0, 0, + &markinfo->mark)) +#endif exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); if (*flags) exit_error(PARAMETER_PROBLEM, "MARK target: Can't specify --set-mark twice"); *flags = 1; break; - + case '2': + exit_error(PARAMETER_PROBLEM, + "MARK target: kernel too old for --and-mark"); + case '3': + exit_error(PARAMETER_PROBLEM, + "MARK target: kernel too old for --or-mark"); default: return 0; } @@ -68,54 +78,166 @@ final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, - "MARK target: Parameter --set-mark is required"); + "MARK target: Parameter --set/and/or-mark" + " is required"); +} + +/* Function which parses command options; returns true if it + ate an option */ +static int +parse_v1(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + struct ipt_entry_target **target) +{ + struct ipt_mark_target_info_v1 *markinfo + = (struct ipt_mark_target_info_v1 *)(*target)->data; + + switch (c) { + case '1': + markinfo->mode = IPT_MARK_SET; + break; + case '2': + markinfo->mode = IPT_MARK_AND; + break; + case '3': + markinfo->mode = IPT_MARK_OR; + break; + default: + return 0; + } + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &markinfo->mark)) +#else + if (string_to_number_l(optarg, 0, 0, &markinfo->mark)) +#endif + exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); + + if (*flags) + exit_error(PARAMETER_PROBLEM, + "MARK target: Can't specify --set-mark twice"); + + *flags = 1; + return 1; } +#ifdef KERNEL_64_USERSPACE_32 static void -print_mark(unsigned long mark, int numeric) +print_mark(unsigned long long mark) +{ + printf("0x%llx ", mark); +} +#else +static void +print_mark(unsigned long mark) { printf("0x%lx ", mark); } +#endif /* Prints out the targinfo. */ static void -print(const struct ipt_ip *ip, - const struct ipt_entry_target *target, - int numeric) +print_v0(const struct ipt_ip *ip, + const struct ipt_entry_target *target, + int numeric) { const struct ipt_mark_target_info *markinfo = (const struct ipt_mark_target_info *)target->data; printf("MARK set "); - print_mark(markinfo->mark, numeric); + print_mark(markinfo->mark); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void -save(const struct ipt_ip *ip, const struct ipt_entry_target *target) +save_v0(const struct ipt_ip *ip, const struct ipt_entry_target *target) { const struct ipt_mark_target_info *markinfo = (const struct ipt_mark_target_info *)target->data; - printf("--set-mark 0x%lx ", markinfo->mark); + printf("--set-mark "); + print_mark(markinfo->mark); } +/* Prints out the targinfo. */ +static void +print_v1(const struct ipt_ip *ip, + const struct ipt_entry_target *target, + int numeric) +{ + const struct ipt_mark_target_info_v1 *markinfo = + (const struct ipt_mark_target_info_v1 *)target->data; + + switch (markinfo->mode) { + case IPT_MARK_SET: + printf("MARK set "); + break; + case IPT_MARK_AND: + printf("MARK and "); + break; + case IPT_MARK_OR: + printf("MARK or "); + break; + } + print_mark(markinfo->mark); +} + +/* Saves the union ipt_targinfo in parsable form to stdout. */ +static void +save_v1(const struct ipt_ip *ip, const struct ipt_entry_target *target) +{ + const struct ipt_mark_target_info_v1 *markinfo = + (const struct ipt_mark_target_info_v1 *)target->data; + + switch (markinfo->mode) { + case IPT_MARK_SET: + printf("--set-mark "); + break; + case IPT_MARK_AND: + printf("--and-mark "); + break; + case IPT_MARK_OR: + printf("--or-mark "); + break; + } + print_mark(markinfo->mark); +} + +static +struct iptables_target mark_v0 = { + .next = NULL, + .name = "MARK", + .version = IPTABLES_VERSION, + .revision = 0, + .size = IPT_ALIGN(sizeof(struct ipt_mark_target_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_target_info)), + .help = &help, + .init = &init, + .parse = &parse_v0, + .final_check = &final_check, + .print = &print_v0, + .save = &save_v0, + .extra_opts = opts +}; + static -struct iptables_target mark -= { NULL, - "MARK", - IPTABLES_VERSION, - IPT_ALIGN(sizeof(struct ipt_mark_target_info)), - IPT_ALIGN(sizeof(struct ipt_mark_target_info)), - &help, - &init, - &parse, - &final_check, - &print, - &save, - opts +struct iptables_target mark_v1 = { + .next = NULL, + .name = "MARK", + .version = IPTABLES_VERSION, + .revision = 1, + .size = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)), + .help = &help, + .init = &init, + .parse = &parse_v1, + .final_check = &final_check, + .print = &print_v1, + .save = &save_v1, + .extra_opts = opts }; void _init(void) { - register_target(&mark); + register_target(&mark_v0); + register_target(&mark_v1); }