From 3fd6b24ace319b139ec3c4e3031a5f05d21e304e Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Tue, 15 Jun 2010 13:30:55 +0200 Subject: ipset 5 in an almost ready state - milestone Reworked protocol and internal interfaces, missing set types added, backward compatibility verified, lots of tests added (and thanks to the tests, bugs fixed), even the manpage is rewritten ;-). Countless changes everywhere... The missing bits before announcing ipset 5: - net namespace support - new iptables/ip6tables extension library - iptables/ip6tables match and target tests (backward/forward compatibility) - tests on catching syntax errors --- src/Makefile.am | 1 - src/errcode.c | 26 +- src/ipset.8 | 1109 ++++++++++++++++++++++++-------------------- src/ipset.c | 194 ++++---- src/ipset_bitmap_ip.c | 16 +- src/ipset_bitmap_ipmac.c | 14 +- src/ipset_bitmap_port.c | 12 +- src/ipset_hash_ip.c | 52 ++- src/ipset_hash_ipport.c | 66 +-- src/ipset_hash_ipportip.c | 66 +-- src/ipset_hash_ipportnet.c | 83 ++-- src/ipset_hash_net.c | 59 ++- src/ipset_iptreemap.c | 208 --------- src/ipset_list_set.c | 31 +- src/ipset_tree_ip.c | 75 --- src/ui.c | 231 ++++++--- 16 files changed, 1125 insertions(+), 1118 deletions(-) delete mode 100644 src/ipset_iptreemap.c delete mode 100644 src/ipset_tree_ip.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 28b28fa..ebd08a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,6 @@ ipset_SOURCES = ipset.c \ ipset_hash_ipportnet.c \ ipset_hash_net.c \ ipset_list_set.c \ - ipset_tree_ip.c \ ui.c ipset_LDADD = ../lib/libipset.la AM_LDFLAGS = -static diff --git a/src/errcode.c b/src/errcode.c index 34b87a3..c30ecb6 100644 --- a/src/errcode.c +++ b/src/errcode.c @@ -8,6 +8,7 @@ #include /* errno */ #include /* strerror */ +#include /* D() */ #include /* ipset_data_get */ #include /* ipset_err */ #include /* struct ipset_type */ @@ -15,6 +16,7 @@ #include /* prototypes */ #include /* bitmap specific errcodes */ #include /* hash specific errcodes */ +#include /* list specific errcodes */ /* Core kernel error codes */ static const struct ipset_errcode_table core_errcode_table[] = { @@ -45,6 +47,8 @@ static const struct ipset_errcode_table core_errcode_table[] = { /* RENAME specific error codes */ { IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_RENAME, "Set cannot be renamed: a set with the new name already exists" }, + { IPSET_ERR_REFERENCED, IPSET_CMD_RENAME, + "Set cannot be renamed: it is in use by another system" }, /* SWAP specific error codes */ { IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_SWAP, @@ -101,6 +105,24 @@ static const struct ipset_errcode_table hash_errcode_table[] = { { }, }; +/* List type-specific error codes */ +static const struct ipset_errcode_table list_errcode_table[] = { + /* Generic (CADT) error codes */ + { IPSET_ERR_NAME, 0, + "Set to be added/deleted/tested as element does not exist." }, + { IPSET_ERR_LOOP, 0, + "Sets with list:set type cannot be added to the set." }, + { IPSET_ERR_BEFORE, 0, + "No reference set specified." }, + { IPSET_ERR_NAMEREF, 0, + "The set to which you referred with 'before' or 'after' does not exist." }, + { IPSET_ERR_LIST_FULL, 0, + "The set is full, more elements cannot be added." }, + { IPSET_ERR_REF_EXIST, 0, + "The set to which you referred with 'before' or 'after' is not added to the set." }, + { }, +}; + #define MATCH_TYPENAME(a, b) STRNEQ(a, b, strlen(b)) /** @@ -126,8 +148,10 @@ ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode) if (type) { if (MATCH_TYPENAME(type->name, "bitmap:")) table = bitmap_errcode_table; - if (MATCH_TYPENAME(type->name, "hash:")) + else if (MATCH_TYPENAME(type->name, "hash:")) table = hash_errcode_table; + else if (MATCH_TYPENAME(type->name, "list:")) + table = list_errcode_table; } } diff --git a/src/ipset.8 b/src/ipset.8 index fa73298..661d1b4 100644 --- a/src/ipset.8 +++ b/src/ipset.8 @@ -1,537 +1,628 @@ -.TH IPSET 8 "Feb 05, 2004" "" "" -.\" .\" Man page written by Jozsef Kadlecsik -.\" -.\" This program is free software; you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation; either version 2 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program; if not, write to the Free Software -.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -.\" -.\" -.SH NAME +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.TH "IPSET" "8" "Jun 11, 2010" "Jozsef Kadlecsik" "" +.SH "NAME" ipset \(em administration tool for IP sets -.SH SYNOPSIS -.PP -\fBipset \-N\fP \fIset\fP \fItype-specification\fP [\fIoptions\fP...] -.PP -\fBipset\fP {\fB\-F\fP|\fB\-H\fP|\fB\-L\fP|\fB\-S\fP|\fB\-X\fP} [\fIset\fP] -[\fIoptions\fP...] -.PP -\fBipset\fP {\fB\-E\fP|\fB\-W\fP} \fIfrom-set\fP \fIto-set\fP -.PP -\fBipset\fP {\fB\-A\fP|\fB\-D\fP|\fB\-T\fP} \fIset\fP \fIentry\fP -.PP -\fBipset \-R\fP -.PP -\fBipset\fP {\fB-V\fP|\fB\-v\fP} -.SH DESCRIPTION -.B ipset +.SH "SYNOPSIS" +\fBipset\fR [ \fIOPTIONS\fR ] \fICOMMAND\fR [ \fICOMMAND\-OPTIONS\fR ] +.PP +COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR } +.PP +\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR } +.PP +\fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ] +.PP +\fBipset\fR \fBadd\fR \fISETNAME\fR \fIADD\-ENTRY\fR [ \fIADD\-OPTIONS\fR ] +.PP +\fBipset\fR \fBdel\fR \fISETNAME\fR \fIDEL\-ENTRY\fR [ \fIDEL\-OPTIONS\fR ] +.PP +\fBipset\fR \fBtest\fR \fISETNAME\fR \fITEST\-ENTRY\fR [ \fITEST\-OPTIONS\fR ] +.PP +\fBipset\fR \fBdestroy\fR [ \fISETNAME\fR ] +.PP +\fBipset\fR \fBlist\fR [ \fISETNAME\fR ] +.PP +\fBipset\fR \fBsave\fR [ \fISETNAME\fR ] +.PP +\fBipset\fR \fBrestore\fR +.PP +\fBipset\fR \fBflush\fR [ \fISETNAME\fR ] +.PP +\fBipset\fR \fBrename\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR +.PP +\fBipset\fR \fBswap\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR +.PP +\fBipset\fR \fBhelp\fR [ \fITYPENAME\fR ] +.PP +\fBipset\fR \fBversion\fR +.PP +\fBipset\fR \fB\-\fR +.SH "DESCRIPTION" +\fBipset\fR is used to set up, maintain and inspect so called IP sets in the Linux -kernel. Depending on the type, an IP set may store IP addresses, (TCP/UDP) -port numbers or additional informations besides IP addresses: the word IP -means a general term here. See the set type definitions below. -.P -Iptables matches and targets referring to sets creates references, which -protects the given sets in the kernel. A set cannot be removed (destroyed) +kernel. Depending on the type of the set, an IP set may store IP(v4/v6) +addresses, (TCP/UDP) port numbers, IP and MAC address pairs, IP address +and port number pairs, etc. See the set type definitions below. +.PP +\fBIptables\fR +matches and targets referring to sets creates references, which +protect the given sets in the kernel. A set cannot be destroyed while there is a single reference pointing to it. -.SH OPTIONS +.SH "OPTIONS" The options that are recognized by -.B ipset +\fBipset\fR can be divided into several different groups. .SS COMMANDS -These options specify the specific action to perform. Only one of them -can be specified on the command line unless otherwise specified -below. For all the long versions of the command and option names, you -need to use only enough letters to ensure that -.B ipset -can differentiate it from all other options. -.TP -\fB\-N\fP, \fB\-\-create\fP \fIsetname\fP \fItype\fP \fItype-specific-options\fP -Create a set identified with setname and specified type. -Type-specific options must be supplied. -.TP -\fB\-X\fP, \fB\-\-destroy\fP [\fIsetname\fP] +These options specify the desired action to perform. Only one of them +can be specified on the command line unless otherwise specified below. +For all the long versions of the command names, you need to use only enough +letters to ensure that +\fBipset\fR +can differentiate it from all other options. The +\fBipset\fR +parser follows the order here when looking for the shortest match +in the long command names. +.TP +\fBn\fP, \fBcreate\fP \fISETNAME\fP \fITYPENAME\fP [ \fICREATE\-OPTIONS\fP ] +Create a set identified with setname and specified type. The type may require +type specific options. If the +\fB\-exist\fR +option is specified, +\fBipset\fR +ignores the error otherwise raised when the the same set (setname and create parameters +are identical) already exists. +.TP +\fBadd\fP \fISETNAME\fP \fIADD\-ENTRY\fP [ \fIADD\-OPTIONS\fP ] +Add a given entry to the set. If the +\fB\-exist\fR +option is specified, +\fBipset\fR +ignores if the entry already added to the set. +.TP +\fBdel\fP \fISETNAME\fP \fIDEL\-ENTRY\fP [ \fIDEL\-OPTIONS\fP ] +Delete an entry from a set. If the +\fB\-exist\fR +option is specified, +\fBipset\fR +ignores if the entry does not added (expired) to the set. +.TP +\fBtest\fP \fISETNAME\fP \fITEST\-ENTRY\fP [ \fITEST\-OPTIONS\fP ] +Test wether an entry is in a set or not. Exit status number is zero +if the tested entry is in the set and nonzero if it is missing from +the set. +.TP +\fBx\fP, \fBdestroy\fP [ \fISETNAME\fP ] Destroy the specified set or all the sets if none is given. -If the set has got references, nothing is done. -.TP -\fB\-F\fP, \fB\-\-flush\fP [\fIsetname\fP] -Delete all entries from the specified set or flush -all sets if none is given. -.TP -\fB\-E\fP, \fB\-\-rename\fP \fIfrom-setname\fP \fIto-setname\fP -Rename a set. Set identified by to-setname must not exist. -.TP -\fB\-W\fP, \fB\-\-swap\fP \fIfrom-setname\fP \fIto-setname\fP -Swap the content of two sets, or in another words, -exchange the name of two sets. The referred sets must exist and -identical type of sets can be swapped only. -.TP -\fB\-L\fP, \fB\-\-list\fP [\fIsetname\fP] -List the entries for the specified set, or for +If the set has got reference(s), nothing is done and no set destroyed. +.TP +\fBlist\fP [ \fISETNAME\fP ] +List the header data and the entries for the specified set, or for all sets if none is given. The -\fB\-r\fP/\fB\-\-resolve\fP +\fB\-\-resolve\fP option can be used to force name lookups (which may be slow). When the -\fB\-s\fP/\fB\-\-sorted\fP +\fB\-\-sorted\fP option is given, the entries are listed sorted (if the given set -type supports the operation). -.TP -\fB\-S\fP, \fB\-\-save\fP [\fIsetname\fP] +type supports the operation). The option +\fB\-\-output\fR +can be used to control the format of the listing: +\fBplain\fR, \fBsave\fR or \fBxml\fR. +The default is +\fBplain\fR. +.TP +\fBsave\fP [ \fISETNAME\fP ] Save the given set, or all sets if none is given -to stdout in a format that \fB\-\-restore\fP can read. -.TP -\fB\-R\fP, \fB\-\-restore\fP -Restore a saved session generated by \fB\-\-save\fP. The saved session -can be fed from stdin. - -When generating a session file please note that the supported commands -(create set and add element) must appear in a strict order: first create -the set, then add all elements. Then create the next set, add all its elements -and so on. Also, it is a restore operation, so the sets being restored must -not exist. -.TP -\fB\-A\fP, \fB\-\-add\fP \fIsetname\fP \fIentry\fP -Add an entry to a set. -.TP -\fB\-D\fP, \fB\-\-del\fP \fIsetname\fP \fIentry\fP -Delete an entry from a set. -.TP -\fB-T\fP, \fB\-\-test\fP \fIsetname\fP \fIentry\fP -Test wether an entry is in a set or not. Exit status number is zero -if the tested entry is in the set and nonzero if it is missing from -the set. -.TP -\fB\-H\fP, \fB\-\-help\fP [\fIsettype\fP] -Print help and settype specific help if settype specified. -.TP -\fB\-V\fP, \fB\-v\fP, \fB\-\-version\fP -Print program version and protocol version. +to stdout in a format that +\fBrestore\fP +can read. +.TP +\fBrestore\fP +Restore a saved session generated by +\fBsave\fP. +The saved session can be fed from stdin. +.TP +\fBflush\fP [ \fISETNAME\fP ] +Flush all entries from the specified set or flush +all sets if none is given. +.TP +\fBe\fP, \fBrename\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP +Rename a set. Set identified by +\fISETNAME\-TO\fR +must not exist. +.TP +\fBw\fP, \fBswap\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP +Swap the content of two sets, or in another words, +exchange the name of two sets. The referred sets must exist and +identical type of sets can be swapped only. +.TP +\fBhelp\fP [ \fITYPENAME\fP ] +Print help and set type specific help if +\fITYPENAME\fR +is specified. +.TP +\fBversion\fP +Print program version. +.TP +\fB\-\fP +If a dash is specified as command, then +\fBipset\fR +enters a simple interactive mode and the commands are read from the standard input. +The interactive mode can be finished by entering the pseudo\-command +\fBquit\fR. .P .SS "OTHER OPTIONS" -The following additional options can be specified: -.TP -\fB\-r\fP, \fB\-\-resolve\fP +The following additional options can be specified. The long option names +cannot be abbreviated. +.TP +\fB\-!\fP, \fB\-exist\fP +Ignore errors when the exactly the same set is to be created or already +added entry is added or missing entry is deleted. +.TP +\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR } +Select the output format to the +\fBlist\fR +command. +.TP +\fB\-q\fP, \fB\-quiet\fP +Suppress any output to stdout and stderr. +\fBipset\fR +will still exit with error if it cannot continue. +.TP +\fB\-r\fP, \fB\-resolve\fP When listing sets, enforce name lookup. The program will try to display the IP entries resolved to -host names or services (whenever applicable), which can trigger -.B -slow -DNS -lookups. -.TP -\fB\-s\fP, \fB\-\-sorted\fP +host names which requires +\fBslow\fR +DNS lookups. +.TP +\fB\-s\fP, \fB\-sorted\fP Sorted output. When listing sets, entries are listed sorted. -.TP -\fB\-n\fP, \fB\-\-numeric\fP -Numeric output. When listing sets, IP addresses and -port numbers will be printed in numeric format. This is the default. -.TP -\fB\-q\fP, \fB\-\-quiet\fP -Suppress any output to stdout and stderr. ipset will still return -possible errors. -.SH SET TYPES -ipset supports the following set types: -.SS ipmap -The ipmap set type uses a memory range, where each bit represents -one IP address. An ipmap set can store up to 65536 (B-class network) -IP addresses. The ipmap set type is very fast and memory cheap, great -for use when one want to match certain IPs in a range. If the optional -\fB\-\-netmask\fP -parameter is specified with a CIDR netmask value between 1-31 then -network addresses are stored in the given set: i.e an -IP address will be in the set if the network address, which is resulted -by masking the address with the specified netmask, can be found in the set. -.P -Options to use when creating an ipmap set: -.TP -\fB\-\-from\fP \fIfrom-addr\fP -.TP -\fB\-\-to\fP \fIto-addr\fP -Create an ipmap set from the specified address range. -.TP -\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP -Create an ipmap set from the specified network. -.TP -\fB\-\-netmask\fP \fIprefixlen\fP -When the optional -\fB\-\-netmask\fP -parameter specified, network addresses will be -stored in the set instead of IP addresses, and the \fIfrom-addr\fP parameter -must be a network address. The \fIprefixlen\fP value must be between 1-31. -.PP -Example: -.IP -ipset \-N test ipmap \-\-network 192.168.0.0/16 -.SS macipmap -The macipmap set type uses a memory range, where each 8 bytes -represents one IP and a MAC addresses. A macipmap set type can store -up to 65536 (B-class network) IP addresses with MAC. -When adding an entry to a macipmap set, you must specify the entry as -"\fIaddress\fP\fB,\fP\fImac\fP". -When deleting or testing macipmap entries, the -"\fB,\fP\fImac\fP" -part is not mandatory. -.P -Options to use when creating an macipmap set: -.TP -\fB\-\-from\fP \fIfrom-addr\fP -.TP -\fB\-\-to\fP \fIto-addr\fP -Create a macipmap set from the specified address range. -.TP -\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP -Create a macipmap set from the specified network. -.TP -\fB\-\-matchunset\fP -When the optional -\fB\-\-matchunset\fP -parameter specified, IP addresses which could be stored -in the set but not set yet, will always match. -.P -Please note, the -"set" -and -"SET" -netfilter kernel modules -.B -always -use the source MAC address from the packet to match, add or delete -entries from a macipmap type of set. -.SS portmap -The portmap set type uses a memory range, where each bit represents -one port. A portmap set type can store up to 65536 ports. -The portmap set type is very fast and memory cheap. -.P -Options to use when creating an portmap set: -.TP -\fB\-\-from\fP \fIfrom-port\fP -.TP -\fB\-\-to\fP \fIto-port\fP -Create a portmap set from the specified port range. -.SS iphash -The iphash set type uses a hash to store IP addresses. -In order to avoid clashes in the hash double-hashing, and as a last -resort, dynamic growing of the hash performed. The iphash set type is -great to store random addresses. If the optional -\fB\-\-netmask\fP -parameter is specified with a CIDR prefix length value between 1-31 then -network addresses are stored in the given set: i.e an -IP address will be in the set if the network address, which is resulted -by masking the address with the specified netmask, can be found in the set. -.P -Options to use when creating an iphash set: -.TP -\fB\-\-hashsize\fP \fIhashsize\fP -The initial hash size (default 1024) -.TP -\fB\-\-probes\fP \fIprobes\fP -How many times try to resolve clashing at adding an IP to the hash -by double-hashing (default 8). -.TP -\fB\-\-resize\fP \fIpercent\fP -Increase the hash size by this many percent (default 50) when adding -an IP to the hash could not be performed after -\fIprobes\fP -number of double-hashing. -.TP -\fB\-\-netmask\fP \fIprefixlen\fP -When the optional -\fB\-\-netmask\fP -parameter specified, network addresses will be -stored in the set instead of IP addresses. The \fIprefixlen\fP value must -be between 1-31. -.P -The iphash type of sets can store up to 65536 entries. If a set is full, -no new entries can be added to it. -.P -Sets created by zero valued resize parameter won't be resized at all. -The lookup time in an iphash type of set grows approximately linearly with -the value of the -\fIprobes\fP -parameter. In general higher -\fIprobes\fP -value results better utilized hash while smaller value -produces larger, sparser hash. -.PP -Example: -.IP -ipset \-N test iphash \-\-probes 2 -.SS nethash -The nethash set type uses a hash to store different size of -network addresses. The -.I -entry -used in the ipset commands must be in the form -"\fIaddress\fP\fB/\fP\fIprefixlen\fP" -where prefixlen must be in the inclusive range of 1-31. -In order to avoid clashes in the hash -double-hashing, and as a last resort, dynamic growing of the hash performed. -.P -Options to use when creating an nethash set: -.TP -\fB\-\-hashsize\fP \fIhashsize\fP -The initial hash size (default 1024) -.TP -\fB\-\-probes\fP \fIprobes\fP -How many times try to resolve clashing at adding an IP to the hash -by double-hashing (default 4). -.TP -\fB\-\-resize\fP \fIpercent\fP -Increase the hash size by this many percent (default 50) when adding -an IP to the hash could not be performed after -.P -The nethash type of sets can store up to 65536 entries. If a set is full, -no new entries can be added to it. -.P -An IP address will be in a nethash type of set if it belongs to any of the -netblocks added to the set. The matching always start from the smallest -size of netblock (most specific netmask) to the largest ones (least -specific netmasks). When adding/deleting IP addresses -to a nethash set by the -"SET" -netfilter kernel module, it will be added/deleted by the smallest -netblock size which can be found in the set, or by /31 if the set is empty. -.P -The lookup time in a nethash type of set grows approximately linearly -with the times of the -\fIprobes\fP -parameter and the number of different mask parameters in the hash. -Otherwise the same speed and memory efficiency comments applies here -as at the iphash type. -.SS ipporthash -The ipporthash set type uses a hash to store IP address and port pairs. -In order to avoid clashes in the hash double-hashing, and as a last -resort, dynamic growing of the hash performed. An ipporthash set can -store up to 65536 (B-class network) IP addresses with all possible port -values. When adding, deleting and testing values in an ipporthash type of -set, the entries must be specified as -"\fIaddress\fP\fB,\fP\fIport\fP". -.P -The ipporthash types of sets evaluates two src/dst parameters of the -"set" -match and -"SET" -target. -.P -Options to use when creating an ipporthash set: -.TP -\fB\-\-from\fP \fIfrom-addr\fP -.TP -\fB\-\-to\fP \fIto-addr\fP -Create an ipporthash set from the specified address range. -.TP -\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP -Create an ipporthash set from the specified network. -.TP -\fB\-\-hashsize\fP \fIhashsize\fP -The initial hash size (default 1024) -.TP -\fB\-\-probes\fP \fIprobes\fP -How many times try to resolve clashing at adding an IP to the hash -by double-hashing (default 8). -.TP -\fB\-\-resize\fP \fIpercent\fP -Increase the hash size by this many percent (default 50) when adding -an IP to the hash could not be performed after -\fIprobes\fP -number of double-hashing. -.P -The same resizing, speed and memory efficiency comments applies here -as at the iphash type. -.SS ipportiphash -The ipportiphash set type uses a hash to store IP address,port and IP -address triples. The first IP address must come form a maximum /16 -sized network or range while the port number and the second IP address -parameters are arbitrary. When adding, deleting and testing values in an -ipportiphash type of set, the entries must be specified as -"\fIaddress\fP\fB,\fP\fIport\fP\fB,\fP\fIaddress\fP". -.P -The ipportiphash types of sets evaluates three src/dst parameters of the -"set" -match and -"SET" -target. -.P -Options to use when creating an ipportiphash set: -.TP -\fB\-\-from\fP \fIfrom-addr\fP -.TP -\fB\-\-to\fP \fIto-addr\fP -Create an ipportiphash set from the specified address range. -.TP -\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP -Create an ipportiphash set from the specified network. -.TP -\fB\-\-hashsize\fP \fIhashsize\fP -The initial hash size (default 1024) -.TP -\fB\-\-probes\fP \fIprobes\fP -How many times try to resolve clashing at adding an IP to the hash -by double-hashing (default 8). -.TP -\fB\-\-resize\fP \fIpercent\fP -Increase the hash size by this many percent (default 50) when adding -an IP to the hash could not be performed after -\fIprobes\fP -number of double-hashing. -.P -The same resizing, speed and memory efficiency comments applies here -as at the iphash type. -.SS ipportnethash -The ipportnethash set type uses a hash to store IP address, port, and -network address triples. The IP address must come form a maximum /16 -sized network or range while the port number and the network address -parameters are arbitrary, but the size of the network address must be -between /1-/31. When adding, deleting -and testing values in an ipportnethash type of set, the entries must be -specified as -"\fIaddress\fP\fB,\fP\fIport\fP\fB,\fP\fIaddress\fP\fB/\fP\fIprefixlen\fP". -.P -The ipportnethash types of sets evaluates three src/dst parameters of the -"set" -match and -"SET" -target. -.P -Options to use when creating an ipportnethash set: -.TP -\fB\-\-from\fP \fIfrom-address\fP -.TP -\fB\-\-to\fP \fIto-address\fP -Create an ipporthash set from the specified range. -.TP -\fB\-\-network\fP \fIaddress\fP\fB/\fP\fImask\fP -Create an ipporthash set from the specified network. -.TP -\fB\-\-hashsize\fP \fIhashsize\fP -The initial hash size (default 1024) -.TP -\fB\-\-probes\fP \fIprobes\fP -How many times try to resolve clashing at adding an IP to the hash -by double-hashing (default 8). -.TP -\fB\-\-resize\fP \fIpercent\fP -Increase the hash size by this many percent (default 50) when adding -an IP to the hash could not be performed after -\fIprobes\fP -number of double-hashing. -.P -The same resizing, speed and memory efficiency comments applies here -as at the iphash type. -.SS iptree -The iptree set type uses a tree to store IP addresses, optionally -with timeout values. -.P -Options to use when creating an iptree set: -.TP -\fB\-\-timeout\fP \fIvalue\fP -The timeout value for the entries in seconds (default 0) -.P -If a set was created with a nonzero valued -\fB\-\-timeout\fP -parameter then one may add IP addresses to the set with a specific -timeout value using the syntax -"\fIaddress\fP\fB,\fP\fItimeout-value\fP". -Similarly to the hash types, the iptree type of sets can store up to 65536 -entries. -.SS iptreemap -The iptreemap set type uses a tree to store IP addresses or networks, -where the last octet of an IP address are stored in a bitmap. -As input entry, you can add IP addresses, CIDR blocks or network ranges -to the set. Network ranges can be specified in the format -"\fIaddress1\fP\fB-\fP\fIaddress2\fP". -.P -Options to use when creating an iptreemap set: -.TP -\fB\-\-gc\fP \fIvalue\fP -How often the garbage collection should be called, in seconds (default 300) -.SS setlist -The setlist type uses a simple list in which you can store sets. By the -ipset -command you can add, delete and test sets in a setlist type of set. -You can specify the sets as -"\fIsetname\fP[\fB,\fP{\fBafter\fP|\fBbefore\fP},\fIsetname\fP]". -By default new sets are added after (appended to) the existing -elements. Setlist type of sets cannot be added to a setlist type of set. -.P -Options to use when creating a setlist type of set: -.TP -\fB\-\-size\fP \fIsize\fP -Create a setlist type of set with the given size (default 8). -.PP -By the -"set" -match or -"SET" -target of -\fBiptables\fP(8) -you can test, add or delete entries in the sets. The match -will try to find a matching IP address/port in the sets and -the target will try to add the IP address/port to the first set -to which it can be added. The number of src,dst options of -the match and target are important: sets which eats more src,dst -parameters than specified are skipped, while sets with equal -or less parameters are checked, elements added. For example -if -.I -a -and -.I -b -are setlist type of sets then in the command -.IP -iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add-set b src,dst -.PP -the match and target will skip any set in -.I a -and -.I b -which stores -data triples, but will check all sets with single or double -data storage in -.I a +.SH "SET TYPES" +A set type comprises of the storage method by which the data is stored and +the data type(s) which are stored in the set. Therefore the +\fITYPENAME\fR +parameter of the +\fBcreate\fR +command follows the syntax + +\fITYPENAME\fR := \fImethod\fR\fB:\fR\fItype\fR[\fB,\fR\fItype\fR[\fB,\fR\fItype\fR]] + +where the current list of the methods are +\fBbitmap\fR, \fBhash\fR, \fBlist\fR and the possible data types are \fBip\fR, +\fBmac\fR and \fBport\fR. + +When adding, deleting or testing entries in a set, the same comma separated +data syntax must be used for the entry parameter of the commands, i.e + +ipset add foo ipaddr,portnum,ipaddr + +All set types support the optional + +\fBtimeout\fR \fIvalue\fR + +parameter when creating a set and adding entries. The value of the \fBtimeout\fR +parameter for the \fBcreate\fR command means the default timeout value (in seconds) +for new entries. If a set is created with timeout support, then the same +\fBtimeout\fR option can be used to specify non\-default timeout values +when adding entries. Zero timeout value means the entry is added permanent to the set. +.SS bitmap:ip +The \fBbitmap:ip\fR set type uses a memory range to store either IPv4 host +(default) or IPv4 network addresses. A \fBbitmap:ip\fR type of set can store up +to 65536 entries. +.PP +\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfrom\-ip\fP\-\fIto\-ip\fR|\fIip\fR/\fIcidr\fR [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIipaddr\fR/\fIcidr\fR } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIipaddr\fR/\fIcidr\fR } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR } +.PP +Mandatory \fBcreate\fR options: +.TP +\fBrange\fP \fIfrom\-ip\fP\-\fIto\-ip\fR|\fIip\fR/\fIcidr\fR +Create the set from the specified inclusive address range expressed in an +IPv4 address range or network. The size of the range (in entries) cannot exceed +the limit of maximum 65536 elements. +.PP +Optional \fBcreate\fR options: +.TP +\fBnetmask\fP \fIcidr\fP +When the optional \fBnetmask\fP parameter specified, network addresses will be +stored in the set instead of IP host addresses. The \fIcidr\fR value must be +between 1\-32. +An IP address will be in the set if the network address, which is resulted by +masking the address with the specified netmask calculated from the cidr value, +can be found in the set. +.PP +Examples: +.IP +ipset create foo bitmap:ip range 192.168.0.0/16 +.IP +ipset add foo 192.168.1/24 +.IP +ipset test foo 192.168.1.1 +.SS bitmap:ip,mac +The \fBbitmap:ip,mac\fR set type uses a memory range to store IPv4 and a MAC address pairs. A \fBbitmap:ip,mac\fR type of set can store up to 65536 entries. +.PP +\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfrom\-ip\fP\-\fIto\-ip\fR|\fIip\fR/\fIcidr\fR [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] } +.PP +Mandatory options to use when creating a \fBbitmap:ip,mac\fR type of set: +.TP +\fBrange\fP \fIfrom\-ip\fP\-\fIto\-ip\fR|\fIip\fR/\fIcidr\fR +Create the set from the specified inclusive address range expressed in an +IPv4 address range or network. The size of the range cannot exceed the limit +of maximum 65536 entries. +.PP +The \fBbitmap:ip,mac\fR type is exceptional in the sense that the MAC part can +be left out when adding/deleting/testing entries in the set. If +we add an entry without the MAC address specified, when the first time the entry is +matched by the kernel, it will automatically fill out the missing part with the +source MAC address from the packet. If the entry was specified with a timeout value, +the timer starts off when the IP and MAC address pair is complete. +.PP +Please note, the \fBset\fR match and \fBSET\fR target netfilter kernel modules +\fBalways\fR use the source MAC address from the packet to match, add or delete +entries from a \fBbitmap:ip,mac\fR type of set. +.PP +Examples: +.IP +ipset create foo bitmap:ip,mac range 192.168.0.0/16 +.IP +ipset add foo 192.168.1,12:34:56:78:9A:BC +.IP +ipset test foo 192.168.1.1 +.SS bitmap:port +The \fBbitmap:port\fR set type uses a memory range to store port numbers +and such a set can store up to 65536 ports. +.PP +\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfrom\-port\fP\-\fIto\-port [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIport\fR | \fIfrom\-port\fR\-\fIto\-port\fR } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := {\fIport\fR | \fIfrom\-port\fR\-\fIto\-port\fR } +.PP +\fITEST\-ENTRY\fR := { \fIport\fR } +.PP +Mandatory options to use when creating a \fBbitmap:port\fR type of set: +.TP +\fBrange\fP \fIfrom\-port\fP\-\fIto\-port\fR +Create the set from the specified inclusive port range. +.PP +Examples: +.IP +ipset create foo bitmap:port range 0\-1024 +.IP +ipset add foo 80 +.IP +ipset test foo 80 +.SS hash:ip +The \fBhash:ip\fR set type uses a hash to store IP addresses. +In order to avoid clashes in the hash a limited number of chaining, and then +if that is exhausted, the doubling of the hash is performed. +.PP +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR } +.PP +For the \fBinet\fR family one can add or delete multiple entries by specifying +a range or a network: +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIipaddr\fR/\fIcidr\fR } +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIipaddr\fR/\fIcidr\fR } +.PP +Optional \fBcreate\fR options: +.TP +\fBfamily\fR { \fBinet\fR|\fBinet6\fR } +The protocol family of the IP addresses to be stored in the set. The default is +\fBinet\fR, i.e IPv4. +.TP +\fBhashsize\fR \fIvalue\fR +The initial hash size for the set, default is 1024. The hash size must be a power +of two, the kernel automatically rounds up non power of two hash sizes to the first +correct value. +.TP +\fBmaxelem\fR \fIvalue\fR +The maximal number of elements which can be stored in the set, default 65536. +.TP +\fBnetmask\fP \fIcidr\fP +When the optional \fBnetmask\fP parameter specified, network addresses will be +stored in the set instead of IP host addresses. The \fIcidr\fP value must be +between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set +if the network address, which is resulted by masking the address with the netmask +calculated from the cidr, can be found in the set. +.PP +Examples: +.IP +ipset create foo hash:ip netmask 24 +.IP +ipset add foo 192.168.1.1 +.IP +ipset test foo 192.168.1.2 +.SS hash:net +The \fBhash:net\fR set type uses a hash to store different sized of IP networks. +In order to avoid clashes in the hash a limited number of chaining, and then +if that is exhausted, the doubling of the hash is performed. +.PP +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] } +.PP +Optional \fBcreate\fR options: +.TP +\fBfamily\fR { \fBinet\fR|\fBinet6\fR } +The protocol family of the IP addresses to be stored in the set. The default is +\fBinet\fR, i.e IPv4. +.TP +\fBhashsize\fR \fIvalue\fR +The initial hash size for the set, default is 1024. The hash size must be a power +of two, the kernel automatically rounds up non power of two hash sizes to the first +correct value. +.TP +\fBmaxelem\fR \fIvalue\fR +The maximal number of elements which can be stored in the set, default 65536. +.PP +When adding/deleting/testing entries, if the cidr parameter is not specified, +then the host cidr value is assumed. +.PP +From the \fBset\fR netfilter match point of view an IP address will be in a \fBhash:net\fR type of set if it belongs to any of the netblocks added to the set. +The matching always start from the smallest size of netblock (most specific +cidr) to the largest ones (least specific cidr). When adding/deleting IP +addresses to the set by the \fBSET\fR netfilter target, it will be +added/deleted by the most specific cidr which can be found in the +set, or by the host cidr value if the set is empty. +.PP +The lookup time grows linearly with the number of the different \fIcidr\fR +values added to the set. +.PP +Examples: +.IP +ipset create foo hash:net +.IP +ipset add foo 192.168.0/24 +.IP +ipset add foo 10.1.0.0/16 +.IP +ipset test foo 192.168.0/24 +.SS hash:ip,port +The \fBhash:ip,port\fR set type uses a hash to store IP address and port pairs. +In order to avoid clashes in the hash a limited number of chaining, and then +if that is exhausted, the doubling of the hash is performed. +.PP +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR } +.PP +Optional \fBcreate\fR options: +.TP +\fBfamily\fR { \fBinet\fR|\fBinet6\fR } +The protocol family of the IP addresses to be stored in the set. The default is +\fBinet\fR, i.e IPv4. +.TP +\fBhashsize\fR \fIvalue\fR +The initial hash size for the set, default is 1024. The hash size must be a power +of two, the kernel automatically rounds up non power of two hash sizes to the first +correct value. +.TP +\fBmaxelem\fR \fIvalue\fR +The maximal number of elements which can be stored in the set, default 65536. +.PP +The \fBhash:ip,port\fR type of sets require two \fBsrc\fR/\fBdst\fR parameters of +the \fBset\fR match and \fBSET\fR target kernel modules. +.PP +Examples: +.IP +ipset create foo hash:ip,port +.IP +ipset add foo 192.168.1.1,80 +.IP +ipset test foo 192.168.1.1,80 +.SS hash:ip,port,ip +The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port and +IP address triples. In order to avoid clashes in the hash a limited number of +chaining, and then if that is exhausted, the doubling of the hash is performed. +.PP +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR } +.PP +Optional \fBcreate\fR options: +.TP +\fBfamily\fR { \fBinet\fR|\fBinet6\fR } +The protocol family of the IP addresses to be stored in the set. The default is +\fBinet\fR, i.e IPv4. +.TP +\fBhashsize\fR \fIvalue\fR +The initial hash size for the set, default is 1024. The hash size must be a power +of two, the kernel automatically rounds up non power of two hash sizes to the first +correct value. +.TP +\fBmaxelem\fR \fIvalue\fR +The maximal number of elements which can be stored in the set, default 65536. +.PP +The \fBhash:ip,port,ip\fR type of sets require three \fBsrc\fR/\fBdst\fR parameters of +the \fBset\fR match and \fBSET\fR target kernel modules. +.PP +Examples: +.IP +ipset create foo hash:ip,port,ip +.IP +ipset add foo 192.168.1.1,80,10.0.0.1 +.IP +ipset test foo 192.168.1.1,80,10.0.0.1 +.SS hash:ip,port,net +The \fBhash:ip,port,net\fR set type uses a hash to store IP address, port and +IP network triples. +In order to avoid clashes in the hash a limited number of chaining, and then +if that is exhausted, the doubling of the hash is performed. +.PP +\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] } +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] } +.PP +\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] } +.PP +Optional \fBcreate\fR options: +.TP +\fBfamily\fR { \fBinet\fR|\fBinet6\fR } +The protocol family of the IP addresses to be stored in the set. The default is +\fBinet\fR, i.e IPv4. +.TP +\fBhashsize\fR \fIvalue\fR +The initial hash size for the set, default is 1024. The hash size must be a power +of two, the kernel automatically rounds up non power of two hash sizes to the first +correct value. +.TP +\fBmaxelem\fR \fIvalue\fR +The maximal number of elements which can be stored in the set, default 65536. +.PP +When adding/deleting/testing entries, if the cidr parameter is not specified, +then the host cidr value is assumed. +.PP +From the \fBset\fR netfilter match point of view a triple will be in a \fBhash:ip,port,net\fR type of set (when the first IP and the port match) +if the second IP belongs to any of the netblocks added to the set. +The matching always start from the smallest size of netblock (most specific +cidr) to the largest ones (least specific cidr). When adding/deleting triples +to the set by the \fBSET\fR netfilter target, it will be +added/deleted by the most specific cidr which can be found in the +set, or by the host cidr value if the set is empty. +.PP +The lookup time grows linearly with the number of the different \fIcidr\fR +values added to the set. +.PP +The \fBhash:ip,port,net\fR type of sets require three \fBsrc\fR/\fBdst\fR parameters of +the \fBset\fR match and \fBSET\fR target kernel modules. +.PP +Examples: +.IP +ipset create foo hash:ip,port,net +.IP +ipset add foo 192.168.1,80,10.0.0/24 +.IP +ipset add foo 192.168.2,25,10.1.0.0/16 +.IP +ipset test foo 192.168.1,80.10.0.0/24 +.SS list:set +The \fBlist:set\fR type uses a simple list in which you can store +sets. +.PP +\fICREATE\-OPTIONS\fR := [ \fBsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIADD\-ENTRY\fR := \fIsetname\fR [ \fBbefore\fR|\fBafter\fR \fIsetname\fR ] +.PP +\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ] +.PP +\fIDEL\-ENTRY\fR := \fIsetname\fR [ \fBbefore\fR|\fBafter\fR \fIsetname\fR ] +.PP +\fITEST\-ENTRY\fR := \fIsetname\fR [ \fBbefore\fR|\fBafter\fR \fIsetname\fR ] +.PP +Optional \fBcreate\fR options: +.TP +\fBsize\fR \fIvalue\fR +The size of the list, the default is 8. +.PP +By the \fBipset\fR commad you can add, delete and test sets in a +\fBlist:set\fR type of set. +.PP +By the \fBset\fR match or \fBSET\fR target of netfiler +you can test, add or delete entries in the sets added to the \fBlist:set\fR +type of set. The match will try to find a matching entry in the sets and +the target will try to add an entry to the first set to which it can be added. +The number of src,dst options of the match and target are important: sets which +eats more src,dst parameters than specified are skipped, while sets with equal +or less parameters are checked, elements added. For example if \fIa\fR and +\fIb\fR are \fBlist:set\fR type of sets then in the command +.IP +iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add\-set b src,dst +.PP +the match and target will skip any set in \fIa\fR and \fIb\fR +which stores data triples, but will check all sets with single or double +data storage in \fIa\fR set and add src to the first single or src,dst to the first double -data storage set in -\fIb\fP. -.P +data storage set in \fIb\fR. +.PP You can imagine a setlist type of set as an ordered union of the set elements. -.SH GENERAL RESTRICTIONS -Setnames starting with colon (:) cannot be defined. Zero valued set -entries cannot be used with hash type of sets. -.SH COMMENTS +.SH "GENERAL RESTRICTIONS" +Zero valued set entries cannot be used with hash methods. +.SH "COMMENTS" If you want to store same size subnets from a given network -(say /24 blocks from a /8 network), use the ipmap set type. +(say /24 blocks from a /8 network), use the \fBbitmap:ip\fR set type. If you want to store random same size networks (say random /24 blocks), -use the iphash set type. If you have got random size of netblocks, -use nethash. -.P -Old separator tokens (':' and '%") are still accepted. -.P -Binding support is removed. -.SH DIAGNOSTICS +use the \fBhash:ip\fR set type. If you have got random size of netblocks, +use \fBhash:net\fR. +.PP +Backward compatibility is maintained and old \fBipset\fR syntax is still supported. +.PP +The \fBiptree\fR and \fBiptreemap\fR set types are removed: if you refer to them, +they are automatically replaced by \fBhash:ip\fR type of sets. +.SH "DIAGNOSTICS" Various error messages are printed to standard error. The exit code -is 0 for correct functioning. Errors which appear to be caused by -invalid or abused command line parameters cause an exit code of 2, and -other errors cause an exit code of 1. -.SH BUGS -Bugs? No, just funny features. :-) +is 0 for correct functioning. +.SH "BUGS" +Bugs? No, just funny features. :\-) OK, just kidding... -.SH SEE ALSO -.BR iptables (8), -.SH AUTHORS +.SH "SEE ALSO" +\fBiptables\fR(8), +\fBip6tables\fR(8) +.SH "AUTHORS" Jozsef Kadlecsik wrote ipset, which is based on ippool by Joakim Axelsson, Patrick Schaaf and Martin Josefsson. -.P +.br Sven Wegener wrote the iptreemap type. -.SH LAST REMARK -.BR "I stand on the shoulders of giants." +.SH "LAST REMARK" +\fBI stand on the shoulders of giants.\fR diff --git a/src/ipset.c b/src/ipset.c index d29042d..69fcd09 100644 --- a/src/ipset.c +++ b/src/ipset.c @@ -15,11 +15,12 @@ #include +#include /* D() */ #include /* ipset_parse_* */ #include /* ipset_session_* */ #include /* struct ipset_type */ #include /* core options, commands */ -#include /* ipset_name_match */ +#include /* STREQ */ static char program_name[] = PACKAGE; static char program_version[] = PACKAGE_VERSION; @@ -31,6 +32,18 @@ static char cmdline[1024]; static char *newargv[255]; static int newargc = 0; +/* The known set types: (typename, revision, family) is unique */ +extern struct ipset_type ipset_bitmap_ip0; +extern struct ipset_type ipset_bitmap_ipmac0; +extern struct ipset_type ipset_bitmap_port0; +extern struct ipset_type ipset_hash_ip0; +extern struct ipset_type ipset_hash_net0; +extern struct ipset_type ipset_hash_ipport0; +extern struct ipset_type ipset_hash_ipportip0; +extern struct ipset_type ipset_hash_ipportnet0; +extern struct ipset_type ipset_tree_ip0; +extern struct ipset_type ipset_list_set0; + enum exittype { NO_PROBLEM = 0, OTHER_PROBLEM, @@ -38,7 +51,7 @@ enum exittype { VERSION_PROBLEM, }; -static void __attribute__((format(printf,2,3))) +static int __attribute__((format(printf,2,3))) exit_error(int status, const char *msg, ...) { bool quiet = !interactive @@ -52,7 +65,8 @@ exit_error(int status, const char *msg, ...) va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); - fprintf(stderr, "\n"); + if (msg[strlen(msg) - 1] != '\n') + fprintf(stderr, "\n"); if (status == PARAMETER_PROBLEM) fprintf(stderr, @@ -63,7 +77,7 @@ exit_error(int status, const char *msg, ...) if (status && interactive) { if (session) ipset_session_report_reset(session); - return; + return -1; } if (session) @@ -71,6 +85,8 @@ exit_error(int status, const char *msg, ...) D("status: %u", status); exit(status); + /* Unreached */ + return -1; } static int @@ -81,8 +97,8 @@ handle_error(void) fprintf(stderr, "Warning: %s\n", ipset_session_warning(session)); if (ipset_session_error(session)) - exit_error(OTHER_PROBLEM, "%s", - ipset_session_error(session)); + return exit_error(OTHER_PROBLEM, "%s", + ipset_session_error(session)); if (!interactive) { ipset_session_fini(session); @@ -96,19 +112,15 @@ handle_error(void) static void help(void) { - enum ipset_cmd cmd; + const struct ipset_commands *c; const struct ipset_envopts *opt = ipset_envopts; printf("%s v%s\n\n" "Usage: %s [options] COMMAND\n\nCommands:\n", program_name, program_version, program_name); - for (cmd = IPSET_CMD_NONE + 1; cmd < IPSET_CMD_MAX; cmd++) { - if (!ipset_commands[cmd-1].name[0]) - continue; - printf("%s %s\n", - ipset_commands[cmd-1].name[0], - ipset_commands[cmd-1].help); + for (c = ipset_commands; c->cmd; c++) { + printf("%s %s\n", c->name[0], c->help); } printf("\nOptions:\n"); @@ -136,9 +148,11 @@ build_argv(char *buffer) while ((ptr = strtok(NULL, " \t\n")) != NULL) { if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *))) newargv[newargc++] = ptr; - else + else { exit_error(PARAMETER_PROBLEM, "Line is too long to parse."); + return; + } } } @@ -188,57 +202,61 @@ restore(char *argv0) } static int -call_parser(int argc, char *argv[], const struct ipset_arg *args) +call_parser(int argc, char *argv[], const struct ipset_arg *args) { int i = 1, ret = 0; const struct ipset_arg *arg; + const char *optstr; - /* Currently CREATE and ADD may have got additional arguments */ + /* Currently CREATE and ADT may have got additional arguments */ if (!args) goto done; for (arg = args; arg->opt; arg++) { for (i = 1; i < argc; ) { - D("argc: %u, i: %u", argc, i); - if (!(ipset_name_match(argv[i], arg->name))) { + D("argc: %u, i: %u: %s vs %s", argc, i, argv[i], arg->name[0]); + if (!(ipset_match_option(argv[i], arg->name))) { i++; continue; } + optstr = argv[i]; /* Shift off matched option */ D("match %s", arg->name[0]); ipset_shift_argv(&argc, argv, i); D("argc: %u, i: %u", argc, i); switch (arg->has_arg) { case IPSET_MANDATORY_ARG: - if (i + 1 > argc) { - exit_error(PARAMETER_PROBLEM, - "Missing mandatory argument of option `%s'", - arg->name[0]); - return 1; - } + if (i + 1 > argc) + return exit_error(PARAMETER_PROBLEM, + "Missing mandatory argument of option `%s'", + arg->name[0]); /* Fall through */ case IPSET_OPTIONAL_ARG: if (i + 1 <= argc) { - ret = arg->parse(session, arg->opt, - argv[i]); + ret = ipset_call_parser(session, + arg->parse, + optstr, arg->opt, + argv[i]); if (ret < 0) return ret; ipset_shift_argv(&argc, argv, i); + break; } - break; + /* Fall through */ default: - ret = ipset_data_set(ipset_session_data(session), - arg->opt, arg->name[0]); + ret = ipset_call_parser(session, + arg->parse, + optstr, arg->opt, + optstr); if (ret < 0) return ret; } } } done: - if (i < argc) { - exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", - argv[i]); - return 1; - } + if (i < argc) + return exit_error(PARAMETER_PROBLEM, + "Unknown argument: `%s'", + argv[i]); return ret; } @@ -256,12 +274,20 @@ check_mandatory(const struct ipset_type *type, int cmd) mandatory &= ~flags; if (!mandatory) return; + if (!arg) { + exit_error(OTHER_PROBLEM, + "There are missing mandatory flags but can't check them. " + "It's a bug, please report the problem."); + return; + } for (; arg->opt; arg++) - if (mandatory & IPSET_FLAG(arg->opt)) + if (mandatory & IPSET_FLAG(arg->opt)) { exit_error(PARAMETER_PROBLEM, "Mandatory option `%s' is missing", arg->name[0]); + return; + } } static const struct ipset_type * @@ -270,7 +296,7 @@ type_find(const char *name) const struct ipset_type *t = ipset_types(); while (t) { - if (STREQ(t->name, name) || STREQ(t->alias, name)) + if (ipset_match_typename(name, t)) return t; t = t->next; } @@ -299,7 +325,7 @@ parse_commandline(int argc, char *argv[]) { int ret = 0; enum ipset_cmd cmd = IPSET_CMD_NONE; - int i = 0, j; + int i; char *arg0 = NULL, *arg1 = NULL, *c; const struct ipset_envopts *opt; const struct ipset_commands *command; @@ -309,16 +335,16 @@ parse_commandline(int argc, char *argv[]) if (session == NULL) { session = ipset_session_init(printf); if (session == NULL) - exit_error(OTHER_PROBLEM, - "Cannot initialize ipset session, aborting."); + return exit_error(OTHER_PROBLEM, + "Cannot initialize ipset session, aborting."); } /* Commandline parsing, somewhat similar to that of 'ip' */ /* First: parse core options */ - for (opt = ipset_envopts; opt->flag ; opt++) { + for (opt = ipset_envopts; opt->flag; opt++) { for (i = 1; i < argc; ) { - if (!ipset_name_match(argv[i], opt->name)) { + if (!ipset_match_envopt(argv[i], opt->name)) { i++; continue; } @@ -327,9 +353,9 @@ parse_commandline(int argc, char *argv[]) switch (opt->has_arg) { case IPSET_MANDATORY_ARG: if (i + 1 > argc) - exit_error(PARAMETER_PROBLEM, - "Missing mandatory argument to option %s", - opt->name[0]); + return exit_error(PARAMETER_PROBLEM, + "Missing mandatory argument to option %s", + opt->name[0]); /* Fall through */ case IPSET_OPTIONAL_ARG: if (i + 1 <= argc) { @@ -340,53 +366,49 @@ parse_commandline(int argc, char *argv[]) ipset_shift_argv(&argc, argv, i); } break; - default: - ret = opt->parse(session, opt->flag, argv[i]); + case IPSET_NO_ARG: + ret = opt->parse(session, opt->flag, + opt->name[0]); if (ret < 0) return handle_error(); break; + default: + break; } } } /* Second: parse command */ - for (j = IPSET_CMD_NONE + 1; j < IPSET_CMD_MAX; j++) { - command = &ipset_commands[j - 1]; - if (!command->name[0]) - continue; + for (command = ipset_commands; + command->cmd && cmd == IPSET_CMD_NONE; + command++) { for (i = 1; i < argc; ) { - if (!ipset_name_match(argv[i], command->name)) { + if (!ipset_match_cmd(argv[1], command->name)) { i++; continue; } - if (cmd != IPSET_CMD_NONE) - exit_error(PARAMETER_PROBLEM, - "Commands `%s' and `%s'" - "cannot be specified together.", - ipset_commands[cmd - 1].name[0], - command->name[0]); if (restore_line != 0 - && (j == IPSET_CMD_RESTORE - || j == IPSET_CMD_VERSION - || j == IPSET_CMD_HELP)) - exit_error(PARAMETER_PROBLEM, - "Command `%s' is invalid in restore mode.", - command->name[0]); - if (interactive && j == IPSET_CMD_RESTORE) { - printf("Restore command ignored in interactive mode\n"); + && (command->cmd == IPSET_CMD_RESTORE + || command->cmd == IPSET_CMD_VERSION + || command->cmd == IPSET_CMD_HELP)) + return exit_error(PARAMETER_PROBLEM, + "Command `%s' is invalid in restore mode.", + command->name[0]); + if (interactive && command->cmd == IPSET_CMD_RESTORE) { + printf("Restore command ignored in interactive mode\n"); return 0; } /* Shift off matched command arg */ ipset_shift_argv(&argc, argv, i); - cmd = j; + cmd = command->cmd; switch (command->has_arg) { case IPSET_MANDATORY_ARG: case IPSET_MANDATORY_ARG2: if (i + 1 > argc) - exit_error(PARAMETER_PROBLEM, - "Missing mandatory argument to command %s", - command->name[0]); + return exit_error(PARAMETER_PROBLEM, + "Missing mandatory argument to command %s", + command->name[0]); /* Fall through */ case IPSET_OPTIONAL_ARG: arg0 = argv[i]; @@ -399,13 +421,14 @@ parse_commandline(int argc, char *argv[]) } if (command->has_arg == IPSET_MANDATORY_ARG2) { if (i + 1 > argc) - exit_error(PARAMETER_PROBLEM, - "Missing second mandatory argument to command %s", - command->name[0]); + return exit_error(PARAMETER_PROBLEM, + "Missing second mandatory argument to command %s", + command->name[0]); arg1 = argv[i]; /* Shift off second arg */ ipset_shift_argv(&argc, argv, i); } + break; } } @@ -433,14 +456,14 @@ parse_commandline(int argc, char *argv[]) parse_commandline(newargc, newargv); printf("%s> ", program_name); } - exit_error(NO_PROBLEM, NULL); + return exit_error(NO_PROBLEM, NULL); } - exit_error(PARAMETER_PROBLEM, "No command specified."); + return exit_error(PARAMETER_PROBLEM, "No command specified."); case IPSET_CMD_VERSION: printf("%s v%s.\n", program_name, program_version); if (interactive) return 0; - exit_error(NO_PROBLEM, NULL); + return exit_error(NO_PROBLEM, NULL); case IPSET_CMD_HELP: help(); @@ -450,8 +473,8 @@ parse_commandline(int argc, char *argv[]) /* Type-specific help, without kernel checking */ type = type_find(arg0); if (!type) - exit_error(PARAMETER_PROBLEM, - "Unknown settype: `%s'", arg0); + return exit_error(PARAMETER_PROBLEM, + "Unknown settype: `%s'", arg0); printf("\n%s type specific options:\n\n%s", type->name, type->usage); if (type->family == AF_UNSPEC) @@ -475,7 +498,9 @@ parse_commandline(int argc, char *argv[]) } if (interactive) return 0; - exit_error(NO_PROBLEM, NULL); + return exit_error(NO_PROBLEM, NULL); + case IPSET_CMD_QUIT: + return exit_error(NO_PROBLEM, NULL); default: break; } @@ -525,7 +550,7 @@ parse_commandline(int argc, char *argv[]) ret = ipset_parse_setname(session, IPSET_SETNAME, arg0); if (ret < 0) return handle_error(); - ret = ipset_parse_name(session, IPSET_OPT_SETNAME2, arg1); + ret = ipset_parse_setname(session, IPSET_OPT_SETNAME2, arg1); if (ret < 0) return handle_error(); break; @@ -582,5 +607,16 @@ parse_commandline(int argc, char *argv[]) int main(int argc, char *argv[]) { + /* Register types */ + ipset_type_add(&ipset_bitmap_ip0); + ipset_type_add(&ipset_bitmap_ipmac0); + ipset_type_add(&ipset_bitmap_port0); + ipset_type_add(&ipset_hash_ip0); + ipset_type_add(&ipset_hash_net0); + ipset_type_add(&ipset_hash_ipport0); + ipset_type_add(&ipset_hash_ipportip0); + ipset_type_add(&ipset_hash_ipportnet0); + ipset_type_add(&ipset_list_set0); + return parse_commandline(argc, argv); } diff --git a/src/ipset_bitmap_ip.c b/src/ipset_bitmap_ip.c index 471cc96..e28432b 100644 --- a/src/ipset_bitmap_ip.c +++ b/src/ipset_bitmap_ip.c @@ -11,28 +11,28 @@ /* Parse commandline arguments */ static const struct ipset_arg bitmap_ip_create_args[] = { - { .name = { "range", "--range", NULL }, + { .name = { "range", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_netrange, .print = ipset_print_ip, }, - { .name = { "netmask", "--netmask", NULL }, + { .name = { "netmask", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK, .parse = ipset_parse_netmask, .print = ipset_print_number, }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_single_ip, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO, .parse = ipset_parse_single_ip, }, - { .name = { "--network", NULL }, + { .name = { "network", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_net, }, @@ -40,7 +40,7 @@ static const struct ipset_arg bitmap_ip_create_args[] = { }; static const struct ipset_arg bitmap_ip_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -56,7 +56,7 @@ static const char bitmap_ip_usage[] = struct ipset_type ipset_bitmap_ip0 = { .name = "bitmap:ip", - .alias = "ipmap", + .alias = { "ipmap", NULL }, .revision = 0, .family = AF_INET, .dimension = IPSET_DIM_ONE, diff --git a/src/ipset_bitmap_ipmac.c b/src/ipset_bitmap_ipmac.c index 4985fc4..382ebb5 100644 --- a/src/ipset_bitmap_ipmac.c +++ b/src/ipset_bitmap_ipmac.c @@ -11,24 +11,24 @@ /* Parse commandline arguments */ static const struct ipset_arg bitmap_ipmac_create_args[] = { - { .name = { "range", "--range", NULL }, + { .name = { "range", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_netrange, .print = ipset_print_ip, }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_single_ip, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO, .parse = ipset_parse_single_ip, }, - { .name = { "--network", NULL }, + { .name = { "network", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, .parse = ipset_parse_net, }, @@ -36,7 +36,7 @@ static const struct ipset_arg bitmap_ipmac_create_args[] = { }; static const struct ipset_arg bitmap_ipmac_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -52,7 +52,7 @@ static const char bitmap_ipmac_usage[] = struct ipset_type ipset_bitmap_ipmac0 = { .name = "bitmap:ip,mac", - .alias = "macipmap", + .alias = { "macipmap", NULL }, .revision = 0, .family = AF_INET, .dimension = IPSET_DIM_TWO, diff --git a/src/ipset_bitmap_port.c b/src/ipset_bitmap_port.c index 11566ce..7871891 100644 --- a/src/ipset_bitmap_port.c +++ b/src/ipset_bitmap_port.c @@ -11,20 +11,20 @@ /* Parse commandline arguments */ static const struct ipset_arg bitmap_port_create_args[] = { - { .name = { "range", "--range", NULL }, + { .name = { "range", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT, .parse = ipset_parse_port, .print = ipset_print_port, }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT, .parse = ipset_parse_single_port, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT_TO, .parse = ipset_parse_single_port, }, @@ -32,7 +32,7 @@ static const struct ipset_arg bitmap_port_create_args[] = { }; static const struct ipset_arg bitmap_port_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -48,7 +48,7 @@ static const char bitmap_port_usage[] = struct ipset_type ipset_bitmap_port0 = { .name = "bitmap:port", - .alias = "portmap", + .alias = { "portmap", NULL }, .revision = 0, .family = AF_UNSPEC, .dimension = IPSET_DIM_ONE, diff --git a/src/ipset_hash_ip.c b/src/ipset_hash_ip.c index 212cb22..6609eea 100644 --- a/src/ipset_hash_ip.c +++ b/src/ipset_hash_ip.c @@ -11,35 +11,54 @@ /* Parse commandline arguments */ static const struct ipset_arg hash_ip_create_args[] = { - { .name = { "hashsize", "--hashsize", NULL }, + { .name = { "family", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, .print = ipset_print_family, + }, + /* Alias: family inet */ + { .name = { "-4", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + /* Alias: family inet6 */ + { .name = { "-6", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + { .name = { "hashsize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "maxelem", "--maxleme", NULL }, + { .name = { "maxelem", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "probes", "--probes", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "resize", "--resize", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "netmask", "--netmask", NULL }, + { .name = { "netmask", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK, .parse = ipset_parse_netmask, .print = ipset_print_number, }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, + /* Ignored options: backward compatibilty */ + { .name = { "probes", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "resize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "gc", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_GC, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, { }, }; static const struct ipset_arg hash_ip_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -48,8 +67,8 @@ static const struct ipset_arg hash_ip_add_args[] = { static const char hash_ip_usage[] = "create SETNAME hash:ip\n" +" [family inet|inet6]\n" " [hashsize VALUE] [maxelem VALUE]\n" -" [probes VALUE] [resize VALUE]\n" " [netmask CIDR] [timeout VALUE]\n" "add SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n" "del SETNAME IP|IP/CIDR|FROM-TO\n" @@ -57,7 +76,7 @@ static const char hash_ip_usage[] = struct ipset_type ipset_hash_ip0 = { .name = "hash:ip", - .alias = "iphash", + .alias = { "iphash", "iptree", "iptreemap", NULL }, .revision = 0, .family = AF_INET46, .dimension = IPSET_DIM_ONE, @@ -68,6 +87,7 @@ struct ipset_type ipset_hash_ip0 = { .opt = IPSET_OPT_IP }, }, + .compat_parse_elem = ipset_parse_iptimeout, .args = { [IPSET_CREATE] = hash_ip_create_args, [IPSET_ADD] = hash_ip_add_args, @@ -81,8 +101,6 @@ struct ipset_type ipset_hash_ip0 = { .full = { [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) | IPSET_FLAG(IPSET_OPT_MAXELEM) - | IPSET_FLAG(IPSET_OPT_PROBES) - | IPSET_FLAG(IPSET_OPT_RESIZE) | IPSET_FLAG(IPSET_OPT_NETMASK) | IPSET_FLAG(IPSET_OPT_TIMEOUT), [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) diff --git a/src/ipset_hash_ipport.c b/src/ipset_hash_ipport.c index a8cc7ad..4a9b8cf 100644 --- a/src/ipset_hash_ipport.c +++ b/src/ipset_hash_ipport.c @@ -11,48 +11,58 @@ /* Parse commandline arguments */ static const struct ipset_arg hash_ipport_create_args[] = { - { .name = { "range", "--range", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_netrange, .print = ipset_print_ip, + { .name = { "family", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, .print = ipset_print_family, + }, + /* Alias: family inet */ + { .name = { "-4", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + /* Alias: family inet6 */ + { .name = { "-6", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, }, - { .name = { "hashsize", "--hashsize", NULL }, + { .name = { "hashsize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "maxelem", "--maxleme", NULL }, + { .name = { "maxelem", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "probes", "--probes", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "resize", "--resize", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "probes", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "resize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--network", NULL }, + { .name = { "network", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_net, + .parse = ipset_parse_ignored, }, { }, }; static const struct ipset_arg hash_ipport_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -60,10 +70,9 @@ static const struct ipset_arg hash_ipport_add_args[] = { }; static const char hash_ipport_usage[] = -"create SETNAME hash:ip,port range IP/CIDR|FROM-TO\n" +"create SETNAME hash:ip,port\n" " [family inet|inet6]\n" " [hashsize VALUE] [maxelem VALUE]\n" -" [probes VALUE] [resize VALUE]\n" " [timeout VALUE]\n" "add SETNAME IP,PORT [timeout VALUE]\n" "del SETNAME IP,PORT\n" @@ -71,7 +80,7 @@ static const char hash_ipport_usage[] = struct ipset_type ipset_hash_ipport0 = { .name = "hash:ip,port", - .alias = "ipporthash", + .alias = { "ipporthash", NULL }, .revision = 0, .family = AF_INET46, .dimension = IPSET_DIM_TWO, @@ -92,8 +101,7 @@ struct ipset_type ipset_hash_ipport0 = { [IPSET_ADD] = hash_ipport_add_args, }, .mandatory = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO), + [IPSET_CREATE] = 0, [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT), [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP) @@ -102,12 +110,8 @@ struct ipset_type ipset_hash_ipport0 = { | IPSET_FLAG(IPSET_OPT_PORT), }, .full = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO) - | IPSET_FLAG(IPSET_OPT_HASHSIZE) + [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) | IPSET_FLAG(IPSET_OPT_MAXELEM) - | IPSET_FLAG(IPSET_OPT_PROBES) - | IPSET_FLAG(IPSET_OPT_RESIZE) | IPSET_FLAG(IPSET_OPT_TIMEOUT), [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) diff --git a/src/ipset_hash_ipportip.c b/src/ipset_hash_ipportip.c index 71ed3c5..299e362 100644 --- a/src/ipset_hash_ipportip.c +++ b/src/ipset_hash_ipportip.c @@ -11,48 +11,58 @@ /* Parse commandline arguments */ static const struct ipset_arg hash_ipportip_create_args[] = { - { .name = { "range", "--range", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_netrange, .print = ipset_print_ip, + { .name = { "family", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, .print = ipset_print_family, + }, + /* Alias: family inet */ + { .name = { "-4", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + /* Alias: family inet6 */ + { .name = { "-6", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, }, - { .name = { "hashsize", "--hashsize", NULL }, + { .name = { "hashsize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "maxelem", "--maxleme", NULL }, + { .name = { "maxelem", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "probes", "--probes", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "resize", "--resize", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "probes", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "resize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--network", NULL }, + { .name = { "network", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_net, + .parse = ipset_parse_ignored, }, { }, }; static const struct ipset_arg hash_ipportip_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -60,10 +70,9 @@ static const struct ipset_arg hash_ipportip_add_args[] = { }; static const char hash_ipportip_usage[] = -"create SETNAME hash:ip,port,ip range IP/CIDR|FROM-TO\n" +"create SETNAME hash:ip,port,ip\n" " [family inet|inet6]\n" " [hashsize VALUE] [maxelem VALUE]\n" -" [probes VALUE] [resize VALUE]\n" " [timeout VALUE]\n" "add SETNAME IP,PORT,IP [timeout VALUE]\n" "del SETNAME IP,PORT,IP\n" @@ -71,7 +80,7 @@ static const char hash_ipportip_usage[] = struct ipset_type ipset_hash_ipportip0 = { .name = "hash:ip,port,ip", - .alias = "ipportiphash", + .alias = { "ipportiphash", NULL }, .revision = 0, .family = AF_INET46, .dimension = IPSET_DIM_THREE, @@ -97,8 +106,7 @@ struct ipset_type ipset_hash_ipportip0 = { [IPSET_ADD] = hash_ipportip_add_args, }, .mandatory = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO), + [IPSET_CREATE] = 0, [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) | IPSET_FLAG(IPSET_OPT_IP2), @@ -110,12 +118,8 @@ struct ipset_type ipset_hash_ipportip0 = { | IPSET_FLAG(IPSET_OPT_IP2), }, .full = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO) - | IPSET_FLAG(IPSET_OPT_HASHSIZE) + [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) | IPSET_FLAG(IPSET_OPT_MAXELEM) - | IPSET_FLAG(IPSET_OPT_PROBES) - | IPSET_FLAG(IPSET_OPT_RESIZE) | IPSET_FLAG(IPSET_OPT_TIMEOUT), [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) diff --git a/src/ipset_hash_ipportnet.c b/src/ipset_hash_ipportnet.c index 769304d..13a0487 100644 --- a/src/ipset_hash_ipportnet.c +++ b/src/ipset_hash_ipportnet.c @@ -11,48 +11,58 @@ /* Parse commandline arguments */ static const struct ipset_arg hash_ipportnet_create_args[] = { - { .name = { "range", "--range", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_netrange, .print = ipset_print_ip, + { .name = { "family", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, .print = ipset_print_family, + }, + /* Alias: family inet */ + { .name = { "-4", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + /* Alias: family inet6 */ + { .name = { "-6", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, }, - { .name = { "hashsize", "--hashsize", NULL }, + { .name = { "hashsize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "maxelem", "--maxleme", NULL }, + { .name = { "maxelem", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "probes", "--probes", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "resize", "--resize", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, /* Backward compatibility */ - { .name = { "--from", NULL }, + { .name = { "probes", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "resize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, + .parse = ipset_parse_ignored, .print = ipset_print_number, + }, + { .name = { "from", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--to", NULL }, + { .name = { "to", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO, - .parse = ipset_parse_single_ip, + .parse = ipset_parse_ignored, }, - { .name = { "--network", NULL }, + { .name = { "network", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP, - .parse = ipset_parse_net, + .parse = ipset_parse_ignored, }, { }, }; static const struct ipset_arg hash_ipportnet_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -60,18 +70,17 @@ static const struct ipset_arg hash_ipportnet_add_args[] = { }; static const char hash_ipportnet_usage[] = -"create SETNAME hash:ip,port,net range IP/CIDR|FROM-TO\n" +"create SETNAME hash:ip,port,net\n" " [family inet|inet6]\n" " [hashsize VALUE] [maxelem VALUE]\n" -" [probes VALUE] [resize VALUE]\n" " [timeout VALUE]\n" -"add SETNAME IP,PORT,IP/CIDR [timeout VALUE]\n" -"del SETNAME IP,PORT,IP/CIDR\n" -"test SETNAME IP,PORT,IP/CIDR\n"; +"add SETNAME IP,PORT,IP[/CIDR] [timeout VALUE]\n" +"del SETNAME IP,PORT,IP[/CIDR]\n" +"test SETNAME IP,PORT,IP[/CIDR]\n"; struct ipset_type ipset_hash_ipportnet0 = { .name = "hash:ip,port,net", - .alias = "ipportnethash", + .alias = { "ipportnethash", NULL }, .revision = 0, .family = AF_INET46, .dimension = IPSET_DIM_THREE, @@ -87,7 +96,7 @@ struct ipset_type ipset_hash_ipportnet0 = { .opt = IPSET_OPT_PORT }, [IPSET_DIM_THREE] = { - .parse = ipset_parse_net, + .parse = ipset_parse_ipnet, .print = ipset_print_ip, .opt = IPSET_OPT_IP2 }, @@ -97,28 +106,20 @@ struct ipset_type ipset_hash_ipportnet0 = { [IPSET_ADD] = hash_ipportnet_add_args, }, .mandatory = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO), + [IPSET_CREATE] = 0, [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) - | IPSET_FLAG(IPSET_OPT_IP2) - | IPSET_FLAG(IPSET_OPT_CIDR2), + | IPSET_FLAG(IPSET_OPT_IP2), [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) - | IPSET_FLAG(IPSET_OPT_IP2) - | IPSET_FLAG(IPSET_OPT_CIDR2), + | IPSET_FLAG(IPSET_OPT_IP2), [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) - | IPSET_FLAG(IPSET_OPT_IP2) - | IPSET_FLAG(IPSET_OPT_CIDR2), + | IPSET_FLAG(IPSET_OPT_IP2), }, .full = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO) - | IPSET_FLAG(IPSET_OPT_HASHSIZE) + [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) | IPSET_FLAG(IPSET_OPT_MAXELEM) - | IPSET_FLAG(IPSET_OPT_PROBES) - | IPSET_FLAG(IPSET_OPT_RESIZE) | IPSET_FLAG(IPSET_OPT_TIMEOUT), [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_PORT) diff --git a/src/ipset_hash_net.c b/src/ipset_hash_net.c index 1d70900..c14652d 100644 --- a/src/ipset_hash_net.c +++ b/src/ipset_hash_net.c @@ -11,31 +11,46 @@ /* Parse commandline arguments */ static const struct ipset_arg hash_net_create_args[] = { - { .name = { "hashsize", "--hashsize", NULL }, + { .name = { "family", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, .print = ipset_print_family, + }, + /* Alias: family inet */ + { .name = { "-4", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + /* Alias: family inet6 */ + { .name = { "-6", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY, + .parse = ipset_parse_family, + }, + { .name = { "hashsize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "maxelem", "--maxleme", NULL }, + { .name = { "maxelem", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "probes", "--probes", NULL }, + { .name = { "timeout", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, + .parse = ipset_parse_uint32, .print = ipset_print_number, + }, + /* Ignored options: backward compatibilty */ + { .name = { "probes", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES, - .parse = ipset_parse_uint8, .print = ipset_print_number, + .parse = ipset_parse_ignored, .print = ipset_print_number, }, - { .name = { "resize", "--resize", NULL }, + { .name = { "resize", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE, - .parse = ipset_parse_uint8, .print = ipset_print_number, - }, - { .name = { "timeout", "--timeout", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, - .parse = ipset_parse_uint32, .print = ipset_print_number, + .parse = ipset_parse_ignored, .print = ipset_print_number, }, { }, }; static const struct ipset_arg hash_net_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, @@ -46,21 +61,20 @@ static const char hash_net_usage[] = "create SETNAME hash:net\n" " [family inet|inet6]\n" " [hashsize VALUE] [maxelem VALUE]\n" -" [probes VALUE] [resize VALUE]\n" " [timeout VALUE]\n" -"add SETNAME IP/CIDR [timeout VALUE]\n" -"del SETNAME IP/CIDR\n" -"test SETNAME IP/CIDR\n"; +"add SETNAME IP[/CIDR] [timeout VALUE]\n" +"del SETNAME IP[/CIDR]\n" +"test SETNAME IP[/CIDR]\n"; struct ipset_type ipset_hash_net0 = { .name = "hash:net", - .alias = "nethash", + .alias = { "nethash", NULL }, .revision = 0, .family = AF_INET46, .dimension = IPSET_DIM_ONE, .elem = { [IPSET_DIM_ONE] = { - .parse = ipset_parse_net, + .parse = ipset_parse_ipnet, .print = ipset_print_ip, .opt = IPSET_OPT_IP }, @@ -71,18 +85,13 @@ struct ipset_type ipset_hash_net0 = { }, .mandatory = { [IPSET_CREATE] = 0, - [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_CIDR), - [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_CIDR), - [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_CIDR), + [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP), + [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP), + [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP), }, .full = { [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) | IPSET_FLAG(IPSET_OPT_MAXELEM) - | IPSET_FLAG(IPSET_OPT_PROBES) - | IPSET_FLAG(IPSET_OPT_RESIZE) | IPSET_FLAG(IPSET_OPT_TIMEOUT), [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) | IPSET_FLAG(IPSET_OPT_CIDR) diff --git a/src/ipset_iptreemap.c b/src/ipset_iptreemap.c deleted file mode 100644 index 22bdcb3..0000000 --- a/src/ipset_iptreemap.c +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright 2007 Sven Wegener - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include /* UINT_MAX */ -#include /* *printf */ -#include /* mem* */ - -#include "ipset.h" - -#include - -#define OPT_CREATE_GC 0x1 - -static void -iptreemap_create_init(void *data) -{ - struct ip_set_req_iptreemap_create *mydata = data; - - mydata->gc_interval = 0; -} - -static int -iptreemap_create_parse(int c, char *argv[] UNUSED, void *data, - unsigned int *flags) -{ - struct ip_set_req_iptreemap_create *mydata = data; - - switch (c) { - case 'g': - string_to_number(optarg, 0, UINT_MAX, &mydata->gc_interval); - - *flags |= OPT_CREATE_GC; - break; - default: - return 0; - break; - } - - return 1; -} - -static void -iptreemap_create_final(void *data UNUSED, unsigned int flags UNUSED) -{ -} - -static const struct option create_opts[] = { - {.name = "gc", .has_arg = required_argument, .val = 'g'}, - {NULL}, -}; - -static ip_set_ip_t -iptreemap_adt_parser(int cmd UNUSED, const char *arg, void *data) -{ - struct ip_set_req_iptreemap *mydata = data; - ip_set_ip_t mask; - - char *saved = ipset_strdup(arg); - char *ptr, *tmp = saved; - - if (strchr(tmp, '/')) { - parse_ipandmask(tmp, &mydata->ip, &mask); - mydata->end = mydata->ip | ~mask; - } else { - if ((ptr = strchr(tmp, ':')) != NULL && ++warn_once == 1) - fprintf(stderr, "Warning: please use '-' separator token between IP range.\n" - "Next release won't support old separator token.\n"); - ptr = strsep(&tmp, "-:"); - parse_ip(ptr, &mydata->ip); - - if (tmp) { - parse_ip(tmp, &mydata->end); - } else { - mydata->end = mydata->ip; - } - } - - ipset_free(saved); - - return 1; -} - -static void -iptreemap_initheader(struct set *set, const void *data) -{ - const struct ip_set_req_iptreemap_create *header = data; - struct ip_set_iptreemap *map = set->settype->header; - - map->gc_interval = header->gc_interval; -} - -static void -iptreemap_printheader(struct set *set, unsigned int options UNUSED) -{ - struct ip_set_iptreemap *mysetdata = set->settype->header; - - if (mysetdata->gc_interval) - printf(" gc: %u", mysetdata->gc_interval); - - printf("\n"); -} - -static void -iptreemap_printips_sorted(struct set *set UNUSED, void *data, - u_int32_t len, unsigned int options, char dont_align) -{ - struct ip_set_req_iptreemap *req; - size_t offset = 0; - - while (len >= offset + sizeof(struct ip_set_req_iptreemap)) { - req = data + offset; - - printf("%s", ip_tostring(req->ip, options)); - if (req->ip != req->end) - printf("-%s", ip_tostring(req->end, options)); - printf("\n"); - - offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align); - } -} - -static void -iptreemap_saveheader(struct set *set, unsigned int options UNUSED) -{ - struct ip_set_iptreemap *mysetdata = set->settype->header; - - printf("-N %s %s", set->name, set->settype->typename); - - if (mysetdata->gc_interval) - printf(" --gc %u", mysetdata->gc_interval); - - printf("\n"); -} - -static void -iptreemap_saveips(struct set *set UNUSED, void *data, - u_int32_t len, unsigned int options, char dont_align) -{ - struct ip_set_req_iptreemap *req; - size_t offset = 0; - - while (len >= offset + sizeof(struct ip_set_req_iptreemap)) { - req = data + offset; - - printf("-A %s %s", set->name, ip_tostring(req->ip, options)); - - if (req->ip != req->end) - printf("-%s", ip_tostring(req->end, options)); - - printf("\n"); - - offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align); - } -} - -static void -iptreemap_usage(void) -{ - printf( - "-N set iptreemap --gc interval\n" - "-A set IP\n" - "-D set IP\n" - "-T set IP\n" - ); -} - -static struct settype settype_iptreemap = { - .typename = SETTYPE_NAME, - .protocol_version = IP_SET_PROTOCOL_VERSION, - - .create_size = sizeof(struct ip_set_req_iptreemap_create), - .create_init = iptreemap_create_init, - .create_parse = iptreemap_create_parse, - .create_final = iptreemap_create_final, - .create_opts = create_opts, - - .adt_size = sizeof(struct ip_set_req_iptreemap), - .adt_parser = iptreemap_adt_parser, - - .header_size = sizeof(struct ip_set_iptreemap), - .initheader = iptreemap_initheader, - .printheader = iptreemap_printheader, - .printips = iptreemap_printips_sorted, - .printips_sorted = iptreemap_printips_sorted, - .saveheader = iptreemap_saveheader, - .saveips = iptreemap_saveips, - - .usage = iptreemap_usage, -}; - -CONSTRUCTOR(iptreemap) -{ - settype_register(&settype_iptreemap); -} diff --git a/src/ipset_list_set.c b/src/ipset_list_set.c index 11b2523..76cf9b2 100644 --- a/src/ipset_list_set.c +++ b/src/ipset_list_set.c @@ -11,48 +11,59 @@ /* Parse commandline arguments */ static const struct ipset_arg list_set_create_args[] = { - { .name = { "size", "--size", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, - .parse = ipset_parse_uint32, .print = ipset_print_ip, + { .name = { "size", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SIZE, + .parse = ipset_parse_uint32, .print = ipset_print_number, }, - { .name = { "timeout", "--timeout", NULL }, + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, { }, }; -static const struct ipset_arg list_set_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, +static const struct ipset_arg list_set_adt_args[] = { + { .name = { "timeout", NULL }, .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, .parse = ipset_parse_uint32, .print = ipset_print_number, }, + { .name = { "before", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF, + .parse = ipset_parse_before, + }, + { .name = { "after", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF, + .parse = ipset_parse_after, + }, { }, }; static const char list_set_usage[] = "create SETNAME list:set\n" " [size VALUE] [timeout VALUE]\n" -"add SETNAME NAME[,before|after,NAME] [timeout VALUE]\n" +"add SETNAME NAME [before|after NAME] [timeout VALUE]\n" "del SETNAME NAME\n" "test SETNAME NAME\n"; struct ipset_type ipset_list_set0 = { .name = "list:set", - .alias = "setlist", + .alias = { "setlist", NULL }, .revision = 0, .family = AF_UNSPEC, .dimension = IPSET_DIM_ONE, .elem = { [IPSET_DIM_ONE] = { - .parse = ipset_parse_name, + .parse = ipset_parse_setname, .print = ipset_print_name, .opt = IPSET_OPT_NAME }, }, + .compat_parse_elem = ipset_parse_name_compat, .args = { [IPSET_CREATE] = list_set_create_args, - [IPSET_ADD] = list_set_add_args, + [IPSET_ADD] = list_set_adt_args, + [IPSET_DEL] = list_set_adt_args, + [IPSET_TEST] = list_set_adt_args, }, .mandatory = { [IPSET_CREATE] = 0, diff --git a/src/ipset_tree_ip.c b/src/ipset_tree_ip.c deleted file mode 100644 index 7f7d842..0000000 --- a/src/ipset_tree_ip.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@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. - */ -#include /* IPSET_OPT_* */ -#include /* parser functions */ -#include /* printing functions */ -#include /* prototypes */ - -/* Parse commandline arguments */ -static const struct ipset_arg tree_ip_create_args[] = { - { .name = { "gc", "--gc", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_GC, - .parse = ipset_parse_uint32, .print = ipset_print_number, - }, - { .name = { "timeout", "--timeout", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, - .parse = ipset_parse_uint32, .print = ipset_print_number, - }, - { }, -}; - -static const struct ipset_arg tree_ip_add_args[] = { - { .name = { "timeout", "--timeout", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, - .parse = ipset_parse_uint32, .print = ipset_print_number, - }, - { }, -}; - -static const char tree_ip_usage[] = -"create SETNAME tree:ip\n" -" [gc VALUE] [timeout VALUE]\n" -"add SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n" -"del SETNAME IP|IP/CIDR|FROM-TO\n" -"test SETNAME IP\n"; - -struct ipset_type ipset_tree_ip0 = { - .name = "tree:ip", - .alias = "iptree", - .revision = 0, - .family = AF_INET, - .dimension = IPSET_DIM_ONE, - .elem = { - [IPSET_DIM_ONE] = { - .parse = ipset_parse_ip, - .print = ipset_print_ip, - .opt = IPSET_OPT_IP - }, - }, - .args = { - [IPSET_CREATE] = tree_ip_create_args, - [IPSET_ADD] = tree_ip_add_args, - }, - .mandatory = { - [IPSET_CREATE] = 0, - [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP), - [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP), - [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP), - }, - .full = { - [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_GC) - | IPSET_FLAG(IPSET_OPT_TIMEOUT), - [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO) - | IPSET_FLAG(IPSET_OPT_TIMEOUT), - [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP) - | IPSET_FLAG(IPSET_OPT_IP_TO), - [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP), - }, - - .usage = tree_ip_usage, -}; diff --git a/src/ui.c b/src/ui.c index bc01e61..d8face5 100644 --- a/src/ui.c +++ b/src/ui.c @@ -4,107 +4,155 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include /* assert */ +#include /* tolower */ +#include /* memcmp, str* */ + #include /* IPSET_CMD_* */ #include /* IPSET_*_ARG */ #include /* ipset_envopt_parse */ #include /* ipset_parse_family */ #include /* ipset_print_family */ +#include /* STREQ */ #include /* prototypes */ /* Commands and environment options */ const struct ipset_commands ipset_commands[] = { - [IPSET_CMD_CREATE - 1] = { - .name = { "create", "c", "-N", "--create", NULL }, + /* Order is important */ + + { /* c[reate], --create, n, -N */ + .cmd = IPSET_CMD_CREATE, + .name = { "create", "n" }, .has_arg = IPSET_MANDATORY_ARG2, .help = "SETNAME TYPENAME [type-specific-options]\n" " Create a new set", }, - [IPSET_CMD_DESTROY - 1] = { - .name = { "destroy", "x", "-X", "--destroy", NULL }, - .has_arg = IPSET_OPTIONAL_ARG, - .help = "[SETNAME]\n" - " Destroy a named set or all sets", - }, - [IPSET_CMD_FLUSH - 1] = { - .name = { "flush", "f", "-F", "--flush", NULL }, - .has_arg = IPSET_OPTIONAL_ARG, - .help = "[SETNAME]\n" - " Flush a named set or all sets", + { /* a[dd], --add, -A */ + .cmd = IPSET_CMD_ADD, + .name = { "add", NULL }, + .has_arg = IPSET_MANDATORY_ARG2, + .help = "SETNAME ENTRY\n" + " Add entry to the named set", }, - [IPSET_CMD_RENAME - 1] = { - .name = { "rename", "e", "-E", "--rename", NULL }, + { /* d[el], --del, -D */ + .cmd = IPSET_CMD_DEL, + .name = { "del", NULL }, .has_arg = IPSET_MANDATORY_ARG2, - .help = "FROM-SETNAME TO-SETNAME\n" - " Rename two sets", + .help = "SETNAME ENTRY\n" + " Delete entry from the named set", }, - [IPSET_CMD_SWAP - 1] = { - .name = { "swap", "w", "-W", "--swap", NULL }, + { /* t[est], --test, -T */ + .cmd = IPSET_CMD_TEST, + .name = { "test", NULL }, .has_arg = IPSET_MANDATORY_ARG2, - .help = "FROM-SETNAME TO-SETNAME\n" - " Swap the contect of two existing sets", + .help = "SETNAME ENTRY\n" + " Test entry in the named set", + }, + { /* des[troy], --destroy, x, -X */ + .cmd = IPSET_CMD_DESTROY, + .name = { "destroy", "x" }, + .has_arg = IPSET_OPTIONAL_ARG, + .help = "[SETNAME]\n" + " Destroy a named set or all sets", }, - [IPSET_CMD_LIST - 1] = { - .name = { "list", "l", "-L", "--list", NULL }, + { /* l[ist], --list, -L */ + .cmd = IPSET_CMD_LIST, + .name = { "list", NULL }, .has_arg = IPSET_OPTIONAL_ARG, .help = "[SETNAME]\n" " List the entries of a named set or all sets", }, - [IPSET_CMD_SAVE - 1] = { - .name = { "save", "s", "-S", "--save", NULL }, + { /* s[save], --save, -S */ + .cmd = IPSET_CMD_SAVE, + .name = { "save", NULL }, .has_arg = IPSET_OPTIONAL_ARG, .help = "[SETNAME]\n" " Save the named set or all sets to stdout", }, - [IPSET_CMD_ADD - 1] = { - .name = { "add", "a", "-A", "--add", NULL }, - .has_arg = IPSET_MANDATORY_ARG2, - .help = "SETNAME ENTRY\n" - " Add entry to a named set", + { /* r[estore], --restore, -R */ + .cmd = IPSET_CMD_RESTORE, + .name = { "restore", NULL }, + .has_arg = IPSET_NO_ARG, + .help = "\n" + " Restore a saved state", + }, + { /* f[lush], --flush, -F */ + .cmd = IPSET_CMD_FLUSH, + .name = { "flush", NULL }, + .has_arg = IPSET_OPTIONAL_ARG, + .help = "[SETNAME]\n" + " Flush a named set or all sets", }, - [IPSET_CMD_DEL - 1] = { - .name = { "del", "d", "-D", "--del", NULL }, + { /* ren[ame], --rename, e, -E */ + .cmd = IPSET_CMD_RENAME, + .name = { "rename", "e" }, .has_arg = IPSET_MANDATORY_ARG2, - .help = "SETNAME ENTRY\n" - " Delete entry from a named set", + .help = "FROM-SETNAME TO-SETNAME\n" + " Rename two sets", }, - [IPSET_CMD_TEST - 1] = { - .name = { "test", "t", "-T", "--test", NULL }, + { /* sw[ap], --swap, w, -W */ + .cmd = IPSET_CMD_SWAP, + .name = { "swap", "w" }, .has_arg = IPSET_MANDATORY_ARG2, - .help = "SETNAME ENTRY\n" - " Test if entry exists in the named set", + .help = "FROM-SETNAME TO-SETNAME\n" + " Swap the contect of two existing sets", }, - [IPSET_CMD_HELP - 1] = { - .name = { "help", "h", "-H", "-h", "--help", NULL }, + { /* h[elp, --help, -H */ + .cmd = IPSET_CMD_HELP, + .name = { "help", NULL }, .has_arg = IPSET_OPTIONAL_ARG, .help = "[TYPENAME]\n" " Print help, and settype specific help", }, - [IPSET_CMD_RESTORE - 1] = { - .name = { "restore", "r", "-R", "--restore", NULL }, + { /* v[ersion], --version, -V */ + .cmd = IPSET_CMD_VERSION, + .name = { "version", NULL }, .has_arg = IPSET_NO_ARG, .help = "\n" - " Restore a saved state", + " Print version information", }, - [IPSET_CMD_VERSION - 1] = { - .name = { "version", "v", "-V", "-v", "--version", NULL }, + { /* q[uit] */ + .cmd = IPSET_CMD_QUIT, + .name = { "quit", NULL }, .has_arg = IPSET_NO_ARG, .help = "\n" - " Print version information", + " Quit interactive mode", }, - [IPSET_CMD_MAX - 1] = { }, + { }, }; +/* Match a command: try to match as a prefix or letter-command */ +bool +ipset_match_cmd(const char *arg, const char * const name[]) +{ + size_t len; + + assert(arg); + assert(name && name[0]); + + /* Ignore (two) leading dashes */ + if (arg[0] == '-') + arg++; + if (arg[0] == '-') + arg++; + + len = strlen(arg); + + if (len > strlen(name[0]) || !len) + return false; + else if (memcmp(arg, name[0], len) == 0) + return true; + else if (len != 1) + return false; + else if (name[1] == NULL) + return tolower(arg[0]) == name[0][0]; + else + return tolower(arg[0]) == name[1][0]; +} + const struct ipset_envopts ipset_envopts[] = { - { .name = { "family", "--family", NULL }, - .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_FAMILY, - .parse = ipset_parse_family, .print = ipset_print_family, - .help = "inet|inet6\n" - " Specify family when creating a set\n" - " which supports multiple families.\n" - " The default family is INET.", - }, - { .name = { "-o", "--output", NULL }, + { .name = { "-o", "-output" }, .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX, .parse = ipset_parse_output, .help = "plain|save|xml\n" @@ -112,25 +160,25 @@ const struct ipset_envopts ipset_envopts[] = { " Default value for \"list\" command is mode \"plain\"\n" " and for \"save\" command is mode \"save\".", }, - { .name = { "-s", "--sorted", NULL }, + { .name = { "-s", "-sorted" }, .parse = ipset_envopt_parse, .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_SORTED, .help = "\n" " Print elements sorted (if supported by the set type).", }, - { .name = { "-q", "--quiet", NULL }, + { .name = { "-q", "-quiet" }, .parse = ipset_envopt_parse, .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_QUIET, .help = "\n" " Suppress any notice or warning message.", }, - { .name = { "-r", "--resolve", NULL }, + { .name = { "-r", "-resolve" }, .parse = ipset_envopt_parse, .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_RESOLVE, .help = "\n" " Try to resolve IP addresses in the output (slow!)", }, - { .name = { "-x", "--exist", NULL }, + { .name = { "-!", "-exist" }, .parse = ipset_envopt_parse, .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_EXIST, .help = "\n" @@ -138,14 +186,59 @@ const struct ipset_envopts ipset_envopts[] = { " when adding already existing elements\n" " or when deleting non-existing elements.", }, - /* Aliases */ - { .name = { "-4", NULL }, - .has_arg = IPSET_NO_ARG, .flag = IPSET_OPT_FAMILY, - .parse = ipset_parse_family, - }, - { .name = { "-6", NULL }, - .has_arg = IPSET_NO_ARG, .flag = IPSET_OPT_FAMILY, - .parse = ipset_parse_family, - }, { }, }; + +/* Strict option matching */ +bool +ipset_match_option(const char *arg, const char * const name[]) +{ + assert(arg); + assert(name && name[0]); + + /* Skip two leading dashes */ + if (arg[0] == '-' && arg[1] == '-') + arg++, arg++; + + return STREQ(arg, name[0]) + || (name[1] != NULL && STREQ(arg, name[1])); +} + +/* Strict envopt matching */ +bool +ipset_match_envopt(const char *arg, const char * const name[]) +{ + assert(arg); + assert(name && name[0]); + + /* Skip one leading dash */ + if (arg[0] == '-' && arg[1] == '-') + arg++; + + return STREQ(arg, name[0]) + || (name[1] != NULL && STREQ(arg, name[1])); +} + +/** + * ipset_shift_argv - shift off an argument + * @arc: argument count + * @argv: array of argument strings + * @from: from where shift off an argument + * + * Shift off the argument at "from" from the array of + * arguments argv of size argc. + */ +void +ipset_shift_argv(int *argc, char *argv[], int from) +{ + int i; + + assert(*argc >= from + 1); + + for (i = from + 1; i <= *argc; i++) { + argv[i-1] = argv[i]; + } + (*argc)--; + return; +} + -- cgit v1.2.3