diff --git a/network/pom.xml b/network/pom.xml
index 24fa27e..d080923 100644
--- a/network/pom.xml
+++ b/network/pom.xml
@@ -74,5 +74,12 @@
jar
compile
+
+
+ commons-net
+ commons-net
+ compile
+ 3.2
+
diff --git a/network/src/main/java/de/muehlencord/shared/network/CidrTool.java b/network/src/main/java/de/muehlencord/shared/network/CidrTool.java
new file mode 100644
index 0000000..f36c63b
--- /dev/null
+++ b/network/src/main/java/de/muehlencord/shared/network/CidrTool.java
@@ -0,0 +1,77 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package de.muehlencord.shared.network;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author jomu
+ */
+public class CidrTool {
+
+ public static List rangeToCidrList(String startIp, String endIp) {
+ long start = ipToLong(startIp);
+ long end = ipToLong(endIp);
+
+ ArrayList pairs = new ArrayList<>();
+ while (end >= start) {
+ byte maxsize = 32;
+ while (maxsize > 0) {
+ long mask = CIDR2MASK[ maxsize - 1];
+ long maskedBase = start & mask;
+
+ if (maskedBase != start) {
+ break;
+ }
+
+ maxsize--;
+ }
+ double x = Math.log(end - start + 1) / Math.log(2);
+ byte maxdiff = (byte) (32 - Math.floor(x));
+ if (maxsize < maxdiff) {
+ maxsize = maxdiff;
+ }
+ String ip = longToIP(start);
+ pairs.add(ip + "/" + maxsize);
+ start += Math.pow(2, (32 - maxsize));
+ }
+ return pairs;
+ }
+
+
+ public static final int[] CIDR2MASK = new int[]{0x00000000, 0x80000000,
+ 0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
+ 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
+ 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
+ 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,
+ 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
+ 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
+ 0xFFFFFFFF};
+
+ private static long ipToLong(String strIP) {
+ long[] ip = new long[4];
+ String[] ipSec = strIP.split("\\.");
+ for (int k = 0; k < 4; k++) {
+ ip[k] = Long.valueOf(ipSec[k]);
+ }
+
+ return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
+ }
+
+ private static String longToIP(long longIP) {
+ StringBuilder sb = new StringBuilder("");
+ sb.append(String.valueOf(longIP >>> 24));
+ sb.append(".");
+ sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16));
+ sb.append(".");
+ sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8));
+ sb.append(".");
+ sb.append(String.valueOf(longIP & 0x000000FF));
+
+ return sb.toString();
+ }
+}
diff --git a/network/src/main/java/de/muehlencord/shared/network/NetworkInformation.java b/network/src/main/java/de/muehlencord/shared/network/NetworkInformation.java
new file mode 100644
index 0000000..f3a78d1
--- /dev/null
+++ b/network/src/main/java/de/muehlencord/shared/network/NetworkInformation.java
@@ -0,0 +1,109 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package de.muehlencord.shared.network;
+
+/**
+ *
+ * @author jomu
+ */
+public class NetworkInformation {
+
+ // private String network;
+ private String netname;
+ private String description;
+ private String country;
+ private String adminC;
+ private String techC;
+ private String maintainedBy;
+ private String status;
+
+ NetworkInformation(String netname, String descr, String country) {
+ this.netname = netname;
+ this.description = descr;
+ this.country = country;
+ this.adminC = null;
+ this.techC = null;
+ this.status = null;
+ this.maintainedBy = null;
+ }
+
+ /* *** getter / setter *** */
+ /**
+ * @return the netname
+ */
+ public String getNetname() {
+ return netname;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return the country
+ */
+ public String getCountry() {
+ return country;
+ }
+
+ /**
+ * @return the adminC
+ */
+ public String getAdminC() {
+ return adminC;
+ }
+
+ /**
+ * @param adminC the adminC to set
+ */
+ public void setAdminC(String adminC) {
+ this.adminC = adminC;
+ }
+
+ /**
+ * @return the techC
+ */
+ public String getTechC() {
+ return techC;
+ }
+
+ /**
+ * @param techC the techC to set
+ */
+ public void setTechC(String techC) {
+ this.techC = techC;
+ }
+
+ /**
+ * @return the maintainedBy
+ */
+ public String getMaintainedBy() {
+ return maintainedBy;
+ }
+
+ /**
+ * @param maintainedBy the maintainedBy to set
+ */
+ public void setMaintainedBy(String maintainedBy) {
+ this.maintainedBy = maintainedBy;
+ }
+
+ /**
+ * @return the status
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * @param status the status to set
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+}
diff --git a/network/src/main/java/de/muehlencord/shared/network/Whois.java b/network/src/main/java/de/muehlencord/shared/network/Whois.java
new file mode 100644
index 0000000..b4949ad
--- /dev/null
+++ b/network/src/main/java/de/muehlencord/shared/network/Whois.java
@@ -0,0 +1,132 @@
+package de.muehlencord.shared.network;
+
+import de.muehlencord.shared.util.StringUtil;
+import java.io.IOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.text.ParseException;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.commons.net.whois.WhoisClient;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author jomu
+ */
+public class Whois {
+
+ /** logger object */
+ private final static Logger logger = Logger.getLogger(Whois.class);
+ /** whois client from commons-net package to execute commands with */
+ WhoisClient whois;
+ /** the complete output */
+ String whoIsString = null;
+ /** network list in CIDR form the host belongs to */
+ private List network;
+ /** network list in CIDDR form network belongs to */
+ private List rootNetwork;
+ /** network information of host */
+ private NetworkInformation networkInformation;
+
+ public Whois() {
+ whois = new WhoisClient();
+ whois.setDefaultTimeout(60000);
+
+ }
+
+ public void execute(String whoIsServer, String ip) throws UnknownHostException, SocketException, IOException, ParseException {
+ whois.connect(whoIsServer);
+ whoIsString = whois.query(ip);
+ // split by blank lines to identify blocks
+ String[] blocks = whoIsString.split("\n\n");
+ for (String block : blocks) {
+ analyseBlock(block);
+ }
+ whois.disconnect();
+ }
+
+ // TODO introduce parer per RIR
+ private void analyseBlock(String block) throws ParseException {
+ logger.debug("Start analysing block");
+ logger.debug("\n---\n" + block + "\n---\n");
+
+ if ((block == null) || (block.equals("")) || (!block.contains(" "))) {
+ logger.debug("Skippig empty block");
+ return;
+ }
+
+ String startString = block.substring(0, block.indexOf(" "));
+ if (startString.equals("%")) {
+ startString = block.substring(0, block.indexOf(" ", 2));
+ }
+
+ switch (startString) {
+
+ case "inetnum:":
+ // information on network server belongs to (upper level / level -1)
+ String inetnum = StringUtil.getValueBetweenKeywords(block, "inetnum:", "netname:");
+ logger.info("inetnum: = " + inetnum);
+ String netname = StringUtil.getValueBetweenKeywords(block, "netname:", "descr:");
+ logger.info("netname: = " + netname);
+ String descr = StringUtil.getValueBetweenKeywords(block, "descr:", "country:");
+ logger.info("descr: = " + descr);
+ String country = StringUtil.getValueBetweenKeywords(block, "country:", "admin-c:");
+ logger.info("country: = " + country);
+ String adminC = StringUtil.getValueBetweenKeywords(block, "admin-c:", "tech-c:");
+ logger.info("admin-c: = " + adminC);
+ String techC = StringUtil.getValueBetweenKeywords(block, "tech-c:", "status:");
+ logger.info("tech-c: = " + techC);
+ String status = StringUtil.getValueBetweenKeywords(block, "status:", "mnt-by:");
+ logger.info("status: = " + status);
+ String mntBy = StringUtil.getValueBetweenKeywords(block, "mnt-by:", "source:");
+ logger.info("mnt-by: = " + mntBy);
+
+ // convert inetnum to CDIR
+ String[] ipAddresses = inetnum.split(" "); // TODO - what happens if not 3 parts are found
+ // FIXME add CDIR notation support
+ String startIpAddress = ipAddresses[0];
+ String endIPAddress = ipAddresses[2];
+ network = CidrTool.rangeToCidrList(startIpAddress, endIPAddress);
+ logger.info("Network:" + network.toString());
+
+ this.networkInformation = new NetworkInformation(netname, descr, country);
+
+ break;
+ case "route:":
+ // get information on level-2 network
+ String route = StringUtil.getValueBetweenKeywords(block, "route:", "descr:");
+ this.rootNetwork = new LinkedList<>();
+ this.rootNetwork.add(route);
+ logger.info ("Root network "+this.rootNetwork.toString());
+ break;
+
+
+
+ case "role:":
+ // admin company of network server belongs to
+ logger.info("Skipping role block");
+ break;
+ case "person:":
+ // admin person of network server belongs to
+ logger.info("Skipping person block");
+ break;
+ case "% Information":
+ case "% Note:":
+ case "% This":
+ case "%":
+ logger.info("Skipping comment block");
+ break;
+ default:
+ logger.info("Unknown block found");
+ }
+ }
+
+ public List getNetwork() {
+ return this.network;
+ }
+
+ public List getRootNetwork() {
+ return this.rootNetwork;
+ }
+}
diff --git a/network/src/test/java/de/muehlencord/shared/network/RangeToCidrTest.java b/network/src/test/java/de/muehlencord/shared/network/RangeToCidrTest.java
new file mode 100644
index 0000000..4cacab2
--- /dev/null
+++ b/network/src/test/java/de/muehlencord/shared/network/RangeToCidrTest.java
@@ -0,0 +1,16 @@
+package de.muehlencord.shared.network;
+
+import org.junit.Test;
+
+/**
+ *
+ * @author jomu
+ */
+public class RangeToCidrTest extends BaseTest {
+
+
+ @Test
+ public void testRangeToCidr() {
+ System.out.println (CidrTool.rangeToCidrList("212.204.60.0", "212.204.60.255"));
+ }
+}
\ No newline at end of file
diff --git a/network/src/test/java/de/muehlencord/shared/network/WhoisTest.java b/network/src/test/java/de/muehlencord/shared/network/WhoisTest.java
new file mode 100644
index 0000000..008640b
--- /dev/null
+++ b/network/src/test/java/de/muehlencord/shared/network/WhoisTest.java
@@ -0,0 +1,48 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package de.muehlencord.shared.network;
+
+import java.io.IOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.text.ParseException;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jomu
+ */
+public class WhoisTest extends BaseTest {
+
+
+ @Test
+ @Ignore
+ public void testDenicWhoIs() throws UnknownHostException, SocketException, IOException, ParseException {
+ Whois whoIsClient = new Whois();
+ // Denic answers "status: connect" only
+ whoIsClient.execute ("whois.denic.de", "-T dn,ace muehlencord.de");
+ }
+
+ @Test
+ @Ignore
+ public void testInternic() throws UnknownHostException, SocketException, IOException, ParseException {
+ Whois whoIsClient = new Whois();
+ // Denic answers "status: connect" only
+ whoIsClient.execute ("whois.1api.net", "egameladder.com");
+ }
+
+ @Test
+ public void testStepWise() throws UnknownHostException, SocketException, IOException, ParseException {
+ Whois whoIsClient = new Whois();
+ // whoIsClient.execute ("whois.ripe.net", "88.198.181.181");
+ whoIsClient.execute ("whois.ripe.net", "212.204.60.1");
+ assertTrue ("network", whoIsClient.getNetwork().contains("212.204.60.0/24"));
+ // whoIsClient.execute ("whois.ripe.net", "212.204.60.0");
+ // whoIsClient.execute ("whois.ripe.net", "212.0.0.0/8");
+
+ }
+}
\ No newline at end of file
diff --git a/network/src/test/resources/logging.properties b/network/src/test/resources/logging.properties
index cc1b852..1429cd2 100644
--- a/network/src/test/resources/logging.properties
+++ b/network/src/test/resources/logging.properties
@@ -5,4 +5,4 @@ log4j.debug=false
log4j.appender.ConsoleLogger=org.apache.log4j.ConsoleAppender
log4j.appender.ConsoleLogger.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleLogger.layout.ConversionPattern= %d - %m (%c)%n
-log4j.appender.ConsoleLogger.threshold=INFO
\ No newline at end of file
+log4j.appender.ConsoleLogger.threshold=DEBUG
\ No newline at end of file