View | Details | Raw Unified | Return to bug 51953
Collapse All | Expand All

(-)a/java/org/apache/catalina/util/NetMask.java (-1 / +103 lines)
Line 0 Link Here
0
- 
1
package org.apache.catalina.util;
2
3
import java.math.BigInteger;
4
import java.net.InetAddress;
5
import java.net.UnknownHostException;
6
7
/**
8
 * A class representing a netmask, which is at the core of this valve.
9
 *
10
 * <p>The constructor takes a {@link java.lang.String} representing a
11
 * CIDR netmask as an argument and extracts two informations from it: the
12
 * network address and the CIDR. It then turns the address into a {@link
13
 * java.math.BigInteger}, calculates the right shift and shifts that
14
 * BigInteger by it.</p>
15
 * <p>The process to verify whether an IP address falls within the mask
16
 * is to also convert it to a BigInteger, shifting it right and comparing
17
 * it to the stored BigInteger.
18
 * </p>
19
 */
20
21
public final class NetMask {
22
    /**
23
     * The argument to the constructor, used for .toString()
24
     */
25
    private final String expression;
26
27
    /**
28
     * The number of bits a matching candidate needs to be shifted right
29
     * in order to see if it matches
30
     */
31
    private final int shift;
32
33
    /**
34
     * The network address, already shifted right
35
     */
36
    private final BigInteger mask;
37
38
    /**
39
     * Constructor.
40
     *
41
     * @param expression the CIDR netmask
42
     * @throws IllegalArgumentException if the netmask is not correct
43
     * (invalid address specification, malformed CIDR prefix, etc)
44
     */
45
    public NetMask(final String expression) {
46
        final int idx = expression.indexOf("/");
47
        final int cidr, addrlen;
48
        final String addressPart;
49
        final InetAddress addr;
50
        final byte[] bytes;
51
52
        if (idx == -1) {
53
            cidr = -1;
54
            addressPart = expression;
55
        } else {
56
            final String substring = expression.substring(idx + 1);
57
            try {
58
                cidr = Integer.parseInt(substring);
59
                if (cidr < 0)
60
                    throw new NumberFormatException("CIDR is negative");
61
            } catch (NumberFormatException ignored) {
62
                throw new IllegalArgumentException("provided CIDR mask ("
63
                    + substring + ") is invalid");
64
            }
65
            addressPart = expression.substring(0, idx);
66
        }
67
68
        try {
69
            addr = InetAddress.getByName(addressPart);
70
        } catch (UnknownHostException e) {
71
            throw new IllegalArgumentException("provided address ("
72
                + addressPart + ") is invalid");
73
        }
74
75
        bytes = addr.getAddress();
76
        addrlen = bytes.length * 8;
77
        shift = cidr == -1 ? 0 : addrlen - cidr;
78
79
        if (shift < 0)
80
            throw new IllegalArgumentException("CIDR prefix (" + cidr
81
                + ") is greater than address length (" + addrlen + ")");
82
        mask = new BigInteger(bytes).shiftRight(shift);
83
        this.expression = expression;
84
    }
85
86
    /**
87
     * Test if a given address matches this netmask
88
     *
89
     * @param addr The {@link java.net.InetAddress} to test
90
     * @return true on match, false otherwise
91
     */
92
    public boolean matches (final InetAddress addr) {
93
        final BigInteger provided = new BigInteger(addr.getAddress())
94
            .shiftRight(shift);
95
96
        return mask.equals(provided);
97
    }
98
99
    @Override
100
    public String toString() {
101
        return expression;
102
    }
103
}

Return to bug 51953