aboutsummaryrefslogtreecommitdiffstats
path: root/mbone/vat/files/patch-af
blob: 6b73cca9f5c8602a3297b98951dd0d65b852adcf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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: