4

OS X doesn't offer the SO_PROTOCOL socket option which allows the caller to "...retrieve the socket type as an integer." (http://linux.die.net/man/7/socket)

In other words the following program builds and works under linux but won't compile under OS X:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
    int c, s, type, len;
    len = sizeof(type);

    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s < 0)
    {  
        fprintf(stderr, "socket kaboom: %s\n", strerror(errno));
        return 1;
    }
    if (getsockopt(s, SOL_SOCKET, SO_PROTOCOL, &type, &len) < 0)
    {  
        fprintf(stderr, "getsosockopt kaboom: %s\n", strerror(errno));
        return 1;
    }
    printf("socket type: %d\n", type);
    return 0;
}

How to accomplish this under OS X?

Mike Schiffman
  • 240
  • 3
  • 9
  • It looks to me like this doesn't seem to be supported on OS X. What do you need this for? Can you not just remember what protocol you used to create the socket in the call to `socket(2)`? – Adam Rosenfield Jun 25 '14 at 22:38
  • 3
    `SO_PROTOCOL` is not [standard](http://pubs.opengroup.org/onlinepubs/009695399/functions/getsockopt.html). What do you intend to do after finding out whether a socket is TCP or UDP? – dreamlax Jun 25 '14 at 22:39

1 Answers1

2

The standard SO_TYPE socket option, which returns values like SOCK_STREAM (corresponding to TCP) and SOCK_DGRAM (corresponding to UDP), should suffice. With SCTP, SOCK_STREAM might correspond to TCP or SCTP and SO_PROTOCOL is useful to distinguish them, but MacOS X does not support SCTP.

Unix domain sockets do not use protocol numbers; therefore, SO_TYPE is the right choice there as well.

jilles
  • 10,509
  • 2
  • 26
  • 39
  • 1
    How do you distinguish between a Unix domain socket opened with SOCK_STREAM and a TCP socket with SOCK_STREAM ? – Brennan Vincent Sep 10 '15 at 21:37
  • This seems a different question, but the standard offers getsockname() and getpeername() only, which only work if the socket is bound or connected, respectively. You might also use the fact that only Unix domain sockets can send and receive data without being bound to an address. The SO_DOMAIN socket option is not ubiquitously available. – jilles Sep 12 '15 at 12:18