blob: 3bec9c89dd86c5160abc344dd7020673187fbeea [file] [log] [blame]
# 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 */