[英]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) */
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.