]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Kernels higher than 2.6.10 don't support multiple --to arguments in
authorPhil Oester <kernel@linuxace.com>
Mon, 19 Sep 2005 15:00:33 +0000 (15:00 +0000)
committerHarald Welte <laforge@gnumonks.org>
Mon, 19 Sep 2005 15:00:33 +0000 (15:00 +0000)
DNAT and SNAT targets.  At present, the error is somewhat vague:

# iptables -t nat -A foo -j SNAT --to 1.2.3.4 --to 2.3.4.5
iptables: Invalid argument

But if we want current iptables to work with kernels <= 2.6.10, we
cannot simply disallow this in all cases.

So the below patch adds kernel version checking to iptables, and
utilizes it in [DS]NAT.  Now, users will see a more informative error:

# iptables -t nat -A foo -j SNAT --to 1.2.3.4 --to 2.3.4.5
iptables v1.3.3: Multiple --to-source not supported

This generic infrastructure (shamelessly lifted from procps btw) may
come in handy in the future for other changes.

This fixes bugzilla #367. (Phil Oester)

extensions/libipt_DNAT.c
extensions/libipt_SNAT.c
include/iptables.h
iptables.c

index 3b0d146c18fa911a4f356ab636ffee5f56223b18..bdc15eb836cefbea2f9afa4afc308e3e381e3193 100644 (file)
@@ -155,6 +155,13 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                        exit_error(PARAMETER_PROBLEM,
                                   "Unexpected `!' after --to-destination");
 
+               if (*flags) {
+                       if (!kernel_version)
+                               get_kernel_version();
+                       if (kernel_version > LINUX_VERSION(2, 6, 10))
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Multiple --to-destination not supported");
+               }
                *target = parse_to(optarg, portok, info);
                *flags = 1;
                return 1;
index 746076031e63ee09cc5e2b563680fd632322e9ea..867c9d010336fe59a3156dd7e80c9d3eeb442357 100644 (file)
@@ -155,6 +155,13 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                        exit_error(PARAMETER_PROBLEM,
                                   "Unexpected `!' after --to-source");
 
+               if (*flags) {
+                       if (!kernel_version)
+                               get_kernel_version();
+                       if (kernel_version > LINUX_VERSION(2, 6, 10))
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Multiple --to-source not supported");
+               }
                *target = parse_to(optarg, portok, info);
                *flags = 1;
                return 1;
index f0cad8daa672fa0039078fe7ed7df546044f2f8f..fbcf2eb4b26701402afbe952e6248e554bbd503b 100644 (file)
@@ -175,4 +175,13 @@ extern int flush_entries(const ipt_chainlabel chain, int verbose,
                        iptc_handle_t *handle);
 extern int for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
                int verbose, int builtinstoo, iptc_handle_t *handle);
+
+/* kernel revision handling */
+extern int kernel_version;
+extern void get_kernel_version(void);
+#define LINUX_VERSION(x,y,z)   (0x10000*(x) + 0x100*(y) + z)
+#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF)
+#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF)
+#define LINUX_VERSION_PATCH(x) ( (x)      & 0xFF)
+
 #endif /*_IPTABLES_USER_H*/
index 7e8ba59ef61d1137e38f03bea0b67a225678c105..aec9613755a3f8b412b3abdbe1c2b201804572ca 100644 (file)
@@ -39,6 +39,7 @@
 #include <iptables.h>
 #include <fcntl.h>
 #include <sys/wait.h>
+#include <sys/utsname.h>
 
 #ifndef TRUE
 #define TRUE 1
@@ -193,6 +194,8 @@ const char *program_version;
 const char *program_name;
 char *lib_dir;
 
+int kernel_version;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct iptables_match *iptables_matches = NULL;
 struct iptables_target *iptables_targets = NULL;
@@ -1804,6 +1807,21 @@ static void set_revision(char *name, u_int8_t revision)
        name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
 }
 
+void
+get_kernel_version(void) {
+       static struct utsname uts;
+       int x = 0, y = 0, z = 0;
+
+       if (uname(&uts) == -1) {
+               fprintf(stderr, "Unable to retrieve kernel version.\n");
+               free_opts(1);
+               exit(1); 
+       }
+
+       sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
+       kernel_version = LINUX_VERSION(x, y, z);
+}
+
 int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
 {
        struct ipt_entry fw, *e = NULL;