GetHostEntry() doesn't resolve the address anymore - c#

I recently switched from .NET v3.5 to v4.0 Client Profile and at first run GetHostEntry() got problem.
tcpClient.SocketInfo.SourceName = remoteMatcher.Host; // "88.255.126.48"
tcpClient.SocketInfo.SourcePort = remoteMatcher.Port; // 999
IPHostEntry ipEntry = Dns.GetHostEntry(tcpClient.SocketInfo.SourceName);
GetHostEntry() causes an exception:
WSANO_DATA
11004
Valid name, no data record of requested type.
The requested name is valid and was found in the database, but it does not have the correct associated data being resolved for. The usual example for this is a host name-to-address translation attempt (using gethostbyname or WSAAsyncGetHostByName) which uses the DNS (Domain Name Server). An MX record is returned but no A record—indicating the host itself exists, but is not directly reachable.
I'm gonna reboot the machine and wanted to ask this question before all things lost on my mind.
UPDATE:
My workaround:
// .NET Framework v4.0 bug??
IPAddress ip;
if (IPAddress.TryParse(tcpClient.SocketInfo.SourceName, out ip))
tcpClient.SocketInfo.SourceIP = tcpClient.SocketInfo.SourceName;
else
{
IPHostEntry ipEntry = Dns.GetHostEntry(tcpClient.SocketInfo.SourceName);
IPAddress[] addr = ipEntry.AddressList;
tcpClient.SocketInfo.SourceIP = addr[addr.Length - 1].ToString();
}

here is something that I have tried, I recall running into the same problem
feel free to use my example to test your stuff
** I used IPHostEntry instead **
string[] host = (address.Split('#'));
string hostname = host[1];
IPHostEntry IPhst = Dns.Resolve(hostname);
IPEndPoint endPt = new IPEndPoint(IPhst.AddressList[0], 25);
Socket s= new Socket(endPt.AddressFamily,
SocketType.Stream,ProtocolType.Tcp);
s.Connect(endPt);
or
when I used it to get hostname of email address
try
{
Response.Write("One");
string[] host = (txtEmailAddress.Text.Split('#'));
string hostname = host[1];
Response.Write(host);
IPHostEntry IPhst = Dns.Resolve(hostname);
IPEndPoint endPt = new IPEndPoint(IPhst.AddressList[0], 25);
Socket s = new Socket(endPt.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
Response.Write(endPt);
s.Connect(endPt);
}
catch (SocketException se)
{
lblErrMsg.Text = se.Message.ToString();
PublicUtils.AddError("Error: " + se.Message + txtEmailAddress.Text);
txtEmailAddress.Focus();
return;
}

Encountered the same problem recently, GetHostEntry does a reverse lookup on host name when given an IP Address, in my particular scenario, NetBIOS on the target machine was turned off, that's why hostname resolution was failing, and GetHostEntry was throwing the above exception mentioned.
GetHostAddresses was more suitable for my needs, it does not do a reverse lookup when given an IP address, it just parses it and returns IPAddress itself.
From MSDN: http://msdn.microsoft.com/en-us/library/system.net.dns.gethostaddresses.aspx
GetHostEntry method exhibits the following behavior when an IP string literal is passed:
The method tries to parse the address. If the hostNameOrAddress
contains a legal IP string literal, then the first phase succeeds.
A reverse lookup using the IP address of the IP string literal is
attempted to obtain the host name. This result is set as the
HostName property.
The host name from this reverse lookup is used
again to obtain all the possible IP addresses associated with the
name and set as the AddressList property.

Related

Why am I getting an ArgumentNullException notification and how do I solve it?

I'm trying to complete a project for school that involves me prompting a user for an IP address, then displaying the hostname associated with it. I'm new at C#.
This is my code that I have so far:
Console.WriteLine("Enter an IP address:"); //prompt user to input IP address
string host = Console.ReadLine();
IPHostEntry hostEntry;
hostEntry = NewMethod(host);
if (hostEntry.AddressList.Length > 0)
{
var ip = hostEntry.AddressList[0];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
s.Connect(ip, 80);
}
}
private static IPHostEntry NewMethod(string host)
{
return Dns.GetHostEntry(host); // NEED FIX
}
}
The part that has "Need fix" is where the error is showing up. Thanks in advance!
EDIT: How would I be able to display the results in this format: "Host name of x.x.x.x is: hhhhhh", where 'x.x.x.x' is the IP address user entered and 'hhhhh' is the host name of the IP?
EDIT(for StackOverflow): My question is more specific for this instance and is not a general question regarding the NullException issue.
host is never set, so you're passing null to Dns.GetHostEntry which generates the exception.
At the start of your program it looks like you need to read the IP address from the user:
Console.WriteLine("Enter an IP address:"); //prompt user to input IP address
string host = Console.ReadLine();

Get IP address from hostname in LAN

I found many samples on how to get a hostname by an IP address, how can I get the IP address of a host in the LAN?
Try this
public static void DoGetHostAddresses(string hostname)
{
IPAddress[] ips;
ips = Dns.GetHostAddresses(hostname);
Console.WriteLine("GetHostAddresses({0}) returns:", hostname);
foreach (IPAddress ip in ips)
{
Console.WriteLine(" {0}", ip);
}
}
i got this from http://msdn.microsoft.com/en-us/library/system.net.dns.gethostaddresses.aspx
Here is simple code if you want to get the IP Address(V4) from your pc.
Import this library into your class
using System.Net;
Initialize and declare these variables into your codes. They contain hostname, ipaddress and an array of Host Addresses:
string HostName = Dns.GetHostName().ToString();
IPAddress[] IpInHostAddress = Dns.GetHostAddresses(HostName);
string IPV4Address = IpInHostAddress[1].ToString(); //Default IPV4Address. This might be the ip address you need to retrieve
string IPV6Address = IpInHostAddress[0].ToString(); //Default Link local IPv6 Address
Open your command prompt, just type "ipconfig" and press enter.Once you are done, you could check if the string IPV4Address matches to IPv4Address in our pc.
As long as you know the name of a machine, you can use Dns.GetHostAddresses. Your network DNS should recognize it as LAN computer and return proper IP.
Use Dns.GetHostEntry(hostname) instead of obsolete Dns.GetHostAddresses.
Here is an excellent example of how it is doing: http://www.codeproject.com/Articles/854/How-To-Get-IP-Address-Of-A-Machine
you could use the windows management classes to do this, it also works for remote machines that are in the same domain (but I don't know if they need to enable or disable any security or policy settings for this to work). for example:
public List<NetworkAdapter> GetAdapterList()
{
ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapterConfiguration ");
ManagementObjectCollection moc = mgmt.GetInstances();
List<NetworkAdapter> adapters = new List<NetworkAdapter>();
// Search for adapters with IP addresses
foreach(ManagementObject mob in moc)
{
string[] addresses = (string[])mob.Properties["IPAddress"].Value;
if (null == addresses)
{
continue;
}
NetworkAdapter na = new NetworkAdapter();
na.Description = (string) mob.Properties["Description"].Value;
na.MacAddress = (string) mob.Properties["MACAddress"].Value;
na.IPAddresses = addresses;
adapters.Add(na);
}
return adapters;
}
and to access a remote machine create the management class like this instead:
ManagementClass mgmt = new ManagementClass
(\\\\servername\\root\\cimv2:Win32_NetworkAdapterConfiguration);
this approach may get you more IPs than just the ones that have been registered in the DNS.

.Net IPAddress IPv4

I have the following code:
Dim ipAdd As IPAddress = Dns.GetHostEntry(strHostname).AddressList(0)
Dim strIP As String = ipAdd.ToString()
When I convert to String instead of an IPv4 address like 192.168.1.0 or similar I get the IPv6 version: fd80::5dbe:5d89:e51b:d313 address.
Is there a way I can return the IPv4 address from IPAddress type?
Thanks
Instead of unconditionally taking the first element of the AddressList, you could take the first IPv4 address:
var address = Dns.GetHostEntry(strHostname)
.AddressList
.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
dtb's solution will work in many situations. In many cases, however, users may have multiple v4 IPs setup on their system. Sometimes this is because they have some 'virtual' adapters (from applications like VirtualBox or VMWare) or because they have more than one physical network adapter connected to their computer.
It goes without saying that in these situations it's important that the correct IP is used. You may want to consider asking the user which IP is appropriate.
To get a list of usable v4 IPs you can use code similar to:
'Get an array which contains all available IPs:
Dim IPList() As IPAddress = Net.Dns.GetHostEntry(Net.Dns.GetHostName.ToString).AddressList
'Copy valid IPs from IPList to FinalIPList
Dim FinalIPList As New ArrayList(IPList.Length)
For Each IP As IPAddress In IPList
'We want to keep IPs only if they are IPv4 and not a 'LoopBack' device
'(an InterNetwork AddressFamily indicates a v4 IP)
If ((Not IPAddress.IsLoopback(IP)) And (IP.AddressFamily = AddressFamily.InterNetwork)) Then
FinalIPList.Add(IP)
End If
Next IP
For me the solution with the "First" predicate did not work properly, this is the code that works for me:
public static string GetLocalIP()
{
string ipv4Address = String.Empty;
foreach (IPAddress currrentIPAddress in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (currrentIPAddress.AddressFamily.ToString() == System.Net.Sockets.AddressFamily.InterNetwork.ToString())
{
ipv4Address = currrentIPAddress.ToString();
break;
}
}
return ipv4Address;
}

Problem Converting ipv6 to ipv4

I have some code in an asp.net app that needsto get the ipv4 address of the client computer (the users are all on our own network). Recently we upgraded the server the app runs on to windows 2008 server. Now the Request.UserHostAddress code returns the ipv4 when the client is on an older OS and ipv6 when they are on a newer OS (Vista and higher). So the feature that relys on this works for some clients and not others.
I added code that is supposed to convert from ipv6 to ipv4 to try to fix this problem. It's from this online tutorial: https://web.archive.org/web/20211020102847/https://www.4guysfromrolla.com/articles/071807-1.aspx .I'm using dsn.GetHostAddress and then looping through the IPs returned looking for one that is "InterNetwork"
foreach (IPAddress IPA in Dns.GetHostAddresses(HttpContext.Current.Request.UserHostAddress))
{
if (IPA.AddressFamily.ToString() == "InterNetwork")
{
IP4Address = IPA.ToString();
break;
}
}
if (IP4Address != String.Empty)
{
return IP4Address;
}
foreach (IPAddress IPA in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (IPA.AddressFamily.ToString() == "InterNetwork")
{
IP4Address = IPA.ToString();
break;
}
}
return IP4Address;
The problem is that this isn't working for me. The clients connecting from ipv4 continue to return the correct ipv4 IP of the client computer, but the clients connecting from Vista and Windows 7 it is returning the ipv4 IP of the SERVER machine not the client computer.
Simple answer: Disable IPV6 on the server, or remove the IPV6 address of the server from the DNS entry.
There is not a magic IPV4<->IPV6 converter. They're completely different protocols, and addresses in one don't translate to the other. If you want to reliably retrieve the IPV4 address of the client, you need to make sure that the client connects over IPV4.
I also had copied the example code and a colleague pointed out that it was obviously buggy.
This line uses the host name of the server, hence the incorrect result:
foreach (IPAddress IPA in Dns.GetHostAddresses(Dns.GetHostName()))
I have corrected the code in my project as follows:
/// <summary>
/// Returns the IPv4 address of the specified host name or IP address.
/// </summary>
/// <param name="sHostNameOrAddress">The host name or IP address to resolve.</param>
/// <returns>The first IPv4 address associated with the specified host name, or null.</returns>
public static string GetIPv4Address(string sHostNameOrAddress)
{
try
{
// Get the list of IP addresses for the specified host
IPAddress[] aIPHostAddresses = Dns.GetHostAddresses(sHostNameOrAddress);
// First try to find a real IPV4 address in the list
foreach (IPAddress ipHost in aIPHostAddresses)
if (ipHost.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
return ipHost.ToString();
// If that didn't work, try to lookup the IPV4 addresses for IPV6 addresses in the list
foreach (IPAddress ipHost in aIPHostAddresses)
if (ipHost.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
IPHostEntry ihe = Dns.GetHostEntry(ipHost);
foreach (IPAddress ipEntry in ihe.AddressList)
if (ipEntry.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
return ipEntry.ToString();
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex);
}
return null;
}
The code above works in ASP.Net 2.0 on Windows 7/Server 2008.
Hope this helps.
if you are using .Net 4.5 Framework then there is a method provide to convert IP6 to IP4
public IPAddress MapToIPv4()
You can find the details here

Getting the ip-address

In C#:
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
for (int i = 0; i < IPHost.AddressList.Length; i++)
{
textBox1.AppendText("My IP address is: "
+ IPHost.AddressList[i].ToString() + "\r\n");
}
In this code, the IPHostEntry variable contains all the IP addresses of the computer.
Now, as far as I know, Windows vista returns a number of IP addresses some in hexadecimal, some in decimal notation and so on.
The problem is that the decimal notation which is desired changes its location in the IPHostEntry variable: It initially was occuring in the last location and so could be accessed with the code:
string ipText = IPHost.AddressList[IPHost.AddressList.Length - 1].ToString();
However after changing the IP address of the computer, it now appears in the 2nd last location and so needs to be accessed using the code:
string ipText = IPHost.AddressList[IPHost.AddressList.Length - 2].ToString();
Is there any code that retrieves the IP addresses in decimal notation irrespective of its location in the IPHostEntry variable??
Assuming you only want the IPv4 address, I'm currently using this code (modified a bit for posting) which is robust enough for my use. Just invoke ToString on the result to get the address:
// return the first IPv4, non-dynamic/link-local, non-loopback address
public static IPAddress GetIPAddress()
{
IPAddress[] hostAddresses = Dns.GetHostAddresses("");
foreach (IPAddress hostAddress in hostAddresses)
{
if (hostAddress.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(hostAddress) && // ignore loopback addresses
!hostAddress.ToString().StartsWith("169.254.")) // ignore link-local addresses
return hostAddress;
}
return null; // or IPAddress.None if you prefer
}
The 169.254.* part might seem like a hack, but is documented in IETF RFC 3927.
I believe what you are asking is can you differentiate between the IPv4 and IPv6 address returned from your DNS query. The answer is yes. Check the AddressFamily property on the IPAddress and make sure it returns InterNetwork.
Your hex addresses are IPv6, the 4 decimal numbers ones are ipv4.

Categories

Resources