From 3d39a9a0702f5bcfae88be5d8dfe5e3e28f95dd2 Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 17 Feb 2009 10:40:20 +0000 Subject: * ext/socket/ancdata.c (bsock_sendmsg_internal): should not remove the last padding of control messages, basically. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/socket/ancdata.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'ext') diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index b78af5460a..cbe10f51d6 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -890,6 +890,8 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) #if defined(HAVE_ST_MSG_CONTROL) int i; int last_pad = 0; + int last_level = 0; + int last_type = 0; controls_str = rb_str_tmp_new(0); for (i = 0; i < controls_num; i++) { VALUE elt = controls_ptr[i], v; @@ -925,13 +927,33 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) cmh->cmsg_type = type; cmh->cmsg_len = CMSG_LEN(RSTRING_LEN(cdata)); MEMCPY(CMSG_DATA(cmh), RSTRING_PTR(cdata), char, RSTRING_LEN(cdata)); + last_level = cmh->cmsg_level; + last_type = cmh->cmsg_type; last_pad = cspace - cmh->cmsg_len; } -#if !defined(__OpenBSD__) if (last_pad) { - rb_str_set_len(controls_str, RSTRING_LEN(controls_str)-last_pad); + /* + * This code removes the last padding from msg_controllen. + * + * 4.3BSD-Reno reject the padding for SCM_RIGHTS. (There was no 64bit environments in those days?) + * RFC 2292 require the padding. + * RFC 3542 relaxes the condition - implementation must accept both as valid. + * + * Actual problems: + * + * - NetBSD 4.0.1 + * SCM_RIGHTS with padding causes EINVAL + * IPV6_PKTINFO without padding causes "page fault trap" + * + * - OpenBSD 4.4 + * IPV6_PKTINFO without padding causes EINVAL + * + * Basically, msg_controllen should contains the padding. + * So the padding is removed only if a problem really exists. + */ + if (last_level == SOL_SOCKET && last_type == SCM_RIGHTS) + rb_str_set_len(controls_str, RSTRING_LEN(controls_str)-last_pad); } -#endif #else rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented"); #endif -- cgit v1.2.3