Unix - how to get IP address of domain name? - c

In a C program in UNIX, gethostbyname() can be used to obtain the address of domain like "localhost". How does one convert the result from gethostbyname() to dotted decimal notation.
struct hostent* pHostInfo;
long nHostAddress;
/* get IP address from name */
pHostInfo=gethostbyname("localhost");
if(!pHostInfo){
printf("Could not resolve host name\n");
return 0;
}
/* copy address into long */
memset(&nHostAddress, 0, sizeof(nHostAddress));
memcpy(&nHostAddress,pHostInfo->h_addr,pHostInfo->h_length);
nHostAddress contains the following:
16777243
How do I convert the result so that I can get the output as :
127.0.0.1

It is easy Just Compile This Code
#include<stdio.h>
#include<netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct hostent *ghbn=gethostbyname("www.kamonesium.in");//change the domain name
if (ghbn) {
printf("Host Name->%s\n", ghbn->h_name);
printf("IP ADDRESS->%s\n",inet_ntoa(*(struct in_addr *)ghbn->h_name) );
}
}

You can convert from a struct in_addr directly to a string using inet_ntoa():
char *address = inet_ntoa(pHostInfo->h_addr);
The value you've got (16777243) looks wrong, though -- that comes out to 1.0.0.27!

The inet_ntoa() API does what you're looking for, but is apparently deprecated:
https://beej.us/guide/bgnet/html/multi/inet_ntoaman.html
If you want something more future-proof-IPV6ish, there's inet_ntop():
https://beej.us/guide/bgnet/html/multi/inet_ntopman.html

The variable "h_name" in the last statement needs to change as "h_addr" shown in follows:
printf("IP ADDRESS->%s\n",inet_ntoa(*(struct in_addr *)ghbn->h_addr) );

Related

How gethostbyname() or getnameinfo() work in background?

How gethostbyname() or getnameinfo() work in background?
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
/* paddr: print the IP address in a standard decimal dotted format */
void
paddr(unsigned char *a)
{
printf("%d.%d.%d.%d\n", a[0], a[1], a[2], a[3]);
}
main(int argc, char **argv) {
struct hostent *hp;
char *host = "google.com";
int i;
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
for (i=0; hp->h_addr_list[i] != 0; i++)
paddr((unsigned char*) hp->h_addr_list[i]);
exit(0);
}
output for google.com:
74.125.236.198
74.125.236.199
74.125.236.206
74.125.236.201
74.125.236.200
74.125.236.196
74.125.236.193
74.125.236.197
74.125.236.194
74.125.236.195
74.125.236.192
output for www.google.com:
74.125.236.210
74.125.236.209
74.125.236.212
74.125.236.208
74.125.236.211
Will the above program do a check in the internet to resolve into IP?
Why its showing less IP addresses for www.google.com and more for just google.com?
On a Linux system the gethostbyname() call implemented in the glibc performs lookups according to the configuration files /etc/host.conf and /etc/nsswitch.conf.
Typically in a default configuration it will first look in the /etc/hosts file if a local entry for the given name exists and if so, returns that. Otherwise it will proceed with the DNS protocol that is in turn configured by /etc/resolv.conf where the nameservers are stated.
Much more complex setups can be configured that lookup LDAP servers, databases etc.
You can also look into some man pages like man 5 nsswitch.conf.

How to check open ports using sockets

#include<stdio.h>
#include<stdlib.h>// for exit
#include<string.h>
#include<unistd.h> //for close(),read()
#include<sys/types.h>//
#include<sys/socket.h> //for socket api's
#include<netinet/in.h>//for struct sockaddr_in
#include<arpa/inet.h>// for inet_pton
#define MAX 30
int ssfd; //listenfd
int res; //connfd
int serverlen;
struct sockaddr_in serveraddr;
void main()
{
int i=0,res;
int startPortRange=0;
int stopPortRange=65536;
for(i=startPortRange; i<stopPortRange; i++)
{
ssfd=socket(AF_INET,SOCK_STREAM,0);
if(ssfd==-1)
{
printf("\nSocket Creation Failed....");
}
serveraddr.sin_family=AF_INET;
serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1"); // inet_addr converts an IPV4 from dotted decimal string
//to e.g(127.0.0.1) to its 32-bit network byte ordered binary value.
serveraddr.sin_port=i;
serverlen=sizeof(serveraddr);
res = bind(ssfd,(struct sockaddr*)&serveraddr,serverlen);
if(res==-1)
{
printf("\nPort in Use : %d",i);
}
else
{
printf("\nPort not in use: %d",i);
}
close(ssfd);
}
}
i am trying to read open ports(which are used by some programs) on computer.The program is working fine. But it doesn't gives the correct result.for eg port 3306 is used by mysql on my computer but my program outputs that it is not in use. please help me to try this out
instead of
serveraddr.sin_port=i;
you need to use
serveraddr.sin_port=htons(i);
because the port address in the inetaddr structure must have network byte order
You should bind to 0.0.0.0, not 127.0.0.1, otherwise you only find out what ports you can bind to 17.0.0.1, which isn't what you're trying to find out. But why you want to do this when netstat already exists is a mystery.

pcap_lookupnet returns incorrect IP address

Following example code from the libpcap documentation yields the following code which should report the IP address of the given interface (eth0 in this case) [Error checking omitted for brevity]
#include <stdio.h>
#include <pcap.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 mask;
bpf_u_int32 ip;
struct in_addr ip_addr;
/* Find the properties for the device */
pcap_lookupnet("eth0", &ip, &mask, errbuf);
ip_addr.s_addr = ip;
printf("IP Address: %s\n", inet_ntoa(ip_addr));
return 0;
}
However, this results in 192.168.1.0, rather than the correct 192.168.1.100. Running this on a different machine on a different subnet yields 10.0.0.0 rather than the correct 10.0.0.107 which leads me to believe libpcap is not copying the last octet correctly. I've manually converted the integer returned by pcap_lookupnet to ensure it's not an issue with the use of inet_ntoa (I've also tried inet_ntop, with identical results). Following the code from this question:
Get IP address of an interface on Linux
reports the correct IP address. Is this a bug in libpcap or am I doing something wrong?
Your statement "which should report the IP address of the given interface" is incorrect.
From the manpage:
pcap_lookupnet() is used to determine the IPv4 network number and
mask
associated with the network device device. Both netp and maskp are
bpf_u_int32 pointers.
are you sure you have a network number of 10.0.0.107 or 192.168.1.100 respectively? Sounds rather unusual.

How to detect your IP/name using gethostbyname()

is there a way to get the IP number from gethostname()?
We are randomly generating IP addresses for the computers in the lab we are in. We use gethostbyname(<random ip>) to get the IP of a computer.
What we want to do essentially is compare the ip that we get from gethostbyname() with what we get from gethostname().
We tried:
struct hostent* host;
char temp[MAX_LEN];
gethostname(temp, MAX_LEN);
host = gethostbyname(<random ip address>)
if(host->h_name == temp) printf("They are the same\n");
The problem is, is that host->h_name is '172.125.45.1' (i made that
up) and temp is 'u-my_comp'
so we cant compare the strings cause one gives us the name of the computer (u-my_comp), and the other gives the ip...
Is there anyway to make these functions return the same type of value?
we have tried doing something like
gethostname(temp, 24)
temp_host = gethostbyname(temp)
in hopes that now we could compare temp_host->h_name with host->h_name...but yeah, that didnt work either.
Any ideas?
thanks!
gethostbyname() is for converting a hostname into a socket address. If the "hostname" you supply is a dotted-quad IPv4 address, that will be all you get in the h_name parameter of the result.
To convert a socket address back into a name what you want is the companion function gethostbyaddr() - except that you don't, because both gethostbyname() and gethostbyaddr() are deprecated. Instead, you should be using getaddrinfo() and getnameinfo().
For example:
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in sa;
char host[1024];
int gni_err;
sa.sin_family = AF_INET;
sa.sin_port = 0;
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
gni_err = getnameinfo((struct sockaddr *)&sa, sizeof sa, host, sizeof host, NULL, 0, NI_NAMEREQD | NI_NOFQDN);
if (gni_err == 0) {
printf("host is: %s\n", host);
} else {
fprintf(stderr, "Error looking up host: %s\n", gai_strerror(gni_err));
}
return 0;
}
If you call:
myhost = gethostbyname(temp);
(having allocated myhost) then you will have two hostent structures you will compare - you will have the IP address lists for both the target query host and the current host (not just the hostname for the current host).

problem establishing a TCP socket connection

I'm not a software person, but I could really use some advice.
I'm writing a C program (cut/paste below) to establish a TCP socket connection from my Mac Pro to a Windows XP-based test-instrument sitting next to it over LAN (Ethernet). The program compiles without any warnings or errors. But executing the code using GNU Debugger, I can see it exits at 'exit(2)' which is the "if(connect(MySocket" line. There's no timeout, it just exits immediately.
I compile using:
gcc -g -Wall talk2me.c -o talk2me
but I don't get any hints in the output nor when debugging at to what might be the issue.
I'm sure the 10.0.1.100 and port 5025 are correct (using Matlab code I can communicate fine using these parameters). Any idea where else I could look to debug?
Outside of the code itself, are there any other requirements (perhaps system-level) that need to be satisfied (like running the code from a certain directory, or setting a parameter in unix to allow connections, etc.)? It may be something obvious that I'm missing because I'm a hardware guy, so feel free to assume I'm doing something stupid. I can run a 'hello world' program fine, it that helps. Thanks in advance, ggk
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h> //for inet_addr
#include <unistd.h> // for function 'close'
int main(void)
{
int MySocket;
if((MySocket=socket(PF_INET,SOCK_STREAM,0))==-1) exit(1);
struct in_addr {
unsigned long s_addr;
};
struct sockaddr_in {
short int sin_family; // Address family
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Padding
};
struct sockaddr_in MyAddress;
// Initialize the whole structure to zero
memset(&MyAddress,0,sizeof(struct sockaddr_in));
// Then set the individual fields
MyAddress.sin_family=PF_INET; // IPv4
MyAddress.sin_port=htons(5025); // Port number used by instrument
MyAddress.sin_addr.s_addr=inet_addr("10.0.1.100"); // IP Address
if(connect(MySocket,(struct sockaddr *) &MyAddress,
sizeof(struct sockaddr_in))==-1) exit(2);
// Send SCPI command
if(send(MySocket,"*IDN?\n",6,0)==-1) exit(3);
// Read response
char buffer[200];
int actual;
if((actual=recv(MySocket,&buffer[0],200,0))==-1) exit(4);
buffer[actual]=0; // Add zero character (C string)
printf("Instrument ID: %s\n",buffer);
// Close socket
if(close(MySocket)==-1) exit(99);
return 0;
}
You have defined struct in_addr and struct sockaddr_in yourself at the top of main. Do not do that, these are types found in header files(netinet/in.h), you have to use those, not your own versions.
Try connection with telnet from your mac box to 10.0.1.100 port 5025 , does that work ?
replace that exit(2); with {perror("connect"); exit(2); } to get a description of what is wrong.

Resources