简体   繁体   English

调用bind()时AF_UNIX套接字的正确长度

[英]Proper length of an AF_UNIX socket when calling bind()

bind () needs a length of the sockaddr structure you've given it. bind ()需要一段你给它的sockaddr结构。 Now, for unix sockets, sockaddr_un is used 现在,对于unix套接字,使用了sockaddr_un

What's the proper ways of calculating the length of this when you've filled in the sun_path member ? 当你填写sun_path成员时,计算长度的正确方法是什么? 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 ? 是否可以采取sizeof(sockaddr_un) - 或者正确的方法是什么?

You are supposed to use SUN_LEN macro. 你应该使用SUN_LEN宏。 Here's from /usr/include/sys/un.h on my Mac: 这是我Mac上的/usr/include/sys/un.h

#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? 是的,它不是便携式而不是POSIX,但我们在真实平台上工作,不是吗?

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 . 问题是您必须对路径进行零终止,并且上面的代码与sizeof( struct sockaddr_un )一样好,但是当从用户复制到内核但在strlen浪费几个周期时可能会节省几个字节。

Look at how Linux handles that length (from http://lxr.linux.no/linux+v2.6.32/net/unix/af_unix.c#L200 ): 看看Linux如何处理这个长度(来自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. 这里len直接来自bind系统调用的第三个参数,但是sunaddr已经被复制到具有该长度的内核空间中。 You can't have address longer then sizeof( sockadd_un ) . 你的地址不能sizeof( sockadd_un ) Kernel does the strlen anyway. 无论如何,内核都会执行strlen

So yes, doing sizeof( sockaddr_un ) is probably safer across the board, but telling kernel exact length doesn't hurt either. 所以,是的,执行sizeof( sockaddr_un )可能更安全,但是告诉内核的确切长度也不会造成伤害。

sizeof(struct sockaddr_un) is fine. sizeof(struct sockaddr_un)很好。

Take a look at the manpage unix(7) . 看一下manix unix(7) The field sun_path is a character array that is part of the struct. 字段sun_path是一个字符数组,是结构的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM