aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVytas Dauksa <vytas.dauksa@smoothwall.net>2013-12-17 09:01:44 -0500
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2014-03-06 03:31:42 -0500
commit4d0e5c076d01d3fb4767a502a9517923fb9a080e (patch)
tree07b92b1b3a191bcbd4682253c34f8a2f4a7c8f7f
parent3b02b56cd5988d569731f6c0c26992296e46b758 (diff)
netfilter: ipset: add markmask for hash:ip,mark data type
Introduce packet mark mask for hash:ip,mark data type. This allows to set mark bit filter for the ip set. Change-Id: Id8dd9ca7e64477c4f7b022a1d9c1a5b187f1c96e Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-rw-r--r--include/uapi/linux/netfilter/ipset/ip_set.h2
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h31
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipmark.c9
3 files changed, 42 insertions, 0 deletions
diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h
index 5368f8275774..f636f282b142 100644
--- a/include/uapi/linux/netfilter/ipset/ip_set.h
+++ b/include/uapi/linux/netfilter/ipset/ip_set.h
@@ -89,6 +89,7 @@ enum {
89 IPSET_ATTR_GC, 89 IPSET_ATTR_GC,
90 IPSET_ATTR_HASHSIZE, 90 IPSET_ATTR_HASHSIZE,
91 IPSET_ATTR_MAXELEM, 91 IPSET_ATTR_MAXELEM,
92 IPSET_ATTR_MARKMASK,
92 IPSET_ATTR_NETMASK, 93 IPSET_ATTR_NETMASK,
93 IPSET_ATTR_PROBES, 94 IPSET_ATTR_PROBES,
94 IPSET_ATTR_RESIZE, 95 IPSET_ATTR_RESIZE,
@@ -138,6 +139,7 @@ enum ipset_errno {
138 IPSET_ERR_EXIST, 139 IPSET_ERR_EXIST,
139 IPSET_ERR_INVALID_CIDR, 140 IPSET_ERR_INVALID_CIDR,
140 IPSET_ERR_INVALID_NETMASK, 141 IPSET_ERR_INVALID_NETMASK,
142 IPSET_ERR_INVALID_MARKMASK,
141 IPSET_ERR_INVALID_FAMILY, 143 IPSET_ERR_INVALID_FAMILY,
142 IPSET_ERR_TIMEOUT, 144 IPSET_ERR_TIMEOUT,
143 IPSET_ERR_REFERENCED, 145 IPSET_ERR_REFERENCED,
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index be6932ad3a86..b1eed81e24c5 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -263,6 +263,9 @@ struct htype {
263 u32 maxelem; /* max elements in the hash */ 263 u32 maxelem; /* max elements in the hash */
264 u32 elements; /* current element (vs timeout) */ 264 u32 elements; /* current element (vs timeout) */
265 u32 initval; /* random jhash init value */ 265 u32 initval; /* random jhash init value */
266#ifdef IP_SET_HASH_WITH_MARKMASK
267 u32 markmask; /* markmask value for mark mask to store */
268#endif
266 struct timer_list gc; /* garbage collection when timeout enabled */ 269 struct timer_list gc; /* garbage collection when timeout enabled */
267 struct mtype_elem next; /* temporary storage for uadd */ 270 struct mtype_elem next; /* temporary storage for uadd */
268#ifdef IP_SET_HASH_WITH_MULTI 271#ifdef IP_SET_HASH_WITH_MULTI
@@ -454,6 +457,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
454#ifdef IP_SET_HASH_WITH_NETMASK 457#ifdef IP_SET_HASH_WITH_NETMASK
455 x->netmask == y->netmask && 458 x->netmask == y->netmask &&
456#endif 459#endif
460#ifdef IP_SET_HASH_WITH_MARKMASK
461 x->markmask == y->markmask &&
462#endif
457 a->extensions == b->extensions; 463 a->extensions == b->extensions;
458} 464}
459 465
@@ -908,6 +914,10 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
908 nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) 914 nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask))
909 goto nla_put_failure; 915 goto nla_put_failure;
910#endif 916#endif
917#ifdef IP_SET_HASH_WITH_MARKMASK
918 if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask))
919 goto nla_put_failure;
920#endif
911 if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || 921 if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
912 nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize))) 922 nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)))
913 goto nla_put_failure; 923 goto nla_put_failure;
@@ -1016,6 +1026,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1016 struct nlattr *tb[], u32 flags) 1026 struct nlattr *tb[], u32 flags)
1017{ 1027{
1018 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 1028 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
1029#ifdef IP_SET_HASH_WITH_MARKMASK
1030 u32 markmask;
1031#endif
1019 u8 hbits; 1032 u8 hbits;
1020#ifdef IP_SET_HASH_WITH_NETMASK 1033#ifdef IP_SET_HASH_WITH_NETMASK
1021 u8 netmask; 1034 u8 netmask;
@@ -1026,6 +1039,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1026 1039
1027 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 1040 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
1028 return -IPSET_ERR_INVALID_FAMILY; 1041 return -IPSET_ERR_INVALID_FAMILY;
1042
1043#ifdef IP_SET_HASH_WITH_MARKMASK
1044 markmask = 0xffffffff;
1045#endif
1029#ifdef IP_SET_HASH_WITH_NETMASK 1046#ifdef IP_SET_HASH_WITH_NETMASK
1030 netmask = set->family == NFPROTO_IPV4 ? 32 : 128; 1047 netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
1031 pr_debug("Create set %s with family %s\n", 1048 pr_debug("Create set %s with family %s\n",
@@ -1034,6 +1051,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1034 1051
1035 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 1052 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
1036 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 1053 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
1054#ifdef IP_SET_HASH_WITH_MARKMASK
1055 !ip_set_optattr_netorder(tb, IPSET_ATTR_MARKMASK) ||
1056#endif
1037 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 1057 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
1038 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 1058 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
1039 return -IPSET_ERR_PROTOCOL; 1059 return -IPSET_ERR_PROTOCOL;
@@ -1057,6 +1077,14 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1057 return -IPSET_ERR_INVALID_NETMASK; 1077 return -IPSET_ERR_INVALID_NETMASK;
1058 } 1078 }
1059#endif 1079#endif
1080#ifdef IP_SET_HASH_WITH_MARKMASK
1081 if (tb[IPSET_ATTR_MARKMASK]) {
1082 markmask = ntohl(nla_get_u32(tb[IPSET_ATTR_MARKMASK]));
1083
1084 if ((markmask > 4294967295u) || markmask == 0)
1085 return -IPSET_ERR_INVALID_MARKMASK;
1086 }
1087#endif
1060 1088
1061 hsize = sizeof(*h); 1089 hsize = sizeof(*h);
1062#ifdef IP_SET_HASH_WITH_NETS 1090#ifdef IP_SET_HASH_WITH_NETS
@@ -1071,6 +1099,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1071#ifdef IP_SET_HASH_WITH_NETMASK 1099#ifdef IP_SET_HASH_WITH_NETMASK
1072 h->netmask = netmask; 1100 h->netmask = netmask;
1073#endif 1101#endif
1102#ifdef IP_SET_HASH_WITH_MARKMASK
1103 h->markmask = markmask;
1104#endif
1074 get_random_bytes(&h->initval, sizeof(h->initval)); 1105 get_random_bytes(&h->initval, sizeof(h->initval));
1075 set->timeout = IPSET_NO_TIMEOUT; 1106 set->timeout = IPSET_NO_TIMEOUT;
1076 1107
diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c
index e56c0d916fac..1bf8e8524218 100644
--- a/net/netfilter/ipset/ip_set_hash_ipmark.c
+++ b/net/netfilter/ipset/ip_set_hash_ipmark.c
@@ -34,6 +34,7 @@ MODULE_ALIAS("ip_set_hash:ip,mark");
34 34
35/* Type specific function prefix */ 35/* Type specific function prefix */
36#define HTYPE hash_ipmark 36#define HTYPE hash_ipmark
37#define IP_SET_HASH_WITH_MARKMASK
37 38
38/* IPv4 variant */ 39/* IPv4 variant */
39 40
@@ -85,11 +86,13 @@ hash_ipmark4_kadt(struct ip_set *set, const struct sk_buff *skb,
85 const struct xt_action_param *par, 86 const struct xt_action_param *par,
86 enum ipset_adt adt, struct ip_set_adt_opt *opt) 87 enum ipset_adt adt, struct ip_set_adt_opt *opt)
87{ 88{
89 const struct hash_ipmark *h = set->data;
88 ipset_adtfn adtfn = set->variant->adt[adt]; 90 ipset_adtfn adtfn = set->variant->adt[adt];
89 struct hash_ipmark4_elem e = { }; 91 struct hash_ipmark4_elem e = { };
90 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 92 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
91 93
92 e.mark = skb->mark; 94 e.mark = skb->mark;
95 e.mark &= h->markmask;
93 96
94 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 97 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
95 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 98 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
@@ -122,6 +125,7 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
122 return ret; 125 return ret;
123 126
124 e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK])); 127 e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK]));
128 e.mark &= h->markmask;
125 129
126 if (adt == IPSET_TEST || 130 if (adt == IPSET_TEST ||
127 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) { 131 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) {
@@ -213,11 +217,13 @@ hash_ipmark6_kadt(struct ip_set *set, const struct sk_buff *skb,
213 const struct xt_action_param *par, 217 const struct xt_action_param *par,
214 enum ipset_adt adt, struct ip_set_adt_opt *opt) 218 enum ipset_adt adt, struct ip_set_adt_opt *opt)
215{ 219{
220 const struct hash_ipmark *h = set->data;
216 ipset_adtfn adtfn = set->variant->adt[adt]; 221 ipset_adtfn adtfn = set->variant->adt[adt];
217 struct hash_ipmark6_elem e = { }; 222 struct hash_ipmark6_elem e = { };
218 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 223 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
219 224
220 e.mark = skb->mark; 225 e.mark = skb->mark;
226 e.mark &= h->markmask;
221 227
222 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 228 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
223 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 229 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
@@ -227,6 +233,7 @@ static int
227hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[], 233hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[],
228 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 234 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
229{ 235{
236 const struct hash_ipmark *h = set->data;
230 ipset_adtfn adtfn = set->variant->adt[adt]; 237 ipset_adtfn adtfn = set->variant->adt[adt];
231 struct hash_ipmark6_elem e = { }; 238 struct hash_ipmark6_elem e = { };
232 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 239 struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -250,6 +257,7 @@ hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[],
250 return ret; 257 return ret;
251 258
252 e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK])); 259 e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK]));
260 e.mark &= h->markmask;
253 261
254 if (adt == IPSET_TEST) { 262 if (adt == IPSET_TEST) {
255 ret = adtfn(set, &e, &ext, &ext, flags); 263 ret = adtfn(set, &e, &ext, &ext, flags);
@@ -275,6 +283,7 @@ static struct ip_set_type hash_ipmark_type __read_mostly = {
275 .revision_max = IPSET_TYPE_REV_MAX, 283 .revision_max = IPSET_TYPE_REV_MAX,
276 .create = hash_ipmark_create, 284 .create = hash_ipmark_create,
277 .create_policy = { 285 .create_policy = {
286 [IPSET_ATTR_MARKMASK] = { .type = NLA_U32 },
278 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 287 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
279 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 288 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
280 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 289 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },