gethostbyname() function returns empty buffer - c

I am new to internet programming, and I am trying to use the gethostbyname() function. When I input a string such as "www.yahoo.com" to gethostbyname function it works fine, but when I input a char array, it will always return an empty buffer.
char hostname[100];
struct hostent* h;
gethostname(hostname, sizeof hostname );
printf("Hostname: %s\n", hostname);
h = gethostbyname(hostname);
Any idea how to solve this?

Your server can't resolve itself. The most common way of "fixing" this is to put its own name into its hostfile. While this is a good idea for various reasons, the underlying problem really should be fixed.
The DNS search list should normally be set to the domainname that contains the hostname -or- the hostname should be fully qualified itself.
DNS should be correctly set up for the host.
This makes it not really a C problem at all, but a server configuration problem. Off it goes then.

WSADATA wsaData;
int error;
if ((error = WSAStartup(MAKEWORD(1, 1), &wsaData)) !=0)
{
printf("Error %d in WSAStartup, result will fail\n",error);
}
char hostname[100];
struct hostent* h;
gethostname(hostname, sizeof hostname );
printf("Hostname: %s\n", hostname);
h = gethostbyname(hostname);

In the linux programmers manual the function has the following declaration:
struct hostent *gethostbyname(const char *name);
This means the parameter must be a char array (or string in layman terms). A quoted string such as "yahoo.com" can be used directly when calling the function.
The following code is a working example on how gethostbyname works:
#include <stdio.h>
#include <string.h>
#include <netdb.h>
int main(){
struct hostent* h=gethostbyname("yahoo.com");
printf("Hostname: %s\n", h->h_name);
printf("Address type #: %d\n", h->h_addrtype);
printf("Address length: %d\n", h->h_length);
char text[50]; // allocate 50 bytes (a.k.a. char array)
strcpy(text,"bing.ca"); //copy string "bing.ca" to first 7 bytes of the array
h=gethostbyname(text); //plug in the value into the function. text="bing.ca"
printf("Hostname: %s\n", h->h_name);
printf("Address type #: %d\n", h->h_addrtype);
printf("Address length: %d\n", h->h_length);
return 0;
}
I called it twice. Once for yahoo.com and once for bing.ca and I retrieved the hostname, the address type number and the address length (which is the number of bytes required to store the IP).
For calling the bing address, I allocated a char array, filled it with a string then passed that char array as a parameter to the function.

One good reason why it's returning NULL is because the hostname what you are passing is not correct.
Sometimes even doing hostname -v will not give the correct host name.
Try following:
cat /etc/hosts
this will show you output as:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain
That 'localhost' next to 127.0.0.1 in the output above is your host name. This will work perfectly with gethostbyname.

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.

c get server public ip

I would like to know how to get the public ip of my server with C programming language.I already know how to do this with libcurl but now i want to understand how to get this info with the socket programming (if it is possible).I've already tried with struct hostent *hp but i get only the local address 127.0.0.1
This is the code i've used:
int main(int argc, char *argv[]){
struct hostent *hp;
int i=0;
if((hp=gethostbyname(argv[1])) == NULL){
herror("gethostbyname()");
exit(1);
}
fprintf(stdout, "Hostname: %s\n", hp->h_name);
/* fprintf (stdout,"IP server: %s\n",inet_ntoa(*((struct in_addr *)hp->h_addr))); con questa printo solo 1 ip */
while (hp->h_addr_list[i] != NULL) { /* mentre così printo tutti gli eventuali ip */
printf("IP: %s\n", inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i])));
i++;
}
return 0;
}
You can't do it on your own, there's no reliable way. Let's say you're behind a NAT box: you can never know the inside global address (i.e. the public address used by the NAT box). What's more, the NAT box might have multiple public addresses.
This happens because your public address is not your address. The public address is just a mirage, i.e. the way outside hosts perceive you. So it makes sense: you can only find it out by asking outside hosts.
TLDR
Do a request to an outside host:
[cnicutar#fresh ~]$ curl ifconfig.me
192.0.2.42
It is trivial to do it using libcurl or with your own sockets.

Unix - how to get IP address of domain name?

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) );

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).

get LAN ip and print it

Does anyone know how do I get my LAN IP and print it on the screen.
*I don't mean on shell, but in c programming.
**I will appreciate if you'll post me a sample code.
There's a few approaches; first, you could set up a connection to a known peer using connect(2) and then read the local socket 'name' with getsockname(2). This is a pretty poor mechanism, but it is easy.
But, getsockname(2) will only report one IP address, when a machine may have thousands of IP addresses, and which IP is returned will depend in part upon the peer that you chose! So, not very reliable.
A much better answer is to use rtnetlink(7) to read the IP addresses for the machine directly from the kernel: you would send RTM_GETADDR messages to the kernel for each interface on the machine and read the answers back. Your best bet for understanding how to use this is probably to read the source code for the ip program.
Another option is to use the SIOCGIFCONF ioctl(2) on an IP socket. This interface isn't as flexible as the rtnetlink(7) interface, so it might not always be correct, but it'll be a mid-way point. The ifconfig(8) utility uses this approach for displaying ifconfig -a output. Again, your best bet would be to read the source. (There is some slight documentation in ioctl_list(2).)
The getifaddrs() function from <ifaddrs.h> is the simplest way to get the current interfaces and corresponding addresses:
#include <stdio.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct ifaddrs *iflist, *iface;
if (getifaddrs(&iflist) < 0) {
perror("getifaddrs");
return 1;
}
for (iface = iflist; iface; iface = iface->ifa_next) {
int af = iface->ifa_addr->sa_family;
const void *addr;
char addrp[INET6_ADDRSTRLEN];
switch (af) {
case AF_INET:
addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr;
break;
case AF_INET6:
addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr;
break;
default:
addr = NULL;
}
if (addr) {
if (inet_ntop(af, addr, addrp, sizeof addrp) == NULL) {
perror("inet_ntop");
continue;
}
printf("Interface %s has address %s\n", iface->ifa_name, addrp);
}
}
freeifaddrs(iflist);
return 0;
}
gethostbyname should help you to do this. Example:
GetLocalAddress()
{
char ac[80];
// Get my host name
if (gethostname(ac, sizeof(ac)) != -1)
{
printf("Host name: %s\n", ac);
// Find IP addresses
struct hostent* p_he = gethostbyname(ac);
if (p_he != 0)
{
for (int i=0; p_he->h_addr_list[i] != 0; ++i)
{
struct in_addr addr;
memcpy(&addr, p_he->h_addr_list[i], sizeof(struct in_addr));
printf("IP address %d: %s\n", i, inet_ntoa(addr));
}
}
}
You might want to filter to remove 127.0.0.1 from the list.

Resources