Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper length of an AF_UNIX socket when calling bind()

Tags:

c

unix

sockets

bind() needs a length of the sockaddr structure you've given it. Now, for unix sockets, sockaddr_un is used

What's the proper ways of calculating the length of this when you've filled in the sun_path member ? I've seen multiple approaches:

socklen_t len = sizeof(sockaddr_un);
socklen_t len = offsetof(sockaddr_un,sun_path) + strlen(addr.sun_path);
socklen_t len = offsetof(sockaddr_un,sun_path) + strlen(addr.sun_path) + 1;
socklen_t len = sizeof(sockaddr.sun_family  ) + strlen(addr.sun_path);

And even other approaches. Is it ok to just take the sizeof(sockaddr_un) - or what is the proper way ?

like image 336
nos Avatar asked Feb 21 '10 21:02

nos


People also ask

What is AF_UNIX socket?

The AF_UNIX (also known as AF_LOCAL) socket family is used to communicate between processes on the same machine efficiently. Traditionally, UNIX domain sockets can be either unnamed, or bound to a filesystem pathname (marked as being of type socket).

How do you bind a socket in UNIX?

After a UNIX domain socket is created, you must bind the socket to a unique file path by using the bind function. Unlike internet sockets in the AF_INET domain where the socket is bound to a unique IP address and port number, a UNIX domain socket is bound to a file path.

Is TCP or UNIX socket faster?

Unix domain sockets are often twice as fast as a TCP socket when both peers are on the same host. The Unix domain protocols are not an actual protocol suite, but a way of performing client/server communication on a single host using the same API that is used for clients and servers on different hosts.

What is path to socket?

The default location for the Unix socket file that the server uses for communication with local clients is /var/lib/mysql/mysql. sock. In case you are using VPS, depending on the Operating system you choose - the socket path might differ.


2 Answers

You are supposed to use SUN_LEN macro. Here's from /usr/include/sys/un.h on my Mac:

#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
/* actual length of an initialized sockaddr_un */
#define SUN_LEN(su) \
        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */

Edit:

Yes, it's not portable and not POSIX, but we work on real platforms, don't we?

The thing is that you have to zero-terminate the path and the above code is as good as sizeof( struct sockaddr_un ) but might save you a few bytes when copying from user to kernel but wastes a few cycles in strlen.

Look at how Linux handles that length (from http://lxr.linux.no/linux+v2.6.32/net/unix/af_unix.c#L200):

static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp)
{
    if (len <= sizeof(short) || len > sizeof(*sunaddr))
        return -EINVAL;
    if (!sunaddr || sunaddr->sun_family != AF_UNIX)
        return -EINVAL;
    if (sunaddr->sun_path[0]) {
        /*
         * This may look like an off by one error but it is a bit more
         * subtle. 108 is the longest valid AF_UNIX path for a binding.
         * sun_path[108] doesnt as such exist.  However in kernel space
         * we are guaranteed that it is a valid memory location in our
         * kernel address buffer.
         */
        ((char *)sunaddr)[len] = 0;
        len = strlen(sunaddr->sun_path)+1+sizeof(short);
        return len;
    }

    *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
    return len;
}

Here len is directly from third argument to bind system call, but sunaddr is already copied into kernel space with that length. You can't have address longer then sizeof( sockadd_un ). Kernel does the strlen anyway.

So yes, doing sizeof( sockaddr_un ) is probably safer across the board, but telling kernel exact length doesn't hurt either.

like image 141
Nikolai Fetissov Avatar answered Oct 18 '22 14:10

Nikolai Fetissov


sizeof(struct sockaddr_un) is fine.

Take a look at the manpage unix(7). The field sun_path is a character array that is part of the struct.

like image 25
Stéphan Kochen Avatar answered Oct 18 '22 14:10

Stéphan Kochen