[netfilter-cvslog] r3304 - trunk/iptables/extensions

kadlec at netfilter.org kadlec at netfilter.org
Wed Dec 1 10:11:33 CET 2004


Author: kadlec at netfilter.org
Date: 2004-12-01 10:11:33 +0100 (Wed, 01 Dec 2004)
New Revision: 3304

Added:
   trunk/iptables/extensions/libipt_SET.man
   trunk/iptables/extensions/libipt_set.h
   trunk/iptables/extensions/libipt_set.man
Modified:
   trunk/iptables/extensions/libipt_SET.c
   trunk/iptables/extensions/libipt_set.c
Log:
ipset 2 related updates (JK)


Modified: trunk/iptables/extensions/libipt_SET.c
===================================================================
--- trunk/iptables/extensions/libipt_SET.c	2004-12-01 09:07:34 UTC (rev 3303)
+++ trunk/iptables/extensions/libipt_SET.c	2004-12-01 09:11:33 UTC (rev 3304)
@@ -1,3 +1,13 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem at linux.nu>
+ *                         Patrick Schaaf <bof at bof.de>
+ *                         Martin Josefsson <gandalf at wlug.westbo.se>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * 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.  
+ */
+
 /* Shared library add-on to iptables to add IP set mangling target. */
 #include <stdio.h>
 #include <netdb.h>
@@ -11,14 +21,14 @@
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/netfilter_ipv4/ipt_set.h>
-#include "../ipset/libipt_set.h"
+#include "libipt_set.h"
 
 /* Function which prints out usage message. */
 static void help(void)
 {
 	printf("SET v%s options:\n"
-	       " --add-set name[:flags] flags\n"
-	       " --del-set name[:flags] flags\n"
+	       " --add-set name flags\n"
+	       " --del-set name flags\n"
 	       "		add/del src/dst IP/port from/to named sets,\n"
 	       "		where flags are the comma separated list of\n"
 	       "		'src' and 'dst'.\n"
@@ -38,13 +48,42 @@
 	    (struct ipt_set_info_target *) target->data;
 
 	memset(info, 0, sizeof(struct ipt_set_info_target));
-	info->add_set.id = -1;
-	info->del_set.id = -1;
+	info->add_set.index =
+	info->del_set.index = IP_SET_INVALID_ID;
 
 	/* Can't cache this */
 	*nfcache |= NFC_UNKNOWN;
 }
 
+static void
+parse_target(char **argv, int invert, unsigned int *flags,
+             struct ipt_set_info *info, const char *what)
+{
+	if (info->flags[0])
+		exit_error(PARAMETER_PROBLEM,
+			   "--%s can be specified only once", what);
+
+	if (check_inverse(optarg, &invert, NULL, 0))
+		exit_error(PARAMETER_PROBLEM,
+			   "Unexpected `!' after --%s", what);
+
+	if (!argv[optind]
+	    || argv[optind][0] == '-' || argv[optind][0] == '!')
+		exit_error(PARAMETER_PROBLEM,
+			   "--%s requires two args.", what);
+
+	if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
+		exit_error(PARAMETER_PROBLEM,
+			   "setname `%s' too long, max %d characters.",
+			   argv[optind-1], IP_SET_MAXNAMELEN - 1);
+
+	get_set_byname(argv[optind - 1], info);
+	parse_bindings(argv[optind], info);
+	optind++;
+	
+	*flags = 1;
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -53,44 +92,15 @@
 {
 	struct ipt_set_info_target *myinfo =
 	    (struct ipt_set_info_target *) (*target)->data;
-	struct ipt_set_info *info;
 
 	switch (c) {
-	case '1':		/* --add-set <set>[:<flags>] <flags> */
-		info = &myinfo->add_set;
-
-		if (check_inverse(optarg, &invert, NULL, 0))
-			exit_error(PARAMETER_PROBLEM,
-				   "Unexpected `!' after --add-set");
-
-		if (!argv[optind]
-		    || argv[optind][0] == '-' || argv[optind][0] == '!')
-			exit_error(PARAMETER_PROBLEM,
-				   "--add-set requires two args.");
-
-		parse_pool(argv[optind - 1], info);
-		parse_ipflags(argv[optind++], info);
-		
-		*flags = 1;
+	case '1':		/* --add-set <set> <flags> */
+		parse_target(argv, invert, flags,
+			     &myinfo->add_set, "add-set");
 		break;
 	case '2':		/* --del-set <set>[:<flags>] <flags> */
-		info = &myinfo->del_set;
-
-		if (check_inverse(optarg, &invert, NULL, 0))
-			exit_error(PARAMETER_PROBLEM,
-				   "Unexpected `!' after --del-set");
-
-		if (!argv[optind]
-		    || argv[optind][0] == '-' || argv[optind][0] == '!')
-			exit_error(PARAMETER_PROBLEM,
-				   "--del-set requires two args.");
-
-		parse_pool(argv[optind - 1], info);
-		if (parse_ipflags(argv[optind++], info))
-			exit_error(PARAMETER_PROBLEM,
-				   "Can't use overwrite flag with --del-set.");
-		
-		*flags = 1;
+		parse_target(argv, invert, flags,
+			     &myinfo->del_set, "del-set");
 		break;
 
 	default:
@@ -112,21 +122,17 @@
 {
 	int i;
 	char setname[IP_SET_MAXNAMELEN];
-
-	if (info->id >= 0) {
-		get_set_byid(setname, info->id);
-		printf("%s %s", prefix, setname);
-		for (i = 0; i < info->set_level; i++)
-			printf("%s%s",
-			       i == 0 ? ":" : ",",
-			       info->flags[i] & IPSET_SRC ? "src" : "dst");
-		for (i = info->set_level; i < info->ip_level; i++)
-			printf("%s%s%s",
-			       i == info->set_level ? " " : ",",
-			       info->flags[i] & IPSET_ADD_OVERWRITE ? "+" : "",
-			       info->flags[i] & IPSET_SRC ? "src" : "dst");
-		printf(" ");
+	
+	get_set_byid(setname, info->index);
+	printf("%s %s", prefix, setname);
+	for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
+		if (!info->flags[i])
+			break;		
+		printf("%s%s",
+		       i == 0 ? " " : ",",
+		       info->flags[i] & IPSET_SRC ? "src" : "dst");
 	}
+	printf(" ");
 }
 
 /* Prints out the targinfo. */

Added: trunk/iptables/extensions/libipt_SET.man
===================================================================
--- trunk/iptables/extensions/libipt_SET.man	2004-12-01 09:07:34 UTC (rev 3303)
+++ trunk/iptables/extensions/libipt_SET.man	2004-12-01 09:11:33 UTC (rev 3304)
@@ -0,0 +1,16 @@
+This modules adds and/or deletes entries from IP sets which can be defined 
+by ipset(8).
+.TP
+.BR "--add-set " "setname flag[,flag...]"
+add the address(es)/port(s) of the packet to the sets
+.TP
+.BR "--del-set " "setname flag[,flag...]"
+delete the address(es)/port(s) of the packet from the sets,
+where flags are
+.BR "src"
+and/or
+.BR "dst"
+and there can be no more than six of them.
+.TP
+The bindings to follow must previously be defined in order to use 
+multilevel adding/deleting by the SET target.

Modified: trunk/iptables/extensions/libipt_set.c
===================================================================
--- trunk/iptables/extensions/libipt_set.c	2004-12-01 09:07:34 UTC (rev 3303)
+++ trunk/iptables/extensions/libipt_set.c	2004-12-01 09:11:33 UTC (rev 3304)
@@ -1,4 +1,14 @@
-/* Shared library add-on to iptables to add IP address set matching. */
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem at linux.nu>
+ *                         Patrick Schaaf <bof at bof.de>
+ *                         Martin Josefsson <gandalf at wlug.westbo.se>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * 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.  
+ */
+
+/* Shared library add-on to iptables to add IP set matching. */
 #include <stdio.h>
 #include <netdb.h>
 #include <string.h>
@@ -10,14 +20,14 @@
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ipt_set.h>
-#include "../ipset/libipt_set.h"
+#include "libipt_set.h"
 
 /* Function which prints out usage message. */
 static void help(void)
 {
 	printf("set v%s options:\n"
-	       " [!] --set     name[:flags] flags\n"
-	       "		'name' is the set name from to match.\n" 
+	       " [!] --set     name flags\n"
+	       "		'name' is the set name from to match,\n" 
 	       "		'flags' are the comma separated list of\n"
 	       "		'src' and 'dst'.\n"
 	       "\n", IPTABLES_VERSION);
@@ -36,7 +46,6 @@
 	
 
 	memset(info, 0, sizeof(struct ipt_set_info_match));
-	info->match.id = -1;
 
 	/* Can't cache this - XXX */
 	*nfcache |= NFC_UNKNOWN;
@@ -50,23 +59,33 @@
 {
 	struct ipt_set_info_match *myinfo = 
 		(struct ipt_set_info_match *) (*match)->data;
-	struct ipt_set_info *info = &myinfo->match;
+	struct ipt_set_info *info = &myinfo->match_set;
 
 	switch (c) {
-	case '1':		/* --set <set>[:<flags>] <flags> */
+	case '1':		/* --set <set> <flag>[,<flag> */
+		if (info->flags[0])
+			exit_error(PARAMETER_PROBLEM,
+				   "--set can be specified only once");
+
 		check_inverse(optarg, &invert, &optind, 0);
 		if (invert)
 			info->flags[0] |= IPSET_MATCH_INV;
 
 		if (!argv[optind]
-		    || argv[optind][0] == '-' || argv[optind][0] == '!')
+		    || argv[optind][0] == '-'
+		    || argv[optind][0] == '!')
 			exit_error(PARAMETER_PROBLEM,
 				   "--set requires two args.");
 
-		parse_pool(argv[optind - 1], info);
-		if (parse_ipflags(argv[optind++], info))
+		if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
 			exit_error(PARAMETER_PROBLEM,
-				   "Can't use overwrite flag with --set.");
+				   "setname `%s' too long, max %d characters.",
+				   argv[optind-1], IP_SET_MAXNAMELEN - 1);
+
+		get_set_byname(argv[optind - 1], info);
+		parse_bindings(argv[optind], info);
+		DEBUGP("parse: set index %u\n", info->index);
+		optind++;
 		
 		*flags = 1;
 		break;
@@ -83,7 +102,8 @@
 {
 	if (!flags)
 		exit_error(PARAMETER_PROBLEM,
-			   "You must specify either `--set'");
+			   "You must specify `--set' with proper arguments");
+	DEBUGP("final check OK\n");
 }
 
 static void
@@ -92,22 +112,19 @@
 	int i;
 	char setname[IP_SET_MAXNAMELEN];
 
-	if (info->id >= 0) {
-		get_set_byid(setname, info->id);
-		printf("%s%s %s", 
-		       (info->flags[0] & IPSET_MATCH_INV) ? "!" : "",
-		       prefix,
-		       setname); 
-		for (i = 0; i < info->set_level; i++)
-			printf("%s%s",
-			       i == 0 ? ":" : ",",
-			       info->flags[i] & IPSET_SRC ? "src" : "dst");
-		for (i = info->set_level; i < info->ip_level; i++)
-			printf("%s%s",
-			       i == info->set_level ? " " : ",",
-			       info->flags[i] & IPSET_SRC ? "src" : "dst");
-		printf(" ");
+	get_set_byid(setname, info->index);
+	printf("%s%s %s", 
+	       (info->flags[0] & IPSET_MATCH_INV) ? "!" : "",
+	       prefix,
+	       setname); 
+	for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
+		if (!info->flags[i])
+			break;		
+		printf("%s%s",
+		       i == 0 ? " " : ",",
+		       info->flags[i] & IPSET_SRC ? "src" : "dst");
 	}
+	printf(" ");
 }
 
 /* Prints out the matchinfo. */
@@ -118,7 +135,7 @@
 	struct ipt_set_info_match *info = 
 		(struct ipt_set_info_match *) match->data;
 
-	print_match("set", &info->match);
+	print_match("set", &info->match_set);
 }
 
 /* Saves the matchinfo in parsable form to stdout. */
@@ -128,11 +145,11 @@
 	struct ipt_set_info_match *info = 
 		(struct ipt_set_info_match *) match->data;
 
-	print_match("--set", &info->match);
+	print_match("--set", &info->match_set);
 }
 
 static
-struct iptables_match set = { NULL,
+struct iptables_match set = {
 	.name		= "set",
 	.version	= IPTABLES_VERSION,
 	.size		= IPT_ALIGN(sizeof(struct ipt_set_info_match)),

Added: trunk/iptables/extensions/libipt_set.h
===================================================================
--- trunk/iptables/extensions/libipt_set.h	2004-12-01 09:07:34 UTC (rev 3303)
+++ trunk/iptables/extensions/libipt_set.h	2004-12-01 09:11:33 UTC (rev 3304)
@@ -0,0 +1,104 @@
+#ifndef _LIBIPT_SET_H
+#define _LIBIPT_SET_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#ifdef DEBUG
+#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
+#else
+#define DEBUGP(x, args...) 
+#endif
+
+static void
+parse_bindings(const char *optarg, struct ipt_set_info *info)
+{
+	char *saved = strdup(optarg);
+	char *ptr, *tmp = saved;
+	int i = 0;
+	
+	while (i < (IP_SET_MAX_BINDINGS - 1) && tmp != NULL) {
+		ptr = strsep(&tmp, ",");
+		if (strncmp(ptr, "src", 3) == 0)
+			info->flags[i++] |= IPSET_SRC;
+		else if (strncmp(ptr, "dst", 3) == 0)
+			info->flags[i++] |= IPSET_DST;
+		else
+			exit_error(PARAMETER_PROBLEM,
+				   "You must spefify (the comma separated list of) 'src' or 'dst'.");
+	}
+
+	if (tmp)
+		exit_error(PARAMETER_PROBLEM,
+			   "Can't follow bindings deeper than %i.", 
+			   IP_SET_MAX_BINDINGS - 1);
+
+	free(saved);
+}
+
+static int get_set_getsockopt(void *data, size_t * size)
+{
+	int sockfd = -1;
+	sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+	if (sockfd < 0)
+		exit_error(OTHER_PROBLEM,
+			   "Can't open socket to ipset.\n");
+	/* Send! */
+	return getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
+}
+
+static void get_set_byname(const char *setname, struct ipt_set_info *info)
+{
+	struct ip_set_req_get_set req;
+	int size = sizeof(struct ip_set_req_get_set);
+	int res;
+
+	req.op = IP_SET_OP_GET_BYNAME;
+	req.version = IP_SET_PROTOCOL_VERSION;
+	strncpy(req.set.name, setname, IP_SET_MAXNAMELEN);
+	req.set.name[IP_SET_MAXNAMELEN - 1] = '\0';
+	res = get_set_getsockopt(&req, &size);
+	if (res != 0)
+		exit_error(OTHER_PROBLEM,
+			   "Problem when communicating with ipset, errno=%d.\n",
+			   errno);
+	if (size != sizeof(struct ip_set_req_get_set))
+		exit_error(OTHER_PROBLEM,
+			   "Incorrect return size from kernel during ipset lookup, "
+			   "(want %d, got %d)\n",
+			   sizeof(struct ip_set_req_get_set), size);
+	if (req.set.index == IP_SET_INVALID_ID)
+		exit_error(PARAMETER_PROBLEM,
+			   "Set %s doesn't exist.\n", setname);
+
+	info->index = req.set.index;
+}
+
+static void get_set_byid(char * setname, ip_set_id_t index)
+{
+	struct ip_set_req_get_set req;
+	int size = sizeof(struct ip_set_req_get_set);
+	int res;
+
+	req.op = IP_SET_OP_GET_BYINDEX;
+	req.version = IP_SET_PROTOCOL_VERSION;
+	req.set.index = index;
+	res = get_set_getsockopt(&req, &size);
+	if (res != 0)
+		exit_error(OTHER_PROBLEM,
+			   "Problem when communicating with ipset, errno=%d.\n",
+			   errno);
+	if (size != sizeof(struct ip_set_req_get_set))
+		exit_error(OTHER_PROBLEM,
+			   "Incorrect return size from kernel during ipset lookup, "
+			   "(want %d, got %d)\n",
+			   sizeof(struct ip_set_req_get_set), size);
+	if (req.set.name[0] == '\0')
+		exit_error(PARAMETER_PROBLEM,
+			   "Set id %i in kernel doesn't exist.\n", index);
+
+	strncpy(setname, req.set.name, IP_SET_MAXNAMELEN);
+}
+
+#endif /*_LIBIPT_SET_H*/

Added: trunk/iptables/extensions/libipt_set.man
===================================================================
--- trunk/iptables/extensions/libipt_set.man	2004-12-01 09:07:34 UTC (rev 3303)
+++ trunk/iptables/extensions/libipt_set.man	2004-12-01 09:11:33 UTC (rev 3304)
@@ -0,0 +1,17 @@
+This modules macthes IP sets which can be defined by ipset(8).
+.TP
+.BR "--set " "setname flag[,flag...]"
+where flags are
+.BR "src"
+and/or
+.BR "dst" 
+and there can be no more than six of them. Hence the command
+.nf
+ iptables -A FORWARD -m set --set test src,dst
+.fi
+will match packets, for which (depending on the type of the set) the source
+address or port number of the packet can be found in the specified set. If 
+there is a binding belonging to the mached set element or there is a default 
+binding for the given set, then the rule will match the packet only if 
+additionally (depending on the type of the set) the destination address or 
+port number of the packet can be found in the set according to the binding.




More information about the netfilter-cvslog mailing list