FileDocCategorySizeDatePackage
IpFilterImpl.javaAPI DocAzureus 3.0.3.423752Tue Aug 14 10:24:10 BST 2007org.gudy.azureus2.core3.ipfilter.impl

IpFilterImpl

public class IpFilterImpl extends Object implements IpFilter
author
Olivier

Fields Summary
private static final org.gudy.azureus2.core3.logging.LogIDs
LOGID
private static final long
BAN_IP_PERSIST_TIME
private static final int
MAX_BLOCKS_TO_REMEMBER
private static IpFilterImpl
ipFilter
private static AEMonitor
class_mon
private IPAddressRangeManager
range_manager
private Map
bannedIps
private LinkedList
ipsBlocked
private int
num_ips_blocked
private int
num_ips_blocked_loggable
private long
last_update_time
private List
listeners
FrequencyLimitedDispatcher
blockedListChangedDispatcher
private IpFilterAutoLoaderImpl
ipFilterAutoLoader
Constructors Summary
private IpFilterImpl()

	
	  
	
	  ipFilter = this;
	  
	  bannedIps = new HashMap();
	  
	  ipsBlocked = new LinkedList();
	  
		blockedListChangedDispatcher = new FrequencyLimitedDispatcher(
				new AERunnable() {
					public void runSupport() {
						Object[] listenersArray = listeners.toArray();
						for (int i = 0; i < listenersArray.length; i++) {
							try {
								IPFilterListener l = (IPFilterListener) listenersArray[i];
								l.IPBlockedListChanged(IpFilterImpl.this);
							} catch (Exception e) {
								Debug.out(e);
							}
						}
					}
				}, 10000);

		ipFilterAutoLoader = new IpFilterAutoLoaderImpl(this);
		
		try{
		  loadBannedIPs();
		  
	  }catch( Throwable e ){
		  
		  Debug.printStackTrace(e);
	  }
	  try{
	  	
	  	loadFilters(true, true);
	  	
	  }catch( Exception e ){
	  	
	  	Debug.printStackTrace( e );
	  }
	  
	  COConfigurationManager.addParameterListener(new String[] {
			"Ip Filter Allow",
			"Ip Filter Enabled"
		}, new ParameterListener() {
			public void parameterChanged(String parameterName) {
				markAsUpToDate();
			}
		});
	
Methods Summary
private booleanaddBlockedIP(BlockedIp ip, byte[] torrent_hash, boolean loggable)

		if ( torrent_hash != null ){
			
			List	listeners_ref = listeners;
	
			for (int j=0;j<listeners_ref.size();j++){
	
				try{
					if ( !((IPFilterListener)listeners_ref.get(j)).canIPBeBlocked( ip.getBlockedIp(), torrent_hash )){
	
						return( false );
					}
	
				}catch( Throwable e ){
	
					Debug.printStackTrace(e);
				}
			}
		}
		
		try{  class_mon.enter();

			ipsBlocked.addLast( ip );
	
			num_ips_blocked++;
	
			if ( loggable ){
	
				num_ips_blocked_loggable++;
			}
	
			if( ipsBlocked.size() > MAX_BLOCKS_TO_REMEMBER ) {  //only "remember" the last few blocks occurrences
	
				ipsBlocked.removeFirst();
			}
		}finally{
			class_mon.exit();  
		}
		
		return( true );
	
public voidaddListener(IPFilterListener l)

		try{
			class_mon.enter();
		
			List	new_listeners = new ArrayList( listeners );
			
			new_listeners.add( l );
			
			listeners	= new_listeners;
			
		}finally{
			
			class_mon.exit();
		}
	
public voidaddRange(IpRange range)

		try{
			class_mon.enter();
		
			((IpRangeImpl)range).setAddedToRangeList(true);
			
				// we only allow the validity check to take effect once its added to
				// the list of all ip ranges (coz safepeer creates lots of dummy entries
				// during refresh and then never adds them...
			
			range.checkValid();
			
		}finally{
			
			class_mon.exit();
		}
		
		markAsUpToDate();
	
public booleanban(java.lang.String ipAddress, java.lang.String torrent_name, boolean manual)

			// always allow manual bans through
		
		if ( !manual ){
			
			List	listeners_ref = listeners;
			
			for (int j=0;j<listeners_ref.size();j++){
				
				try{
					if ( !((IPFilterListener)listeners_ref.get(j)).canIPBeBanned( ipAddress )){
						
						return( false );
					}
					
				}catch( Throwable e ){
					
					Debug.printStackTrace(e);
				}
			}
		}
		
		boolean	block_ban = false;
		
		List	new_bans = new ArrayList();
		
		try{
			class_mon.enter();
			
			int	address = range_manager.addressToInt( ipAddress );
			
			Integer	i_address = new Integer( address );
			
			if ( bannedIps.get(i_address) == null ){
				
				BannedIpImpl	new_ban = new BannedIpImpl( ipAddress, torrent_name );
				
				new_bans.add( new_ban );
				
				bannedIps.put( i_address, new_ban );
				
					// check for block-banning, but only for real addresses
				
				if ( !UnresolvableHostManager.isPseudoAddress( ipAddress )){
					
					long	l_address = address;
					
			    	if ( l_address < 0 ){
			     		
						l_address += 0x100000000L;
			     	}
					
					long	start 	= l_address & 0xffffff00;
					long	end		= start+256;
					
					int	hits = 0;
					
					for (long i=start;i<end;i++){
						
						Integer	a = new Integer((int)i);
						
						if ( bannedIps.get(a) != null ){
							
							hits++;
						}
					}
									
					int	hit_limit = COConfigurationManager.getIntParameter("Ip Filter Ban Block Limit");
					
					if ( hits >= hit_limit ){
						
						block_ban	= true;
						
						for (long i=start;i<end;i++){
							
							Integer	a = new Integer((int)i);
							
							if ( bannedIps.get(a) == null ){
								
								BannedIpImpl	new_block_ban = new BannedIpImpl( PRHelpers.intToAddress((int)i), torrent_name + " [block ban]" );
								
								new_bans.add( new_block_ban );

								bannedIps.put( a, new_block_ban );
							}
						}
					}
				}
				
				saveBannedIPs();
			}
		}finally{
			
			class_mon.exit();
		}
			
		List	listeners_ref = listeners;

		for (int i=0;i<new_bans.size();i++){
			
			BannedIp entry	= (BannedIp)new_bans.get(i);
			
			for (int j=0;j<listeners_ref.size();j++){
				
				try{
					((IPFilterListener)listeners_ref.get(j)).IPBanned( entry );
					
				}catch( Throwable e ){
					
					Debug.printStackTrace(e);
				}
			}
		}
		
		return( block_ban );
	
public voidclearBannedIps()

		try{
			class_mon.enter();
		
			bannedIps.clear();
			
			saveBannedIPs();
			
		}finally{
			
			class_mon.exit();
		}
	
public voidclearBlockedIPs()

		try{
			class_mon.enter();
			
			ipsBlocked.clear();
      
			num_ips_blocked 			= 0;
			num_ips_blocked_loggable	= 0;
			
		}finally{
			
			class_mon.exit();
		}
	
public IpRangecreateRange(boolean sessionOnly)

		return ( new IpRangeImpl("","","",sessionOnly));
	
public BannedIp[]getBannedIps()

		try{
			class_mon.enter();
			
			BannedIp[]	res = new BannedIp[bannedIps.size()];
		
			bannedIps.values().toArray(res);
			
			return( res );
			
		}finally{
			
			class_mon.exit();
		}
  	
public BlockedIp[]getBlockedIps()

		try{
			class_mon.enter();
			
			BlockedIp[]	res = new BlockedIp[ipsBlocked.size()];
		
			ipsBlocked.toArray(res);
			
			return( res );
		}finally{
			
			class_mon.exit();
		}
  	
public java.io.FilegetFile()

		return( FileUtil.getUserFile("filters.config"));
	
public booleangetInRangeAddressesAreAllowed()

	  boolean allow = COConfigurationManager.getBooleanParameter("Ip Filter Allow");
	  
	  return( allow );
	
public static IpFiltergetInstance()

		try{
			class_mon.enter();
		
			  if(ipFilter == null) {
				ipFilter = new IpFilterImpl();
			  }
			  return ipFilter;
		}finally{
			
			class_mon.exit();
		}
	
public java.util.ListgetIpRanges()

return
deprecated

		try{
			class_mon.enter();

			return new ArrayList( range_manager.getEntries() );
			
		}finally{
			
			class_mon.exit();
		}
	
public longgetLastUpdateTime()

		return( last_update_time );
	
public intgetNbBannedIps()

		return( bannedIps.size());
	
public intgetNbIpsBlocked()

	  return num_ips_blocked;
	
public intgetNbIpsBlockedAndLoggable()

	  return num_ips_blocked_loggable;
	
public intgetNbRanges()

		List entries = range_manager.getEntries();

	  return entries.size();
	
public IpRange[]getRanges()

		try{
			class_mon.enter();
			
			List entries = range_manager.getEntries();
			IpRange[]	res = new IpRange[entries.size()];
			
			entries.toArray( res );
			
			return( res );
			
		}finally{
			
			class_mon.exit();
		}
	
public longgetTotalAddressesInRange()

		return( range_manager.getTotalSpan());
	
private booleanisBanned(java.net.InetAddress ipAddress)

	  try{
	  	class_mon.enter();
	  
		int	address = range_manager.addressToInt( ipAddress );
		
		Integer	i_address = new Integer( address );
		
	    return( bannedIps.get(i_address) != null );
	    
	  }finally{
	  	
	  	class_mon.exit();
	  }
	
private booleanisBanned(java.lang.String ipAddress)

	  try{
	  	class_mon.enter();
	  
		int	address = range_manager.addressToInt( ipAddress );
		
		Integer	i_address = new Integer( address );
		
	    return( bannedIps.get(i_address) != null );
	    
	  }finally{
	  	
	  	class_mon.exit();
	  }
	
public booleanisEnabled()

		return( COConfigurationManager.getBooleanParameter("Ip Filter Enabled"));	
	
protected booleanisInRange(IpRange range, java.lang.String address)

		return( range_manager.isInRange( range, address ));
	
public booleanisInRange(java.lang.String ipAddress)

    return isInRange( ipAddress, "", null );
  
public booleanisInRange(java.lang.String ipAddress, java.lang.String torrent_name, byte[] torrent_hash)

		return( isInRange( ipAddress, torrent_name, torrent_hash, true ));
	
public booleanisInRange(java.lang.String ipAddress, java.lang.String torrent_name, byte[] torrent_hash, boolean loggable)

		//In all cases, block banned ip addresses
		
		  if(isBanned(ipAddress)){
		  
			  return true;
		  }
		  

		if ( !isEnabled()){
			
			return( false );
		}
		
	  	// never bounce the local machine (peer guardian has a range that includes it!)
	  
	  if ( ipAddress.equals("127.0.0.1")){
	  	
		  return( false );
	  }
	  
	  	// don't currently support IPv6
	  
	  if ( ipAddress.indexOf( ":" ) != -1 ){
		  
		  return( false );
	  }
	  
	  	//never block lan local addresses
	  
	  if( AddressUtils.isLANLocalAddress( ipAddress ) != AddressUtils.LAN_LOCAL_NO ) {
	  	return false;
	  }
	  	  
	  boolean allow = COConfigurationManager.getBooleanParameter("Ip Filter Allow");
	  
	  IpRange	match = (IpRange)range_manager.isInRange( ipAddress );

	  if(match != null) {
	    if(!allow) {
	    	
	      	// don't bounce non-public addresses (we can ban them but not filter them as they have no sensible
		  	// real filter address
		  
		  if ( AENetworkClassifier.categoriseAddress( ipAddress ) != AENetworkClassifier.AT_PUBLIC ){
			  
			  return( false );
		  }
		  
	      if ( addBlockedIP( new BlockedIpImpl( ipAddress, match, torrent_name, loggable), torrent_hash, loggable )){
	      
		      if (Logger.isEnabled())
						Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : "
								+ ipAddress + ", in range : " + match));
		      
		      return true;
		      
	      }else{
	    	  
		      if (Logger.isEnabled())
					Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : "
							+ ipAddress + ", in range : " + match));
	      
		      return false;
	      }
	    }
      
	    return false;  
	  }

	
	  if( allow ){  
		  
		if ( AENetworkClassifier.categoriseAddress( ipAddress ) != AENetworkClassifier.AT_PUBLIC ){
			  
		  return( false );
		}
		  
	    if ( addBlockedIP( new BlockedIpImpl(ipAddress,null, torrent_name, loggable), torrent_hash, loggable )){
	    
		    if (Logger.isEnabled())
					Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : "
							+ ipAddress + ", not in any range"));
		    
		    return true;
		    
	    }else{
	    	
		    if (Logger.isEnabled())
				Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : "
						+ ipAddress + ", not in any range"));
	    
		    return false;
	    }
	  }
	  
	  return false;
	
public booleanisInRange(java.net.InetAddress ipAddress, java.lang.String torrent_name, byte[] torrent_hash, boolean loggable)

		//In all cases, block banned ip addresses
		
		  if(isBanned(ipAddress)){
		  
			  return true;
		  }

		if ( !isEnabled()){
			
			return( false );
		}
			  
	  	// never bounce the local machine (peer guardian has a range that includes it!)
	  
	  if ( ipAddress.isLoopbackAddress() || ipAddress.isLinkLocalAddress() || ipAddress.isSiteLocalAddress()){
	  	
		  return( false );
	  }
	  
	  	// don't currently support IPv6
	  
	  if ( ipAddress instanceof Inet6Address ){
		  
		  return( false );
	  }
	  
	  	//never block lan local addresses
	  
	  if( AddressUtils.isLANLocalAddress( ipAddress ) != AddressUtils.LAN_LOCAL_NO ) {
		  
	  	return false;
	  }
	  	  
	  boolean allow = COConfigurationManager.getBooleanParameter("Ip Filter Allow");
	  
	  IpRange	match = (IpRange)range_manager.isInRange( ipAddress );

	  if ( match != null ){
		  
	    if(!allow) {
	    			  
	      if ( addBlockedIP( new BlockedIpImpl(ipAddress.getHostAddress(),match, torrent_name, loggable), torrent_hash, loggable )){
	      
		      if (Logger.isEnabled())
						Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : "
								+ ipAddress + ", in range : " + match));
		      
		      return true;
		      
	      }else{
		      
		      if (Logger.isEnabled())
						Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied: "
								+ ipAddress + ", in range : " + match));
		      
		      return false;

	      }
	    }
      
	    return false;  
	  }

	
	  if( allow ){  
		  
	    if ( addBlockedIP( new BlockedIpImpl(ipAddress.getHostAddress(),null, torrent_name, loggable), torrent_hash, loggable )){
	    
		    if (Logger.isEnabled())
					Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : "
							+ ipAddress + ", not in any range"));
		    
		    return true;
	    }else{
	    	
		    if (Logger.isEnabled())
				Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : "
						+ ipAddress + ", not in any range"));
	    
		    return false;
	    }
	  }
	  
	  return false;
	
protected voidloadBannedIPs()

		if ( !COConfigurationManager.getBooleanParameter("Ip Filter Banning Persistent" )){
			
			return;
		}
		
		try{
			class_mon.enter();
			
			Map	map = FileUtil.readResilientConfigFile( "banips.config" );
		
			List	ips = (List)map.get( "ips" );
			
			if ( ips != null ){
				
				long	now = SystemTime.getCurrentTime();
				
				for (int i=0;i<ips.size();i++){
					
					Map	entry = (Map)ips.get(i);
					
					String	ip 		= new String((byte[])entry.get("ip"));
					String	desc 	= new String((byte[])entry.get("desc"), "UTF-8");
					Long	ltime	= (Long)entry.get("time");
					
					long	time = ltime.longValue();
					
					boolean	drop	= false;
					
					if ( time > now ){
						
						time	= now;
						
					}else if ( now - time >= BAN_IP_PERSIST_TIME ){
						
						drop	= true;
						
					    if (Logger.isEnabled()){
					    	
								Logger.log(
									new LogEvent(
										LOGID, LogEvent.LT_INFORMATION, 
										"Persistent ban dropped as too old : "
											+ ip + ", " + desc));
					      }
					}
					
					if ( !drop ){
						
						int	int_ip = range_manager.addressToInt( ip );
						
						bannedIps.put( new Integer( int_ip ), new BannedIpImpl(ip, desc, time ));
					}
				}
			}
		}catch( Throwable e ){
			
			Debug.printStackTrace(e);
			
		}finally{
			
			class_mon.exit();
		}
	
private voidloadFilters(boolean allowAsyncDownloading, boolean loadOldWhileAsyncDownloading)

		long startTime = System.currentTimeMillis();
		ipFilterAutoLoader.loadOtherFilters(allowAsyncDownloading, loadOldWhileAsyncDownloading);
		
		if (getNbRanges() > 0) {
			Logger.log(new LogEvent(LOGID, (System.currentTimeMillis() - startTime)
					+ "ms for " + getNbRanges() + ". now loading norm"));
		}

		try{
			class_mon.enter();
		
		  List new_ipRanges = new ArrayList(1024);
	
		  FileInputStream fin = null;
		  BufferedInputStream bin = null;
		  try {
			//open the file
			File filtersFile = FileUtil.getUserFile("filters.config");
			if (filtersFile.exists()) {
				fin = new FileInputStream(filtersFile);
				bin = new BufferedInputStream(fin, 16384);
				Map map = BDecoder.decode(bin);
				List list = (List) map.get("ranges");
				Iterator iter = list.listIterator();
				while(iter.hasNext()) {
				  Map range = (Map) iter.next();
				  String description =  new String((byte[])range.get("description"), "UTF-8");
				  String startIp =  new String((byte[])range.get("start"));
				  String endIp = new String((byte[])range.get("end"));
		        
				  IpRangeImpl ipRange = new IpRangeImpl(description,startIp,endIp,false);

				  ipRange.setAddedToRangeList(true);
				  
				  new_ipRanges.add( ipRange );
				}
			}		
		  }finally{
		  
			if ( bin != null ){
				try{
				    bin.close();
				}catch( Throwable e ){
				}
			}
			if ( fin != null ){
				try{
					fin.close();
				}catch( Throwable e ){
				}
			}
			
		  	
		  	Iterator	it = new_ipRanges.iterator();
		  	
		  	while( it.hasNext()){
		  		  		
		  		((IpRange)it.next()).checkValid();
		  	}
		  	
		  	markAsUpToDate();
		  }
		}finally{
			
			class_mon.exit();
		}
		Logger.log(new LogEvent(LOGID, (System.currentTimeMillis() - startTime)
				+ "ms to load all IP Filters"));
	
public static voidmain(java.lang.String[] args)

		IpFilterImpl	filter = new IpFilterImpl();
		
		filter.ban( "255.1.1.1", "parp", true );
		filter.ban( "255.1.1.2", "parp", true );
		filter.ban( "255.1.2.2", "parp", true );
		
		System.out.println( "is banned:" + filter.isBanned( "255.1.1.4" ));
	
public voidmarkAsUpToDate()

	  	last_update_time	= SystemTime.getCurrentTime();
	  	
	  	blockedListChangedDispatcher.dispatch();
	
public voidreload()

		reload(true);
	
public voidreload(boolean allowAsyncDownloading)

		range_manager.clearAllEntries();
		markAsUpToDate();
		loadFilters(allowAsyncDownloading, false);
	
public voidremoveListener(IPFilterListener l)

		try{
			class_mon.enter();
		
			List	new_listeners = new ArrayList( listeners );
			
			new_listeners.remove( l );
			
			listeners	= new_listeners;
			
		}finally{
			
			class_mon.exit();
		}
	
public voidremoveRange(IpRange range)

		try{
			class_mon.enter();
		
			((IpRangeImpl)range).setAddedToRangeList( false );
			
			range_manager.removeRange( range );
			
		}finally{
			
			class_mon.exit();
		}
		
		markAsUpToDate();
	
public voidsave()

		try{
			class_mon.enter();
		
			Map map = new HashMap();
		 
	
			List filters = new ArrayList();
			map.put("ranges",filters);
			List entries = range_manager.getEntries();
			Iterator iter = entries.iterator();
			while(iter.hasNext()) {
			  IpRange range = (IpRange) iter.next();
			  if(range.isValid() && ! range.isSessionOnly()) {
				String description =  range.getDescription();
				String startIp = range.getStartIp();
				String endIp = range.getEndIp();
				Map mapRange = new HashMap();
				mapRange.put("description",description.getBytes( "UTF-8" ));
				mapRange.put("start",startIp);
				mapRange.put("end",endIp);
				filters.add(mapRange);
			  }
			}
		  
		  	FileOutputStream fos  = null;
	    
	    	try {
	      	
	    		//  Open the file
	    		
	    		File filtersFile = FileUtil.getUserFile("filters.config");
	        
	    		fos = new FileOutputStream(filtersFile);
	    		
	    		fos.write(BEncoder.encode(map));
	    		
	    	}finally{
		  	
		  		if ( fos != null ){
		  			
		  			fos.close();
		  		}
	    	}
		}finally{
			
			class_mon.exit();
		}
	
protected voidsaveBannedIPs()

		if ( !COConfigurationManager.getBooleanParameter("Ip Filter Banning Persistent" )){
			
			return;
		}
		
		try{
			class_mon.enter();
			
			Map	map = new HashMap();
			
			List	ips = new ArrayList();
			
			Iterator	it = bannedIps.values().iterator();
			
			while( it.hasNext()){
				
				BannedIpImpl	bip = (BannedIpImpl)it.next();
				
				Map	entry = new HashMap();
				
				entry.put( "ip", bip.getIp());
				entry.put( "desc", bip.getTorrentName().getBytes( "UTF-8" ));
				entry.put( "time", new Long( bip.getBanningTime()));
				
				ips.add( entry );
			}
			
			map.put( "ips", ips );
			
			FileUtil.writeResilientConfigFile( "banips.config", map );
		
		}catch( Throwable e ){
			
			Debug.printStackTrace(e);
			
		}finally{
			
			class_mon.exit();
		}
	
public voidsetEnabled(boolean enabled)

		COConfigurationManager.setParameter( "Ip Filter Enabled", enabled );
	
public voidsetInRangeAddressesAreAllowed(boolean b)

		COConfigurationManager.setParameter("Ip Filter Allow", b );
	
protected voidsetValidOrNot(IpRange range, boolean valid)

		try{
			class_mon.enter();

				// this is an optimisation to deal with the way safepeer validates stuff
				// before adding it in
			
			if ( !range.getAddedToRangeList()){
				
				return;
			}
			
		}finally{
			
			class_mon.exit();
		}
		
		if ( valid ){
					
			range_manager.addRange( range );
				
		}else{
			
			range_manager.removeRange( range );
		}
	
public voidunban(java.lang.String ipAddress)

		try{
			class_mon.enter();
		
			int	address = range_manager.addressToInt( ipAddress );
			
			Integer	i_address = new Integer( address );
			
			if ( bannedIps.remove(i_address) != null ){
			
				saveBannedIPs();
			}
			
		}finally{
			
			class_mon.exit();
		}
	
public voidunban(java.lang.String ipAddress, boolean block)

		if ( block ){
	
			int	address = range_manager.addressToInt( ipAddress );	
				
			long	l_address = address;
			
	    	if ( l_address < 0 ){
	     		
				l_address += 0x100000000L;
	     	}
			
			long	start 	= l_address & 0xffffff00;
			long	end		= start+256;
		
			boolean	hit = false;
			
			try{
				class_mon.enter();

				for (long i=start;i<end;i++){
					
					Integer	a = new Integer((int)i);
	
					if ( bannedIps.remove(a) != null ){
						
						hit = true;
					}
				}
				
				if ( hit ){
					
					saveBannedIPs();
				}
			}finally{
				
				class_mon.exit();
			}
			
		}else{
			
			try{
				class_mon.enter();
			
				int	address = range_manager.addressToInt( ipAddress );
				
				Integer	i_address = new Integer( address );
				
				if ( bannedIps.remove(i_address) != null ){
				
					saveBannedIPs();
				}
				
			}finally{
				
				class_mon.exit();
			}
		}