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>

authored by Jozsef Kadlecsik and committed by Patrick McHardy 5e0c1eb7 b26fa4e0

+48 -94
+10
include/linux/netfilter/ipset/ip_set_getport.h
··· 18 18 extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, 19 19 __be16 *port); 20 20 21 + static 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 31 #endif /*_IP_SET_GETPORT_H*/
+10 -24
net/netfilter/ipset/ip_set_hash_ipport.c
··· 150 150 struct hash_ipport4_elem data = { }; 151 151 u32 ip, ip_to, p, port, port_to; 152 152 u32 timeout = h->timeout; 153 + bool with_ports = false; 153 154 int ret; 154 155 155 156 if (unlikely(!tb[IPSET_ATTR_IP] || ··· 173 172 174 173 if (tb[IPSET_ATTR_PROTO]) { 175 174 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 175 + with_ports = ip_set_proto_with_ports(data.proto); 176 176 177 177 if (data.proto == 0) 178 178 return -IPSET_ERR_INVALID_PROTO; 179 179 } else 180 180 return -IPSET_ERR_MISSING_PROTO; 181 181 182 - switch (data.proto) { 183 - case IPPROTO_UDP: 184 - case IPPROTO_TCP: 185 - case IPPROTO_ICMP: 186 - break; 187 - default: 182 + if (!(with_ports || data.proto == IPPROTO_ICMP)) 188 183 data.port = 0; 189 - break; 190 - } 191 184 192 185 if (tb[IPSET_ATTR_TIMEOUT]) { 193 186 if (!with_timeout(h->timeout)) ··· 190 195 } 191 196 192 197 if (adt == IPSET_TEST || 193 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 194 198 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 195 199 tb[IPSET_ATTR_PORT_TO])) { 196 200 ret = adtfn(set, &data, timeout); ··· 213 219 } else 214 220 ip_to = ip; 215 221 216 - port = ntohs(data.port); 217 - if (tb[IPSET_ATTR_PORT_TO]) { 222 + port_to = port = ntohs(data.port); 223 + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 218 224 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 219 225 if (port > port_to) 220 226 swap(port, port_to); 221 - } else 222 - port_to = port; 227 + } 223 228 224 229 for (; !before(ip_to, ip); ip++) 225 230 for (p = port; p <= port_to; p++) { ··· 354 361 struct hash_ipport6_elem data = { }; 355 362 u32 port, port_to; 356 363 u32 timeout = h->timeout; 364 + bool with_ports = false; 357 365 int ret; 358 366 359 367 if (unlikely(!tb[IPSET_ATTR_IP] || ··· 379 385 380 386 if (tb[IPSET_ATTR_PROTO]) { 381 387 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 388 + with_ports = ip_set_proto_with_ports(data.proto); 382 389 383 390 if (data.proto == 0) 384 391 return -IPSET_ERR_INVALID_PROTO; 385 392 } else 386 393 return -IPSET_ERR_MISSING_PROTO; 387 394 388 - switch (data.proto) { 389 - case IPPROTO_UDP: 390 - case IPPROTO_TCP: 391 - case IPPROTO_ICMPV6: 392 - break; 393 - default: 395 + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 394 396 data.port = 0; 395 - break; 396 - } 397 397 398 398 if (tb[IPSET_ATTR_TIMEOUT]) { 399 399 if (!with_timeout(h->timeout)) ··· 395 407 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 396 408 } 397 409 398 - if (adt == IPSET_TEST || 399 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 400 - !tb[IPSET_ATTR_PORT_TO]) { 410 + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 401 411 ret = adtfn(set, &data, timeout); 402 412 return ip_set_eexist(ret, flags) ? 0 : ret; 403 413 }
+10 -24
net/netfilter/ipset/ip_set_hash_ipportip.c
··· 154 154 struct hash_ipportip4_elem data = { }; 155 155 u32 ip, ip_to, p, port, port_to; 156 156 u32 timeout = h->timeout; 157 + bool with_ports = false; 157 158 int ret; 158 159 159 160 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || ··· 181 180 182 181 if (tb[IPSET_ATTR_PROTO]) { 183 182 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 183 + with_ports = ip_set_proto_with_ports(data.proto); 184 184 185 185 if (data.proto == 0) 186 186 return -IPSET_ERR_INVALID_PROTO; 187 187 } else 188 188 return -IPSET_ERR_MISSING_PROTO; 189 189 190 - switch (data.proto) { 191 - case IPPROTO_UDP: 192 - case IPPROTO_TCP: 193 - case IPPROTO_ICMP: 194 - break; 195 - default: 190 + if (!(with_ports || data.proto == IPPROTO_ICMP)) 196 191 data.port = 0; 197 - break; 198 - } 199 192 200 193 if (tb[IPSET_ATTR_TIMEOUT]) { 201 194 if (!with_timeout(h->timeout)) ··· 198 203 } 199 204 200 205 if (adt == IPSET_TEST || 201 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 202 206 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 203 207 tb[IPSET_ATTR_PORT_TO])) { 204 208 ret = adtfn(set, &data, timeout); ··· 221 227 } else 222 228 ip_to = ip; 223 229 224 - port = ntohs(data.port); 225 - if (tb[IPSET_ATTR_PORT_TO]) { 230 + port_to = port = ntohs(data.port); 231 + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 226 232 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 227 233 if (port > port_to) 228 234 swap(port, port_to); 229 - } else 230 - port_to = port; 235 + } 231 236 232 237 for (; !before(ip_to, ip); ip++) 233 238 for (p = port; p <= port_to; p++) { ··· 368 375 struct hash_ipportip6_elem data = { }; 369 376 u32 port, port_to; 370 377 u32 timeout = h->timeout; 378 + bool with_ports = false; 371 379 int ret; 372 380 373 381 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || ··· 397 403 398 404 if (tb[IPSET_ATTR_PROTO]) { 399 405 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 406 + with_ports = ip_set_proto_with_ports(data.proto); 400 407 401 408 if (data.proto == 0) 402 409 return -IPSET_ERR_INVALID_PROTO; 403 410 } else 404 411 return -IPSET_ERR_MISSING_PROTO; 405 412 406 - switch (data.proto) { 407 - case IPPROTO_UDP: 408 - case IPPROTO_TCP: 409 - case IPPROTO_ICMPV6: 410 - break; 411 - default: 413 + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 412 414 data.port = 0; 413 - break; 414 - } 415 415 416 416 if (tb[IPSET_ATTR_TIMEOUT]) { 417 417 if (!with_timeout(h->timeout)) ··· 413 425 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 414 426 } 415 427 416 - if (adt == IPSET_TEST || 417 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 418 - !tb[IPSET_ATTR_PORT_TO]) { 428 + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 419 429 ret = adtfn(set, &data, timeout); 420 430 return ip_set_eexist(ret, flags) ? 0 : ret; 421 431 }
+10 -24
net/netfilter/ipset/ip_set_hash_ipportnet.c
··· 174 174 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; 175 175 u32 ip, ip_to, p, port, port_to; 176 176 u32 timeout = h->timeout; 177 + bool with_ports = false; 177 178 int ret; 178 179 179 180 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || ··· 209 208 210 209 if (tb[IPSET_ATTR_PROTO]) { 211 210 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 211 + with_ports = ip_set_proto_with_ports(data.proto); 212 212 213 213 if (data.proto == 0) 214 214 return -IPSET_ERR_INVALID_PROTO; 215 215 } else 216 216 return -IPSET_ERR_MISSING_PROTO; 217 217 218 - switch (data.proto) { 219 - case IPPROTO_UDP: 220 - case IPPROTO_TCP: 221 - case IPPROTO_ICMP: 222 - break; 223 - default: 218 + if (!(with_ports || data.proto == IPPROTO_ICMP)) 224 219 data.port = 0; 225 - break; 226 - } 227 220 228 221 if (tb[IPSET_ATTR_TIMEOUT]) { 229 222 if (!with_timeout(h->timeout)) ··· 226 231 } 227 232 228 233 if (adt == IPSET_TEST || 229 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 230 234 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 231 235 tb[IPSET_ATTR_PORT_TO])) { 232 236 ret = adtfn(set, &data, timeout); ··· 249 255 } else 250 256 ip_to = ip; 251 257 252 - port = ntohs(data.port); 253 - if (tb[IPSET_ATTR_PORT_TO]) { 258 + port_to = port = ntohs(data.port); 259 + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 254 260 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 255 261 if (port > port_to) 256 262 swap(port, port_to); 257 - } else 258 - port_to = port; 263 + } 259 264 260 265 for (; !before(ip_to, ip); ip++) 261 266 for (p = port; p <= port_to; p++) { ··· 422 429 struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; 423 430 u32 port, port_to; 424 431 u32 timeout = h->timeout; 432 + bool with_ports = false; 425 433 int ret; 426 434 427 435 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || ··· 459 465 460 466 if (tb[IPSET_ATTR_PROTO]) { 461 467 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 468 + with_ports = ip_set_proto_with_ports(data.proto); 462 469 463 470 if (data.proto == 0) 464 471 return -IPSET_ERR_INVALID_PROTO; 465 472 } else 466 473 return -IPSET_ERR_MISSING_PROTO; 467 474 468 - switch (data.proto) { 469 - case IPPROTO_UDP: 470 - case IPPROTO_TCP: 471 - case IPPROTO_ICMPV6: 472 - break; 473 - default: 475 + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 474 476 data.port = 0; 475 - break; 476 - } 477 477 478 478 if (tb[IPSET_ATTR_TIMEOUT]) { 479 479 if (!with_timeout(h->timeout)) ··· 475 487 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 476 488 } 477 489 478 - if (adt == IPSET_TEST || 479 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 480 - !tb[IPSET_ATTR_PORT_TO]) { 490 + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 481 491 ret = adtfn(set, &data, timeout); 482 492 return ip_set_eexist(ret, flags) ? 0 : ret; 483 493 }
+8 -22
net/netfilter/ipset/ip_set_hash_netport.c
··· 170 170 struct hash_netport4_elem data = { .cidr = HOST_MASK }; 171 171 u32 port, port_to; 172 172 u32 timeout = h->timeout; 173 + bool with_ports = false; 173 174 int ret; 174 175 175 176 if (unlikely(!tb[IPSET_ATTR_IP] || ··· 199 198 200 199 if (tb[IPSET_ATTR_PROTO]) { 201 200 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 201 + with_ports = ip_set_proto_with_ports(data.proto); 202 202 203 203 if (data.proto == 0) 204 204 return -IPSET_ERR_INVALID_PROTO; 205 205 } else 206 206 return -IPSET_ERR_MISSING_PROTO; 207 207 208 - switch (data.proto) { 209 - case IPPROTO_UDP: 210 - case IPPROTO_TCP: 211 - case IPPROTO_ICMP: 212 - break; 213 - default: 208 + if (!(with_ports || data.proto == IPPROTO_ICMP)) 214 209 data.port = 0; 215 - break; 216 - } 217 210 218 211 if (tb[IPSET_ATTR_TIMEOUT]) { 219 212 if (!with_timeout(h->timeout)) ··· 215 220 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 216 221 } 217 222 218 - if (adt == IPSET_TEST || 219 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 220 - !tb[IPSET_ATTR_PORT_TO]) { 223 + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 221 224 ret = adtfn(set, &data, timeout); 222 225 return ip_set_eexist(ret, flags) ? 0 : ret; 223 226 } ··· 383 390 struct hash_netport6_elem data = { .cidr = HOST_MASK }; 384 391 u32 port, port_to; 385 392 u32 timeout = h->timeout; 393 + bool with_ports = false; 386 394 int ret; 387 395 388 396 if (unlikely(!tb[IPSET_ATTR_IP] || ··· 412 418 413 419 if (tb[IPSET_ATTR_PROTO]) { 414 420 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 421 + with_ports = ip_set_proto_with_ports(data.proto); 415 422 416 423 if (data.proto == 0) 417 424 return -IPSET_ERR_INVALID_PROTO; 418 425 } else 419 426 return -IPSET_ERR_MISSING_PROTO; 420 427 421 - switch (data.proto) { 422 - case IPPROTO_UDP: 423 - case IPPROTO_TCP: 424 - case IPPROTO_ICMPV6: 425 - break; 426 - default: 428 + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 427 429 data.port = 0; 428 - break; 429 - } 430 430 431 431 if (tb[IPSET_ATTR_TIMEOUT]) { 432 432 if (!with_timeout(h->timeout)) ··· 428 440 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 429 441 } 430 442 431 - if (adt == IPSET_TEST || 432 - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 433 - !tb[IPSET_ATTR_PORT_TO]) { 443 + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 434 444 ret = adtfn(set, &data, timeout); 435 445 return ip_set_eexist(ret, flags) ? 0 : ret; 436 446 }