Commit | Line | Data |
---|---|---|
93f65158 KT |
1 | /* |
2 | * ebt_ip6 | |
3 | * | |
4 | * Authors: | |
5 | * Manohar Castelino <manohar.r.castelino@intel.com> | |
6 | * Kuo-Lang Tseng <kuo-lang.tseng@intel.com> | |
408ffaa4 | 7 | * Jan Engelhardt <jengelh@medozas.de> |
93f65158 KT |
8 | * |
9 | * Summary: | |
10 | * This is just a modification of the IPv4 code written by | |
11 | * Bart De Schuymer <bdschuym@pandora.be> | |
12 | * with the changes required to support IPv6 | |
13 | * | |
14 | * Jan, 2008 | |
15 | */ | |
93f65158 KT |
16 | #include <linux/ipv6.h> |
17 | #include <net/ipv6.h> | |
18 | #include <linux/in.h> | |
19 | #include <linux/module.h> | |
20 | #include <net/dsfield.h> | |
18219d3f JE |
21 | #include <linux/netfilter/x_tables.h> |
22 | #include <linux/netfilter_bridge/ebtables.h> | |
23 | #include <linux/netfilter_bridge/ebt_ip6.h> | |
93f65158 | 24 | |
6faee60a FW |
25 | union pkthdr { |
26 | struct { | |
27 | __be16 src; | |
28 | __be16 dst; | |
29 | } tcpudphdr; | |
30 | struct { | |
31 | u8 type; | |
32 | u8 code; | |
33 | } icmphdr; | |
93f65158 KT |
34 | }; |
35 | ||
2d06d4a5 | 36 | static bool |
62fc8051 | 37 | ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) |
93f65158 | 38 | { |
f7108a20 | 39 | const struct ebt_ip6_info *info = par->matchinfo; |
93f65158 KT |
40 | const struct ipv6hdr *ih6; |
41 | struct ipv6hdr _ip6h; | |
6faee60a FW |
42 | const union pkthdr *pptr; |
43 | union pkthdr _pkthdr; | |
93f65158 KT |
44 | |
45 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); | |
46 | if (ih6 == NULL) | |
8cc784ee | 47 | return false; |
93f65158 KT |
48 | if (info->bitmask & EBT_IP6_TCLASS && |
49 | FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) | |
8cc784ee | 50 | return false; |
acab78b9 LFCE |
51 | if ((info->bitmask & EBT_IP6_SOURCE && |
52 | FWINV(ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk, | |
53 | &info->saddr), EBT_IP6_SOURCE)) || | |
54 | (info->bitmask & EBT_IP6_DEST && | |
0898f99a | 55 | FWINV(ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, |
acab78b9 | 56 | &info->daddr), EBT_IP6_DEST))) |
8cc784ee | 57 | return false; |
93f65158 KT |
58 | if (info->bitmask & EBT_IP6_PROTO) { |
59 | uint8_t nexthdr = ih6->nexthdr; | |
75f2811c | 60 | __be16 frag_off; |
93f65158 KT |
61 | int offset_ph; |
62 | ||
75f2811c | 63 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off); |
93f65158 | 64 | if (offset_ph == -1) |
8cc784ee | 65 | return false; |
93f65158 | 66 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) |
8cc784ee | 67 | return false; |
c1bc1d25 IM |
68 | if (!(info->bitmask & (EBT_IP6_DPORT | |
69 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) | |
8cc784ee | 70 | return true; |
6faee60a FW |
71 | |
72 | /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */ | |
73 | pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr), | |
74 | &_pkthdr); | |
93f65158 | 75 | if (pptr == NULL) |
8cc784ee | 76 | return false; |
93f65158 | 77 | if (info->bitmask & EBT_IP6_DPORT) { |
6faee60a | 78 | u16 dst = ntohs(pptr->tcpudphdr.dst); |
93f65158 KT |
79 | if (FWINV(dst < info->dport[0] || |
80 | dst > info->dport[1], EBT_IP6_DPORT)) | |
8cc784ee | 81 | return false; |
93f65158 KT |
82 | } |
83 | if (info->bitmask & EBT_IP6_SPORT) { | |
6faee60a | 84 | u16 src = ntohs(pptr->tcpudphdr.src); |
93f65158 KT |
85 | if (FWINV(src < info->sport[0] || |
86 | src > info->sport[1], EBT_IP6_SPORT)) | |
8cc784ee | 87 | return false; |
93f65158 | 88 | } |
6faee60a FW |
89 | if ((info->bitmask & EBT_IP6_ICMP6) && |
90 | FWINV(pptr->icmphdr.type < info->icmpv6_type[0] || | |
91 | pptr->icmphdr.type > info->icmpv6_type[1] || | |
92 | pptr->icmphdr.code < info->icmpv6_code[0] || | |
93 | pptr->icmphdr.code > info->icmpv6_code[1], | |
94 | EBT_IP6_ICMP6)) | |
95 | return false; | |
93f65158 | 96 | } |
8cc784ee | 97 | return true; |
93f65158 KT |
98 | } |
99 | ||
b0f38452 | 100 | static int ebt_ip6_mt_check(const struct xt_mtchk_param *par) |
93f65158 | 101 | { |
9b4fce7a JE |
102 | const struct ebt_entry *e = par->entryinfo; |
103 | struct ebt_ip6_info *info = par->matchinfo; | |
93f65158 | 104 | |
93f65158 | 105 | if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO) |
bd414ee6 | 106 | return -EINVAL; |
93f65158 | 107 | if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK) |
bd414ee6 | 108 | return -EINVAL; |
93f65158 KT |
109 | if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) { |
110 | if (info->invflags & EBT_IP6_PROTO) | |
bd414ee6 | 111 | return -EINVAL; |
93f65158 KT |
112 | if (info->protocol != IPPROTO_TCP && |
113 | info->protocol != IPPROTO_UDP && | |
114 | info->protocol != IPPROTO_UDPLITE && | |
115 | info->protocol != IPPROTO_SCTP && | |
116 | info->protocol != IPPROTO_DCCP) | |
bd414ee6 | 117 | return -EINVAL; |
93f65158 KT |
118 | } |
119 | if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1]) | |
bd414ee6 | 120 | return -EINVAL; |
93f65158 | 121 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) |
bd414ee6 | 122 | return -EINVAL; |
6faee60a FW |
123 | if (info->bitmask & EBT_IP6_ICMP6) { |
124 | if ((info->invflags & EBT_IP6_PROTO) || | |
125 | info->protocol != IPPROTO_ICMPV6) | |
126 | return -EINVAL; | |
127 | if (info->icmpv6_type[0] > info->icmpv6_type[1] || | |
128 | info->icmpv6_code[0] > info->icmpv6_code[1]) | |
129 | return -EINVAL; | |
130 | } | |
bd414ee6 | 131 | return 0; |
93f65158 KT |
132 | } |
133 | ||
043ef46c JE |
134 | static struct xt_match ebt_ip6_mt_reg __read_mostly = { |
135 | .name = "ip6", | |
001a18d3 JE |
136 | .revision = 0, |
137 | .family = NFPROTO_BRIDGE, | |
2d06d4a5 JE |
138 | .match = ebt_ip6_mt, |
139 | .checkentry = ebt_ip6_mt_check, | |
fc0e3df4 | 140 | .matchsize = sizeof(struct ebt_ip6_info), |
93f65158 KT |
141 | .me = THIS_MODULE, |
142 | }; | |
143 | ||
144 | static int __init ebt_ip6_init(void) | |
145 | { | |
043ef46c | 146 | return xt_register_match(&ebt_ip6_mt_reg); |
93f65158 KT |
147 | } |
148 | ||
149 | static void __exit ebt_ip6_fini(void) | |
150 | { | |
043ef46c | 151 | xt_unregister_match(&ebt_ip6_mt_reg); |
93f65158 KT |
152 | } |
153 | ||
154 | module_init(ebt_ip6_init); | |
155 | module_exit(ebt_ip6_fini); | |
156 | MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match"); | |
8244f4ba | 157 | MODULE_AUTHOR("Kuo-Lang Tseng <kuo-lang.tseng@intel.com>"); |
93f65158 | 158 | MODULE_LICENSE("GPL"); |