SHR
SHR

Reputation: 8313

Got local host name, working on windows, but not in Linux

I wrote a program to get local host name. if it is not obvious, I mean to get the host name of the local machine similar to gethostname method, not to get the string localhost

I'm using getaddrinfo with NULL for host name and then call to getnameinfo with the first address.

It works perfectly on windows machines, and giving me the canonical host name, but in Linux it failed to give me the local host name and gives me :: for IPv6 or 0.0.0.0 for IPv4.

Note that I'm using AI_PASSIVE flag in getaddrinfo, means it gives me no more than two addresses.

In the getnameinfo if I use the NI_NAMEREQD it fail.

I'm doing so because I have a server, sometimes I want to listen to all interfaces and sometimes to a specific interface, I'm already have the addrinfo and I just want to get the hostname from it if possible.

How can I make it work on Linux? did I missed anything?

Thanks for any help.

Here is my code: (cross platform, windows and Linux, just copy & past) You can compile and run on both and see the difference.

#include <iostream> 

#ifdef WIN32

#ifdef UNICODE
#undef UNICODE /* don't want Unicode, to keep code compatibility */
#endif

#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
class CWSAInitializer{
public:
    CWSAInitializer(){
        WSADATA data;
        WSAStartup(MAKEWORD(2,2),&data);
    }
    ~CWSAInitializer(){
        WSACleanup();
    }
}autoInit;

#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif

const char* get_hostname(struct addrinfo* info, char buff[], int buff_len)
{
    int addrlen = (int)info->ai_addrlen;
    int res = getnameinfo(info->ai_addr, addrlen, buff, buff_len, NULL, 0, 0);
    if(res){
        return NULL;
    }
    return buff;
}

int main () 
{
    char temp[100];
    addrinfo *ai,hints;
    memset(&hints,0,sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_NUMERICSERV;
    hints.ai_flags |= AI_PASSIVE;

    int res = getaddrinfo(NULL, "0", &hints, &ai); 
    if(res){
        std::cerr<<gai_strerror(res)<<std::endl;
        return -1;
    }
    std::cout<< get_hostname(ai,temp,100)<<std::endl;
    freeaddrinfo(ai);

    return 0;
}

EDIT

  1. The server should accept client from other machines as well, so it can't report listening on :: or 0.0.0.0.

  2. I know I can patch it like this:

if(std::string("::") == hostname || std::string("0.0.0.0") == hostname) gethostname(hostname,100)

  1. I don't want to get localhost as result, unless the address is 127.0.0.1 or ::1.

Upvotes: 1

Views: 1308

Answers (1)

alk
alk

Reputation: 70911

getaddrinfo() returns the head of list of struct addrinfo nodes.

Travers this list using struct addrinfo's a member ai_next to find the addresses of all interfaces of the machine.

To receive anything else but wildcard addresses do not specify the AI_PASSIVE flag in the hints passed.


Update on the various names given to a machine and/or its interfaces' addresses:

  1. The host's name ("hostname") as returend by gethostname() is an attribute to the host. It is configured on the host and not held in any external database. This host name per definition is not linked to any of the names the possible interfaces' addresses resolve to. The host name might however be configured to match the name that one of the addresses (of the interfaces of the machine) resolves to.

  2. There might be more then one interface provided by a machine. Each of these interfaces' address should resolves to a different name, which in turn could also all differ from the name returned by gethostname() (see 1. above). This applies to all types of interfaces including IPv4 and IPv6. There also it the virtual wildcard-address (0.0.0.0for IPv4) which allows programs to bind to and listen on all interfaces (IPv4 typed here) a machine provides. The wildcard-adresse has no name.

The conclusion from 1. and 2. is: There is no name "... like [returned by] gethostname() but canonical."!

Upvotes: 1

Related Questions