summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2005-01-03 03:48:40 +0000
committerRusty Russell <rusty@rustcorp.com.au>2005-01-03 03:48:40 +0000
commit3aef54dce4f9bbe0b466478fd33a1d3131efbbb8 (patch)
tree58c303308741dab836833dc15cade877a6bf6939 /extensions
parent708f7b97a5a7455abf5c3c5a86bf6603c6c7a1c5 (diff)
Extension revision number support (if kernel supports the getsockopts).
Enhance MARK match with second revision. Committed in anticipation of the kernel patch being applied.
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libipt_MARK.c140
1 files changed, 126 insertions, 14 deletions
diff --git a/extensions/libipt_MARK.c b/extensions/libipt_MARK.c
index bc3dd42e..457f6ad3 100644
--- a/extensions/libipt_MARK.c
+++ b/extensions/libipt_MARK.c
@@ -16,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 }
};
@@ -34,9 +38,9 @@ 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;
@@ -56,7 +60,12 @@ parse(int c, char **argv, int invert, unsigned int *flags,
"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;
}
@@ -69,7 +78,47 @@ 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
@@ -88,9 +137,9 @@ print_mark(unsigned long mark)
/* 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;
@@ -100,7 +149,7 @@ print(const struct ipt_ip *ip,
/* 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;
@@ -109,23 +158,86 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
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 = {
+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,
+ .parse = &parse_v0,
+ .final_check = &final_check,
+ .print = &print_v0,
+ .save = &save_v0,
+ .extra_opts = opts
+};
+
+static
+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,
- .save = &save,
+ .print = &print_v1,
+ .save = &save_v1,
.extra_opts = opts
};
void _init(void)
{
- register_target(&mark);
+ register_target(&mark_v0);
+ register_target(&mark_v1);
}