C++ / Qt: How can I detect when a hostname or IP address refers to the current system? - c++

I'm writing a macOS C++ application using Qt that acts as both a UDP client and UDP server. The server functionality allows the user to configure which port the UDP packets will be received on, and the client functionality allows specifying both a target host and a port number. The host can be either a hostname or an IP address, including addresses or hostnames that resolve to a multicast or broadcast address.
In order to help prevent circularity, when the server functionality is enabled I need to be able to warn the user when the host and port they've entered for the client would send the packets directly to the app's server. Of course it's easy to check if the port numbers match, but this means I need to know whether the host they've entered refers to the current system.
Examples of hostnames or IP addresses that would typically be problematic:
127.0.0.1
localhost
192.168.1.255 (assuming the system is on a 192.168.1.0/24 subnet)
any of the IP addresses assigned to the current system's network interfaces
the system's local DNS name
any other loopback addresses that may be configured other than 127.0.0.1
How could I go about detecting this?
Since this app is being written using Qt, a solution that exclusively uses Qt's framework would be ideal. But if that's not possible (since Qt doesn't handle every possible use case) a macOS-specific solution will work too.

QNetworkInterface class should provide the most information you may need.
You can obtain a list of IP addresses using QNetworkInterface::allAddresses() static function.
You can also get a list of all interfaces using QNetworkInterface::allInterfaces().
Calling QNetworkInterface::addressEntries() for each QNetworkInterface returned by QNetworkInterface::allInterfaces() will give you more information about address entries for each interface.
auto ifs = QNetworkInterface::allInterfaces();
foreach (auto interface , ifs){
auto addresses = interface.addressEntries();
foreach ( auto addy , addresses){
///play with the addy here.
}
}
You can also test hostnames against those ip addresses which you are going to ban, using QDnsLookup class.

Related

iOS NAT64 IPv6 environment issue

Now that apple has changed their review environment to an IPv6 only network ive been running into troubles with my application while testing.
The application requires the user to input their server/systems IP address, port (4401) and credentials to gain access to the application. Following the guidelines provided by apple i set up a NAT64 environment to test my application's compatibility. Running iOS 9.3.2 on an iphone 5s.
My work environment has several internal networks. I connected my iMac to the internal server (10.10.50.XX) via Ethernet which also has an external IP which is what i provide to apple. The 50 network does not run behind a proxy, but there are some sites which get filtered, but can access by confirming. I then shared my Ethernet connection through WiFI.
I connected the device and had internet access with the same pages being filtered. The device gets assigned a local-link address of 169.254.XX.XX. From what ive read my device is connecting to the ipv6 only network correctly, as the iphone does not show the ipv6 address only local link.
If I am correctly connected to the shared IPv6 network, the problem I am having is connecting to my server on the 50 network from my application. The application fails when ever i try to connected to the 10.10.50.XX network or the external(understandable because my imac is on the 50 internal network) .
Testing the application using IPv4 with a wireless router that is connected to the 50 network runs perfectly.I think it is an issue with the local link address not being able to see the 50 network or something.
Heres some brief background info on how i connect to the server. The user inputs all the credentials and the IP address and port of the server they want to connect to. The application saves this as a text (utf-8) and uses boost shared_ptr to send it to the cpp connection class which validates the credentials and provides access to the user. This cpp connection class handles the connection, synchronization, logging, requests and response from the server.
Is it possible to somehow get access to the 50 network, using the NAT64 internet sharing option?
If you're passing an IP address straight down to your network lib, then no. When your device is on the IPv6-only side of the NAT64, the server's IPv4 address is useless.
You almost certainly need a DNS name for the server you're trying to reach. The NAT64 relies first on DNS64 to create IPv6 addresses for your application when the server is IPv4-only. These synthesised addresses contain the IPv4 address(es) for the server, giving the NAT64 the information it needs to translate from IPv6 to IPv4.
Updating this to add: as suggested by user102008 in the comment thread attached to this answer, you may also be able to pass the IPv4 string literal though getaddrinfo() (see code listing 10-1 on this page). When you're behind a NAT64, a synthesised IPv6 address should be among the results returned by that call. The NAT64 will translate from this address back to IPv4 to reach the host you specified. In this case, if the system knows the correct prefix to use for the NAT64, a hostname is not necessary.

How to make a .cpp file to act as an accessible server

I have written a simple program with Linux (Cent OS 7.0) and C++. It is a very small server which sends back a string of characters to the client. But my problem is that I don't know how should I access that server using an IP address?
I have used Linux Socket Interface (Berkeley), and in the section which defines the address, my code does the following:
serverObject.
sin_family = AF_INET;
serverObject.sin_addr.
s_addr = htonl(INADDR_ANY);
serverObject.
sin_port = htonl(portNumber);
I use INADDR_ANY as my server's address which is defined in its definition as:
/* Address to accept any incoming messages. */
Now, how should I run the server, and then use my simple client program to send request to it. My simple client program accepts an IP address as it's destination address, this address should be the one destined toward to the server. How should I relate it then?
INADDR_ANY goes to specify that all active network interfaces in the system should be bound to. So if you're connected to more than one network, you'll be able to communicate with connections coming in from all of them. Most systems will usually have just one, though, and this still goes to say that if the IP bound to that interface happens to change, you'll still bind to that interface.
So, once you specify INADDR_ANY, you need to initiate connections according to the following rules:
If you're connecting from the same physical machine, the easiest thing would be to use the loopback interface (127.0.0.1). However, you can still do (2).
If you're connecting from another machine, you need to pick the accessible IP address of your server from that machine. As said above, if your server is only connected to one network, this will simply be the IP address of the server. Within an internal network this will often be something like 192.168.x.y, or 10.0.x.y—but it doesn't have to.
If you're connecting from a different network which uses a gateway to access your server, then you will need to set up port forwarding in the relevant routers so that when they receive connection to port X, they will know to internally transfer it to your server.
As a server programmer, you decide the port on which to listen, but not the address.
The internet address is provided by your internet provider, or 127.0.0.1 to test on your own machine.
There are plenty of web pages on internet that provide tools to tell you your current public address (search for What is my Ip).
Most of the "home" internet routers implement NAT: they have a single internet address and map them to many device, that carry the Port number to be changed (your port 80 become port (e.g.) 2345 for outside). To allows a client from outside your home to access your server, you are required to configure your router to map the server port, so for example your public port 80 map to your server port 80.
With that said, you should be able to connect your client to your server through an address and port.
If then you want to use a name (example.org) instead of an IP (93.184.216.34), a Domain Name Server is used. But that is another topic.

List of all hosts on LAN network

How can I get all the IP addresses and associated host names in a LAN?
To get the list of interfaces and IP addresses, use getifaddrs().
Search for interfaces with ifa_addr->sa_family == AF_INET
The IP address is in sin_addr.s_addr.
You can then use gethostbyaddr() to look up the DNS name for that IP address.
Update:
It was pointed out to me that the OP was probably asking about discovering other hosts, rather than the addresses of interfaces on the local machine.
There is no reliable way to discover other machines on the local area network, but there are a couple of tricks.
Ping method: Use the ping utility (or a programatic equivalent) to ping the local broadcast address, then see who responds. The broadcast address can be found by listing the interfaces as shown above. I believe ICMP does not require root access under OSX. Note that many systems may have ICMP ping disabled or firewalled, so you will only get responses from the non-stealth ones.
ARP method: Check the system ARP cache to see what IP addresses have been recently active. This will only show systems which have broadcast packets on the same network segment in recent minutes.
Both methods can be blocked by firewalls, routers, and even switches, so the exact borders of the "LAN" can be pretty narrow. Both methods can be implemented programmatically, but it might be simpler and more portable to just call out to the command line ping or arp commands.

A Reliable way to Identify a computer by its ip address

I have a network of computers that they will connect to the a server with DHCP, so I don't know what Ip address a computer will get when I connects to the server. If 192.168.0.39 for example is connected to the server can I identify the real computer behinde this ip address? ( I can install an external application on each client in order to send some data to server for example mac address or so... )
If you are responsible for the DHCP server, you can configure it to hand out a specific IP to a specific MAC. Having done that, you can be reasonably confident of that mapping -- it is possible to spoof MACs, so if you are worried about security, you'll need a much more heavy duty approach. If this is a casual application where the risk of that is low, you configure your DHCP server to hand out IPs based on MACs and then make use of those mappings in your application.
You might not even need the IP address. On an Ethernet network, all communication from a computer, whether it's IPv4, IPv6, or even IPX will be labelled with a MAC address that's stable over time and unique per network card.

Get the ip addresses of an interface

Using the output of "ipconfig /all" i can get what I need but I want a more reliable technique to get ip of an interface (practically the interface has to be identified by it's name) in case of ipconfig was corrupted or was not available for any reason.
I'm not sure what you mean by "server and client", but if you're looking for an API that tells you the IP address(es) associated with the local machine's network interfaces, check out getifaddrs() (for Linux/MacOSX/POSIX) and GetAdaptersAddresses() (for Windows). If you want a usage example for those calls, have a look at the GetNetworkInterfaceInfos() function in this file.
(If you wanted to get the IP address of a client connected to the local machine, call getpeername() on the socket that is associated with that client's connection)
Since you mentioned ipconfig, I assume you want to do this on windows.
Windows has a set of IP Helper apis designed for retrieval and modify networking settings.
And here is a simple sample: http://msdn.microsoft.com/en-us/library/aa366298(VS.85).aspx