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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# HG changeset patch
# User Lars Ellenberg <lars@linbit.com>
# Date 1392200751 -3600
# Node ID 37f57a36a2dd1abf8461a9b758e62f6fe7a22f77
# Parent 6d4324633600dc7ae7aa08c56d86c2fcc767977f
Medium: fix usage of SO_REUSEPORT in ucast sockets
Linux learned SO_REUSEPORT only with kernel 3.9,
but some linux headers already define SO_REUSEPORT.
Which, on older kernels, will result in ENOPROTOOPT,
"Protocol not available".
Failure to set SO_REUSEPORT is NOT critical in general.
It *may* be a problem on certain BSDs,
with more than two nodes, all using ucast.
Refusing to start because of failure to set SO_REUSEPORT is
not helpful for the vast majority of the clusters out there.
While at it, downgrade "critical" log messages to warnings
in non-fatal situations.
--- a/lib/plugins/HBcomm/ucast.c
+++ b/lib/plugins/HBcomm/ucast.c
@@ -461,12 +461,6 @@ static int HB_make_send_sock(struct hb_m
int sockfd;
struct ip_private *ei;
int tos;
-#if defined(SO_BINDTODEVICE)
- struct ifreq i;
-#endif
-#if defined(SO_REUSEPORT)
- int i = 1;
-#endif
UCASTASSERT(mp);
ei = (struct ip_private*)mp->pd;
@@ -494,6 +488,7 @@ static int HB_make_send_sock(struct hb_m
#if defined(SO_BINDTODEVICE)
{
+ struct ifreq i;
/*
* We want to send out this particular interface
*
@@ -515,12 +510,13 @@ static int HB_make_send_sock(struct hb_m
#endif
#if defined(SO_REUSEPORT)
{
+ int one = 1;
/* this is for OpenBSD to allow multiple *
* ucast connections, e.g. a more than *
* two node cluster */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
- &i, sizeof(i)) == -1) {
+ &one, sizeof(one)) == -1) {
PILCallLog(LOG, PIL_CRIT,
"ucast: error setting option SO_REUSEPORT(w): %s", strerror(errno));
close(sockfd);
@@ -548,7 +544,7 @@ static int HB_make_receive_sock(struct h
int sockfd;
int bindtries;
int boundyet = 0;
- int j;
+ int one = 1;
UCASTASSERT(mp);
ei = (struct ip_private*)mp->pd;
@@ -563,22 +559,19 @@ static int HB_make_receive_sock(struct h
strerror(errno));
return -1;
}
- /*
- * Set SO_REUSEADDR on the server socket s. Variable j is used
- * as a scratch varable.
- *
- * 16th February 2000
- * Added by Horms <horms@vergenet.net>
- * with thanks to Clinton Work <work@scripty.com>
- */
- j = 1;
+ /*
+ * Set SO_REUSEADDR on the server socket s.
+ * Below, also try to set SO_REUSEPORT,
+ * if known and supported.
+ */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
- (void *)&j, sizeof j) < 0) {
+ &one, sizeof(one)) < 0) {
/* Ignore it. It will almost always be OK anyway. */
- PILCallLog(LOG, PIL_CRIT,
+ PILCallLog(LOG, PIL_WARN,
"ucast: error setting socket option SO_REUSEADDR: %s",
strerror(errno));
- }
+ } else
+ PILCallLog(LOG, PIL_INFO, "ucast: set SO_REUSEADDR");
#if defined(SO_BINDTODEVICE)
{
/*
@@ -600,20 +593,32 @@ static int HB_make_receive_sock(struct h
}
#endif
#if defined(SO_REUSEPORT)
- {
+ /*
+ * Needed for OpenBSD for more than two nodes in a ucast cluster
+ */
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
+ &one, sizeof(one)) == -1) {
/*
- * Needed for OpenBSD for more than two nodes in a ucast cluster
+ * Linux learned SO_REUSEPORT only with kernel 3.9,
+ * but some linux headers already define SO_REUSEPORT.
+ * Which will result in ENOPROTOOPT, "Protocol not available"
+ * on older kernels.
+ * Failure to set SO_REUSEPORT is NOT critical in general.
+ * It *may* be a problem on certain BSDs with more than
+ * two nodes all using ucast.
+ * Refusing to start because of failure to set SO_REUSEPORT is
+ * not helpful for the vast majority of the clusters out there.
*/
- int i = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
- &i, sizeof(i)) == -1) {
+ if (errno == ENOPROTOOPT) {
+ PILCallLog(LOG, PIL_WARN,
+ "ucast: error setting option SO_REUSEPORT: %s", strerror(errno));
+ } else {
PILCallLog(LOG, PIL_CRIT,
- "ucast: error setting option SO_REUSEPORT(r) %s", strerror(errno));
- close(sockfd);
+ "ucast: error setting option SO_REUSEPORT: %s", strerror(errno));
return -1;
}
- PILCallLog(LOG, PIL_INFO, "ucast: set SO_REUSEPORT(w)");
- }
+ } else
+ PILCallLog(LOG, PIL_INFO, "ucast: set SO_REUSEPORT");
#endif
/* Try binding a few times before giving up */
|