1package org.bouncycastle.util;
2
3/**
4 * Utility methods for processing String objects containing IP addresses.
5 */
6public class IPAddress
7{
8    /**
9     * Validate the given IPv4 or IPv6 address.
10     *
11     * @param address the IP address as a String.
12     *
13     * @return true if a valid address, false otherwise
14     */
15    public static boolean isValid(
16        String address)
17    {
18        return isValidIPv4(address) || isValidIPv6(address);
19    }
20
21    /**
22     * Validate the given IPv4 or IPv6 address and netmask.
23     *
24     * @param address the IP address as a String.
25     *
26     * @return true if a valid address with netmask, false otherwise
27     */
28    public static boolean isValidWithNetMask(
29        String address)
30    {
31        return isValidIPv4WithNetmask(address) || isValidIPv6WithNetmask(address);
32    }
33
34    /**
35     * Validate the given IPv4 address.
36     *
37     * @param address the IP address as a String.
38     *
39     * @return true if a valid IPv4 address, false otherwise
40     */
41    public static boolean isValidIPv4(
42        String address)
43    {
44        if (address.length() == 0)
45        {
46            return false;
47        }
48
49        int octet;
50        int octets = 0;
51
52        String temp = address+".";
53
54        int pos;
55        int start = 0;
56        while (start < temp.length()
57            && (pos = temp.indexOf('.', start)) > start)
58        {
59            if (octets == 4)
60            {
61                return false;
62            }
63            try
64            {
65                octet = Integer.parseInt(temp.substring(start, pos));
66            }
67            catch (NumberFormatException ex)
68            {
69                return false;
70            }
71            if (octet < 0 || octet > 255)
72            {
73                return false;
74            }
75            start = pos + 1;
76            octets++;
77        }
78
79        return octets == 4;
80    }
81
82    public static boolean isValidIPv4WithNetmask(
83        String address)
84    {
85        int index = address.indexOf("/");
86        String mask = address.substring(index + 1);
87
88        return (index > 0) && isValidIPv4(address.substring(0, index))
89                           && (isValidIPv4(mask) || isMaskValue(mask, 32));
90    }
91
92    public static boolean isValidIPv6WithNetmask(
93        String address)
94    {
95        int index = address.indexOf("/");
96        String mask = address.substring(index + 1);
97
98        return (index > 0) && (isValidIPv6(address.substring(0, index))
99                           && (isValidIPv6(mask) || isMaskValue(mask, 128)));
100    }
101
102    private static boolean isMaskValue(String component, int size)
103    {
104        try
105        {
106            int value = Integer.parseInt(component);
107
108            return value >= 0 && value <= size;
109        }
110        catch (NumberFormatException e)
111        {
112            return false;
113        }
114    }
115
116    /**
117     * Validate the given IPv6 address.
118     *
119     * @param address the IP address as a String.
120     *
121     * @return true if a valid IPv4 address, false otherwise
122     */
123    public static boolean isValidIPv6(
124        String address)
125    {
126        if (address.length() == 0)
127        {
128            return false;
129        }
130
131        int octet;
132        int octets = 0;
133
134        String temp = address + ":";
135        boolean doubleColonFound = false;
136        int pos;
137        int start = 0;
138        while (start < temp.length()
139            && (pos = temp.indexOf(':', start)) >= start)
140        {
141            if (octets == 8)
142            {
143                return false;
144            }
145
146            if (start != pos)
147            {
148                String value = temp.substring(start, pos);
149
150                if (pos == (temp.length() - 1) && value.indexOf('.') > 0)
151                {
152                    if (!isValidIPv4(value))
153                    {
154                        return false;
155                    }
156
157                    octets++; // add an extra one as address covers 2 words.
158                }
159                else
160                {
161                    try
162                    {
163                        octet = Integer.parseInt(temp.substring(start, pos), 16);
164                    }
165                    catch (NumberFormatException ex)
166                    {
167                        return false;
168                    }
169                    if (octet < 0 || octet > 0xffff)
170                    {
171                        return false;
172                    }
173                }
174            }
175            else
176            {
177                if (pos != 1 && pos != temp.length() - 1 && doubleColonFound)
178                {
179                    return false;
180                }
181                doubleColonFound = true;
182            }
183            start = pos + 1;
184            octets++;
185        }
186
187        return octets == 8 || doubleColonFound;
188    }
189}
190
191
192