--- 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: