* Feeders now return ScanningSubject containing InetAddress, in order to provide more metadata to the Fetchers

* FileFeeder now provides requestedPort if it is specified in the file - useful for scanning of IP:Port list files
* PortTextFetcher now uses the requestedPort if it is available

git-svn-id: https://ipscan.svn.sourceforge.net/svnroot/ipscan/trunk@357 375186e5-ef17-0410-b0b6-91563547dcda
This commit is contained in:
angryziber 2008-04-03 21:51:21 +00:00
parent e3c48e005d
commit 07cd90eb52
15 changed files with 126 additions and 94 deletions

View File

@ -5,8 +5,6 @@
*/
package net.azib.ipscan.core;
import java.net.InetAddress;
import net.azib.ipscan.core.values.NotAvailable;
import net.azib.ipscan.core.values.NotScanned;
import net.azib.ipscan.fetchers.Fetcher;
@ -28,15 +26,10 @@ public class Scanner {
/**
* Executes all registered fetchers for the current IP address.
* @param address the IP address to scan
* @param scanningSubject containing the IP address to scan
* @param result where the results are injected
*/
public void scan(InetAddress address, ScanningResult result) {
// create a scanning subject object, which will be used by fetchers
// to cache common information
ScanningSubject scanningSubject = new ScanningSubject(address);
public void scan(ScanningSubject scanningSubject, ScanningResult result) {
// populate results
int fetcherIndex = 0;
boolean isScanningInterrupted = false;

View File

@ -5,7 +5,6 @@
*/
package net.azib.ipscan.core;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@ -76,36 +75,33 @@ public class ScannerDispatcherThread extends Thread implements ThreadFactory, St
long lastNotifyTime = 0;
try {
InetAddress address = null;
ScanningSubject subject = null;
while(feeder.hasNext() && stateMachine.inState(ScanningState.SCANNING)) {
// make a small delay between thread creation
Thread.sleep(config.threadDelay);
// see if this iteration must be skipped until more threads can be created
boolean canStartNewThread = numActiveThreads.intValue() < config.maxThreads;
if (canStartNewThread) {
if ((numActiveThreads.intValue() < config.maxThreads)) {
// retrieve the next IP address to scan
address = feeder.next();
subject = feeder.next();
// check if this is a likely broadcast address and needs to be skipped
if (config.skipBroadcastAddresses && InetAddressUtils.isLikelyBroadcast(address)) {
if (config.skipBroadcastAddresses && InetAddressUtils.isLikelyBroadcast(subject.getAddress())) {
continue;
}
// prepare results receiver for upcoming results
ScanningResult result = scanningResultList.createResult(address);
ScanningResult result = scanningResultList.createResult(subject.getAddress());
resultsCallback.prepareForResults(result);
// scan each IP in parallel, in a separate thread
AddressScannerTask scanningTask = new AddressScannerTask(address, result);
AddressScannerTask scanningTask = new AddressScannerTask(subject, result);
threadPool.execute(scanningTask);
}
// notify listeners of the progress we are doing (max 5 times per second)
if (System.currentTimeMillis() - lastNotifyTime >= UI_UPDATE_INTERVAL) {
lastNotifyTime = System.currentTimeMillis();
progressCallback.updateProgress(address, numActiveThreads.intValue(), feeder.percentageComplete());
progressCallback.updateProgress(subject.getAddress(), numActiveThreads.intValue(), feeder.percentageComplete());
}
}
}
@ -170,21 +166,21 @@ public class ScannerDispatcherThread extends Thread implements ThreadFactory, St
* scanning.
*/
class AddressScannerTask implements Runnable {
private InetAddress address;
private ScanningSubject subject;
private ScanningResult result;
AddressScannerTask(InetAddress address, ScanningResult result) {
this.address = address;
AddressScannerTask(ScanningSubject subject, ScanningResult result) {
this.subject = subject;
this.result = result;
numActiveThreads.incrementAndGet();
}
public void run() {
// set current thread's name to ease debugging
Thread.currentThread().setName(getClass().getSimpleName() + ": " + address.getHostAddress());
Thread.currentThread().setName(getClass().getSimpleName() + ": " + subject);
try {
scanner.scan(address, result);
scanner.scan(subject, result);
resultsCallback.consumeResults(result);
}
finally {

View File

@ -30,6 +30,8 @@ public class ScanningSubject {
/** The address being scanned */
private InetAddress address;
/** The requested port that the user wishes to put more attention to, can be null. E.g. port 3128 for scanning of proxy servers. */
private Integer requestedPort;
/** Arbitrary parameters for sharing among different (but related) Fetchers */
private Map<String, Object> parameters;
/** The result type constant value, can be modified by some Fetchers */
@ -103,6 +105,20 @@ public class ScanningSubject {
public void abortAddressScanning() {
this.isAborted = true;
}
/**
* @return the port that the user wishes to pay attention to, e.g. 3128 for proxies, or null.
*/
public Integer getRequestedPort() {
return requestedPort;
}
/**
* @param requestedPort the port that user wants to scan
*/
public void setRequestedPort(Integer requestedPort) {
this.requestedPort = requestedPort;
}
/**
* @return adapted port timeout for this host if available
@ -123,5 +139,10 @@ public class ScanningSubject {
// if no pinging results are available yet, return the full timeout
return config.portTimeout;
}
@Override
public String toString() {
return address.getHostAddress() + requestedPort != null ? ":" + requestedPort : "";
}
}

View File

@ -1,10 +1,11 @@
/**
*
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*/
package net.azib.ipscan.feeders;
import java.net.InetAddress;
import net.azib.ipscan.core.ScanningSubject;
import net.azib.ipscan.core.plugins.Pluggable;
/**
@ -31,7 +32,7 @@ public interface Feeder extends Pluggable {
/**
* @return the next IP for processing
*/
public InetAddress next();
public ScanningSubject next();
/**
* @return value from 0 to 100, describing the amount of work already done

View File

@ -18,30 +18,27 @@ import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.azib.ipscan.config.LoggerFactory;
import net.azib.ipscan.core.InetAddressUtils;
import net.azib.ipscan.core.ScanningSubject;
/**
* Feeder, taking IP addresses from text files in any format.
* It uses regular expressions for matching of IP addresses.
* TODO: tests!!!
*
* @author Anton Keks
*/
public class FileFeeder extends AbstractFeeder {
private static final Pattern PORT_REGEX = Pattern.compile("\\d{1,5}\\b");
static final Logger LOG = LoggerFactory.getLogger();
/** Found IP address Strings are put here */
private List<String> foundIPAddresses;
private Iterator<String> foundIPAddressesIterator;
/**
* Total number of found IP addresses. Equivalent to foundIPAddresses.size(),
* which is very ineffective in case of a LinkedList.
*/
private int totalAddresses;
private List<ScanningSubject> foundIPAddresses;
private Iterator<ScanningSubject> foundIPAddressesIterator;
private int currentIndex;
@ -54,7 +51,7 @@ public class FileFeeder extends AbstractFeeder {
public FileFeeder(String fileName) {
try {
initialize(new FileReader(fileName));
readAddresses(new FileReader(fileName));
}
catch (FileNotFoundException e) {
throw new FeederException("file.notExists");
@ -62,25 +59,37 @@ public class FileFeeder extends AbstractFeeder {
}
public FileFeeder(Reader reader) {
initialize(reader);
readAddresses(reader);
}
private void initialize(Reader reader) {
private void readAddresses(Reader reader) {
BufferedReader fileReader = new BufferedReader(reader);
totalAddresses = 0;
currentIndex = 0;
foundIPAddresses = new LinkedList<String>();
foundIPAddresses = new LinkedList<ScanningSubject>();
try {
String fileLine;
while ((fileLine = fileReader.readLine()) != null) {
Matcher matcher = InetAddressUtils.IP_ADDRESS_REGEX.matcher(fileLine);
while (matcher.find()) {
foundIPAddresses.add(matcher.group());
totalAddresses++;
try {
String address = matcher.group();
ScanningSubject subject = new ScanningSubject(InetAddress.getByName(address));
if (!matcher.hitEnd() && fileLine.charAt(matcher.end()) == ':') {
// see if any valid port is requested
Matcher portMatcher = PORT_REGEX.matcher(fileLine.substring(matcher.end()+1));
if (portMatcher.lookingAt()) {
subject.setRequestedPort(Integer.valueOf(portMatcher.group()));
}
}
foundIPAddresses.add(subject);
}
catch (UnknownHostException e) {
LOG.log(Level.WARNING, "malformedIP", e);
}
}
}
if (totalAddresses == 0) {
if (foundIPAddresses.isEmpty()) {
throw new FeederException("file.nothingFound");
}
}
@ -100,27 +109,21 @@ public class FileFeeder extends AbstractFeeder {
}
public int percentageComplete() {
return Math.round((float)currentIndex * 100 / totalAddresses);
return Math.round((float)currentIndex * 100 / foundIPAddresses.size());
}
public boolean hasNext() {
return foundIPAddressesIterator.hasNext();
}
public InetAddress next() {
try {
currentIndex++;
return InetAddress.getByName(foundIPAddressesIterator.next());
}
catch (UnknownHostException e) {
LOG.log(Level.WARNING, "malformedIP", e);
throw new FeederException("malformedIP");
}
public ScanningSubject next() {
currentIndex++;
return foundIPAddressesIterator.next();
}
public String getInfo() {
// let's return the number of found addresses
return Integer.toString(totalAddresses);
return Integer.toString(foundIPAddresses.size());
}
}

View File

@ -10,6 +10,7 @@ import java.net.UnknownHostException;
import java.security.SecureRandom;
import net.azib.ipscan.core.InetAddressUtils;
import net.azib.ipscan.core.ScanningSubject;
/**
* A feeder, that generates random IP addresses.
@ -70,12 +71,12 @@ public class RandomFeeder extends AbstractFeeder {
return currentNumber < addressCount;
}
public InetAddress next() {
public ScanningSubject next() {
currentNumber++;
random.nextBytes(currentBytes);
try {
InetAddressUtils.maskPrototypeAddressBytes(currentBytes, maskBytes, prototypeBytes);
return InetAddress.getByAddress(currentBytes);
return new ScanningSubject(InetAddress.getByAddress(currentBytes));
}
catch (UnknownHostException e) {
// this should never happen

View File

@ -9,6 +9,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import net.azib.ipscan.core.InetAddressUtils;
import net.azib.ipscan.core.ScanningSubject;
import org.savarese.vserv.tcpip.OctetConverter;
@ -74,11 +75,11 @@ public class RangeFeeder extends AbstractFeeder {
return !currentIP.equals(endIP);
}
public InetAddress next() {
public ScanningSubject next() {
percentageComplete += percentageIncrement;
InetAddress prevIP = this.currentIP;
this.currentIP = InetAddressUtils.increment(prevIP);
return prevIP;
return new ScanningSubject(prevIP);
}
public int percentageComplete() {

View File

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import net.azib.ipscan.config.Labels;
import net.azib.ipscan.core.ScanningSubject;
/**
* A Feeder for rescanning - takes a predefined list of IP addresses.
@ -70,8 +71,8 @@ public class RescanFeeder extends AbstractFeeder {
return current < addresses.size();
}
public InetAddress next() {
return addresses.get(current++);
public ScanningSubject next() {
return new ScanningSubject(addresses.get(current++));
}
public int percentageComplete() {

View File

@ -5,7 +5,7 @@
*/
package net.azib.ipscan.feeders;
import java.net.InetAddress;
import net.azib.ipscan.core.ScanningSubject;
/**
* Smart text feeder for advanced users.
@ -44,7 +44,7 @@ public class SmartTextFeeder extends AbstractFeeder {
return false;
}
public InetAddress next() {
public ScanningSubject next() {
return null;
}

View File

@ -33,13 +33,13 @@ public abstract class PortTextFetcher extends AbstractFetcher {
private ScannerConfig scannerConfig;
private int port;
private int defaultPort;
private String textToSend;
private Pattern matchingRegexp;
public PortTextFetcher(ScannerConfig scannerConfig, int port, String textToSend, String matchingRegexp) {
public PortTextFetcher(ScannerConfig scannerConfig, int defaultPort, String textToSend, String matchingRegexp) {
this.scannerConfig = scannerConfig;
this.port = port;
this.defaultPort = defaultPort;
this.textToSend = textToSend;
this.matchingRegexp = Pattern.compile(matchingRegexp);
}
@ -48,9 +48,9 @@ public abstract class PortTextFetcher extends AbstractFetcher {
Socket socket = new Socket();
try {
// TODO: support multiple ports and check them sequentially
socket.connect(new InetSocketAddress(subject.getAddress(), port), subject.getAdaptedPortTimeout());
socket.connect(new InetSocketAddress(subject.getAddress(), subject.getRequestedPort() != null ? subject.getRequestedPort() : defaultPort), subject.getAdaptedPortTimeout());
socket.setTcpNoDelay(true);
socket.setSoTimeout(scannerConfig.portTimeout);
socket.setSoTimeout(scannerConfig.portTimeout*2);
socket.setSoLinger(true, 0);
socket.getOutputStream().write(textToSend.getBytes());
@ -59,7 +59,7 @@ public abstract class PortTextFetcher extends AbstractFetcher {
String line;
while ((line = in.readLine()) != null) {
Matcher matcher = matchingRegexp.matcher(line);
if (matcher.matches()) {
if (matcher.find()) {
// mark that additional info is available
subject.setResultType(ResultType.WITH_PORTS);
// return the required contents

View File

@ -60,7 +60,7 @@ public class ScannerTest {
public void testScan() throws Exception {
// scan the local host
ScanningResult scanningResult = new ScanningResult(InetAddress.getLocalHost(), 4);
scanner.scan(InetAddress.getLocalHost(), scanningResult);
scanner.scan(new ScanningSubject(InetAddress.getLocalHost()), scanningResult);
assertEquals(ResultType.ALIVE, scanningResult.getType());
assertEquals(InetAddress.getLocalHost(), scanningResult.getAddress());
@ -82,7 +82,7 @@ public class ScannerTest {
// scan the local host
ScanningResult scanningResult = new ScanningResult(InetAddress.getLocalHost(), 3);
scanner.scan(InetAddress.getLocalHost(), scanningResult);
scanner.scan(new ScanningSubject(InetAddress.getLocalHost()), scanningResult);
assertEquals(ResultType.UNKNOWN, scanningResult.getType());
assertEquals(InetAddress.getLocalHost(), scanningResult.getAddress());

View File

@ -1,7 +1,11 @@
package net.azib.ipscan.feeders;
import static org.junit.Assert.*;
import static net.azib.ipscan.feeders.FeederTestUtils.*;
import static net.azib.ipscan.feeders.FeederTestUtils.assertFeederException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.StringReader;
@ -22,11 +26,11 @@ public class FileFeederTest {
StringReader reader = new StringReader("10.11.12.13 10.11.12.14 10.11.12.15");
FileFeeder fileFeeder = new FileFeeder(reader);
assertTrue(fileFeeder.hasNext());
assertEquals("10.11.12.13", fileFeeder.next().getHostAddress());
assertEquals("10.11.12.13", fileFeeder.next().getAddress().getHostAddress());
assertTrue(fileFeeder.hasNext());
assertEquals("10.11.12.14", fileFeeder.next().getHostAddress());
assertEquals("10.11.12.14", fileFeeder.next().getAddress().getHostAddress());
assertTrue(fileFeeder.hasNext());
assertEquals("10.11.12.15", fileFeeder.next().getHostAddress());
assertEquals("10.11.12.15", fileFeeder.next().getAddress().getHostAddress());
assertFalse(fileFeeder.hasNext());
}
@ -110,6 +114,17 @@ public class FileFeederTest {
FileFeeder fileFeeder = new FileFeeder(reader);
assertEquals("3", fileFeeder.getInfo());
}
@Test
public void requestedPortsAreDetected() throws Exception {
StringReader reader = new StringReader("1.2.3.4:1234\n2.3.4.5:\n 7.6.5.4:789004\n 1.2.3.5:80 ");
FileFeeder fileFeeder = new FileFeeder(reader);
assertEquals(1234, fileFeeder.next().getRequestedPort());
assertNull(fileFeeder.next().getRequestedPort());
assertNull(fileFeeder.next().getRequestedPort());
assertEquals(80, fileFeeder.next().getRequestedPort());
}
private void assertAddressCount(String s, int addressCount) {
StringReader reader = new StringReader(s);

View File

@ -16,9 +16,9 @@ public class RandomFeederTest {
public void testHappyPath() throws FeederException {
RandomFeeder randomFeeder = new RandomFeeder("255.255.255.255", "255...0", 2);
assertTrue(randomFeeder.hasNext());
assertTrue(randomFeeder.next().getHostAddress().startsWith("255.255.255"));
assertTrue(randomFeeder.next().getAddress().getHostAddress().startsWith("255.255.255"));
assertTrue(randomFeeder.hasNext());
assertTrue(randomFeeder.next().getHostAddress().startsWith("255.255.255"));
assertTrue(randomFeeder.next().getAddress().getHostAddress().startsWith("255.255.255"));
assertFalse(randomFeeder.hasNext());
}
@ -60,7 +60,7 @@ public class RandomFeederTest {
RandomFeeder randomFeeder = null;
randomFeeder = new RandomFeeder("1.2.3.45", "255.255.255.255", 1);
assertTrue(randomFeeder.hasNext());
assertEquals("1.2.3.45", randomFeeder.next().getHostAddress());
assertEquals("1.2.3.45", randomFeeder.next().getAddress().getHostAddress());
assertFalse(randomFeeder.hasNext());
}
@ -69,7 +69,7 @@ public class RandomFeederTest {
RandomFeeder randomFeeder = null;
randomFeeder = new RandomFeeder("1.2.3.45", "0.0.0.0", 1);
assertTrue(randomFeeder.hasNext());
assertFalse("1.2.3.45".equals(randomFeeder.next().getHostAddress()));
assertFalse("1.2.3.45".equals(randomFeeder.next().getAddress().getHostAddress()));
assertFalse(randomFeeder.hasNext());
}
@ -78,7 +78,7 @@ public class RandomFeederTest {
RandomFeeder randomFeeder = null;
randomFeeder = new RandomFeeder("1.2.3.45", "255.0.0.255", 1);
assertTrue(randomFeeder.hasNext());
String address = randomFeeder.next().getHostAddress();
String address = randomFeeder.next().getAddress().getHostAddress();
assertTrue(address.startsWith("1."));
assertTrue(address.endsWith(".45"));
assertFalse(randomFeeder.hasNext());
@ -91,15 +91,15 @@ public class RandomFeederTest {
randomFeeder = new RandomFeeder("1.2.3.45", "255.0.255.0", 2);
assertTrue(randomFeeder.hasNext());
address = randomFeeder.next().getHostAddress();
address = randomFeeder.next().getAddress().getHostAddress();
assertFalse("1.2.3.45".equals(address));
assertTrue(randomFeeder.hasNext());
assertFalse(address.equals(randomFeeder.next().getHostAddress()));
assertFalse(address.equals(randomFeeder.next().getAddress().getHostAddress()));
assertFalse(randomFeeder.hasNext());
randomFeeder = new RandomFeeder("1.2.3.45", "255.0.127.0", 1);
assertTrue(randomFeeder.hasNext());
assertFalse(address.equals(randomFeeder.next().getHostAddress()));
assertFalse(address.equals(randomFeeder.next().getAddress().getHostAddress()));
assertFalse(randomFeeder.hasNext());
}

View File

@ -16,11 +16,11 @@ public class RangeFeederTest {
public void testHappyPath() throws FeederException {
RangeFeeder rangeFeeder = new RangeFeeder("10.11.12.13", "10.11.12.15");
assertTrue(rangeFeeder.hasNext());
assertEquals("10.11.12.13", rangeFeeder.next().getHostAddress());
assertEquals("10.11.12.13", rangeFeeder.next().getAddress().getHostAddress());
assertTrue(rangeFeeder.hasNext());
assertEquals("10.11.12.14", rangeFeeder.next().getHostAddress());
assertEquals("10.11.12.14", rangeFeeder.next().getAddress().getHostAddress());
assertTrue(rangeFeeder.hasNext());
assertEquals("10.11.12.15", rangeFeeder.next().getHostAddress());
assertEquals("10.11.12.15", rangeFeeder.next().getAddress().getHostAddress());
assertFalse(rangeFeeder.hasNext());
}
@ -59,12 +59,12 @@ public class RangeFeederTest {
rangeFeeder = new RangeFeeder("0.0.0.0", "0.0.0.0");
assertTrue(rangeFeeder.hasNext());
assertEquals("0.0.0.0", rangeFeeder.next().getHostAddress());
assertEquals("0.0.0.0", rangeFeeder.next().getAddress().getHostAddress());
assertFalse(rangeFeeder.hasNext());
rangeFeeder = new RangeFeeder("255.255.255.255", "255.255.255.255");
assertTrue(rangeFeeder.hasNext());
assertEquals("255.255.255.255", rangeFeeder.next().getHostAddress());
assertEquals("255.255.255.255", rangeFeeder.next().getAddress().getHostAddress());
assertFalse(rangeFeeder.hasNext());
}

View File

@ -41,15 +41,15 @@ public class RescanFeederTest {
assertTrue(feeder.hasNext());
assertEquals(0, feeder.percentageComplete());
assertEquals("127.0.0.15", feeder.next().getHostAddress());
assertEquals("127.0.0.15", feeder.next().getAddress().getHostAddress());
assertTrue(feeder.hasNext());
assertEquals(33, feeder.percentageComplete());
assertEquals("127.0.1.35", feeder.next().getHostAddress());
assertEquals("127.0.1.35", feeder.next().getAddress().getHostAddress());
assertTrue(feeder.hasNext());
assertEquals(66, feeder.percentageComplete());
assertEquals("127.0.2.2", feeder.next().getHostAddress());
assertEquals("127.0.2.2", feeder.next().getAddress().getHostAddress());
assertFalse(feeder.hasNext());
assertEquals(100, feeder.percentageComplete());