package com.limegroup.gnutella.filters; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.limewire.io.Address; import org.limewire.io.Connectable; import org.limewire.io.IP; import org.limewire.mojito.messages.DHTMessage; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.messages.PingReply; import com.limegroup.gnutella.messages.PushRequest; import com.limegroup.gnutella.messages.QueryReply; import com.limegroup.gnutella.messages.QueryRequest; public abstract class AbstractIPFilter implements IPFilter { private static final Log LOG = LogFactory.getLog(AbstractIPFilter.class); /** * Marker object for IPs which are allowed. */ private static final IP ALLOWED = new IP(new byte[4]); protected IP extractAddress(Message m) { if (m instanceof PingReply) { PingReply pr = (PingReply)m; return getIP(pr.getAddress()); } else if (m instanceof QueryReply) { QueryReply qr = (QueryReply)m; return getIP(qr.getIPBytes()); } else if (m instanceof PushRequest) { PushRequest push=(PushRequest)m; return getIP(push.getIP()); } else if (m instanceof QueryRequest) { QueryRequest query = (QueryRequest)m; if (query.desiresOutOfBandReplies()) return getIP(query.getGUID()); else return ALLOWED; } else if (m instanceof DHTMessage){ DHTMessage message = (DHTMessage)m; InetSocketAddress addr = (InetSocketAddress) message.getContact().getContactAddress(); if (addr != null && addr.getAddress() instanceof Inet4Address) return getIP(addr.getAddress().getAddress()); // dht messages do not require contact address. return ALLOWED; } else { // we dont want to block other kinds of messages return ALLOWED; } } private IP getIP(byte [] host) { IP ip = null; try { ip = new IP(host, 0); } catch(IllegalArgumentException badHost) { } return ip; } private IP getIP(String host) { IP ip = null; try { ip = new IP(host); } catch (IllegalArgumentException badHost) { try { if (LOG.isDebugEnabled()) LOG.debug("doing dns lookup for "+host); InetAddress lookUp = InetAddress.getByName(host); host = lookUp.getHostAddress(); ip = new IP(host); } catch(UnknownHostException unknownHost) { // could not look up this host. } catch(IllegalArgumentException stillBadHost) { // couldn't construct IP still. } } return ip; } /** * Checks if a given Message's host is banned. * @return true if this Message's host is allowed, false if it is banned * or we are unable to create correct IP addr out of it. */ public boolean allow(Message m) { return allow(extractAddress(m)); } public boolean allow(SocketAddress addr) { if(!(addr instanceof InetSocketAddress)) { return false; } return allow(((InetSocketAddress)addr).getAddress().getAddress()); } /** * Checks to see if a given host is banned. * @param host the host's IP in byte form */ public boolean allow(byte[] host) { return allow(getIP(host)); } public boolean allow(String host) { return allow(getIP(host)); } public boolean allow(IP ip) { return allowAndLog(ip); } private boolean allowAndLog(IP ip) { if (ip == ALLOWED) { LOG.debug("Allowing non-checkable IP"); return true; } if (ip == null) { LOG.debug("Not allowing invalid IP"); return false; } boolean yes = allowImpl(ip); if (LOG.isDebugEnabled()) { if (yes) LOG.debug(getClass().getSimpleName() + " allowing " + ip); else LOG.debug(getClass().getSimpleName() + " not allowing " + ip); } return yes; } protected abstract boolean allowImpl(IP ip); @Override public boolean allow(Address address) { if (address instanceof Connectable) { return allow(((Connectable)address).getInetAddress().getAddress()); } return true; } }