--- linux-2.4.19-mb/include/linux/netfilter_ipv4/ip_tables.h 2002/08/15 10:57:41 1.1 +++ linux-2.4.19-mb/include/linux/netfilter_ipv4/ip_tables.h 2002/08/15 10:59:34 @@ -197,11 +197,12 @@ { u_int8_t type; /* type to match */ u_int8_t code[2]; /* range of code */ - u_int8_t invflags; /* Inverse flags */ + u_int8_t flags; /* Flags */ }; /* Values for "inv" field for struct ipt_icmp. */ -#define IPT_ICMP_INV 0x01 /* Invert the sense of type/code test */ +#define IPT_ICMP_INV 0x01 /* Invert the sense of type/code test */ +#define IPT_ICMP_TYPE_ANY 0x02 /* Match any type */ /* The argument to IPT_SO_GET_INFO */ struct ipt_getinfo --- linux-2.4.19-mb/net/ipv4/netfilter/ip_tables.c 2002/08/15 10:59:49 1.1 +++ linux-2.4.19-mb/net/ipv4/netfilter/ip_tables.c 2002/08/15 11:40:31 @@ -1627,10 +1627,11 @@ static inline int icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, u_int8_t type, u_int8_t code, - int invert) + u_int8_t flags) { - return (type == test_type && code >= min_code && code <= max_code) - ^ invert; + return (((flags & IPT_ICMP_TYPE_ANY) || (type == test_type)) + && code >= min_code && code <= max_code) + ^ !!(flags&IPT_ICMP_INV); } static int @@ -1654,13 +1655,20 @@ return 0; } - /* Must not be a fragment. */ - return !offset - && icmp_type_code_match(icmpinfo->type, + if(offset) { + /* fragments can only match wildcard */ + if((icmpinfo->flags & IPT_ICMP_TYPE_ANY) && + (icmpinfo->code[0] == 0x00) && (icmpinfo->code[1] == 0xFF)) + return !(icmpinfo->flags&IPT_ICMP_INV); + else + return 0; + } + + return icmp_type_code_match(icmpinfo->type, icmpinfo->code[0], icmpinfo->code[1], icmp->type, icmp->code, - !!(icmpinfo->invflags&IPT_ICMP_INV)); + icmpinfo->flags); } /* Called when user tries to insert an entry of this type. */ @@ -1673,11 +1681,11 @@ { const struct ipt_icmp *icmpinfo = matchinfo; - /* Must specify proto == ICMP, and no unknown invflags */ + /* Must specify proto == ICMP, and no unknown flags */ return ip->proto == IPPROTO_ICMP && !(ip->invflags & IPT_INV_PROTO) && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp)) - && !(icmpinfo->invflags & ~IPT_ICMP_INV); + && !(icmpinfo->flags & ~(IPT_ICMP_INV|IPT_ICMP_TYPE_ANY)); } /* The built-in targets: standard (NULL) and error. */ --- netfilter/userspace/extensions/libipt_icmp.c 2002/08/15 11:19:52 1.1 +++ netfilter/userspace/extensions/libipt_icmp.c 2002/08/15 12:11:29 @@ -106,12 +106,14 @@ }; static unsigned int -parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[]) +parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[], u_int8_t *flags) { unsigned int limit = sizeof(icmp_codes)/sizeof(struct icmp_names); unsigned int match = limit; unsigned int i; + *flags &= ~IPT_ICMP_TYPE_ANY; + for (i = 0; i < limit; i++) { if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype)) == 0) { @@ -141,9 +143,14 @@ if (slash) *slash = '\0'; - if (string_to_number(buffer, 0, 255, &number) == -1) - exit_error(PARAMETER_PROBLEM, - "Invalid ICMP type `%s'\n", buffer); + if(!strncasecmp(buffer, "any", 3)) { + number = 0; + *flags |= IPT_ICMP_TYPE_ANY; + } else { + if (string_to_number(buffer, 0, 255, &number) == -1) + exit_error(PARAMETER_PROBLEM, + "Invalid ICMP type `%s'\n", buffer); + } *type = number; if (slash) { if (string_to_number(slash+1, 0, 255, &number) == -1) @@ -168,6 +175,7 @@ { struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data; + icmpinfo->flags = IPT_ICMP_TYPE_ANY; icmpinfo->code[1] = 0xFF; } @@ -186,9 +194,10 @@ check_inverse(optarg, &invert, &optind, 0); *nfcache |= parse_icmp(argv[optind-1], &icmpinfo->type, - icmpinfo->code); + icmpinfo->code, + &icmpinfo->flags); if (invert) - icmpinfo->invflags |= IPT_ICMP_INV; + icmpinfo->flags |= IPT_ICMP_INV; break; default: @@ -200,10 +209,12 @@ static void print_icmptype(u_int8_t type, u_int8_t code_min, u_int8_t code_max, - int invert, + u_int8_t flags, int numeric) { - if (!numeric) { + int invert = flags & IPT_ICMP_INV; + + if (!numeric && (!flags & IPT_ICMP_TYPE_ANY)) { unsigned int i; for (i = 0; @@ -226,7 +237,12 @@ if (invert) printf("!"); - printf("type %u", type); + + if(flags & IPT_ICMP_TYPE_ANY) + printf("type any"); + else + printf("type %u", type); + if (code_min == 0 && code_max == 0xFF) printf(" "); else if (code_min == code_max) @@ -245,12 +261,12 @@ printf("icmp "); print_icmptype(icmp->type, icmp->code[0], icmp->code[1], - icmp->invflags & IPT_ICMP_INV, - numeric); + icmp->flags, + numeric); - if (icmp->invflags & ~IPT_ICMP_INV) - printf("Unknown invflags: 0x%X ", - icmp->invflags & ~IPT_ICMP_INV); + if (icmp->flags & ~(IPT_ICMP_INV|IPT_ICMP_TYPE_ANY)) + printf("Unknown icmp flags: 0x%X ", + icmp->flags & ~(IPT_ICMP_INV|IPT_ICMP_TYPE_ANY)); } /* Saves the match in parsable form to stdout. */ @@ -258,10 +274,13 @@ { const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data; - if (icmp->invflags & IPT_ICMP_INV) + if (icmp->flags & IPT_ICMP_INV) printf("! "); - printf("--icmp-type %u", icmp->type); + if(icmp->flags & IPT_ICMP_TYPE_ANY) + printf("--icmp-type any"); + else + printf("--icmp-type %u", icmp->type); if (icmp->code[0] != 0 || icmp->code[1] != 0xFF) printf("/%u", icmp->code[0]); printf(" ");