]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Minor changes and return code bugfix
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kadlec/emailAddress=kadlec@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kadlec/emailAddress=kadlec@netfilter.org>
Mon, 9 Oct 2006 11:47:39 +0000 (11:47 +0000)
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kadlec/emailAddress=kadlec@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kadlec/emailAddress=kadlec@netfilter.org>
Mon, 9 Oct 2006 11:47:39 +0000 (11:47 +0000)
ChangeLog
Makefile
ipset.c
ipset.h
ipset_iphash.c
ipset_ipmap.c
ipset_ipporthash.c
ipset_macipmap.c
ipset_nethash.c
ipset_portmap.c

index 8331a6d0124781a6be9285dd920ffc39c5c1003d..63a6e4251c47ba69b737f516fa0e0cf808f64def 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2.2.9a
+ - use correct type (socklen_t) for getsockopt (H. Nakano)
+ - incorrect return codes fixed (Tomasz Lemiech, Alexey Bortnikov)
+ - kernel header dependency removed (asm/bitops.h)
+ - ipset now tries to load in the ip_set kernel module if the protocol
+   is not available
+
 2.2.9
  - 'ipset -N' did not generate proper return code
  - 'limit' module parameter added to the kernel modules of the
index 808992c728e89bf72a46164f07e31f54074d81f9..7e206fd5054c2d9887ff5dca3de1312aebb427a9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ ifndef KERNEL_DIR
 KERNEL_DIR=/usr/src/linux
 endif
 
-IPSET_VERSION:=2.2.9
+IPSET_VERSION:=2.2.9a
 
 PREFIX:=/usr/local
 LIBDIR:=$(PREFIX)/lib
diff --git a/ipset.c b/ipset.c
index aab4baaa966c052cae46e2b35eb6c43a188de6a3..a63b8ec353dd69f7c2ef50ef2d24bf6a36be3aa4 100644 (file)
--- a/ipset.c
+++ b/ipset.c
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 #include <arpa/inet.h>
 #include <stdarg.h>
 #include <netdb.h>
 #include <dlfcn.h>
-#include <asm/bitops.h>
+#include <fcntl.h>
+/* #include <asm/bitops.h> */
 
 #include "ipset.h"
 
+#ifndef PROC_SYS_MODPROBE
+#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
+#endif
+
 char program_name[] = "ipset";
 char program_version[] = IPSET_VERSION;
 
@@ -42,7 +48,8 @@ static int option_quiet = 0;
 static int restore = 0;
 void *restore_data = NULL;
 struct ip_set_restore *restore_set = NULL;
-size_t restore_offset = 0, restore_size;
+size_t restore_offset = 0;
+socklen_t restore_size;
 unsigned line = 0;
 
 #define TEMPFILE_PATTERN       "/ipsetXXXXXX"
@@ -239,6 +246,73 @@ static char cmd2char(int option)
        return cmdflags[option];
 }
 
+/* From iptables.c ... */
+static char *get_modprobe(void)
+{
+       int procfile;
+       char *ret;
+
+#define PROCFILE_BUFSIZ        1024
+       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
+       if (procfile < 0)
+               return NULL;
+
+       ret = (char *) malloc(PROCFILE_BUFSIZ);
+       if (ret) {
+               memset(ret, 0, PROCFILE_BUFSIZ);
+               switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
+               case -1: goto fail;
+               case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
+               }
+               if (ret[strlen(ret)-1]=='\n') 
+                       ret[strlen(ret)-1]=0;
+               close(procfile);
+               return ret;
+       }
+ fail:
+       free(ret);
+       close(procfile);
+       return NULL;
+}
+
+static int ipset_insmod(const char *modname, const char *modprobe)
+{
+       char *buf = NULL;
+       char *argv[3];
+       struct stat junk;
+       int status;
+       
+       if (!stat(modprobe, &junk)) {
+               /* Try to read out of the kernel */
+               buf = get_modprobe();
+               if (!buf)
+                       return -1;
+               modprobe = buf;
+       }
+       
+       switch (fork()) {
+       case 0:
+               argv[0] = (char *)modprobe;
+               argv[1] = (char *)modname;
+               argv[2] = NULL;
+               execv(argv[0], argv);
+               
+               /* Should not reach */
+               exit(1);
+       case -1:
+               return -1;
+       
+       default: /* parent */
+               wait(&status);
+       }
+       
+       free(buf);
+       
+       if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+               return 0;
+       return -1;
+}
+
 static int kernel_getsocket(void)
 {
        int sockfd = -1;
@@ -292,30 +366,50 @@ static void kernel_error(unsigned cmd, int err)
        exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
 }
 
-static void kernel_getfrom(unsigned cmd, void *data, size_t * size)
+static inline int wrapped_getsockopt(void *data, socklen_t *size)
 {
        int res;
        int sockfd = kernel_getsocket();
 
        /* Send! */
        res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
+       if (res != 0 
+           && errno == ENOPROTOOPT 
+           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
+               res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
        DP("res=%d errno=%d", res, errno);
-
-       if (res != 0)
-               kernel_error(cmd, errno);
+       
+       return res;
 }
 
-static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
-                                    void *data, size_t size)
+static inline int wrapped_setsockopt(void *data, socklen_t size)
 {
        int res;
        int sockfd = kernel_getsocket();
 
        /* Send! */
        res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
+       if (res != 0 
+           && errno == ENOPROTOOPT 
+           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
+               res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
        DP("res=%d errno=%d", res, errno);
+       
+       return res;
+}
+
+static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size)
+{
+       int res = wrapped_getsockopt(data, size);
+
+       if (res != 0)
+               kernel_error(cmd, errno);
+}
+
+static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
+                                    void *data, socklen_t size)
+{
+       int res = wrapped_setsockopt(data, size);
 
        if (res != 0) {
                if (errno == EEXIST)
@@ -329,13 +423,7 @@ static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
 
 static void kernel_sendto(unsigned cmd, void *data, size_t size)
 {
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
-       DP("res=%d errno=%d", res, errno);
+       int res = wrapped_setsockopt(data, size);
 
        if (res != 0)
                kernel_error(cmd, errno);
@@ -343,13 +431,7 @@ static void kernel_sendto(unsigned cmd, void *data, size_t size)
 
 static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
 {
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
-       DP("res=%d errno=%d", res, errno);
+       int res = wrapped_getsockopt(data, size);
 
        if (res != 0) {
                if (errno == EAGAIN)
@@ -364,7 +446,7 @@ static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
 static void check_protocolversion(void)
 {
        struct ip_set_req_version req_version;
-       size_t size = sizeof(struct ip_set_req_version);
+       socklen_t size = sizeof(struct ip_set_req_version);
        int sockfd = kernel_getsocket();
        int res;
 
@@ -958,7 +1040,7 @@ static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
        struct ip_set_name_list *name_list;
        struct set *set;
        ip_set_id_t i;
-       size_t size, req_size;
+       socklen_t size, req_size;
        int repeated = 0, res = 0;
 
        DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
@@ -1132,7 +1214,7 @@ static size_t save_default_bindings(void *data, int *bindings)
 static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
 {
        void *data = NULL;
-       size_t size, req_size = 0;
+       socklen_t size, req_size = 0;
        ip_set_id_t index;
        int res = 0, bindings = 0;
        time_t now = time(NULL);
@@ -1447,7 +1529,7 @@ static struct set *set_adt_get(const char *name)
 {
        struct ip_set_req_adt_get req_adt_get;
        struct set *set;
-       size_t size;
+       socklen_t size;
 
        DP("%s", name);
 
@@ -1456,7 +1538,7 @@ static struct set *set_adt_get(const char *name)
        strcpy(req_adt_get.set.name, name);
        size = sizeof(struct ip_set_req_adt_get);
 
-       kernel_getfrom(CMD_ADT_GET, &req_adt_get, &size);
+       kernel_getfrom(CMD_ADT_GET, (void *) &req_adt_get, &size);
 
        set = ipset_malloc(sizeof(struct set));
        strcpy(set->name, name);
@@ -1705,7 +1787,7 @@ static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
 {
        void *data = NULL;
        ip_set_id_t index;
-       size_t size, req_size;
+       socklen_t size, req_size;
        int res = 0;
 
        DP("%s", name);
@@ -2043,6 +2125,7 @@ int parse_commandline(int argc, char *argv[])
                                                   "Unknown arg `%s'",
                                                   argv[optind - 1]);
 
+                               res = 0;
                                break;
                        }
 
diff --git a/ipset.h b/ipset.h
index 50a3476d6f766323f3c220ea6157c5a21d012454..4ac2da9afce2c2b19dd7b703f3331467e112cb3e 100644 (file)
--- a/ipset.h
+++ b/ipset.h
@@ -184,4 +184,9 @@ extern void *ipset_malloc(size_t size);
 extern char *ipset_strdup(const char *);
 extern void ipset_free(void **data);
 
+#define BITSPERBYTE    (8*sizeof(char))
+#define ID2BYTE(id)    ((id)/BITSPERBYTE)
+#define ID2MASK(id)    (1 << ((id)%BITSPERBYTE))
+#define test_bit(id, heap)     ((((char *)(heap))[ID2BYTE(id)] & ID2MASK(id)) != 0)
+
 #endif /* __IPSET_H */
index 3272e6e49ee87082f2c97a6bc37ab7601e70f371..114cfadff524b5e06a5351e6f6bef647783b5f52 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
index 2d1c81c455fee09b07f7b97604961d5b80df0b0f..ed38ec97655047bb227f7e1e0ddc6ca3a93ed9f2 100644 (file)
@@ -22,7 +22,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
+/* #include <asm/bitops.h> */
 
 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
 #include "ipset.h"
index 1ebbc508a034315ab2089bf8a1fd6a7665a08884..0548b8623e1c420b3a4a75b649b7fb1b036202b5 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_ipporthash.h>
index 3ef8fb1156a1ad65341e2ef50c1e7e0dac2f08f1..c14547adcbedebd860ac6333f8aba755a263bac3 100644 (file)
@@ -24,7 +24,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <linux/if_ether.h>
 
 #include <linux/netfilter_ipv4/ip_set_macipmap.h>
index 758c4c187c9130f192b8a8034c5ad1a4b0d43d98..fed4a0202f6fb18dab8a099ba10d4625f81698fa 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_nethash.h>
index 1c3965b47b7bfc7361460d0b496ca8c4e10c9077..1d4f8074caaeae33e86114049447d9c0e07e461b 100644 (file)
@@ -21,7 +21,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 
 #include <linux/netfilter_ipv4/ip_set_portmap.h>
 #include "ipset.h"