diff options
-rw-r--r-- | extensions/ebt_ip.c | 44 | ||||
-rw-r--r-- | useful_functions.c | 35 |
2 files changed, 65 insertions, 14 deletions
diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c index 42660d4..1ffdb95 100644 --- a/extensions/ebt_ip.c +++ b/extensions/ebt_ip.c @@ -25,6 +25,7 @@ #define IP_SPORT '5' #define IP_DPORT '6' #define IP_ICMP '7' +#define IP_IGMP '8' static const struct option opts[] = { @@ -40,6 +41,7 @@ static const struct option opts[] = { "ip-destination-port" , required_argument, 0, IP_DPORT }, { "ip-dport" , required_argument, 0, IP_DPORT }, { "ip-icmp-type" , required_argument, 0, IP_ICMP }, + { "ip-igmp-type" , required_argument, 0, IP_IGMP }, { 0 } }; @@ -97,6 +99,14 @@ static const struct ebt_icmp_names icmp_codes[] = { { "address-mask-reply", 18, 0, 0xFF } }; +static const struct ebt_icmp_names igmp_types[] = { + { "membership-query", 0x11 }, + { "membership-report-v1", 0x12 }, + { "membership-report-v2", 0x16 }, + { "leave-group", 0x17 }, + { "membership-report-v3", 0x22 }, +}; + /* put the mask into 4 bytes */ /* transform a protocol and service name into a port number */ static uint16_t parse_port(const char *protocol, const char *name) @@ -162,10 +172,13 @@ static void print_help() "--ip-proto [!] protocol : ip protocol specification\n" "--ip-sport [!] port[:port] : tcp/udp source port or port range\n" "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n" -"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"); +"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n" +"--ip-igmp-type [!] type[:type] : igmp type or type range\n"); printf("\nValid ICMP Types:\n"); ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes)); + printf("\nValid IGMP Types:\n"); + ebt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types)); } static void init(struct ebt_entry_match *match) @@ -183,6 +196,7 @@ static void init(struct ebt_entry_match *match) #define OPT_SPORT 0x10 #define OPT_DPORT 0x20 #define OPT_ICMP 0x40 +#define OPT_IGMP 0x80 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags, struct ebt_entry_match **match) { @@ -241,6 +255,16 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, return 0; break; + case IP_IGMP: + ebt_check_option2(flags, OPT_IGMP); + ipinfo->bitmask |= EBT_IP_IGMP; + if (ebt_check_inverse2(optarg)) + ipinfo->invflags |= EBT_IP_IGMP; + if (ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg, + ipinfo->igmp_type, NULL)) + return 0; + break; + case IP_myTOS: ebt_check_option2(flags, OPT_TOS); if (ebt_check_inverse2(optarg)) @@ -300,6 +324,12 @@ static void final_check(const struct ebt_u_entry *entry, ipinfo->protocol != IPPROTO_ICMP)) { ebt_print_error("For ICMP filtering the IP protocol must be " "1 (icmp)"); + } else if ((ipinfo->bitmask & EBT_IP_IGMP) && + (!(ipinfo->bitmask & EBT_IP_PROTO) || + ipinfo->invflags & EBT_IP_PROTO || + ipinfo->protocol != IPPROTO_IGMP)) { + ebt_print_error("For IGMP filtering the IP protocol must be " + "2 (igmp)"); } } @@ -365,6 +395,13 @@ static void print(const struct ebt_u_entry *entry, ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes), ipinfo->icmp_type, ipinfo->icmp_code); } + if (ipinfo->bitmask & EBT_IP_IGMP) { + printf("--ip-igmp-type "); + if (ipinfo->invflags & EBT_IP_IGMP) + printf("! "); + ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types), + ipinfo->igmp_type, NULL); + } } static int compare(const struct ebt_entry_match *m1, @@ -414,6 +451,11 @@ static int compare(const struct ebt_entry_match *m1, ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1]) return 0; } + if (ipinfo1->bitmask & EBT_IP_IGMP) { + if (ipinfo1->igmp_type[0] != ipinfo2->igmp_type[0] || + ipinfo1->igmp_type[1] != ipinfo2->igmp_type[1]) + return 0; + } return 1; } diff --git a/useful_functions.c b/useful_functions.c index 8f54bae..8a34f82 100644 --- a/useful_functions.c +++ b/useful_functions.c @@ -486,8 +486,10 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, if (match < n_codes) { type[0] = type[1] = icmp_codes[match].type; - code[0] = icmp_codes[match].code_min; - code[1] = icmp_codes[match].code_max; + if (code) { + code[0] = icmp_codes[match].code_min; + code[1] = icmp_codes[match].code_max; + } } else { char *next = parse_range(icmptype, 0, 255, number); if (!next) { @@ -499,17 +501,21 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, type[1] = (uint8_t) number[1]; switch (*next) { case 0: - code[0] = 0; - code[1] = 255; + if (code) { + code[0] = 0; + code[1] = 255; + } return 0; case '/': - next = parse_range(next+1, 0, 255, number); - code[0] = (uint8_t) number[0]; - code[1] = (uint8_t) number[1]; - if (next == NULL) - return -1; - if (next && *next == 0) - return 0; + if (code) { + next = parse_range(next+1, 0, 255, number); + code[0] = (uint8_t) number[0]; + code[1] = (uint8_t) number[1]; + if (next == NULL) + return -1; + if (next && *next == 0) + return 0; + } /* fallthrough */ default: ebt_print_error("unknown character %c", *next); @@ -521,6 +527,9 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, static void print_icmp_code(uint8_t *code) { + if (!code) + return; + if (code[0] == code[1]) printf("/%"PRIu8 " ", code[0]); else @@ -542,8 +551,8 @@ void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes, if (icmp_codes[i].type != type[0]) continue; - if (icmp_codes[i].code_min == code[0] && - icmp_codes[i].code_max == code[1]) { + if (!code || (icmp_codes[i].code_min == code[0] && + icmp_codes[i].code_max == code[1])) { printf("%s ", icmp_codes[i].name); return; } |