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 | #define EBT_IP_SPORT 0x10 | 25 | #define EBT_IP_SPORT 0x10 |
| 26 | #define EBT_IP_DPORT 0x20 | 26 | #define EBT_IP_DPORT 0x20 |
| 27 | #define EBT_IP_ICMP 0x40 | 27 | #define EBT_IP_ICMP 0x40 |
| 28 | #define EBT_IP_IGMP 0x80 | ||
| 28 | #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ | 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 | #define EBT_IP_MATCH "ip" | 31 | #define EBT_IP_MATCH "ip" |
| 31 | 32 | ||
| 32 | /* the same values are used for the invflags */ | 33 | /* the same values are used for the invflags */ |
| @@ -42,6 +43,7 @@ struct ebt_ip_info { · 9 unmodified lines | |||
| 42 | union { | 43 | union { |
| 43 | __u16 sport[2]; | 44 | __u16 sport[2]; |
| 44 | __u8 icmp_type[2]; | 45 | __u8 icmp_type[2]; |
| 46 | __u8 igmp_type[2]; | ||
| 45 | }; | 47 | }; |
| 46 | union { | 48 | union { |
| 47 | __u16 dport[2]; | 49 | __u16 dport[2]; |
| @@ -28,6 +28,9 @@ union pkthdr { · 27 unmodified lines | |||
| 28 | u8 type; | 28 | u8 type; |
| 29 | u8 code; | 29 | u8 code; |
| 30 | } icmphdr; | 30 | } icmphdr; |
| 31 | struct { | ||
| 32 | u8 type; | ||
| 33 | } igmphdr; | ||
| 31 | }; | 34 | }; |
| 32 | 35 | ||
| 33 | static bool | 36 | static bool |
| @@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) · 23 unmodified lines | |||
| 57 | if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) | 60 | if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) |
| 58 | return false; | 61 | return false; |
| 59 | if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | | 62 | if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | |
| 60 | EBT_IP_ICMP))) | 63 | EBT_IP_ICMP | EBT_IP_IGMP))) |
| 61 | return true; | 64 | return true; |
| 62 | if (ntohs(ih->frag_off) & IP_OFFSET) | 65 | if (ntohs(ih->frag_off) & IP_OFFSET) |
| 63 | return false; | 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 | pptr = skb_header_pointer(skb, ih->ihl*4, | 69 | pptr = skb_header_pointer(skb, ih->ihl*4, |
| 67 | sizeof(_pkthdr), &_pkthdr); | 70 | sizeof(_pkthdr), &_pkthdr); |
| 68 | if (pptr == NULL) | 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 | pptr->icmphdr.code < info->icmp_code[0] || | 91 | pptr->icmphdr.code < info->icmp_code[0] || |
| 89 | pptr->icmphdr.code > info->icmp_code[1])) | 92 | pptr->icmphdr.code > info->icmp_code[1])) |
| 90 | return false; | 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 | return true; | 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 | info->icmp_code[0] > info->icmp_code[1]) | 132 | info->icmp_code[0] > info->icmp_code[1]) |
| 125 | return -EINVAL; | 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 | return 0; | 142 | return 0; |
| 128 | } | 143 | } |
| 129 | 144 | ||