aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2011-03-20 10:33:26 -0400
committerPatrick McHardy <kaber@trash.net>2011-03-20 10:33:26 -0400
commit5e0c1eb7e6b61998c7ecd39b7f69a15773d894d4 (patch)
tree4fba9a1410925d0a6d7a8a39aa8cc447e6f9251c
parentb26fa4e0275426450238a14158bc1db24bb696e6 (diff)
netfilter: ipset: fix address ranges at hash:*port* types
The hash:*port* types with IPv4 silently ignored when address ranges with non TCP/UDP were added/deleted from the set and used the first address from the range only. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/ipset/ip_set_getport.h10
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c34
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c34
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c34
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c30
5 files changed, 48 insertions, 94 deletions
diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h
index 3882a81a3b3c..5aebd170f899 100644
--- a/include/linux/netfilter/ipset/ip_set_getport.h
+++ b/include/linux/netfilter/ipset/ip_set_getport.h
@@ -18,4 +18,14 @@ static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
18extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, 18extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
19 __be16 *port); 19 __be16 *port);
20 20
21static inline bool ip_set_proto_with_ports(u8 proto)
22{
23 switch (proto) {
24 case IPPROTO_TCP:
25 case IPPROTO_UDP:
26 return true;
27 }
28 return false;
29}
30
21#endif /*_IP_SET_GETPORT_H*/ 31#endif /*_IP_SET_GETPORT_H*/
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index adbe787ea5dc..b9214145d357 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
150 struct hash_ipport4_elem data = { }; 150 struct hash_ipport4_elem data = { };
151 u32 ip, ip_to, p, port, port_to; 151 u32 ip, ip_to, p, port, port_to;
152 u32 timeout = h->timeout; 152 u32 timeout = h->timeout;
153 bool with_ports = false;
153 int ret; 154 int ret;
154 155
155 if (unlikely(!tb[IPSET_ATTR_IP] || 156 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
172 173
173 if (tb[IPSET_ATTR_PROTO]) { 174 if (tb[IPSET_ATTR_PROTO]) {
174 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 175 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
176 with_ports = ip_set_proto_with_ports(data.proto);
175 177
176 if (data.proto == 0) 178 if (data.proto == 0)
177 return -IPSET_ERR_INVALID_PROTO; 179 return -IPSET_ERR_INVALID_PROTO;
178 } else 180 } else
179 return -IPSET_ERR_MISSING_PROTO; 181 return -IPSET_ERR_MISSING_PROTO;
180 182
181 switch (data.proto) { 183 if (!(with_ports || data.proto == IPPROTO_ICMP))
182 case IPPROTO_UDP:
183 case IPPROTO_TCP:
184 case IPPROTO_ICMP:
185 break;
186 default:
187 data.port = 0; 184 data.port = 0;
188 break;
189 }
190 185
191 if (tb[IPSET_ATTR_TIMEOUT]) { 186 if (tb[IPSET_ATTR_TIMEOUT]) {
192 if (!with_timeout(h->timeout)) 187 if (!with_timeout(h->timeout))
@@ -195,7 +190,6 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
195 } 190 }
196 191
197 if (adt == IPSET_TEST || 192 if (adt == IPSET_TEST ||
198 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
199 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 193 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
200 tb[IPSET_ATTR_PORT_TO])) { 194 tb[IPSET_ATTR_PORT_TO])) {
201 ret = adtfn(set, &data, timeout); 195 ret = adtfn(set, &data, timeout);
@@ -219,13 +213,12 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
219 } else 213 } else
220 ip_to = ip; 214 ip_to = ip;
221 215
222 port = ntohs(data.port); 216 port_to = port = ntohs(data.port);
223 if (tb[IPSET_ATTR_PORT_TO]) { 217 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
224 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 218 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
225 if (port > port_to) 219 if (port > port_to)
226 swap(port, port_to); 220 swap(port, port_to);
227 } else 221 }
228 port_to = port;
229 222
230 for (; !before(ip_to, ip); ip++) 223 for (; !before(ip_to, ip); ip++)
231 for (p = port; p <= port_to; p++) { 224 for (p = port; p <= port_to; p++) {
@@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
361 struct hash_ipport6_elem data = { }; 354 struct hash_ipport6_elem data = { };
362 u32 port, port_to; 355 u32 port, port_to;
363 u32 timeout = h->timeout; 356 u32 timeout = h->timeout;
357 bool with_ports = false;
364 int ret; 358 int ret;
365 359
366 if (unlikely(!tb[IPSET_ATTR_IP] || 360 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
385 379
386 if (tb[IPSET_ATTR_PROTO]) { 380 if (tb[IPSET_ATTR_PROTO]) {
387 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 381 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
382 with_ports = ip_set_proto_with_ports(data.proto);
388 383
389 if (data.proto == 0) 384 if (data.proto == 0)
390 return -IPSET_ERR_INVALID_PROTO; 385 return -IPSET_ERR_INVALID_PROTO;
391 } else 386 } else
392 return -IPSET_ERR_MISSING_PROTO; 387 return -IPSET_ERR_MISSING_PROTO;
393 388
394 switch (data.proto) { 389 if (!(with_ports || data.proto == IPPROTO_ICMPV6))
395 case IPPROTO_UDP:
396 case IPPROTO_TCP:
397 case IPPROTO_ICMPV6:
398 break;
399 default:
400 data.port = 0; 390 data.port = 0;
401 break;
402 }
403 391
404 if (tb[IPSET_ATTR_TIMEOUT]) { 392 if (tb[IPSET_ATTR_TIMEOUT]) {
405 if (!with_timeout(h->timeout)) 393 if (!with_timeout(h->timeout))
@@ -407,9 +395,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
407 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 395 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
408 } 396 }
409 397
410 if (adt == IPSET_TEST || 398 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
411 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
412 !tb[IPSET_ATTR_PORT_TO]) {
413 ret = adtfn(set, &data, timeout); 399 ret = adtfn(set, &data, timeout);
414 return ip_set_eexist(ret, flags) ? 0 : ret; 400 return ip_set_eexist(ret, flags) ? 0 : ret;
415 } 401 }
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 22e23abb86c6..4642872df6e1 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
154 struct hash_ipportip4_elem data = { }; 154 struct hash_ipportip4_elem data = { };
155 u32 ip, ip_to, p, port, port_to; 155 u32 ip, ip_to, p, port, port_to;
156 u32 timeout = h->timeout; 156 u32 timeout = h->timeout;
157 bool with_ports = false;
157 int ret; 158 int ret;
158 159
159 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 160 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
@@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
180 181
181 if (tb[IPSET_ATTR_PROTO]) { 182 if (tb[IPSET_ATTR_PROTO]) {
182 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 183 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
184 with_ports = ip_set_proto_with_ports(data.proto);
183 185
184 if (data.proto == 0) 186 if (data.proto == 0)
185 return -IPSET_ERR_INVALID_PROTO; 187 return -IPSET_ERR_INVALID_PROTO;
186 } else 188 } else
187 return -IPSET_ERR_MISSING_PROTO; 189 return -IPSET_ERR_MISSING_PROTO;
188 190
189 switch (data.proto) { 191 if (!(with_ports || data.proto == IPPROTO_ICMP))
190 case IPPROTO_UDP:
191 case IPPROTO_TCP:
192 case IPPROTO_ICMP:
193 break;
194 default:
195 data.port = 0; 192 data.port = 0;
196 break;
197 }
198 193
199 if (tb[IPSET_ATTR_TIMEOUT]) { 194 if (tb[IPSET_ATTR_TIMEOUT]) {
200 if (!with_timeout(h->timeout)) 195 if (!with_timeout(h->timeout))
@@ -203,7 +198,6 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
203 } 198 }
204 199
205 if (adt == IPSET_TEST || 200 if (adt == IPSET_TEST ||
206 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
207 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 201 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
208 tb[IPSET_ATTR_PORT_TO])) { 202 tb[IPSET_ATTR_PORT_TO])) {
209 ret = adtfn(set, &data, timeout); 203 ret = adtfn(set, &data, timeout);
@@ -227,13 +221,12 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
227 } else 221 } else
228 ip_to = ip; 222 ip_to = ip;
229 223
230 port = ntohs(data.port); 224 port_to = port = ntohs(data.port);
231 if (tb[IPSET_ATTR_PORT_TO]) { 225 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
232 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 226 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
233 if (port > port_to) 227 if (port > port_to)
234 swap(port, port_to); 228 swap(port, port_to);
235 } else 229 }
236 port_to = port;
237 230
238 for (; !before(ip_to, ip); ip++) 231 for (; !before(ip_to, ip); ip++)
239 for (p = port; p <= port_to; p++) { 232 for (p = port; p <= port_to; p++) {
@@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
375 struct hash_ipportip6_elem data = { }; 368 struct hash_ipportip6_elem data = { };
376 u32 port, port_to; 369 u32 port, port_to;
377 u32 timeout = h->timeout; 370 u32 timeout = h->timeout;
371 bool with_ports = false;
378 int ret; 372 int ret;
379 373
380 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 374 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
@@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
403 397
404 if (tb[IPSET_ATTR_PROTO]) { 398 if (tb[IPSET_ATTR_PROTO]) {
405 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 399 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
400 with_ports = ip_set_proto_with_ports(data.proto);
406 401
407 if (data.proto == 0) 402 if (data.proto == 0)
408 return -IPSET_ERR_INVALID_PROTO; 403 return -IPSET_ERR_INVALID_PROTO;
409 } else 404 } else
410 return -IPSET_ERR_MISSING_PROTO; 405 return -IPSET_ERR_MISSING_PROTO;
411 406
412 switch (data.proto) { 407 if (!(with_ports || data.proto == IPPROTO_ICMPV6))
413 case IPPROTO_UDP:
414 case IPPROTO_TCP:
415 case IPPROTO_ICMPV6:
416 break;
417 default:
418 data.port = 0; 408 data.port = 0;
419 break;
420 }
421 409
422 if (tb[IPSET_ATTR_TIMEOUT]) { 410 if (tb[IPSET_ATTR_TIMEOUT]) {
423 if (!with_timeout(h->timeout)) 411 if (!with_timeout(h->timeout))
@@ -425,9 +413,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
425 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 413 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
426 } 414 }
427 415
428 if (adt == IPSET_TEST || 416 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
429 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
430 !tb[IPSET_ATTR_PORT_TO]) {
431 ret = adtfn(set, &data, timeout); 417 ret = adtfn(set, &data, timeout);
432 return ip_set_eexist(ret, flags) ? 0 : ret; 418 return ip_set_eexist(ret, flags) ? 0 : ret;
433 } 419 }
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 6033e8b54bbd..2cb84a54b7ad 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
174 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; 174 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
175 u32 ip, ip_to, p, port, port_to; 175 u32 ip, ip_to, p, port, port_to;
176 u32 timeout = h->timeout; 176 u32 timeout = h->timeout;
177 bool with_ports = false;
177 int ret; 178 int ret;
178 179
179 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 180 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
@@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
208 209
209 if (tb[IPSET_ATTR_PROTO]) { 210 if (tb[IPSET_ATTR_PROTO]) {
210 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 211 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
212 with_ports = ip_set_proto_with_ports(data.proto);
211 213
212 if (data.proto == 0) 214 if (data.proto == 0)
213 return -IPSET_ERR_INVALID_PROTO; 215 return -IPSET_ERR_INVALID_PROTO;
214 } else 216 } else
215 return -IPSET_ERR_MISSING_PROTO; 217 return -IPSET_ERR_MISSING_PROTO;
216 218
217 switch (data.proto) { 219 if (!(with_ports || data.proto == IPPROTO_ICMP))
218 case IPPROTO_UDP:
219 case IPPROTO_TCP:
220 case IPPROTO_ICMP:
221 break;
222 default:
223 data.port = 0; 220 data.port = 0;
224 break;
225 }
226 221
227 if (tb[IPSET_ATTR_TIMEOUT]) { 222 if (tb[IPSET_ATTR_TIMEOUT]) {
228 if (!with_timeout(h->timeout)) 223 if (!with_timeout(h->timeout))
@@ -231,7 +226,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
231 } 226 }
232 227
233 if (adt == IPSET_TEST || 228 if (adt == IPSET_TEST ||
234 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
235 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 229 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
236 tb[IPSET_ATTR_PORT_TO])) { 230 tb[IPSET_ATTR_PORT_TO])) {
237 ret = adtfn(set, &data, timeout); 231 ret = adtfn(set, &data, timeout);
@@ -255,13 +249,12 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
255 } else 249 } else
256 ip_to = ip; 250 ip_to = ip;
257 251
258 port = ntohs(data.port); 252 port_to = port = ntohs(data.port);
259 if (tb[IPSET_ATTR_PORT_TO]) { 253 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
260 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 254 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
261 if (port > port_to) 255 if (port > port_to)
262 swap(port, port_to); 256 swap(port, port_to);
263 } else 257 }
264 port_to = port;
265 258
266 for (; !before(ip_to, ip); ip++) 259 for (; !before(ip_to, ip); ip++)
267 for (p = port; p <= port_to; p++) { 260 for (p = port; p <= port_to; p++) {
@@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
429 struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; 422 struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
430 u32 port, port_to; 423 u32 port, port_to;
431 u32 timeout = h->timeout; 424 u32 timeout = h->timeout;
425 bool with_ports = false;
432 int ret; 426 int ret;
433 427
434 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 428 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
@@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
465 459
466 if (tb[IPSET_ATTR_PROTO]) { 460 if (tb[IPSET_ATTR_PROTO]) {
467 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 461 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
462 with_ports = ip_set_proto_with_ports(data.proto);
468 463
469 if (data.proto == 0) 464 if (data.proto == 0)
470 return -IPSET_ERR_INVALID_PROTO; 465 return -IPSET_ERR_INVALID_PROTO;
471 } else 466 } else
472 return -IPSET_ERR_MISSING_PROTO; 467 return -IPSET_ERR_MISSING_PROTO;
473 468
474 switch (data.proto) { 469 if (!(with_ports || data.proto == IPPROTO_ICMPV6))
475 case IPPROTO_UDP:
476 case IPPROTO_TCP:
477 case IPPROTO_ICMPV6:
478 break;
479 default:
480 data.port = 0; 470 data.port = 0;
481 break;
482 }
483 471
484 if (tb[IPSET_ATTR_TIMEOUT]) { 472 if (tb[IPSET_ATTR_TIMEOUT]) {
485 if (!with_timeout(h->timeout)) 473 if (!with_timeout(h->timeout))
@@ -487,9 +475,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
487 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 475 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
488 } 476 }
489 477
490 if (adt == IPSET_TEST || 478 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
491 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
492 !tb[IPSET_ATTR_PORT_TO]) {
493 ret = adtfn(set, &data, timeout); 479 ret = adtfn(set, &data, timeout);
494 return ip_set_eexist(ret, flags) ? 0 : ret; 480 return ip_set_eexist(ret, flags) ? 0 : ret;
495 } 481 }
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index 34a165626ee9..8598676f2a05 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
170 struct hash_netport4_elem data = { .cidr = HOST_MASK }; 170 struct hash_netport4_elem data = { .cidr = HOST_MASK };
171 u32 port, port_to; 171 u32 port, port_to;
172 u32 timeout = h->timeout; 172 u32 timeout = h->timeout;
173 bool with_ports = false;
173 int ret; 174 int ret;
174 175
175 if (unlikely(!tb[IPSET_ATTR_IP] || 176 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
198 199
199 if (tb[IPSET_ATTR_PROTO]) { 200 if (tb[IPSET_ATTR_PROTO]) {
200 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 201 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
202 with_ports = ip_set_proto_with_ports(data.proto);
201 203
202 if (data.proto == 0) 204 if (data.proto == 0)
203 return -IPSET_ERR_INVALID_PROTO; 205 return -IPSET_ERR_INVALID_PROTO;
204 } else 206 } else
205 return -IPSET_ERR_MISSING_PROTO; 207 return -IPSET_ERR_MISSING_PROTO;
206 208
207 switch (data.proto) { 209 if (!(with_ports || data.proto == IPPROTO_ICMP))
208 case IPPROTO_UDP:
209 case IPPROTO_TCP:
210 case IPPROTO_ICMP:
211 break;
212 default:
213 data.port = 0; 210 data.port = 0;
214 break;
215 }
216 211
217 if (tb[IPSET_ATTR_TIMEOUT]) { 212 if (tb[IPSET_ATTR_TIMEOUT]) {
218 if (!with_timeout(h->timeout)) 213 if (!with_timeout(h->timeout))
@@ -220,9 +215,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
220 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 215 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
221 } 216 }
222 217
223 if (adt == IPSET_TEST || 218 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
224 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
225 !tb[IPSET_ATTR_PORT_TO]) {
226 ret = adtfn(set, &data, timeout); 219 ret = adtfn(set, &data, timeout);
227 return ip_set_eexist(ret, flags) ? 0 : ret; 220 return ip_set_eexist(ret, flags) ? 0 : ret;
228 } 221 }
@@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
390 struct hash_netport6_elem data = { .cidr = HOST_MASK }; 383 struct hash_netport6_elem data = { .cidr = HOST_MASK };
391 u32 port, port_to; 384 u32 port, port_to;
392 u32 timeout = h->timeout; 385 u32 timeout = h->timeout;
386 bool with_ports = false;
393 int ret; 387 int ret;
394 388
395 if (unlikely(!tb[IPSET_ATTR_IP] || 389 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
418 412
419 if (tb[IPSET_ATTR_PROTO]) { 413 if (tb[IPSET_ATTR_PROTO]) {
420 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 414 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
415 with_ports = ip_set_proto_with_ports(data.proto);
421 416
422 if (data.proto == 0) 417 if (data.proto == 0)
423 return -IPSET_ERR_INVALID_PROTO; 418 return -IPSET_ERR_INVALID_PROTO;
424 } else 419 } else
425 return -IPSET_ERR_MISSING_PROTO; 420 return -IPSET_ERR_MISSING_PROTO;
426 421
427 switch (data.proto) { 422 if (!(with_ports || data.proto == IPPROTO_ICMPV6))
428 case IPPROTO_UDP:
429 case IPPROTO_TCP:
430 case IPPROTO_ICMPV6:
431 break;
432 default:
433 data.port = 0; 423 data.port = 0;
434 break;
435 }
436 424
437 if (tb[IPSET_ATTR_TIMEOUT]) { 425 if (tb[IPSET_ATTR_TIMEOUT]) {
438 if (!with_timeout(h->timeout)) 426 if (!with_timeout(h->timeout))
@@ -440,9 +428,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
440 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 428 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
441 } 429 }
442 430
443 if (adt == IPSET_TEST || 431 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
444 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
445 !tb[IPSET_ATTR_PORT_TO]) {
446 ret = adtfn(set, &data, timeout); 432 ret = adtfn(set, &data, timeout);
447 return ip_set_eexist(ret, flags) ? 0 : ret; 433 return ip_set_eexist(ret, flags) ? 0 : ret;
448 } 434 }