/*******************************************************************************
* Copyright © 2012-2015 eBay Software Foundation
* This program is dual licensed under the MIT and Apache 2.0 licenses.
* Please see LICENSE for more information.
*******************************************************************************/
package com.ebay.jetstream.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* An implementation of a queue of request messages.
*
* *
* @author shmurthy@ebay.com
* @version 1.0
*/
public class InetAddressParser {
private static class AddressElement {
public int m_len =0;
public char m_delimiter =0;
}
private String m_addrStr = null;
private final byte [] m_ipaddr = new byte[4];
private boolean m_hostAddrOnly = false;
private boolean m_networkAddrOnly = false;
private int m_prefixLen = 0;
public InetAddressParser(String ipaddress)
{
m_addrStr = ipaddress;
for (int i=0; i <4; i++)
{
m_ipaddr[i] = 0;
}
parse();
}
public boolean parse()
{
byte [] ipaddr = m_addrStr.getBytes();
int addrLen = ipaddr.length;
if (addrLen > 18) return false;
int offset = 0;
int k = 0;
char prevDelim = 0x1;
AddressElement ae = new AddressElement();
while (offset < addrLen)
{
String subStr = getAddressElement(ipaddr, offset, ae);
byte b = (byte) 0;
try {
b = Integer.decode(subStr).byteValue();
}
catch (NumberFormatException nfe) {
m_hostAddrOnly = false;
return false;
}
if ((ae.m_delimiter == '.') || (ae.m_delimiter == '/'))
{
m_ipaddr[k++] = b;
}
else if ((ae.m_delimiter == 0) && (prevDelim == '/'))
{
m_prefixLen = b;
if ((m_prefixLen > 32) || (m_prefixLen < 0))
return false;
else if (m_prefixLen == 32)
m_hostAddrOnly = true;
else if (m_prefixLen < 32)
m_networkAddrOnly = true;
}
else if ((ae.m_delimiter == 0) && (prevDelim == '.'))
{
m_ipaddr[k] = b;
m_prefixLen = 8 * (k+1);
if (k < 3)
m_networkAddrOnly = true;
else
m_hostAddrOnly = true;
}
else if (ae.m_delimiter == 0)
{
m_ipaddr[k] = b;
m_prefixLen = 8 * (k+1);
if (k < 3)
m_networkAddrOnly = true;
else
m_hostAddrOnly = true;
}
prevDelim = ae.m_delimiter;
offset += ae.m_len;
offset += 1;
ae.m_len=0;
ae.m_delimiter=0;
}
return true;
}
public String getAddressElement(byte [] ipaddr, int offset, AddressElement ae)
{
getSubAddrLen(ipaddr, offset, ae);
byte [] subaddr = new byte[ae.m_len];
for (int j=0; j < ae.m_len; j++)
{
subaddr[j] = ipaddr[offset + j];
}
String subStr = new String(subaddr);
return subStr;
}
private void getSubAddrLen(byte [] addr, int offset, AddressElement sa)
{
for (int i = offset; i < addr.length; i++)
{
if ((addr[i] == '.') || (addr[i] == '/'))
{
sa.m_delimiter = (char) addr[i];
break;
}
sa.m_len += 1;
}
}
public int getPrefixLen()
{
return m_prefixLen;
}
public boolean isHostAddress()
{
return m_hostAddrOnly;
}
public boolean isNetworkAddress()
{
return m_networkAddrOnly;
}
public byte [] getHostAddress()
{
return m_ipaddr;
}
public boolean matches(String provIpAddress, String provHostName)
{
InetAddressParser iap = new InetAddressParser(provIpAddress);
if (!iap.isHostAddress()) return false;
byte [] myaddr = getHostAddress();
byte [] ipaddr = iap.getHostAddress();
if (m_hostAddrOnly)
{
for(int i=0; i < 4; i++)
{
if(myaddr[i] != ipaddr[i])
return false;
}
}
try {
String hostName = InetAddress.getByName(m_addrStr).getHostName();
if (hostName.equals(provHostName))
return true;
return false;
} catch (UnknownHostException e) {
return false;
}
}
/* address must be specified as xxx.yyy.zzz.kkk
*
*/
public boolean matches(String address)
{
InetAddressParser iap = new InetAddressParser(address);
byte [] myaddr = getHostAddress();
byte [] ipaddr = iap.getHostAddress();
if (iap.m_hostAddrOnly)
{
for(int i=0; i < 4; i++)
{
if(myaddr[i] != ipaddr[i])
return false;
}
}
else if (iap.m_networkAddrOnly)
{
int matchlen = 32 - iap.m_prefixLen;
try {
int addr1 = addressToInt(m_ipaddr) >> matchlen;
int addr2 = addressToInt(iap.getHostAddress()) >> matchlen;
if (addr1 == addr2)
return true;
return false;
} catch (Exception e) {
}
}
return true;
}
public static final byte[] intToAddressBytes(int nCompactAddress) {
return new byte[] {
(byte)((nCompactAddress >> 24) & 0xff),
(byte)((nCompactAddress >> 16) & 0xff),
(byte)((nCompactAddress >> 8) & 0xff),
(byte)(nCompactAddress & 0xff)
};
}
public static final String intToAddressString(int nCompactAddress) {
StringBuilder bldr = new StringBuilder(15);
byte[] aBytes = intToAddressBytes(nCompactAddress);
for (int i = 0; i < aBytes.length; i++) {
if (i > 0)
bldr.append('.');
bldr.append(Byte.toString(aBytes[1]));
}
return bldr.toString();
}
public static final InetAddress intToAddress(int nCompactAddress) {
try {
return InetAddress.getByAddress(intToAddressBytes(nCompactAddress));
}
catch (UnknownHostException e) {
throw new IllegalArgumentException("Host not found: " + nCompactAddress, e);
}
}
public static final int addressToInt(byte[] addr) {
if (addr == null)
throw new NullPointerException("input argument is null");
if (addr.length != 4)
throw new IllegalArgumentException("address may not be null and must be IPv4 address of 4-byte length: " + new String(addr));
return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16) | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff);
}
public static final int addressToInt(InetAddress addr) {
if (addr == null)
throw new IllegalArgumentException("address may not be null");
return InetAddressParser.addressToInt(addr.getAddress());
}
public static final int addressToInt(String addr) {
if (addr == null)
throw new IllegalArgumentException("address may not be null");
try {
return InetAddressParser.addressToInt(InetAddress.getByName(addr));
}
catch (UnknownHostException e) {
throw new IllegalArgumentException("Host not found: " + addr, e);
}
}
}