LINUX: Fix error queue processing

Receiving error queues in the Linux kernel is a little different from
userspace. When we encounter a cmsg that is not CMSG_OK, we need to
break out of the loop, and not just continue, since we can keep trying
to process the same cmsg over and over. In addition, on successful
return, the msg_control buffer has been modified to point to the next
available buffer space, and msg_controllen contains how many bytes are
remaining. So, we need to adjust the msg_control and msg_controllen
values to get something more familiar.

Change-Id: I7cc768ea31379915974431d2a3c1fec5e0ac71bb
Reviewed-on: http://gerrit.openafs.org/7927
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
This commit is contained in:
Andrew Deason 2012-08-01 16:31:09 -04:00 committed by Derrick Brashear
parent d55df0ac83
commit 407cfd281e

View File

@ -125,9 +125,14 @@ osi_HandleSocketError(osi_socket so)
if (code < 0 || !(msg.msg_flags & MSG_ERRQUEUE)) if (code < 0 || !(msg.msg_flags & MSG_ERRQUEUE))
goto out; goto out;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { /* kernel_recvmsg changes msg_control to point at the _end_ of the buffer,
if (CMSG_OK(&msg, cmsg) && cmsg->cmsg_level == SOL_IP && * and msg_controllen is set to the number of bytes remaining */
cmsg->cmsg_type == IP_RECVERR) msg.msg_controllen = ((char*)msg.msg_control - (char*)controlmsgbuf);
msg.msg_control = controlmsgbuf;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg && CMSG_OK(&msg, cmsg);
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
break; break;
} }
if (!cmsg) if (!cmsg)