Resolving an IP address from DNS in C# [duplicate] - c#

This question already has answers here:
Can't parse domain into IP in C#?
(6 answers)
Closed 9 years ago.
I am trying to make a TCP socket connection to an IP address. I can do this by directly parsing an IP address like this:
IPAddress ipAddress = IPAddress.Parse("192.168.1.123");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 80);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // This works!
However, I cannot figure out how to divine this IP address from a DNS string. I've tried every combination of the following:
IPAddress ipAddress = Dns.Resolve("www.mydns.org"); // No dice
IPAddress ipAddress = Dns.GetHostEntry("www.mydns.org"); // Nada
IPAddress ipAddress = IPAddress.Parse(Dns.Resolve("www.mydns.org")); // So many errors...
IPAddress ipAddress = IPAddress.Parse(Dns.Resolve("www.mydns.org").toString()); // WTh is this attempt anyway?
Would any of you kind souls have a tip to help me squeeze an IPAddress out of a DNS?

foreach (IPAddress ip in Dns.GetHostAddresses("www.mydns.org"))
{
Console.WriteLine(ip.ToString());
}
or simply IPAddress address = Dns.GetHostAddresses("www.mydns.org")[0]; if you want the first one only.

I've got a very neat extension method for just that!
I takes into account that an IPV6 may be returned as the first address in the list of addresses returned by the DNS class and allows you to "favor" an IPV6 or IPV4 on the result. Here is the fully documented class (only with the pertinent method for this case for reasons of brevity):
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
/// <summary>
/// Basic helper methods around networking objects (IPAddress, IpEndPoint, Socket, etc.)
/// </summary>
public static class NetworkingExtensions
{
/// <summary>
/// Converts a string representing a host name or address to its <see cref="IPAddress"/> representation,
/// optionally opting to return a IpV6 address (defaults to IpV4)
/// </summary>
/// <param name="hostNameOrAddress">Host name or address to convert into an <see cref="IPAddress"/></param>
/// <param name="favorIpV6">When <code>true</code> will return an IpV6 address whenever available, otherwise
/// returns an IpV4 address instead.</param>
/// <returns>The <see cref="IPAddress"/> represented by <paramref name="hostNameOrAddress"/> in either IpV4 or
/// IpV6 (when available) format depending on <paramref name="favorIpV6"/></returns>
public static IPAddress ToIPAddress(this string hostNameOrAddress, bool favorIpV6=false)
{
var favoredFamily = favorIpV6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
var addrs = Dns.GetHostAddresses(hostNameOrAddress);
return addrs.FirstOrDefault(addr => addr.AddressFamily == favoredFamily)
??
addrs.FirstOrDefault();
}
}
Don't forget to put this class inside a namespace! :-)
Now you can simply do this:
var server = "http://simpax.com.br".ToIPAddress();
var blog = "http://simpax.codax.com.br".ToIPAddress();
var google = "google.com.br".ToIPAddress();
var ipv6Google = "google.com.br".ToIPAddress(true); // if available will be an IPV6

IPHostEntry entry = Dns.GetHostEntry(hostNameOrAddress: "www.google.com");
foreach (IPAddress addr in entry.AddressList)
{
// connect, on sucess call 'break'
}
Simply enumerate address by calling GetHostEntry, on sucess break the loop

Related

Retrieving Subnet Mask Address From .NET HttpRequest class

Giving an object instance from the class System.Web.HttpRequest, say myRequest, then using the property System.Web.HttpRequest.UserHostAddress I can retrieve the IP address of the remote client:
string myIp = myRequest.UserHostAddress;
(...)
My need is to retrieve the IP address of the subnet mask of the remote client exclusively from the instance myRequest.
I know that the following is not possible but I would like to accomplish something similar:
string myMaskIp = myRequest.UserHostMaskAddress;
(...)
This because I can't check the local device network interfaces as I could with System.Net.NetworkInformation namespace, so my only available object to probe is the http request made from the remote client to the server.
Thank you very much for your help
I'm pretty sure you can not determine a subnet mask by simply making a request to a remote host - even if the remote host is you.
Oldyis is right for the general case, however it is possible to determine a classful subnetmask from the IPv4 address. Without any further information, determining an classless subnetmask is indeed impossible.
Keep in mind that the classful adressing scheme is virtually not used any more.
Here is an example from this project:
/// <summary>
/// Returns the classfull subnet mask of a given IPv4 network
/// </summary>
/// <param name="ipa">The network to get the classfull subnetmask for</param>
/// <returns>The classfull subnet mask of a given IPv4 network</returns>
public static Subnetmask GetClassfullSubnetMask(IPAddress ipa)
{
if (ipa.AddressFamily != AddressFamily.InterNetwork)
{
throw new ArgumentException("Only IPv4 addresses are supported for classfull address calculations.");
}
IPv4AddressClass ipv4Class = GetClass(ipa);
Subnetmask sm = new Subnetmask();
if (ipv4Class == IPv4AddressClass.A)
{
sm.MaskBytes[0] = 255;
}
if (ipv4Class == IPv4AddressClass.B)
{
sm.MaskBytes[0] = 255;
sm.MaskBytes[1] = 255;
}
if (ipv4Class == IPv4AddressClass.C)
{
sm.MaskBytes[0] = 255;
sm.MaskBytes[1] = 255;
sm.MaskBytes[2] = 255;
}
return sm;
}
(Think of the SubnetMask class as a byte array of length four)

Receiving udp packet on designated network card c#

I have 3 different network cards each with their individual responsibility. Two of the cards are receiving packets from a similar device (plugged directly into each individual network card) which sends data on the same port. I need to save the packets knowing which device they came from.
Given that I am required to not specify the ip address of the devices sending me the packets, how can I listen on a given network card? I am allowed to specify a static ip address for all 3 nics if needed.
Example: nic1 = 169.254.0.27, nic2 = 169.254.0.28, nic3 = 169.254.0.29
Right now I have this receiving the data from nic1 and nic2 without knowing which device it came from.
var myClient = new UdpClient(2000) //Port is random example
var endPoint = new IPEndPoint(IPAddress.Any, 0):
while (!finished)
{
byte[] receivedBytes = myClient.Receive(ref endPoint);
doStuff(receivedBytes);
}
I can't seem to specify the static ip address of the network cards in a manner which will allow me to capture the packets from just one of the devices. How can I separate these packets with only the knowledge that they are coming in on two different network cards?
Thank you.
You're not telling the UdpClient what IP endpoint to listen on. Even if you were to replace IPAddress.Any with the endpoint of your network card, you'd still have the same problem.
If you want to tell the UdpClient to receive packets on a specific network card, you have to specify the IP address of that card in the constructor. Like so:
var listenEndpoint = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 2000);
var myClient = new UdpClient(listenEndpoint);
Now, you may ask "What's the ref endPoint part for when I'm calling myClient.Receive(ref endPoint)?" That endpoint is the IP endpoint of the client. I would suggest replacing your code with something like this:
IPEndpoint clientEndpoint = null;
while (!finished)
{
var receivedBytes = myClient.Receive(ref clientEndpoint);
// clientEndpoint is no longer null - it is now populated
// with the IP address of the client that just sent you data
}
So now you have two endpoints:
listenEndpoint, passed in through the constructor, specifying the address of the network card you want to listen on.
clientEndpoint, passed in as a ref parameter to Receive(), which will be populated with the client's IP address so you know who is talking to you.
Check this out this:
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
Console.WriteLine("Name: " + netInterface.Name);
Console.WriteLine("Description: " + netInterface.Description);
Console.WriteLine("Addresses: ");
IPInterfaceProperties ipProps = netInterface.GetIPProperties();
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
{
Console.WriteLine(" " + addr.Address.ToString());
}
Console.WriteLine("");
}
Then you can choose on which address start listening.
look, if you create your IPEndPoint in the following way it must work:
IPHostEntry hostEntry = null;
// Get host related information.
hostEntry = Dns.GetHostEntry(server);
foreach(IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, port);
...
try to do not pass 0 as port but a valid port number, if you run this code and break the foreach after the first iteration you will have created only 1 IPEndPoint and you can use that one in your call to: myClient.Receive
notice that the UdpClient class has a member calledd Client which is a socket, try to explore the properties of that object as well to find out some details, I have found the code I gave you here: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx

tcp/ip packet listener

I've started to do some basic network programming.
I have read/written my own programs using TcpClient and TcpListener and that has worked fine.
However, the application I am working on now works a bit differently.
I want to set up a program that listens for tcp/ip packets without having to connect.
For example, have a packet sending app send a packet to my program with the appropriate ip add and port number.
I have also looked into using Sharppcap and packet.net but all of the examples I've found only listens on devices found locally (no opportunity to set parameters such as port number and ip add).
Does anyone have a suggestion on how to go about doing this?
You should look at using the UDP protocol instead of TCP/IP.
http://en.wikipedia.org/wiki/User_Datagram_Protocol
Here is the code for the client:
using System.Net;
using System.Net.Sockets;
...
/// <summary>
/// Sends a sepcified number of UDP packets to a host or IP Address.
/// </summary>
/// <param name="hostNameOrAddress">The host name or an IP Address to which the UDP packets will be sent.</param>
/// <param name="destinationPort">The destination port to which the UDP packets will be sent.</param>
/// <param name="data">The data to send in the UDP packet.</param>
/// <param name="count">The number of UDP packets to send.</param>
public static void SendUDPPacket(string hostNameOrAddress, int destinationPort, string data, int count)
{
// Validate the destination port number
if (destinationPort < 1 || destinationPort > 65535)
throw new ArgumentOutOfRangeException("destinationPort", "Parameter destinationPort must be between 1 and 65,535.");
// Resolve the host name to an IP Address
IPAddress[] ipAddresses = Dns.GetHostAddresses(hostNameOrAddress);
if (ipAddresses.Length == 0)
throw new ArgumentException("Host name or address could not be resolved.", "hostNameOrAddress");
// Use the first IP Address in the list
IPAddress destination = ipAddresses[0];
IPEndPoint endPoint = new IPEndPoint(destination, destinationPort);
byte[] buffer = Encoding.ASCII.GetBytes(data);
// Send the packets
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
for(int i = 0; i < count; i++)
socket.SendTo(buffer, endPoint);
socket.Close();
}

Can't parse domain into IP in C#?

I have this code:
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(txtBoxIP.Text), MainForm.port);
When I have an IP in the txtBoxIP (192.168.1.2) for example, it works great.
But if I want to put a DNS? like I'm putting (my.selfip.com) I get:
System.FormatException: An invalid IP address was specified.
at System.Net.IPAddress.InternalParse(String ipString, Boolean tryParse)
How can I make it support both IP and DNS ?
IPAddress ipAddress;
if (!IPAddress.TryParse (txtBoxIP.Text, out ipAddress))
ipAddress = Dns.GetHostEntry (txtBoxIP.Text).AddressList[0];
serverEndPoint = new IPEndPoint(ipAddress, MainForm.port)
Don't forget the error handling.
A DNS name isn't an IP address. Look at Dns.GetHostEntry() for DNS resolution.
Edited to add: Here's what I've done:
public static IPEndPoint CreateEndpoint( string hostNameOrAddress , int port )
{
IPAddress addr ;
bool gotAddr = IPAddress.TryParse( hostNameOrAddress , out addr ) ;
if ( !gotAddr )
{
IPHostEntry dnsInfo = Dns.GetHostEntry( hostNameOrAddress ) ;
addr = dnsInfo.AddressList.First() ;
}
IPEndPoint instance = new IPEndPoint( addr , port ) ;
return instance ;
}
DNS to IP List
IPHostEntry nameToIpAddress;
nameToIpAddress = Dns.GetHostEntry("HostName");
foreach (IPAddress address in nameToIpAddress.AddressList)
Console.WriteLine(address.ToString());
Then you can use the IP's in the AddressList.
Here is a great article
var input = txtBoxIP.Text;
IPAddress ip;
// TryParse returns true when IP is parsed successfully
if (!IPAddress.TryParse (input, out ip))
// in case user input is not an IP, assume it's a hostname
ip = Dns.GetHostEntry (input).AddressList [0]; // you may use the first one
// note that you'll also want to handle input errors
// such as invalid strings that are neither IPs nor valid domains,
// as well as hosts that couldn't be resolved
var serverEndPoint = new IPEndPoint (ip, MainForm.port);
Note: No, it is not déjà vu, this answer is the exact same I provided on another duplicate question... I wanted to make the author of this one aware of the other so the best way I've found was to add it again here as just linking to other answers is frowned upon on Stack Overflow.
I've got a very neat extension method for just that!
I takes into account that an IPV6 may be returned as the first address in the list of addresses returned by the DNS class and allows you to "favor" an IPV6 or IPV4 on the result. Here is the fully documented class (only with the pertinent method for this case for reasons of brevity):
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
/// <summary>
/// Basic helper methods around networking objects (IPAddress, IpEndPoint, Socket, etc.)
/// </summary>
public static class NetworkingExtensions
{
/// <summary>
/// Converts a string representing a host name or address to its <see cref="IPAddress"/> representation,
/// optionally opting to return a IpV6 address (defaults to IpV4)
/// </summary>
/// <param name="hostNameOrAddress">Host name or address to convert into an <see cref="IPAddress"/></param>
/// <param name="favorIpV6">When <code>true</code> will return an IpV6 address whenever available, otherwise
/// returns an IpV4 address instead.</param>
/// <returns>The <see cref="IPAddress"/> represented by <paramref name="hostNameOrAddress"/> in either IpV4 or
/// IpV6 (when available) format depending on <paramref name="favorIpV6"/></returns>
public static IPAddress ToIPAddress(this string hostNameOrAddress, bool favorIpV6=false)
{
var favoredFamily = favorIpV6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
var addrs = Dns.GetHostAddresses(hostNameOrAddress);
return addrs.FirstOrDefault(addr => addr.AddressFamily == favoredFamily)
??
addrs.FirstOrDefault();
}
}
Don't forget to put this class inside a namespace! :-)
Now you can simply do this:
var server = "http://simpax.com.br".ToIPAddress();
var blog = "http://simpax.codax.com.br".ToIPAddress();
var google = "google.com.br".ToIPAddress();
var ipv6Google = "google.com.br".ToIPAddress(true); // if available will be an IPV6
You'll have to look up the IP of the hostname yourself:
string addrText = "www.example.com";
IPAddress[] addresslist = Dns.GetHostAddresses(addrText);
foreach (IPAddress theaddress in addresslist)
{
Console.WriteLine(theaddress.ToString());
}
Edit
To tell the difference between the two (BTW this uses some features of C# that may be in 3.5 and above):
bool isDomain = false;
foreach(char c in addrText.ToCharArray())
{
if (char.IsLetter(c)){
isDomain = true;
break;
}
if (isDomain)
// lookup IP here
else
// parse IP here

How to obtain Local IP?

I read this question in this thread: How to get the IP address of the server on which my C# application is running on?
But this code is not working for me:
string hostname = Dns.GetHostName();
IPHostEntry ip = Dns.GetHostEntry(hostname);
It giving me an err on this second line in the argument:
A field initializer cannot reference
the non-static field, method, or
property.
I want to store my local IP of my machine in a string. Thats all!
public static String GetIP()
{
String ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if(string.IsNullOrEmpty(ip))
{
ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
//This will return the collection of local IP's
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
public static bool IsLocalIpAddress(string host)
{
try
{ // get host IP addresses
IPAddress[] hostIPs = Dns.GetHostAddresses(host);
// get local IP addresses
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
// test if any host IP equals to any local IP or to localhost
foreach (IPAddress hostIP in hostIPs)
{
// is localhost
if (IPAddress.IsLoopback(hostIP)) return true;
// is local address
foreach (IPAddress localIP in localIPs)
{
if (hostIP.Equals(localIP)) return true;
}
}
}
catch { }
return false;
}
//Call this method this will tell Is this your local Ip
IsLocalIpAddress("localhost");
In ASP.Net, you can get the IP address to which the request was made from the Request object:
string myIpAddress = Request.UserHostAddress ;
It may be an IPv4 address or an IPv6 address. To find out, parse it into an System.Net.IPAddress:
IPAddress addr = IPAddress.Parse( myIpAddress ) ;
If you're interested in the IP address of the current host, that turns into a much more complicated (interesting?) question.
Any given host (and for "host" read "individual computer") may have multiple NICs (Network Interface Card) installed. Each NIC (assuming it's attached to an IP network) has an IP address assigned to it—and likely it has both an IPv4 and an IPv6 address assigned to it.
Further, each NIC may itself be multi-homed and have additional IP addresses, either IPv4 and/or IPv6 assigned.
Then we have the IP loopback adapter, for which each host shares the same loopback addresses. For IPv4, the loopback address is defined as the entire 127/8 subnet (that is, IP addresses 127.0.0.0–127.255.255.255 are all IPv4 loopback addresses). IPv6 only assigns a single loopback address (::1).
So, from the vantage point of the host then, you need to know the context (loopback adapter or NIC? if NIC, which one? Ipv4 or IPv6?) And even then, you're not guaranteed a single IP address. You have to ask yourself what, exactly, it is you mean by "my IP address"?

Categories