C - getaddrinfo returns "Servname not supported for ai_socktype"

20,384

Solution 1

TL;DR: There is no tproxy UDP port.


If you look up the tproxy service for UDP sockets in your service database,

getent services tproxy/udp

You get no output, because tproxy is not an UDP service. If you look at all tproxy services regardless of the protocol, getent services | grep -e tproxy, you'll see

tproxy    8081/tcp

which means that tproxy service is only defined for TCP protocol.

This means that if you ask getaddrinfo() for an UDP socket for service 8081, you will not find anything, because tproxy is only defined for TCP and not UDP.

Compare to the case where you ask for and UDP socket for xmpp-client service. At least my service database (getent services xmpp-client/udp) responds with

xmpp-client           5222/udp jabber-client

and indeed, getaddrinfo() happily provides the socket description for such UDP sockets (using xmpp-client or jabber-client as the service).

So, there are services like xmpp-client that do have both TCP and UDP ports defined. On my system, getent services | grep -e xmpp-client shows

xmpp-client           5222/tcp jabber-client
xmpp-client           5222/udp jabber-client

Because TCP and UDP are different protocols over IP, it makes sense that a service could use a different port number for TCP and UDP communications. So, it is unreasonable to assume that the service database should just return the same port numbers for TCP and UDP sockets.

In other words, you encounter the error because you mistakenly assume that because some service uses a TCP port, with a name registered in the service database, you should be able to use that name to specify an UDP port number, too.

TCP and UDP are separate protocols, and their port number spaces are separate. For example, TCP port 512 is used by the Unix exec r-service, whereas UDP port 512 is used by the biff mail notification service.

Solution 2

When a non-numeric value is given for the service parameter, it is looked up (on Linux) in the /etc/services file. This file maps a service name to a port/protocol. Below are some sample entries:

ssh             22/tcp  
telnet          23/tcp
domain          53/tcp                          # name-domain server
domain          53/udp

The reason you're getting an error is because there is no UDP entry in your /etc/services file for "tproxy". Take a look at this file and look for an entry that does specify a UDP port such as "domain". That should have entries for both 53/tcp and 53/udp. If you pass in "domain" as the service name you should get a result back.

Share:
20,384
Brian Salehi
Author by

Brian Salehi

A programmer who rarely uses StackOverflow.

Updated on July 14, 2020

Comments

  • Brian Salehi
    Brian Salehi almost 4 years

    So, after I got this error, I've been looking for an answer in here, almost everyone had a difficult way to fix this error but no one explained why this error occurs at all, so I don't find this question to be exactly duplicate.

    I wrote a TCP socket in C and I used "getaddrinfo" function to make the socket work with hostnames, well it worked perfectly! you can find my codes on github.

    but when I tried to create a UDP socket by "getaddrinfo" I got this error:
    Servname not supported for ai_socktype

    client.c

    const char *host = argv[1];
    const char *service = argv[2];
    const char *string = argv[3];
    
    struct addrinfo addrCriteria;
    memset(&addrCriteria, 0, sizeof(addrCriteria));
    addrCriteria.ai_family = AF_UNSPEC;
    addrCriteria.ai_socktype = SOCK_DGRAM;
    addrCriteria.ai_protocol = IPPROTO_UDP;
    
    struct addrinfo *servAddr;
    int ret = getaddrinfo(host, service, &addrCriteria, &servAddr);
    if(ret != 0)
        sysError(gai_strerror(ret));
    

    I realized that when I give "service" a numeric input like 8080, no errors would return but when I use a string as service name like "tproxy" which points to port/8081, 'gai_strerror' returns mentioned error.

    Obviously, gai_strerror says: "service names not supported for 'SOCK_DGRAM' socket types", but why? I mean the exact reason for "getaddrinfo" not supporting name services over UDP sockets?
    Is there any other way to use service names with UDP sockets instead of port numbers? how?

  • Brian Salehi
    Brian Salehi almost 7 years
    I can't believe I missed '/etc/services' file and different service names for TCP and UDP! this was a great reminder of my major mistakes. it works with 'http-alt' servname as it was defined for both TCP and UDP connections. yep thank you for your great explanation!