我有一个运行在RedHat安装的Linux上的工作代码,内核为2.6.18-194.el5#1 SMP x86_64 。
当我将代码移动到CentOS 6.3新安装的机器时,代码失败
分配套接字选项时出错: 数字参数超出域
后者的内核版本是2.6.32-279.el6.x86_64#1 SMP
下面是机器中正在工作和失败的代码。
struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1500000; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) != 0) { LM_ERR("Error assigning socket option: %s", strerror( errno )); return FALSE; }
尝试使用
tv.tv_sec = 1; tv.tv_usec = 500000;
我看到一些实现不接受超过10 ^ 6的tv_usec
。
编辑:这个问题是有趣的,挖一点点。 在内核源代码中寻找net/core/sock.c
我在net/core/sock.c
找到了下面net/core/sock.c
代码:
int sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { / ... / switch (optname) { / ... / case SO_RCVTIMEO: ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen); break; / ... / }
sock_set_timeout()
函数的开头确实包含一些范围检查:
static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) { struct timeval tv; if (optlen < sizeof(tv)) return -EINVAL; if (copy_from_user(&tv, optval, sizeof(tv))) return -EFAULT; if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC) return -EDOM; /* ... */ }
现在我们足够了解一些git blame
-ing :)引入了以下更改集的更改:
commit ba78073e6f70cd9c64a478a9bd901d7c8736cfbc Author: Vasily Averin <vvs@sw.ru> Date: Thu May 24 16:58:54 2007 -0700 [NET]: "wrong timeout value" in sk_wait_data() v2 sys_setsockopt() do not check properly timeout values for SO_RCVTIMEO/SO_SNDTIMEO, for example it's possible to set negative timeout values. POSIX do not defines behaviour for sys_setsockopt in case negative timeouts, but requires that setsockopt() shall fail with -EDOM if the send and receive timeout values are too big to fit into the timeout fields in the socket structure. In current implementation negative timeout can lead to error messages like "schedule_timeout: wrong timeout value". Proposed patch: - checks tv_usec and returns -EDOM if it is wrong - do not allows to set negative timeout values (sets 0 instead) and outputs ratelimited information message about such attempts. Signed-off-By: Vasily Averin <vvs@sw.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
我相信,提交评论解释了一切。 据我所见,这个改变包含在2.6.22-rc3中。
不应该这样
tv.tv_sec = 1; tv.tv_usec = 500000;
自1百万微秒== 1秒?