1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.ipfilter;
17
18 import org.jboss.netty.logging.InternalLogger;
19 import org.jboss.netty.logging.InternalLoggerFactory;
20
21 import java.math.BigInteger;
22 import java.net.Inet4Address;
23 import java.net.Inet6Address;
24 import java.net.InetAddress;
25 import java.net.UnknownHostException;
26
27
28
29 public class CIDR6 extends CIDR {
30
31 private static final InternalLogger logger = InternalLoggerFactory.getInstance(CIDR6.class);
32
33
34 private BigInteger addressBigInt;
35
36
37 private final BigInteger addressEndBigInt;
38
39 protected CIDR6(Inet6Address newaddress, int newmask) {
40 cidrMask = newmask;
41 addressBigInt = ipv6AddressToBigInteger(newaddress);
42 BigInteger mask = ipv6CidrMaskToMask(newmask);
43 try {
44 addressBigInt = addressBigInt.and(mask);
45 baseAddress = bigIntToIPv6Address(addressBigInt);
46 } catch (UnknownHostException e) {
47
48 }
49 addressEndBigInt = addressBigInt.add(ipv6CidrMaskToBaseAddress(cidrMask)).subtract(BigInteger.ONE);
50 }
51
52 @Override
53 public InetAddress getEndAddress() {
54 try {
55 return bigIntToIPv6Address(addressEndBigInt);
56 } catch (UnknownHostException e) {
57 if (logger.isErrorEnabled()) {
58 logger.error("invalid ip address calculated as an end address");
59 }
60 return null;
61 }
62 }
63
64 public int compareTo(CIDR arg) {
65 if (arg instanceof CIDR4) {
66 BigInteger net = ipv6AddressToBigInteger(arg.baseAddress);
67 int res = net.compareTo(addressBigInt);
68 if (res == 0) {
69 if (arg.cidrMask == cidrMask) {
70 return 0;
71 }
72 if (arg.cidrMask < cidrMask) {
73 return -1;
74 }
75 return 1;
76 }
77 return res;
78 }
79 CIDR6 o = (CIDR6) arg;
80 if (o.addressBigInt.equals(addressBigInt) && o.cidrMask == cidrMask) {
81 return 0;
82 }
83 int res = o.addressBigInt.compareTo(addressBigInt);
84 if (res == 0) {
85 if (o.cidrMask < cidrMask) {
86
87 return -1;
88 }
89 return 1;
90 }
91 return res;
92 }
93
94 @Override
95 public boolean contains(InetAddress inetAddress) {
96 if (inetAddress == null) {
97 throw new NullPointerException("inetAddress");
98 }
99
100 if (cidrMask == 0) {
101 return true;
102 }
103
104 BigInteger search = ipv6AddressToBigInteger(inetAddress);
105 return search.compareTo(addressBigInt) >= 0 && search.compareTo(addressEndBigInt) <= 0;
106 }
107
108
109
110
111
112 private static BigInteger ipv6CidrMaskToBaseAddress(int cidrMask) {
113 return BigInteger.ONE.shiftLeft(128 - cidrMask);
114 }
115
116 private static BigInteger ipv6CidrMaskToMask(int cidrMask) {
117 return BigInteger.ONE.shiftLeft(128 - cidrMask).subtract(BigInteger.ONE).not();
118 }
119
120
121
122
123
124
125
126
127 private static BigInteger ipv6AddressToBigInteger(InetAddress addr) {
128 byte[] ipv6;
129 if (addr instanceof Inet4Address) {
130 ipv6 = getIpV6FromIpV4((Inet4Address) addr);
131 } else {
132 ipv6 = addr.getAddress();
133 }
134 if (ipv6[0] == -1) {
135 return new BigInteger(1, ipv6);
136 }
137 return new BigInteger(ipv6);
138 }
139
140
141
142
143
144
145
146
147 private static InetAddress bigIntToIPv6Address(BigInteger addr) throws UnknownHostException {
148 byte[] a = new byte[16];
149 byte[] b = addr.toByteArray();
150 if (b.length > 16 && !(b.length == 17 && b[0] == 0)) {
151 throw new UnknownHostException("invalid IPv6 address (too big)");
152 }
153 if (b.length == 16) {
154 return InetAddress.getByAddress(b);
155 }
156
157 if (b.length == 17) {
158 System.arraycopy(b, 1, a, 0, 16);
159 } else {
160
161 int p = 16 - b.length;
162 System.arraycopy(b, 0, a, p, b.length);
163 }
164 return InetAddress.getByAddress(a);
165 }
166 }