1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ipfilter;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelHandler.Sharable;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.util.internal.ObjectUtil;
22
23 import java.net.Inet4Address;
24 import java.net.Inet6Address;
25 import java.net.InetSocketAddress;
26 import java.net.SocketAddress;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import java.util.List;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @Sharable
56 public class IpSubnetFilter extends AbstractRemoteAddressFilter<InetSocketAddress> {
57
58 private final boolean acceptIfNotFound;
59 private final IpSubnetFilterRule[] ipv4Rules;
60 private final IpSubnetFilterRule[] ipv6Rules;
61 private final IpFilterRuleType ipFilterRuleTypeIPv4;
62 private final IpFilterRuleType ipFilterRuleTypeIPv6;
63
64
65
66
67
68
69
70 public IpSubnetFilter(IpSubnetFilterRule... rules) {
71 this(true, Arrays.asList(ObjectUtil.checkNotNull(rules, "rules")));
72 }
73
74
75
76
77
78
79
80
81 public IpSubnetFilter(boolean acceptIfNotFound, IpSubnetFilterRule... rules) {
82 this(acceptIfNotFound, Arrays.asList(ObjectUtil.checkNotNull(rules, "rules")));
83 }
84
85
86
87
88
89
90
91 public IpSubnetFilter(List<IpSubnetFilterRule> rules) {
92 this(true, rules);
93 }
94
95
96
97
98
99
100
101
102 public IpSubnetFilter(boolean acceptIfNotFound, List<IpSubnetFilterRule> rules) {
103 ObjectUtil.checkNotNull(rules, "rules");
104 this.acceptIfNotFound = acceptIfNotFound;
105
106 int numAcceptIPv4 = 0;
107 int numRejectIPv4 = 0;
108 int numAcceptIPv6 = 0;
109 int numRejectIPv6 = 0;
110
111 List<IpSubnetFilterRule> unsortedIPv4Rules = new ArrayList<IpSubnetFilterRule>();
112 List<IpSubnetFilterRule> unsortedIPv6Rules = new ArrayList<IpSubnetFilterRule>();
113
114
115 for (IpSubnetFilterRule ipSubnetFilterRule : rules) {
116 ObjectUtil.checkNotNull(ipSubnetFilterRule, "rule");
117
118 if (ipSubnetFilterRule.getFilterRule() instanceof IpSubnetFilterRule.Ip4SubnetFilterRule) {
119 unsortedIPv4Rules.add(ipSubnetFilterRule);
120
121 if (ipSubnetFilterRule.ruleType() == IpFilterRuleType.ACCEPT) {
122 numAcceptIPv4++;
123 } else {
124 numRejectIPv4++;
125 }
126 } else {
127 unsortedIPv6Rules.add(ipSubnetFilterRule);
128
129 if (ipSubnetFilterRule.ruleType() == IpFilterRuleType.ACCEPT) {
130 numAcceptIPv6++;
131 } else {
132 numRejectIPv6++;
133 }
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148 if (numAcceptIPv4 == 0 && numRejectIPv4 > 0) {
149 ipFilterRuleTypeIPv4 = IpFilterRuleType.REJECT;
150 } else if (numAcceptIPv4 > 0 && numRejectIPv4 == 0) {
151 ipFilterRuleTypeIPv4 = IpFilterRuleType.ACCEPT;
152 } else {
153 ipFilterRuleTypeIPv4 = null;
154 }
155
156 if (numAcceptIPv6 == 0 && numRejectIPv6 > 0) {
157 ipFilterRuleTypeIPv6 = IpFilterRuleType.REJECT;
158 } else if (numAcceptIPv6 > 0 && numRejectIPv6 == 0) {
159 ipFilterRuleTypeIPv6 = IpFilterRuleType.ACCEPT;
160 } else {
161 ipFilterRuleTypeIPv6 = null;
162 }
163
164 this.ipv4Rules = unsortedIPv4Rules.isEmpty() ? null : sortAndFilter(unsortedIPv4Rules);
165 this.ipv6Rules = unsortedIPv6Rules.isEmpty() ? null : sortAndFilter(unsortedIPv6Rules);
166 }
167
168 @Override
169 protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) {
170 if (ipv4Rules != null && remoteAddress.getAddress() instanceof Inet4Address) {
171 int indexOf = Arrays.binarySearch(ipv4Rules, remoteAddress, IpSubnetFilterRuleComparator.INSTANCE);
172 if (indexOf >= 0) {
173 if (ipFilterRuleTypeIPv4 == null) {
174 return ipv4Rules[indexOf].ruleType() == IpFilterRuleType.ACCEPT;
175 } else {
176 return ipFilterRuleTypeIPv4 == IpFilterRuleType.ACCEPT;
177 }
178 }
179 } else if (ipv6Rules != null && remoteAddress.getAddress() instanceof Inet6Address) {
180 int indexOf = Arrays.binarySearch(ipv6Rules, remoteAddress, IpSubnetFilterRuleComparator.INSTANCE);
181 if (indexOf >= 0) {
182 if (ipFilterRuleTypeIPv6 == null) {
183 return ipv6Rules[indexOf].ruleType() == IpFilterRuleType.ACCEPT;
184 } else {
185 return ipFilterRuleTypeIPv6 == IpFilterRuleType.ACCEPT;
186 }
187 }
188 }
189
190 return acceptIfNotFound;
191 }
192
193
194
195
196
197
198
199
200 @SuppressWarnings("ZeroLengthArrayAllocation")
201 private static IpSubnetFilterRule[] sortAndFilter(List<IpSubnetFilterRule> rules) {
202 Collections.sort(rules);
203 Iterator<IpSubnetFilterRule> iterator = rules.iterator();
204 List<IpSubnetFilterRule> toKeep = new ArrayList<IpSubnetFilterRule>();
205
206 IpSubnetFilterRule parentRule = iterator.hasNext() ? iterator.next() : null;
207 if (parentRule != null) {
208 toKeep.add(parentRule);
209 }
210
211 while (iterator.hasNext()) {
212
213
214 IpSubnetFilterRule childRule = iterator.next();
215
216
217
218 if (!parentRule.matches(new InetSocketAddress(childRule.getIpAddress(), 1))) {
219 toKeep.add(childRule);
220
221 parentRule = childRule;
222 }
223 }
224
225 return toKeep.toArray(new IpSubnetFilterRule[0]);
226 }
227 }