From d9ba501e5eae2e81dc1a627bea3815ce45f3a416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20J=2E=20Saraiva?= Date: Sat, 16 Mar 2024 21:00:59 +0000 Subject: [PATCH 1/3] Warn when SO_REUSEADDR is not set. This is a "minimum effort" warning. When a socket bind/listen fails without SO_REUSEADDR then the ip-port combination might be in the TIME_WAIT state. There is no way to test if that is actual case, so just warn the user. --- common/net.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/net.c b/common/net.c index 9f774b409..bdcb272ec 100644 --- a/common/net.c +++ b/common/net.c @@ -440,11 +440,14 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) if (fd_array[nsock] < 0) continue; - setsockopt(fd_array[nsock],SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); + error = setsockopt(fd_array[nsock],SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); if ((bind(fd_array[nsock],res->ai_addr,res->ai_addrlen) < 0) || ((sock_type == SOCK_STREAM) && (listen(fd_array[nsock],5) < 0))) { + if (error) { + fprintf(stderr,"Warning: ip_listen: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); + } close(fd_array[nsock]); fd_array[nsock] = -1; continue; @@ -479,7 +482,7 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) if (ip_addr && strlen(ip_addr)) sin.sin_addr.s_addr = inet_addr(ip_addr); - setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); + error = setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); if (bind(sck,(struct sockaddr *)&sin,sizeof(sin)) < 0) { perror("ip_listen: bind"); @@ -495,6 +498,9 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) return(1); error: + if (error) { + fprintf(stderr,"Warning: ip_listen: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); + } close(sck); return(-1); } From cf73f377da4c73722bf944c9d4c2efc0882a9bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20J=2E=20Saraiva?= Date: Sat, 16 Mar 2024 21:22:01 +0000 Subject: [PATCH 2/3] Warn when SO_REUSEADDR is no set in udp_connect. --- common/net.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/net.c b/common/net.c index bdcb272ec..1a5f1c2ad 100644 --- a/common/net.c +++ b/common/net.c @@ -333,11 +333,14 @@ int udp_connect(int local_port,char *remote_host,int remote_port) } /* try to connect to remote host */ - setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + error = setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); if (!bind(sck,(struct sockaddr *)&st,res->ai_addrlen) && !connect(sck,res->ai_addr,res->ai_addrlen)) break; + if (error) { + fprintf(stderr,"Warning: udp_connect: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); + } close(sck); sck = -1; } @@ -377,9 +380,12 @@ int udp_connect(int local_port,char *remote_host,int remote_port) sin.sin_family = PF_INET; sin.sin_port = htons(local_port); - setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + error = setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); if (bind(sck,(struct sockaddr *)&sin,sizeof(sin)) < 0) { perror("udp_connect: bind"); + if (error) { + fprintf(stderr,"Warning: udp_connect: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); + } close(sck); return(-1); } From c94f4cf10725353634ad5d8cd45b4de0ce80d4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20J=2E=20Saraiva?= Date: Tue, 2 Apr 2024 17:00:13 +0100 Subject: [PATCH 3/3] Simplify SO_REUSEADDR warnings and add bind/listen errors. --- common/net.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/common/net.c b/common/net.c index 1a5f1c2ad..d5fbff532 100644 --- a/common/net.c +++ b/common/net.c @@ -333,14 +333,15 @@ int udp_connect(int local_port,char *remote_host,int remote_port) } /* try to connect to remote host */ - error = setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) != 0) + perror("Warning: upd_connect: setsockopt(SO_REUSEADDR)"); + if (!bind(sck,(struct sockaddr *)&st,res->ai_addrlen) && - !connect(sck,res->ai_addr,res->ai_addrlen)) + !connect(sck,res->ai_addr,res->ai_addrlen)) { + perror("udp_connect: bind/connect"); break; - - if (error) { - fprintf(stderr,"Warning: udp_connect: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); } + close(sck); sck = -1; } @@ -380,12 +381,11 @@ int udp_connect(int local_port,char *remote_host,int remote_port) sin.sin_family = PF_INET; sin.sin_port = htons(local_port); - error = setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) != 0) + perror("Warning: upd_connect: setsockopt(SO_REUSEADDR)"); + if (bind(sck,(struct sockaddr *)&sin,sizeof(sin)) < 0) { perror("udp_connect: bind"); - if (error) { - fprintf(stderr,"Warning: udp_connect: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); - } close(sck); return(-1); } @@ -446,14 +446,13 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) if (fd_array[nsock] < 0) continue; - error = setsockopt(fd_array[nsock],SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); + if (setsockopt(fd_array[nsock],SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) != 0) + perror("Warning: ip_listen: setsockopt(SO_REUSEADDR): The same address-port combination can be retried after the TCP TIME_WAIT state expires."); if ((bind(fd_array[nsock],res->ai_addr,res->ai_addrlen) < 0) || ((sock_type == SOCK_STREAM) && (listen(fd_array[nsock],5) < 0))) { - if (error) { - fprintf(stderr,"Warning: ip_listen: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); - } + perror("ip_listen: bind/listen"); close(fd_array[nsock]); fd_array[nsock] = -1; continue; @@ -488,7 +487,8 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) if (ip_addr && strlen(ip_addr)) sin.sin_addr.s_addr = inet_addr(ip_addr); - error = setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); + if (setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) != 0) + perror("Warning: ip_listen: setsockopt(SO_REUSEADDR): The same address-port combination can be retried after the TCP TIME_WAIT state expires."); if (bind(sck,(struct sockaddr *)&sin,sizeof(sin)) < 0) { perror("ip_listen: bind"); @@ -504,9 +504,6 @@ int ip_listen(char *ip_addr,int port,int sock_type,int max_fd,int fd_array[]) return(1); error: - if (error) { - fprintf(stderr,"Warning: ip_listen: SO_REUSEADDR is not set. The same address-port combination can be retried after the TIME_WAIT state expires."); - } close(sck); return(-1); }