diff -uNr iptables-1.2.4.pristine/extensions/libipt_length.c iptables-1.2.4.newlength/extensions/libipt_length.c --- iptables-1.2.4.pristine/extensions/libipt_length.c Mon Aug 6 04:53:41 2001 +++ iptables-1.2.4.newlength/extensions/libipt_length.c Wed Nov 21 17:23:14 2001 @@ -15,13 +15,33 @@ printf( "length v%s options:\n" "[!] --length length[:length] Match packet length against value or range\n" -" of values (inclusive)\n", +" of values (inclusive)\n" +" of values (inclusive)\n" +"[ --length-of keywords ] \n What part of the packet to check above\n" +" length against. Combinable keywords are:\n" +" IP The IP(v4) header\n" +" PROTO The protocol (tcp, udp, etc) header\n" +" PAYLOAD The remainder of the packet\n" +" ALL Shorthand for IP+PROTO+PAYLOAD\n" +" If no --length-of specified, ALL is the default\n", NETFILTER_VERSION); } - + +struct packet_sections { + const char *name; + unsigned char section_type; +}; + +static const struct packet_sections supported_section_types[] = { + { "IP", IPT_LENGTH_IP }, + { "PROTO", IPT_LENGTH_PROTO }, + { "PAYLOAD", IPT_LENGTH_PAYLOAD } +}; + static struct option opts[] = { { "length", 1, 0, '1' }, + { "length-of", 1, 0, '2' }, /* FIXME - check last 3 fields. */ {0} }; @@ -69,6 +89,49 @@ } +static void +parse_section(const char *s, struct ipt_length_info *info) +{ + unsigned int i; + + for (i=0; i < sizeof(supported_section_types)/sizeof(packet_sections); i++) + { + if (strcasecmp(s, supported_section_types[i].name) == 0) + { + info->invert |= supported_section_types[i].section_type; + return; + } + } + exit_error(PARAMETER_PROBLEM, "Unrecognized packet section '%s'", s); +} + + +static void +parse_sections(const char *s, struct ipt_length_info *info) +{ + char *buffer; + char *cp; + + buffer = strdup(s); + while ((cp = strchr(buffer, ',')) != NULL) { +/* Handle the first section before the first comma */ + *cp = '\0'; + cp++; + + if (buffer[0]) + parse_section(buffer, info); + buffer = cp; + } +/* Handle last section after any commas */ + if (buffer[0]) + parse_section(buffer, info); + + /* Do we need to free buffer? */ +} + +#define LENGTH_LENGTH 0x01 +#define LENGTH_LENGTH_OF 0x02 + /* Function which parses command options; returns true if it ate an option */ static int @@ -80,8 +143,8 @@ struct ipt_length_info *info = (struct ipt_length_info *)(*match)->data; switch (c) { - case '1': - if (*flags) + case '1': /* handed option: --length */ + if (*flags & LENGTH_LENGTH) exit_error(PARAMETER_PROBLEM, "length: `--length' may only be " "specified once"); @@ -89,8 +152,23 @@ optind++; parse_lengths(argv[optind-1], info); if (invert) - info->invert = 1; - *flags = 1; + info->invert |= IPT_LENGTH_INVERT; + *flags |= LENGTH_LENGTH; + break; + + case '2': /* handed option: --length-of */ + if (*flags & LENGTH_LENGTH_OF) + exit_error(PARAMETER_PROBLEM, + "length: `--length-of' may only be " + "specified once"); + if (check_inverse(optarg, &invert)) + optind++; + parse_sections(argv[optind-1], info); + if (invert) + exit_error(PARAMETER_PROBLEM, + "length: `--length-of' may not be " + "inverted"); + *flags |= LENGTH_LENGTH_OF; break; default: @@ -106,6 +184,8 @@ if (!flags) exit_error(PARAMETER_PROBLEM, "length: You must specify `--length'"); +/* FIXME - if all section flags clear, set them all. */ + } /* Common match printing code. */ @@ -127,6 +207,7 @@ const struct ipt_entry_match *match, int numeric) { +/* FIXME - update for length-of */ printf("length "); print_length((struct ipt_length_info *)match->data); } @@ -135,6 +216,7 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { +/* FIXME - update for length-of */ printf("--length "); print_length((struct ipt_length_info *)match->data); }