summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/ebt_ip.c44
-rw-r--r--useful_functions.c35
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;
}