| /* Copyright 2015-2020 Rivoreo |
| |
| Permission is hereby granted, free of charge, to any person obtaining |
| a copy of this software and associated documentation files (the |
| "Software"), to deal in the Software without restriction, including |
| without limitation the rights to use, copy, modify, merge, publish, |
| distribute, sublicense, and/or sell copies of the Software, and to |
| permit persons to whom the Software is furnished to do so, subject to |
| the following conditions: |
| |
| The above copyright notice and this permission notice shall be |
| included in all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE |
| FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| package rivoreo.net; |
| |
| import java.net.Inet4Address; |
| import java.util.Arrays; |
| |
| public class Inet4AddressBlock { |
| public Inet4AddressBlock(String s) { |
| int slash_i = s.lastIndexOf('/'); |
| if(slash_i == 0) throw new IllegalArgumentException("malformed address string"); |
| String address_s = slash_i == -1 ? s : s.substring(0, slash_i); |
| prefix_length = slash_i == -1 ? 32 : Integer.parseInt(s.substring(slash_i + 1)); |
| if(prefix_length < 0 || prefix_length > 32) throw new IllegalArgumentException("prefix length out of range"); |
| String[] splited_address = address_s.split("\\."); |
| if(splited_address.length > 4) throw new IllegalArgumentException("malformed address string"); |
| raw_address = new byte[(prefix_length + 7) / 8]; |
| for(int i = 0; i < raw_address.length && i < splited_address.length; i++) { |
| int n = Integer.parseInt(splited_address[i]); |
| if(n < 0 || n > 255) throw new NumberFormatException("malformed address string"); |
| raw_address[i] = (byte)n; |
| } |
| truncate_host_bits(); |
| } |
| public Inet4AddressBlock(Inet4Address address, int prefix_length) { |
| if(prefix_length < 0 || prefix_length > 32) throw new IllegalArgumentException("prefix length out of range"); |
| raw_address = Arrays.copyOf(address.getAddress(), (prefix_length + 7) / 8); |
| this.prefix_length = prefix_length; |
| truncate_host_bits(); |
| } |
| |
| private byte[] raw_address; |
| private int prefix_length; |
| |
| private void truncate_host_bits() { |
| if(prefix_length % 8 == 0) return; |
| int i = prefix_length / 8; |
| int host_bit_len = 8 - (prefix_length - i * 8); |
| raw_address[i] &= (byte)0xff << host_bit_len; |
| } |
| |
| public boolean is_in_block(Inet4Address address) { |
| if(prefix_length == 0) return true; |
| byte[] ba = address.getAddress(); |
| int i = 0; |
| while(i < raw_address.length - 1) { |
| if(ba[i] != raw_address[i]) return false; |
| i++; |
| } |
| int host_bit_len = 8 - (prefix_length - i * 8); |
| return (ba[i] & ((byte)0xff << host_bit_len)) == raw_address[i]; |
| } |
| |
| private static int to_unsigned_byte(byte n) { |
| return n < 0 ? n + 256 : n; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder s = new StringBuilder(18); |
| switch(raw_address.length) { |
| case 0: |
| s.append("0.0.0.0"); |
| break; |
| case 1: |
| s.append(String.valueOf(to_unsigned_byte(raw_address[0]))); |
| s.append(".0.0.0"); |
| break; |
| case 2: |
| s.append(String.valueOf(to_unsigned_byte(raw_address[0]))); |
| s.append('.'); |
| s.append(String.valueOf(to_unsigned_byte(raw_address[1]))); |
| s.append(".0.0"); |
| break; |
| case 3: |
| s.append(String.valueOf(to_unsigned_byte(raw_address[0]))); |
| s.append('.'); |
| s.append(String.valueOf(to_unsigned_byte(raw_address[1]))); |
| s.append('.'); |
| s.append(String.valueOf(to_unsigned_byte(raw_address[2]))); |
| s.append(".0"); |
| break; |
| case 4: |
| s.append(String.format("%d.%d.%d.%d", to_unsigned_byte(raw_address[0]), to_unsigned_byte(raw_address[1]), to_unsigned_byte(raw_address[2]), to_unsigned_byte(raw_address[3]))); |
| break; |
| default: |
| throw new RuntimeException(String.format("Unexpected raw_address.length: %d", raw_address.length)); |
| } |
| s.append('/').append(String.valueOf(prefix_length)); |
| return s.toString(); |
| } |
| } |