To avoid adding a new match revision icmp type/code are stored in the sport/dport area.
Unified · Split
| @@ -18,8 +18,11 @@ · 17 unmodified lines | ||
| 18 | 18 | #define EBT_IP6_PROTO 0x08 |
| 19 | 19 | #define EBT_IP6_SPORT 0x10 |
| 20 | 20 | #define EBT_IP6_DPORT 0x20 |
| 21 | +#define EBT_IP6_ICMP6 0x40 | |
| 22 | + | |
| 21 | 23 | #define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\ |
| 22 | − EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT) | |
| 24 | + EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT | \ | |
| 25 | + EBT_IP6_ICMP6) | |
| 23 | 26 | #define EBT_IP6_MATCH "ip6" |
| 24 | 27 | |
| 25 | 28 | /* the same values are used for the invflags */ |
| @@ -32,8 +35,14 @@ struct ebt_ip6_info { · 6 unmodified lines | ||
| 32 | 35 | uint8_t protocol; |
| 33 | 36 | uint8_t bitmask; |
| 34 | 37 | uint8_t invflags; |
| 35 | − uint16_t sport[2]; | |
| 36 | − uint16_t dport[2]; | |
| 38 | + union { | |
| 39 | + uint16_t sport[2]; | |
| 40 | + uint8_t icmpv6_type[2]; | |
| 41 | + }; | |
| 42 | + union { | |
| 43 | + uint16_t dport[2]; | |
| 44 | + uint8_t icmpv6_code[2]; | |
| 45 | + }; | |
| 37 | 46 | }; |
| 38 | 47 | |
| 39 | 48 | #endif |
| @@ -22,9 +22,15 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/netfilter_bridge/ebtables.h> |
| 23 | 23 | #include <linux/netfilter_bridge/ebt_ip6.h> |
| 24 | 24 | |
| 25 | −struct tcpudphdr { | |
| 26 | − __be16 src; | |
| 27 | − __be16 dst; | |
| 25 | +union pkthdr { | |
| 26 | + struct { | |
| 27 | + __be16 src; | |
| 28 | + __be16 dst; | |
| 29 | + } tcpudphdr; | |
| 30 | + struct { | |
| 31 | + u8 type; | |
| 32 | + u8 code; | |
| 33 | + } icmphdr; | |
| 28 | 34 | }; |
| 29 | 35 | |
| 30 | 36 | static bool |
| @@ -33,8 +39,8 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) · 2 unmodified lines | ||
| 33 | 39 | const struct ebt_ip6_info *info = par->matchinfo; |
| 34 | 40 | const struct ipv6hdr *ih6; |
| 35 | 41 | struct ipv6hdr _ip6h; |
| 36 | − const struct tcpudphdr *pptr; | |
| 37 | − struct tcpudphdr _ports; | |
| 42 | + const union pkthdr *pptr; | |
| 43 | + union pkthdr _pkthdr; | |
| 38 | 44 | |
| 39 | 45 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); |
| 40 | 46 | if (ih6 == NULL) |
| @@ -56,26 +62,34 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) · 15 unmodified lines | ||
| 56 | 62 | return false; |
| 57 | 63 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) |
| 58 | 64 | return false; |
| 59 | − if (!(info->bitmask & EBT_IP6_DPORT) && | |
| 60 | − !(info->bitmask & EBT_IP6_SPORT)) | |
| 65 | + if (!(info->bitmask & ( EBT_IP6_DPORT | | |
| 66 | + EBT_IP6_SPORT | EBT_IP6_ICMP6))) | |
| 61 | 67 | return true; |
| 62 | − pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports), | |
| 63 | − &_ports); | |
| 68 | + | |
| 69 | + /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */ | |
| 70 | + pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr), | |
| 71 | + &_pkthdr); | |
| 64 | 72 | if (pptr == NULL) |
| 65 | 73 | return false; |
| 66 | 74 | if (info->bitmask & EBT_IP6_DPORT) { |
| 67 | − u32 dst = ntohs(pptr->dst); | |
| 75 | + u16 dst = ntohs(pptr->tcpudphdr.dst); | |
| 68 | 76 | if (FWINV(dst < info->dport[0] || |
| 69 | 77 | dst > info->dport[1], EBT_IP6_DPORT)) |
| 70 | 78 | return false; |
| 71 | 79 | } |
| 72 | 80 | if (info->bitmask & EBT_IP6_SPORT) { |
| 73 | − u32 src = ntohs(pptr->src); | |
| 81 | + u16 src = ntohs(pptr->tcpudphdr.src); | |
| 74 | 82 | if (FWINV(src < info->sport[0] || |
| 75 | 83 | src > info->sport[1], EBT_IP6_SPORT)) |
| 76 | 84 | return false; |
| 77 | 85 | } |
| 78 | − return true; | |
| 86 | + if ((info->bitmask & EBT_IP6_ICMP6) && | |
| 87 | + FWINV(pptr->icmphdr.type < info->icmpv6_type[0] || | |
| 88 | + pptr->icmphdr.type > info->icmpv6_type[1] || | |
| 89 | + pptr->icmphdr.code < info->icmpv6_code[0] || | |
| 90 | + pptr->icmphdr.code > info->icmpv6_code[1], | |
| 91 | + EBT_IP6_ICMP6)) | |
| 92 | + return false; | |
| 79 | 93 | } |
| 80 | 94 | return true; |
| 81 | 95 | } |
| @@ -103,6 +117,14 @@ static int ebt_ip6_mt_check(const struct xt_mtchk_param *par) · 21 unmodified lines | ||
| 103 | 117 | return -EINVAL; |
| 104 | 118 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) |
| 105 | 119 | return -EINVAL; |
| 120 | + if (info->bitmask & EBT_IP6_ICMP6) { | |
| 121 | + if ((info->invflags & EBT_IP6_PROTO) || | |
| 122 | + info->protocol != IPPROTO_ICMPV6) | |
| 123 | + return -EINVAL; | |
| 124 | + if (info->icmpv6_type[0] > info->icmpv6_type[1] || | |
| 125 | + info->icmpv6_code[0] > info->icmpv6_code[1]) | |
| 126 | + return -EINVAL; | |
| 127 | + } | |
| 106 | 128 | return 0; |
| 107 | 129 | } |
| 108 | 130 | |