From f284b0d07b5d99e745312cbcc0fd95a6a4a7f5b4 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 18 Mar 2011 17:24:50 +0100 Subject: SCTP, UDPLITE support added SCTP and UDPLITE port support added to the hash:*port* types. --- .../include/linux/netfilter/ipset/ip_set_getport.h | 2 ++ kernel/net/netfilter/ipset/ip_set_getport.c | 16 ++++++++++++- kernel/net/netfilter/ipset/ip_set_hash_ipport.c | 2 +- kernel/net/netfilter/ipset/ip_set_hash_ipportip.c | 2 +- kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c | 2 +- kernel/net/netfilter/ipset/ip_set_hash_netport.c | 2 +- lib/parse.c | 5 ++-- lib/print.c | 2 ++ lib/types.c | 28 +++++++++++----------- src/ipset.8 | 27 +++++++++++++-------- src/ipset_hash_ipport.c | 6 ++--- src/ipset_hash_ipportip.c | 6 ++--- src/ipset_hash_ipportnet.c | 6 ++--- src/ipset_hash_netport.c | 5 ++-- tests/hash:ip,port.t | 6 +++++ 15 files changed, 74 insertions(+), 43 deletions(-) diff --git a/kernel/include/linux/netfilter/ipset/ip_set_getport.h b/kernel/include/linux/netfilter/ipset/ip_set_getport.h index 5aebd17..90d0930 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_getport.h +++ b/kernel/include/linux/netfilter/ipset/ip_set_getport.h @@ -22,7 +22,9 @@ static inline bool ip_set_proto_with_ports(u8 proto) { switch (proto) { case IPPROTO_TCP: + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: return true; } return false; diff --git a/kernel/net/netfilter/ipset/ip_set_getport.c b/kernel/net/netfilter/ipset/ip_set_getport.c index 8d52272..757143b 100644 --- a/kernel/net/netfilter/ipset/ip_set_getport.c +++ b/kernel/net/netfilter/ipset/ip_set_getport.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,20 @@ get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, *port = src ? th->source : th->dest; break; } - case IPPROTO_UDP: { + case IPPROTO_SCTP: { + sctp_sctphdr_t _sh; + const sctp_sctphdr_t *sh; + + sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh); + if (sh == NULL) + /* No choice either */ + return false; + + *port = src ? sh->source : sh->dest; + break; + } + case IPPROTO_UDP: + case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c index b921414..14281b6 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipport.c @@ -491,7 +491,7 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c index 4642872..401c8a2 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -509,7 +509,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c index 2cb84a5..4743e54 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -574,7 +574,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/kernel/net/netfilter/ipset/ip_set_hash_netport.c b/kernel/net/netfilter/ipset/ip_set_hash_netport.c index 8598676..d2a4036 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_netport.c +++ b/kernel/net/netfilter/ipset/ip_set_hash_netport.c @@ -526,7 +526,7 @@ static struct ip_set_type hash_netport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_netport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/lib/parse.c b/lib/parse.c index cd1ad32..0c15231 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -500,10 +500,9 @@ ipset_parse_proto_port(struct ipset_session *session, p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO); switch (p) { case IPPROTO_TCP: - proto = tmp; - tmp = a; - goto parse_port; + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: proto = tmp; tmp = a; goto parse_port; diff --git a/lib/print.c b/lib/print.c index 5284b0a..66b9c1a 100644 --- a/lib/print.c +++ b/lib/print.c @@ -585,7 +585,9 @@ ipset_print_proto_port(char *buf, unsigned int len, switch (proto) { case IPPROTO_TCP: + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: break; case IPPROTO_ICMP: return ipset_print_icmp(buf + offset, len, data, diff --git a/lib/types.c b/lib/types.c index 5eb53c4..f0dbbc9 100644 --- a/lib/types.c +++ b/lib/types.c @@ -198,7 +198,7 @@ create_type_get(struct ipset_session *session) struct ipset_data *data; const char *typename; uint8_t family, tmin = 0, tmax = 0; - const uint8_t *kmin, *kmax; + uint8_t kmin, kmax; int ret; data = ipset_session_data(session); @@ -240,32 +240,32 @@ create_type_get(struct ipset_session *session) if (ret != 0) return NULL; - kmax = ipset_data_get(data, IPSET_OPT_REVISION); + kmax = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION); if (ipset_data_test(data, IPSET_OPT_REVISION_MIN)) - kmin = ipset_data_get(data, IPSET_OPT_REVISION_MIN); + kmin = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION_MIN); else kmin = kmax; - if (MAX(tmin, *kmin) > MIN(tmax, *kmax)) { - if (*kmin > tmax) + if (MAX(tmin, kmin) > MIN(tmax, kmax)) { + if (kmin > tmax) return ipset_errptr(session, - "Kernel supports %s type with family %s " - "in minimal revision %u while ipset library " - "in maximal revision %u. " - "You need to upgrade your ipset library.", + "Kernel supports %s type, family %s " + "with minimal revision %u while ipset program " + "with maximal revision %u.\n" + "You need to upgrade your ipset program.", typename, family == AF_INET ? "INET" : family == AF_INET6 ? "INET6" : "UNSPEC", - *kmin, tmax); + kmin, tmax); else return ipset_errptr(session, - "Kernel supports %s type with family %s " - "in maximal revision %u while ipset library " - "in minimal revision %u. " + "Kernel supports %s type, family %s " + "with maximal revision %u while ipset program " + "with minimal revision %u.\n" "You need to upgrade your kernel.", typename, family == AF_INET ? "INET" : family == AF_INET6 ? "INET6" : "UNSPEC", - *kmax, tmin); + kmax, tmin); } match->kernel_check = IPSET_KERNEL_OK; diff --git a/src/ipset.8 b/src/ipset.8 index b9ca8a5..cad3296 100644 --- a/src/ipset.8 +++ b/src/ipset.8 @@ -330,6 +330,9 @@ Mandatory options to use when creating a \fBbitmap:port\fR type of set: \fBrange\fP \fIfromport\fP\-\fItoport\fR Create the set from the specified inclusive port range. .PP +The \fBset\fR match and \fBSET\fR target netfilter kernel modules interpret +the stored numbers as TCP or UDP port numbers. +.PP Examples: .IP ipset create foo bitmap:port range 0\-1024 @@ -380,9 +383,9 @@ a range or a network: .PP Examples: .IP -ipset create foo hash:ip netmask 24 +ipset create foo hash:ip netmask 30 .IP -ipset add foo 192.168.1.1\-192.168.1.2 +ipset add foo 192.168.1.0/24 .IP ipset test foo 192.168.1.2 .SS hash:net @@ -414,8 +417,10 @@ correct value. The maximal number of elements which can be stored in the set, default 65536. .PP When adding/deleting/testing entries, if the cidr prefix parameter is not specified, -then the host prefix value is assumed. When adding/deleting entries, overlapping -elements are not checked. +then the host prefix value is assumed. When adding/deleting entries, the exact +element is added/deleted and overlapping elements are not checked by the kernel. +When testing entries, if a host address is tested, then the kernel tries to match +the host address in the networks added to the set and reports the result accordingly. .PP From the \fBset\fR netfilter match point of view the searching for a match always starts from the smallest size of netblock (most specific @@ -431,7 +436,7 @@ Examples: .IP ipset create foo hash:net .IP -ipset add foo 192.168.0/24 +ipset add foo 192.168.0.0/24 .IP ipset add foo 10.1.0.0/16 .IP @@ -481,8 +486,8 @@ TCP port or range of ports expressed in TCP portname identifiers from /etc/servi \fIportnumber[\-portnumber]\fR TCP port or range of ports expressed in TCP port numbers .TP -\fBtcp\fR|\fBudp\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR] -TCP or UDP port or port range expressed in port name(s) or port number(s) +\fBtcp\fR|\fBsctp\fR|\fBudp\fR|\fBudplite\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR] +TCP, SCTP, UDP or UDPLITE port or port range expressed in port name(s) or port number(s) .TP \fBicmp\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR ICMP codename or type/code. The supported ICMP codename identifiers can always @@ -508,7 +513,7 @@ ipset add foo 192.168.1.0/24,80\-82 .IP ipset add foo 192.168.1.1,udp:53 .IP -ipset add foo 192.168.1.1,ospf:0 +ipset add foo 192.168.1.1,vrrp:0 .IP ipset test foo 192.168.1.1,80 .SS hash:net,port @@ -547,8 +552,10 @@ part of the elements see the description at the \fBhash:ip,port\fR set type. .PP When adding/deleting/testing entries, if the cidr prefix parameter is not specified, -then the host prefix value is assumed. When adding/deleting entries, overlapping -elements are not checked. +then the host prefix value is assumed. When adding/deleting entries, the exact +element is added/deleted and overlapping elements are not checked by the kernel. +When testing entries, if a host address is tested, then the kernel tries to match +the host address in the networks added to the set and reports the result accordingly. .PP From the \fBset\fR netfilter match point of view the searching for a match always starts from the smallest size of netblock (most specific diff --git a/src/ipset_hash_ipport.c b/src/ipset_hash_ipport.c index 94bda07..3179805 100644 --- a/src/ipset_hash_ipport.c +++ b/src/ipset_hash_ipport.c @@ -82,13 +82,13 @@ static const char hash_ipport_usage[] = " IP is a valid IPv4 or IPv6 address (or hostname).\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipport0 = { .name = "hash:ip,port", .alias = { "ipporthash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_TWO, .elem = { diff --git a/src/ipset_hash_ipportip.c b/src/ipset_hash_ipportip.c index cb90152..944ee81 100644 --- a/src/ipset_hash_ipportip.c +++ b/src/ipset_hash_ipportip.c @@ -82,13 +82,13 @@ static const char hash_ipportip_usage[] = " IP is a valid IPv4 or IPv6 address (or hostname).\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " in the first IP component is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipportip0 = { .name = "hash:ip,port,ip", .alias = { "ipportiphash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_THREE, .elem = { diff --git a/src/ipset_hash_ipportnet.c b/src/ipset_hash_ipportnet.c index ff3a8ec..bd94d12 100644 --- a/src/ipset_hash_ipportnet.c +++ b/src/ipset_hash_ipportnet.c @@ -83,13 +83,13 @@ static const char hash_ipportnet_usage[] = " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " in the first IP component is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipportnet0 = { .name = "hash:ip,port,net", .alias = { "ipportnethash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_THREE, .elem = { diff --git a/src/ipset_hash_netport.c b/src/ipset_hash_netport.c index 843ef31..8ca77df 100644 --- a/src/ipset_hash_netport.c +++ b/src/ipset_hash_netport.c @@ -60,12 +60,13 @@ static const char hash_netport_usage[] = "where depending on the INET family\n" " IP is a valid IPv4 or IPv6 address (or hostname),\n" " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" -" Adding/deleting multiple elements with TCP/UDP port range supported.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_netport0 = { .name = "hash:net,port", .alias = { "netporthash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_TWO, .elem = { diff --git a/tests/hash:ip,port.t b/tests/hash:ip,port.t index aabd861..020be72 100644 --- a/tests/hash:ip,port.t +++ b/tests/hash:ip,port.t @@ -62,6 +62,12 @@ 0 ipset add test 2.0.0.1,vrrp:0 # Test element with vrrp 0 ipset test test 2.0.0.1,vrrp:0 +# Add element with sctp +0 ipset add test 2.0.0.1,sctp:80 +# Test element with sctp +0 ipset test test 2.0.0.1,sctp:80 +# Delete element with sctp +0 ipset del test 2.0.0.1,sctp:80 # List set 0 ipset list test > .foo0 && ./sort.sh .foo0 # Check listing -- cgit v1.2.3