Currently I've got a working port scanner but I want to limit it to only scanning IP address on the local subnet.
The only solution i've found when digging is this:
Does anyone know a java component to check if IP address is from particular network/netmask? however I dont full understand
What is the difference between a subnet and a netmask? I thought they were the same thing?
Secondly, how can i find the values for subnet and netmask for localHost?
So far this is what I have
NetworkInterface network = NetworkInterface.getByInetAddress(localHost);
short subnetMask =
network.getInterfaceAddresses().get(1).getNetworkPrefixLength();
But is this the netmask or the subnet? And how do I get the other value?
The subnetMask you determined is the number of bits in the network. The network address is found by setting all bits in the address that are after the bits in the mask to zero. This code should print the mask and network address in the usual form.
NetworkInterface network = NetworkInterface.getByInetAddress(localhost);
short subnetMask
= network.getInterfaceAddresses().get(1).getNetworkPrefixLength();
int address_int = ByteBuffer.wrap(localhost.getAddress()).getInt();
int mask_int = 0;
for(int i = 0; i < subnetMask-1; i++) {
mask_int = mask_int | (1<<31);
mask_int = mask_int >> 1;
}
byte mask_bytes[] = ByteBuffer.allocate(4).putInt(mask_int).array();
InetAddress mask_address = InetAddress.getByAddress(mask_bytes);
System.out.println("mask_address = " + mask_address);
int network_int = mask_int & address_int;
byte network_bytes[] = ByteBuffer.allocate(4).putInt(network_int).array();
InetAddress network_address = InetAddress.getByAddress(network_bytes);
System.out.println("network_address = " + network_address);
You can test if any address is on this network by using the bitwise and of the address in integer form with the network_mask integer. If it is on the network this should produce the address_int.
Related
I use the following code
InetAddress localhost = InetAddress.getLocalHost();
// this code assumes IPv4 is used
byte[] ip = localhost.getAddress();
for (int i = 1; i <= 254; i++)
{
ip[3] = (byte)i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(1000))
{
System.out.println(address + " machine is turned on and can be pinged");
}
else if (!address.getHostAddress().equals(address.getHostName()))
{
System.out.println(address + " machine is known in a DNS lookup");
}
else
{
System.out.println(address + " the host address and host name " +
"are equal, meaning the host name could not be resolved");
}
}
To try and find all online devices on my wifi network.
However, two problems arise.
All 253 tested IPs come back positive
My computer is the only one that has a device name, and the ip is off.
Any help solving this dilemma?
I tried a similar code with oracle jdk 1.8.0_51 and works fine; but when i test it on oracle jre 1.8.0_91 all the ip's of the network segment come back positive.
Maybe is a Bug with InetAddress.isReachable(1000) on the current jre version, a similar bug was reported on openjdk https://bugs.openjdk.java.net/browse/JDK-8145011
In my Tomcat-hosted web app, the first two lines in a doGet(...) method are:
String ip = request.getRemoteAddr();
System.out.println("ip = " + ip);
With an IPv6 address on our local network, it outputs:
ip = fe80:0:0:0:ac40:98cb:ca2e:c03c%4
The %4 at the end seems extraneous. It is causing requests to our geolocation service to fail. Is this %4 supposed to be there? If so, what does it signify? Is there a reliable way to get a IPv6 address from an HttpServletRequest instance that does NOT have the %4?
It's the scope ID. Using native APIs, your best bet to get rid of it would be as below with help of java.net.InetAddress and Inet6Address#getScopeId():
String ip = request.getRemoteAddr();
InetAddress inetAddress = InetAddress.getByName(ip);
if (inetAddress instanceof Inet6Address) {
Inet6Address inet6Address = (Inet6Address) inetAddress;
int scopeId = inet6Address.getScopeId();
if (scopeId > 0) {
ip = inet6Address.getHostName().replaceAll("%" + scopeId + "$", "");
}
}
This clumsiness is because the standard java.net.Inet6Address API doesn't have any method which returns the bare hostname without scope ID.
On the other hand, I'd wonder if the geolocation service in question should in turn not already be taking that into account. If the support for IPv6 scopes is even not explicitly excluded in their API documentation, then I'd file an issue at their issue tracker.
In trying to avoid having a hostname looked up from the public DNS for testing purposes, I need to essentially set /etc/hosts file, but I don't always know what hostnames I'll need to override the IP address for, so I'm trying to use dnsjava since the default Java DNS resolving doesn't allow for inserting directly into the cache.
Basically, you need to grab the correct DNS Type cache for dnsjava (A, AAAA, etc). Most likely A (for IPv4) or AAAA (for IPv6) is what you should use, although all of the other DNS entry types are also supported. You'll need to create a Name instance, and from that an ARecord which will be inserted into the Cache. Example is as below:
public void addHostToCacheAs(String hostname, String ipAddress) throws UnknownHostException, TextParseException {
//add an ending period assuming the hostname is truly an absolute hostname
Name host = new Name(hostname + ".");
//putting in a good long TTL, and using an A record, but AAAA might be desired as well for IPv6
Record aRec = new ARecord(host, Type.A, 9999999, getInetAddressFromString(ipAddress));
Lookup.getDefaultCache(Type.A).addRecord(aRec, Credibility.NORMAL,this);
}
public InetAddress getInetAddressFromString(String ip) throws UnknownHostException {
//Assume we are using IPv4
byte[] bytes = new byte[4];
String[] ipParts = ip.split("\\.");
InetAddress addr = null;
//if we only have one part, it must actually be a hostname, rather than a real IP
if (ipParts.length <= 1) {
addr = InetAddress.getByName(ip);
} else {
for (int i = 0; i < ipParts.length; i++) {
bytes[i] = Byte.parseByte(ipParts[i]);
}
addr = InetAddress.getByAddress(bytes);
}
return addr
}
I'm writing an Android video game that supports multiplayer. There is a dedicated server running which the androids connect to when the multiplayer button is clicked by opening a socket(this works fine). The server basically just acts as a matchmaking system.
When a client hosts a game, the server adds that client to the list of hosts. Other clients may choose to view this list and then subsequently connect to that host. This is where the problem is. The server is supposed to keep track of the ip/port of hosts, and then other clients are supposed to use this information to open a socket with the host and then the game starts. I'm trying to get the host to send its own IP address to server for other clients to use later.
I have tried many methods so far. One is:
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
}
This returns 10.0.2.15, which is obviously useless for other clients.
The other method I've tried is this:
String hostName = InetAddress.getLocalHost().getHostName();
InetAddress addrs[] = InetAddress.getAllByName(hostName);
for (InetAddress addr: addrs) {
System.out.println ("addr.getHostAddress() = " + addr.getHostAddress());
System.out.println ("addr.getHostName() = " + addr.getHostName());
System.out.println ("addr.isAnyLocalAddress() = " + addr.isAnyLocalAddress());
System.out.println ("addr.isLinkLocalAddress() = " + addr.isLinkLocalAddress());
System.out.println ("addr.isLoopbackAddress() = " + addr.isLoopbackAddress());
System.out.println ("addr.isMulticastAddress() = " + addr.isMulticastAddress());
System.out.println ("addr.isSiteLocalAddress() = " + addr.isSiteLocalAddress());
System.out.println ("");
if (!addr.isLoopbackAddress()){// && addr.isSiteLocalAddress()) {
myIP = addr.getHostAddress();
}
This returns the ip address that I'm looking for when I run it as a java application, but when I run it as an android application, it doesn't work. The last if condition is somehow not satisfied and myIP ends up being null. Note that I have included the permissions: android.permission.INTERNET, android.permission.ACCESS_WIFI_STATE, android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_NETWORK_STATE.
Can anybody help me?
If you just need the IP for the Wifi connection you can retrieve the IP as a 32 bit integer:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
Then, in order to construct the IP in dot-decimal notation; bit-shift and mask the result:
String ipString = String.format(
"%d.%d.%d.%d",
(ip & 0xff),
(ip >> 8 & 0xff),
(ip >> 16 & 0xff),
(ip >> 24 & 0xff));
android.permission.ACCESS_WIFI_STATE permission will be required in the manifest.
Do you have to rely on the host to figure out its own IP address and provide this to the server? If the host opens a connection and sends a message to the server announcing that it is hosting a game, then could the server use the IP address that the connection and message came from? This would avoid the problem altogether.
try this
WifiManager wim= (WifiManager) getSystemService(WIFI_SERVICE) ;
List<WifiConfiguration> l= wim.getConfiguredNetworks();
WifiConfiguration wc=l.get(0);
textview.append( "\n"+ Formatter.formatIpAddress(wim.getConnectionInfo().getIpAddress()));
How do you get the Subnet mask address of the local system using Java?
the netmask of the first address of the localhost interface:
InetAddress localHost = Inet4Address.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength();
a more complete approach:
InetAddress localHost = Inet4Address.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
for (InterfaceAddress address : networkInterface.getInterfaceAddresses()) {
System.out.println(address.getNetworkPrefixLength());
}
/24 means 255.255.255.
You can convert the obtained value into the standard textual format like this:
short prflen=...getNetworkPrefixLength();
int shft = 0xffffffff<<(32-prflen);
int oct1 = ((byte) ((shft&0xff000000)>>24)) & 0xff;
int oct2 = ((byte) ((shft&0x00ff0000)>>16)) & 0xff;
int oct3 = ((byte) ((shft&0x0000ff00)>>8)) & 0xff;
int oct4 = ((byte) (shft&0x000000ff)) & 0xff;
String submask = oct1+"."+oct2+"."+oct3+"."+oct4;
java.net.InterfaceAddress in SE6 has a getNetworkPrefixLength method that returns, as the name suggests, the network prefix length. You can calculate the subnet mask from this if you would rather have it in that format. java.net.InterfaceAddress supports both IPv4 and IPv6.
getSubnetMask() in several network application APIs returns subnet mask in java.net.InetAddress form for specified IP address (a local system may have many local IP addresses)
I found that:
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
To get subnetmask for ipv6 we can use:
networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength();
To get subnetmask for ipv4 we can use:
networkInterface.getInterfaceAddresses().get(1).getNetworkPrefixLength();
I devised an IPv4 only solution that is simple enough. I needed that to generate netmask for subnetworks here in order to delegate those subnets correctly. I know I could have generated a table of the 32 possible masks, but I prefered to get it computed each time.
So here is my solution.
/*
* Get network mask for the IP address and network prefix specified...
* The network mask will be returned has an IP, thus you can
* print it out with .getHostAddress()...
*/
public static InetAddress getIPv4LocalNetMask(InetAddress ip, int netPrefix) {
try {
// Since this is for IPv4, it's 32 bits, so set the sign value of
// the int to "negative"...
int shiftby = (1<<31);
// For the number of bits of the prefix -1 (we already set the sign bit)
for (int i=netPrefix-1; i>0; i--) {
// Shift the sign right... Java makes the sign bit sticky on a shift...
// So no need to "set it back up"...
shiftby = (shiftby >> 1);
}
// Transform the resulting value in xxx.xxx.xxx.xxx format, like if
/// it was a standard address...
String maskString = Integer.toString((shiftby >> 24) & 255) + "." + Integer.toString((shiftby >> 16) & 255) + "." + Integer.toString((shiftby >> 8) & 255) + "." + Integer.toString(shiftby & 255);
// Return the address thus created...
return InetAddress.getByName(maskString);
}
catch(Exception e){e.printStackTrace();
}
// Something went wrong here...
return null;
}
You just call it with the IP and the prefix you want to use, it will generate the netmask for you.
I just finished working on an API for subnetting networks with Java.
https://launchpad.net/subnettingapi
it has that functionality and more.
Here is an answer, how to get a submask from WIFI connection: link
I adapted it for my needs, and here it is:
private static String intToIP(int ipAddress) {
String ret = String.format("%d.%d.%d.%d", (ipAddress & 0xff),
(ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
(ipAddress >> 24 & 0xff));
return ret;
}
public static String GetSubnetMask_WIFI() {
WifiManager wifiManager = (WifiManager) Global.getMainActivity()
.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
DhcpInfo dhcp = wifiManager.getDhcpInfo();
String mask = intToIP(dhcp.netmask);
return mask;
}
In summary, a method to obtain the mask would be like this:
public String mascara() throws SocketException{
try{
InetAddress localHost = Inet4Address.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
prefijo =
""+networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength();
int shft = 0xffffffff<<(32-
networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength());
int oct1 = ((byte) ((shft&0xff000000)>>24)) & 0xff;
int oct2 = ((byte) ((shft&0x00ff0000)>>16)) & 0xff;
int oct3 = ((byte) ((shft&0x0000ff00)>>8)) & 0xff;
int oct4 = ((byte) (shft&0x000000ff)) & 0xff;
mascara = oct1+"."+oct2+"."+oct3+"."+oct4;
// System.out.println(""+mascara);
}catch(UnknownHostException e){
System.out.println("Error: "+e);
}
return mascara;
}
FWIW, in the past I'd tried using InterfaceAddress.getNetworkPrefixLength() and InterfaceAddress.getBroadcast(), but they don't return accurate info (this is on Windows, with Sun JDK 1.6.0 update 10). The network prefix length is 128 (not 24, which it is on my network), and the broadcast address returned is 255.255.255.255 (not 192.168.1.255, which it is on my network).
James
Update: I just found the solution posted here:
http://forums.sun.com/thread.jspa?threadID=5277744
You need to prevent Java from using IPv6, so that it isn't getting to IPv4 via IPv6.
Adding -Djava.net.preferIPv4Stack=true to the command line fixes the results from InterfaceAddress.getNetworkPrefixLength() and InterfaceAddress.getBroadcast() for me.