From 1e0c535fa1ccec5631c76cde51c917550634ea2e Mon Sep 17 00:00:00 2001 From: Bill Fenner Date: Thu, 19 Feb 1998 19:00:40 +0000 Subject: Handle a bug that LBL thought was fixed in 4.4BSD but wasn't: send() on a socket with a pending error doesn't reset the error, so the socket is effectively useless. Use getsockopt(...SO_ERROR...) to clear the error status. The kernel should also be patched, but this patch is required for backwards compatibility. --- mbone/vat/files/patch-af | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 mbone/vat/files/patch-af (limited to 'mbone/vat') diff --git a/mbone/vat/files/patch-af b/mbone/vat/files/patch-af new file mode 100644 index 000000000000..6b73cca9f5c8 --- /dev/null +++ b/mbone/vat/files/patch-af @@ -0,0 +1,117 @@ +--- net.cc.orig 1997/10/07 19:07:01 ++++ net.cc 1998/01/26 22:21:41 +@@ -163,46 +163,48 @@ + { + int cc = ::send(fd, (char*)buf, len, 0); + if (cc < 0) { +- switch (errno) { ++ /* ++ * Due to a bug in kern/uipc_socket.c, on several ++ * systems, datagram sockets incorrectly persist ++ * in an error state on receipt of any ICMP ++ * error. This causes unicast connection ++ * rendezvous problems, and worse, multicast ++ * transmission problems because several systems ++ * incorrectly send port unreachables for ++ * multicast destinations. Our work around ++ * is to call getsockopt(..., SO_ERROR, ...) ++ * which resets so->so_error. ++ * ++ * This bug originated at CSRG in Berkeley ++ * and was present in the BSD Reno networking ++ * code release. It has since been fixed ++ * in OSF-3.x. It is know to remain ++ * in 4.4BSD and AIX-4.1.3. ++ * ++ * A fix is to change the following lines from ++ * kern/uipc_socket.c: ++ * ++ * if (so_serror) ++ * snderr(so->so_error); ++ * ++ * to: ++ * ++ * if (so->so_error) { ++ * error = so->so_error; ++ * so->so_error = 0; ++ * splx(s); ++ * goto release; ++ * } ++ * ++ */ ++ int err, errlen = sizeof(err), savederrno; ++ ++ savederrno = errno; ++ getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, ++ &errlen); ++ switch (savederrno) { + case ECONNREFUSED: + /* no one listening at some site - ignore */ +-#if defined(__osf__) || defined(_AIX) +- /* +- * Due to a bug in kern/uipc_socket.c, on several +- * systems, datagram sockets incorrectly persist +- * in an error state on receipt of an ICMP +- * port-unreachable. This causes unicast connection +- * rendezvous problems, and worse, multicast +- * transmission problems because several systems +- * incorrectly send port unreachables for +- * multicast destinations. Our work around +- * is to simply close and reopen the socket +- * (by calling reset() below). +- * +- * This bug originated at CSRG in Berkeley +- * and was present in the BSD Reno networking +- * code release. It has since been fixed +- * in 4.4BSD and OSF-3.x. It is know to remain +- * in AIX-4.1.3. +- * +- * A fix is to change the following lines from +- * kern/uipc_socket.c: +- * +- * if (so_serror) +- * snderr(so->so_error); +- * +- * to: +- * +- * if (so->so_error) { +- * error = so->so_error; +- * so->so_error = 0; +- * splx(s); +- * goto release; +- * } +- * +- */ +- reset(); +-#endif + break; + + case ENETUNREACH: +@@ -217,7 +219,7 @@ + * icmp unreachable, so we should be able to + * send now. + */ +- (void)::send(ssock_, (char*)buf, len, 0); ++ (void)::send(fd, (char*)buf, len, 0); + break; + + default: +@@ -264,12 +266,14 @@ + } + int cc = ::sendmsg(ssock_, (msghdr*)&mh, 0); + if (cc < 0) { +- switch (errno) { ++ int err, errlen = sizeof(err), savederrno; ++ ++ savederrno = errno; ++ getsockopt(ssock_, SOL_SOCKET, SO_ERROR, &err, ++ &errlen); ++ switch (savederrno) { + case ECONNREFUSED: + /* no one listening at some site - ignore */ +-#if defined(__osf__) || defined(_AIX) +- reset(); +-#endif + break; + + case ENETUNREACH: -- cgit v1.2.3