Qt - Get hostname & MAC address from IP Adreess - c++

In my application I want to get the hostname & MAC address from an IP address (in my LAN).
I used this code to find the hostname, but nothing appeared in lineedit.
QHostInfo HI;
QHostAddress HA("192.168.1.1");
QList<QHostAddress> List;
List.append(HA);
HI.setAddresses(List);
ui->ledHostname->setText(HI.hostName());

To retrieve the Hostname from an IP address you can call lookupHost(), which takes the host name or IP address, a receiver object, and a slot signature as arguments. The slot is invoked when the results are ready. The results are stored in a QHostInfo object. Call addresses() to get the list of IP addresses for the host, and hostName() to get the host name that was looked up.
QHostInfo::lookupHost("92.168.1.1",
this, SLOT(lookedUp(QHostInfo)));
void MyWidget::lookedUp(const QHostInfo &host)
{
if (host.error() != QHostInfo::NoError) {
qDebug() << "Lookup failed:" << host.errorString();
return;
}
foreach (const QHostAddress &address, host.addresses())
qDebug() << "Found address:" << address.toString();
}
For obtaining the MAC address of a remote IP you should use system commands and platform-specific code. There is no way in Qt to do that. For example on Windows it can be done by:
arp -a <IP>

I used this code:
QHostInfo HI = QHostInfo::fromName("192.168.1.50");
ui->ledHostname->setText(HI.hostName());
Worked for some ip addresses & shows the host name! For other ip addresses shows the ip address again.
For my MAC problem, I`m using ARP packet.

Related

What are legal addresses for binding a QUdpSocket?

I tried to bind my socket to some random address 10.1.1.1:12001, and got QAbstractSocket::SocketAddressNotAvailableError.
Than i wrote a simple code:
for (int i = 0; i < 256; i++) {
QHostAddress address0(QString::number(i) + ".0.0.1");
quint16 port = 12101;
QUdpSocket* m_socket = new QUdpSocket();
if (m_socket->bind(address0, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
qDebug() << i;
}
}
Only to learn that IP must start with 127 or 224-239. So it must be Class D address.. But I just didn't find anything in the qt documentation.
Is it a normal behaviour? Is there a possibility to use a global net IP for binding? Or at least use 192.168.x.x as IP of another computer in LAN?
You are not allowed to bind the socket to an arbitrary network IP address. You can only do it with an IP address of one of your network devices or some special IP addresses like 0.0.0.0. By default you always have the 127.0.0.1 but surely you have another network address in your computer.
By the other way if you want to write/read some data over an UDP Socket It's not necessary to bind it to a network address, you can use writeDatagram() or readDatagram() methods of the QUdpSocket class

QHostAddress setAddress not working

I need to change my host IP Address on Linux app using Qt. I have readed documentation about QHostAddress and method setAddress in this class that say the following:
"Sets the IPv4 or IPv6 address specified by the string representation >specified by address (e.g. "127.0.0.1"). Returns true and sets the address >if the address was successfully parsed; otherwise returns false."
I know that it is possible using QProccess but I'm trying to use Qt-way in order to do that. I'm very confused becuase my app is not in running with root privileges so I find very difficult perform this action using Qt class directly. Then I try this:
QHostAddress hostAddress;
bool ipChange = hostAddress.setAddress("192.168.1.143");
if(ipChange) qDebug() << "IP ADDRESS CHANGED";
else qDebug() << "IP ADDRESS NOT CHANGED";
The result of this code is "IP ADDRESS CHANGED" but doing ifconfig in a terminal, my IP address has not been modified. So, my questions are:
How I can do that?
Why I can see IP ADDRESS CHANGED if this method obviously doesn't works?
You are changing the address stored in hostAddress. You can now use hostAddress to (e.g.) open a stream socket to a port on 192.168.1.143. This has no relation to any IP addresses of the host you happen to be running on - QHostAddress is just a representation of any IP address.
To set an address for a network interface on the host machine, you will need to be root, and to use the native facilities (or an external process - /sbin/ifconfig, for example).

How to resolve the real broadcast address for a IPv4 address with Boost.Asio

Is there any possibility to obtain the "real local" broadcast address for a given IPv4 address with Boost.Asio?
ip::address_v4::netmask only returns the netmask based on the IPv4 address class, so it cannot be used reliably with the overload of ip::address_v4::broadcast.
I need to resolve a specific broadcast address for a given (existing) host IPv4 address on the local machine, since I have trouble using an UDP endpoint with a broadcast address of 255.255.255.255.
Edit: For clarification, I do not want to resolve a hostname to an IP address or vice versa.
Edit: Here is an example:
eth0:
host address: 192.168.0.1
net mask...: 255.255.0.0 (**not** class C)
So I want to retrieve the broadcast address 192.168.255.255, but the only input I want to specify is the local net address. Therefore "resolving" or "querying" is the correct term, since I do not want to calculate it.
I have a UDPv4 server, which I bind to a specific local endpoint (by specifying the local IPv4 host address). I want to use this server in both unicast mode and broadcast mode, so I need to specify the remote endpoint as well. I am unable to do this with the "global broadcast" address returned by ip::address_v4::broadcast, because that always returns 255.255.255.255 which leads to undesired behaviour. In addition to the host address I specify a flag to correctly set the socket option to enable broadcasting via basic_datagram_socket::broadcast.
If you have an example how-to achieve this, I would be grateful. Maybe I am thinking too complicated...
I think indeed the boost::asio::ip::address_v4::broadcast overloads are what you are after:
#include <boost/asio.hpp>
#include <iostream>
using boost::asio::ip::tcp;
int main() {
typedef boost::asio::ip::address_v4 A;
A address = A::from_string("192.168.0.1");
std::cout << "Address " << address << " has broadcast address " << A::broadcast(address, A::from_string("255.255.0.0")) << "\n";
}
Prints:
Address 192.168.0.1 has broadcast address 192.168.255.255
See it Live On Coliru
Note Note: if the confusion is from 192.168.0.1 being classified as Class C, this is by design.
IANA defines the 16-bit block 192.168.0.0/16 as "256 contiguous class C networks" (look at the Classful description here The footnote is enlightening, and the Asio implementation matches it).

How to get local IP address of a computer using QT [duplicate]

This question already has answers here:
Get local IP address in Qt
(6 answers)
Closed 8 years ago.
I am trying to get the local ip address (IPV4) of a computer in QT.
I found the following code:
QNetworkInterface *inter = new QNetworkInterface();
QList<QHostAddress> list;
list=inter->allAddresses();
QString str;
for (int i = 0; i < list.size(); ++i) {
str = list.at(i).toString();
}
Going through for loop I can see there are a number of values (ip's) in the list, one of them is the actual local ip address that I get by typing ipconfig in a command window.
My question is how to distinguish the ip address from all the ip's that are in list?
PCs often have more than one IP address. There's not really such a thing as "the" local IP address; the IP address which would be used when connecting to some remote host depends at least on the local routing table (which may change drastically at any time, e.g. when starting/stopping VPN software).
It seems to me that it makes more sense to think about IPs as valid only in the context of remote networks, e.g. "this is the local IP address I'd use if I were to connect to this host on the Internet; but this is the local IP address I'd use to connect to this host over my company's VPN".
If you want to find out the local IP address which would be used for general-purpose Internet connectivity, the most accurate way I know is simply to do a connection test to a representative host (and a host with high reliability!)
QTcpSocket socket;
socket.connectToHost("8.8.8.8", 53); // google DNS, or something else reliable
if (socket.waitForConnected()) {
qDebug()
<< "local IPv4 address for Internet connectivity is"
<< socket.localAddress();
} else {
qWarning()
<< "could not determine local IPv4 address:"
<< socket.errorString();
}
Note: the above example is blocking, you probably want to rewrite it to use signals and slots if your app has a UI.
I think, several attempts should be tried for increasing the chance of the GUESS (Regardless how clever the software is, it would be still a guess, which won't cover 1% of configurations which will be possibly you case :-)
I've combined and extended both solutions. First I'd check for google DNS, and then for local IPs having a standard gateway. The assumption is: Getaway has the same mask with the addreess ending with ".1". I couldn't find out, how to obtain std. gateway in Qt (which would be more reliable).
Here is the code which works ON MY COMPUTERS:
QTcpSocket dnsTestSocket;
QString localIP="127.0.0.1"; //fall back
QString googleDns = "8.8.8.83"; //try google DNS or sth. else reliable first
dnsTestSocket.connectToHost(googleDns, 53);
if (dnsTestSocket.waitForConnected(3000))
{
localIP = dnsTestSocket.localAddress().toString();
}
else
{
foreach (const QHostAddress &address, QNetworkInterface::allAddresses())
{
QString guessedGatewayAddress = address.toString().section( ".",0,2 ) + ".1";
if (address.protocol() == QAbstractSocket::IPv4Protocol
&& address != QHostAddress(QHostAddress::LocalHost)
)
{
dnsTestSocket.connectToHost(guessedGatewayAddress, 53);
if (dnsTestSocket.waitForConnected(3000))
{
localIP = dnsTestSocket.localAddress().toString();
break;
}
}
}
}

How to find ip addresses with BSD sockets?

I am using BSD sockets over a wlan. I have noticed that my server computer's ip address changes occasionally when I connect to it. The problem is that I enter the ip address into my code as a literal string. So whenever it changes I have to go into the code and change it there. How can I change the code so that it will use whatever the ip is at the time? This is the call in the server code
if ((status = getaddrinfo("192.168.2.2", port, &hints, &servinfo)) != 0)
and the client side is the same. I tried NULL for the address on both sides, but the client will not connect and just gives me a "Connection refused" error.
Thanks for any help.
Use a domain name that can be looked up in your hosts file or in DNS, rather than an IP address.
How about a command line parameter?
int main( inr argc, char* argv[] ) {
const char* addr = "myfancyhost.domain.com"; /* default address */
if ( argc > 1 ) {
addr = argv[1]; /* explicit address */
}
if ((status = getaddrinfo(addr, ...
Give your server a name, and use gethostbyname to find its address (and, generally, put the server name into a configuration file instead of hard-coding it, though hard-coding a default if you can't find the config file doesn't hurt).