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

nos*_*nos 9 c unix sockets

bind()需要一段你给它的sockaddr结构.现在,对于unix套接字,使用了sockaddr_un

当你填写sun_path会员时,计算这个长度的正确方法是什么?我见过多种方法:

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);
Run Code Online (Sandbox Code Playgroud)

甚至其他方法.是否可以采取sizeof(sockaddr_un) - 或者正确的方法是什么?

Nik*_*sov 9

你应该使用SUN_LEN宏.这是来自/usr/include/sys/un.h我的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) */
Run Code Online (Sandbox Code Playgroud)

编辑:

是的,它不是便携式而不是POSIX,但我们在真实平台上工作,不是吗?

问题是你必须对路径进行零终止并且上面的代码一样好,sizeof( struct sockaddr_un )但是当从用户复制到内核但是浪费了几个周期时,可能会节省几个字节strlen.

看看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;
}
Run Code Online (Sandbox Code Playgroud)

len是直接从第三个参数到bind系统调用,但sunaddr已经被复制到具有该长度的内核空间中.你不能拥有更长的地址sizeof( sockadd_un ).strlen无论如何,内核都会这样做.

所以是的,做起来sizeof( sockaddr_un )可能更安全,但是告诉内核的确切长度也不会造成伤害.

  • 我不知道`SUN_LEN`,也没有拒绝你。但是我对`SUN_LEN`的来源很感兴趣,所以我用Google搜索了它,并发现了这个非常有用的文章:http://mail-index.netbsd.org/tech-net/2006/10/11/0008。 html (2认同)
  • “ SUN_LEN”不可移植,并且不在POSIX中。 (2认同)

Sté*_*hen 4

sizeof(struct sockaddr_un)很好。

看一下联机帮助页unix(7)。该字段sun_path是一个字符数组,是结构的一部分。

  • 是的,“man 2 bind”也有一个绑定 Unix 域套接字的示例。http://www.opengroup.org/onlinepubs/9699919799/functions/bind.html (3认同)