diff --git a/include/sk-inet.h b/include/sk-inet.h index bb7b67a98..a0817695e 100644 --- a/include/sk-inet.h +++ b/include/sk-inet.h @@ -33,6 +33,7 @@ struct inet_sk_info { int inet_bind(int sk, struct inet_sk_info *); int inet_connect(int sk, struct inet_sk_info *); +void tcp_repair_off(int sk); void tcp_unlock_all(void); void tcp_locked_conn_add(struct inet_sk_info *); void tcp_unlock_connections(void); diff --git a/sk-inet.c b/sk-inet.c index 8c90a1c95..554328463 100644 --- a/sk-inet.c +++ b/sk-inet.c @@ -403,16 +403,23 @@ static int inet_validate_address(InetSkEntry *ie) static int post_open_inet_sk(struct file_desc *d, int sk) { struct inet_sk_info *ii; - int no = 0; + int val; ii = container_of(d, struct inet_sk_info, d); - if (!ii->ie->opts->reuseaddr) { - futex_wait_until(&ii->port->users, 0); + /* SO_REUSEADDR is set for all sockets */ + if (!tcp_connection(ii->ie) && ii->ie->opts->reuseaddr) + return 0; - if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &no)) - return -1; - } + futex_wait_until(&ii->port->users, 0); + + /* Disabling repair mode drops SO_REUSEADDR */ + if (tcp_connection(ii->ie)) + tcp_repair_off(sk); + + val = ii->ie->opts->reuseaddr; + if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val)) + return -1; return 0; } diff --git a/sk-tcp.c b/sk-tcp.c index fa31556db..a9ba6025a 100644 --- a/sk-tcp.c +++ b/sk-tcp.c @@ -55,7 +55,7 @@ static int tcp_repair_on(int fd) return ret; } -static void tcp_repair_off(int fd) +void tcp_repair_off(int fd) { int aux = 0; @@ -484,7 +484,6 @@ int restore_one_tcp(int fd, struct inet_sk_info *ii) if (restore_tcp_conn_state(fd, ii)) return -1; - tcp_repair_off(fd); return 0; }