We already have ICMPv6 type/code matches (which can be used to distinguish different types of MLD packets). Add support for IPv4 IGMP matches in the same way.
Unified · Split
| @@ -25,8 +25,9 @@ · 24 unmodified lines | ||
| 25 | 25 | #define EBT_IP_SPORT 0x10 |
| 26 | 26 | #define EBT_IP_DPORT 0x20 |
| 27 | 27 | #define EBT_IP_ICMP 0x40 |
| 28 | +#define EBT_IP_IGMP 0x80 | |
| 28 | 29 | #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ |
| 29 | − EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP) | |
| 30 | + EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP) | |
| 30 | 31 | #define EBT_IP_MATCH "ip" |
| 31 | 32 | |
| 32 | 33 | /* the same values are used for the invflags */ |
| @@ -42,6 +43,7 @@ struct ebt_ip_info { · 9 unmodified lines | ||
| 42 | 43 | union { |
| 43 | 44 | __u16 sport[2]; |
| 44 | 45 | __u8 icmp_type[2]; |
| 46 | + __u8 igmp_type[2]; | |
| 45 | 47 | }; |
| 46 | 48 | union { |
| 47 | 49 | __u16 dport[2]; |
| @@ -28,6 +28,9 @@ union pkthdr { · 27 unmodified lines | ||
| 28 | 28 | u8 type; |
| 29 | 29 | u8 code; |
| 30 | 30 | } icmphdr; |
| 31 | + struct { | |
| 32 | + u8 type; | |
| 33 | + } igmphdr; | |
| 31 | 34 | }; |
| 32 | 35 | |
| 33 | 36 | static bool |
| @@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) · 23 unmodified lines | ||
| 57 | 60 | if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) |
| 58 | 61 | return false; |
| 59 | 62 | if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | |
| 60 | − EBT_IP_ICMP))) | |
| 63 | + EBT_IP_ICMP | EBT_IP_IGMP))) | |
| 61 | 64 | return true; |
| 62 | 65 | if (ntohs(ih->frag_off) & IP_OFFSET) |
| 63 | 66 | return false; |
| 64 | 67 | |
| 65 | − /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */ | |
| 68 | + /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */ | |
| 66 | 69 | pptr = skb_header_pointer(skb, ih->ihl*4, |
| 67 | 70 | sizeof(_pkthdr), &_pkthdr); |
| 68 | 71 | if (pptr == NULL) |
| @@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) · 19 unmodified lines | ||
| 88 | 91 | pptr->icmphdr.code < info->icmp_code[0] || |
| 89 | 92 | pptr->icmphdr.code > info->icmp_code[1])) |
| 90 | 93 | return false; |
| 94 | + if ((info->bitmask & EBT_IP_IGMP) && | |
| 95 | + NF_INVF(info, EBT_IP_IGMP, | |
| 96 | + pptr->igmphdr.type < info->igmp_type[0] || | |
| 97 | + pptr->igmphdr.type > info->igmp_type[1])) | |
| 98 | + return false; | |
| 91 | 99 | } |
| 92 | 100 | return true; |
| 93 | 101 | } |
| @@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par) · 30 unmodified lines | ||
| 124 | 132 | info->icmp_code[0] > info->icmp_code[1]) |
| 125 | 133 | return -EINVAL; |
| 126 | 134 | } |
| 135 | + if (info->bitmask & EBT_IP_IGMP) { | |
| 136 | + if ((info->invflags & EBT_IP_PROTO) || | |
| 137 | + info->protocol != IPPROTO_IGMP) | |
| 138 | + return -EINVAL; | |
| 139 | + if (info->igmp_type[0] > info->igmp_type[1]) | |
| 140 | + return -EINVAL; | |
| 141 | + } | |
| 127 | 142 | return 0; |
| 128 | 143 | } |
| 129 | 144 | |