How to get the ip address in qt/linux? - c++

I am working on a server client project on Qt. The server is running in a machine with more than one network interface. The design is such that the client will discover the server automatically. ie the client will broadcast its IP to a network the server get that message and sends back the server's IP. The problem now is that when I try to get the IP in the server, There are more than 1 IP. How to get the IP of the interface through which server have received the message?

This might be a solution for you
IPAddress FindLocalIPAddressOfIncomingPacket( senderAddr )
{
foreach( adapter in EnumAllNetworkAdapters() )
{
adapterSubnet = adapter.subnetmask & adapter.ipaddress;
senderSubnet = adapter.subnetmask & senderAddr;
if( adapterSubnet == senderSubnet )
{
return adapter.ipaddress;
}
}
}
How to get your own (local) IP-Address from an udp-socket (C/C++)
In order to get the incoming peer IP address you can use following solution in C
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;
len = sizeof addr;
getpeername(s, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
printf("Peer IP address: %s\n", ipstr);
Getting the source address of an incoming socket connection

Related

Why is this program timing out without any network traffic?

I am trying to create a simple c++ program that hides the differences between Linux and Windows when making sockets and connecting to servers
The Linux part of this code compiles without any warnings or errors but times out after resolving the host IP and does not connect to the server running (nc -lvnp 7777)
Using tcpdump -i eth0 -v port 7777 to capture all the traffic to and from the machine running the program shows nothing
class Socket
{
public:
int initsoc(void);
int connectsoc(int sock, const char * host, int port);
};
int Socket::connectsoc(int sock, const char * host, int port)
#ifdef _WIN32
/* windows part */
#else
struct hostent *server;
struct sockaddr_in server_addr;
struct in_addr *address;
server_addr.sin_family = AF_INET;
server_addr.sin_port = port;
/* resolve host */
server = gethostbyname(host);
if (server == NULL)
{
printf("Error : %s \nFailed to resolve %s:%d", strerror(errno), host, port);
return -1;
}
address = (struct in_addr *) (server->h_addr);
printf("Resolved: [%s] ===> [%s]\n", host, inet_ntoa(*address));
server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address));
iResult = connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
printf("Connect returned : %d\n",iResult);
if (iResult < 0)
{
printf("Error: %s\nFailed to connect\n",strerror(errno));
return -1;
}
printf("Connected to [%s:%d]\n",host,port);
return 0;
I tried to open a netcat listener on a machine on the same network as the computer running the program without any NATs but it still times out
this is how i compiled and what it outputs
g++ -Wall -ggdb3 -pedantic -g main.cpp -o app
Resolved: [10.0.0.100] ===> [10.0.0.100]
Connect returned : -1
Error: Connection timed out
Failed to connect
the ip of the machine running the code is 10.0.0.2
the ip of the machine running the netcat server is 10.0.0.100
As commented by #user253751, this line:
server_addr.sin_port = port;
should be changed to:
server_addr.sin_port = htons(port);

Get computername from hostname in C++?

The IP address is 192.168.23.4. I am able to get the hostname from the ipaddress using the following code snippet:
struct sockaddr_in sa;
char str[INET_ADDRSTRLEN];
inet_pton(AF_INET, "192.168.23.4", &(sa.sin_addr));
struct sockaddr_in saGNI;
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
u_short port = 27015;
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = sa.sin_addr.s_addr;
saGNI.sin_port = htons(port);
DWORD dwRetval = getnameinfo((struct sockaddr *) &saGNI,
sizeof(struct sockaddr),
hostname,
NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);
printf("HostName: %s", hostname);
I am getting an output of the form
ComputerName.domain.com
How do I get the Computername from the hostname?
Eg Input
ComputerName.domain.com
Eg Output
ComputerName
Is there any way to directly get the ComputerName of a system whose IP address is known?
I am looking for the same result as displayed using the Hostname command on the remote system.
Check the manual pages for getnameinfo
http://man7.org/linux/man-pages/man3/getnameinfo.3.html
According to the manual pages, you should set the NI_NOFQDN flags.
NI_NOFQDN
If set, return only the hostname part of the fully qualified
domain name for local hosts.
As suggested by emirc,
the following code is printing Computername:
struct sockaddr_in sa;
char str[INET_ADDRSTRLEN];
inet_pton(AF_INET, "192.168.23.4", &(sa.sin_addr));
struct sockaddr_in saGNI;
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
u_short port = 27015;
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = sa.sin_addr.s_addr;
saGNI.sin_port = htons(port);
DWORD dwRetval = getnameinfo((struct sockaddr *) &saGNI,
sizeof(struct sockaddr),
hostname,
NI_MAXHOST, servInfo, NI_MAXSERV, NI_NOFQDN);
printf("HostName: %s", hostname);
Note:
I have changed the flag from
NI_NUMERICSERV
to
NI_NOFQDN
You mean, you want to truncate the string before the first period?
std::string host(hostname);
size_t pos = host.find('.');
if (pos != std::string::npos)
{
host = host.substr(0,pos);
}
strcpy(hostname, host.c_str());
If you are interested in finding the host name of the computer on which the code is running, Boost.Asio could simplify the task:
#include <iostream>
#include <string>
#include <boost/asio.hpp>
int main() {
std::string hostname = boost::asio::ip::host_name();
std::cout << "hostname = " << hostname << std::endl;
}
Note that this needs to be compiled with the -lpthread option.

Display HTTP Request sent to my server using c++

I am currently learning about the internet. I am trying to set up a simple proxy server that just forwards a request from the server side to its client side. Im currently following this tutorial. This is how far I have gotten:
#define MYPORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(int argc, const char* argv[]) {
struct addrinfo hints;
struct addrinfo *res;
int sockIn;
int sockOut;
memset(&hints, 0, sizeof hints); // make sure its empty
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM; // what kind of socket
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//listens on the hosts ip address:
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockIn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockIn, res->ai_addr, res->ai_addrlen);
listen(sockIn, BACKLOG);
freeaddrinfo(res); // free the linked-list
struct sockaddr_storage their_addr;
socklen_t addr_size;
char buf[512];
while(1) {
addr_size = sizeof their_addr;
struct sockaddr *addr = (struct sockaddr *)&their_addr;
sockOut = accept(sockIn, addr, &addr_size);
recv(sockOut, buf, sizeof buf, 0);
for (auto ch : buf) {
cout << ch;
}
close(sockOut);
}
}
Right now im just displaying "hi" on every page I visit.
Before I implement the client side of the proxy id like to instead display the HTTP Get Request that my browser sends to the server side of the proxy. My issue is that I dont know how to retrieve it. The guide I'm using is not adressering this.
Edit: I added a recv call that is suppose to read everything from the socket in to a buffer. Unfortunately it does not cout anything
download and install wireshark (packet sniffer), or else Fiddler Fiddler(HTTP proxy). You will easily be able to inspect HTTP traffic. I recommend you start with fiddler. Install on computer where your browser is located.

C++ bind UDP Socket Address Family not suppoerted

Running a Linux system on a PowerPC Architecture which is connected via Ethernet to another Device obtaining a UDP connection (Package Based),
I try to setup a socket and bind it to my Port 8813. But whenever I enter a Port different from 0, Binding fails.
Here is the code:
int connector::initUDPSocket(){
struct hostent *server;
//Construct Socket
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
;
sockaddr_in socketaddress;
socklen_t addrlen = sizeof(struct sockaddr_in); /* length of addresses */
udpsocket=socket(AF_INET,SOCK_DGRAM ,0);
if(udpsocket<=0)
{
printf("No Socket opened!");
return 1;
}
else
{
printf("ONE Socket opened!");
memset((char *) &socketaddress,0, sizeof(socketaddress));
socketaddress.sin_family = AF_INET;
socketaddress.sin_addr.s_addr=htonl(inet_addr("192.168.0.10"));//<=That's the external devices address;// htonl(inet_addr("192.168.0.1"));//<=That's my devices address;//htonl(INADDR_ANY);//INADDR_ANY;//
socketaddress.sin_port = htons(8813);//8813;//htonl(8813);//htons(0); //<=Only the last one works
int bind_result=bind(udpsocket,(struct sockaddr *)&socketaddress,sizeof(socketaddress));
if( bind_result == SOCKET_ERROR)
{
printf(LFL_CRI,"BIND failed! Error: %s",strerror(errno)); //Returns "BIND failed! Error: Address family not supported by protocol"
}
else
{
printf(LFL_CRI,"BIND worked!");
//Nun den Listener für den DatenStream aufsetzen.
char SockAddrBuffer[sizeof(struct sockaddr_storage)];
socklen_t SockAddrBufferSize = sizeof(SockAddrBuffer);
int numofbytes=recvfrom(udpsocket, udp_buffer, UDP_BUFFERSIZE, 0, (struct sockaddr *)SockAddrBuffer, &SockAddrBufferSize);
if (numofbytes >0)
{
printf("%i bytes received",numofbytes);
}
}
}
return 0;
}
}
What I found out so far:
Ping 192.168.0.10 is possible
Data seem not to be blocked by the firewall; iptables -nvL mentioned no dropped packages. I added a new rule for that, before this rule was applied, the number or dropped packages increased when the external device was connected.
Using a test tool on my Windows PC (simply debugging, if there's incoming traffic on a port; connecting the external device to it), I receive data; so, the external device definitely sends data
Binding to Port 0 works; the netstat -au mentions a tool listening on port 2, while the program is running
Error Message: BIND failed! Error: Address family not supported by protocol
So, 2 questions are open here:
What am I doing wrong?
What am I understanding wrong about "bind". What sense does it make to listen to "some random port assigned to my program by the system"? I mean, if I setup an http-Server, I want to listen to Port 80 and not to port "RANDOM". What is this good for?
You've redefined struct sockaddr_in in your code. If is in any way different from how the system defines it, any code that attempts to use this struct will not work properly.
You need to #include <netinet/in.h> to get the proper definition of this struct.

How to get client ip adress using libssh

I am using libssh to make my own ssh server (some kind of honeypot). I would like to save the ip address of connected client into my logfile. How to get this IP address? Programming in c++. Thanks in advance guys!
Here is little function I'm using.
string getClientIp(ssh_session session) {
struct sockaddr_storage tmp;
struct sockaddr_in *sock;
unsigned int len = 100;
char ip[100] = "\0";
getpeername(ssh_get_fd(session), (struct sockaddr*)&tmp, &len);
sock = (struct sockaddr_in *)&tmp;
inet_ntop(AF_INET, &sock->sin_addr, ip, len);
string ip_str = ip;
return ip_str;
}
It is based on function "get_client_ip" fromhttps://github.com/PeteMo/sshpot/blob/master/auth.c where is complete SSH honeypot implementation.
s = ssh_get_fd(session);
getpeername(s, ...);