NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/56346: Listening socket instantly closes if TCP_KEEPALIVE options are set on the server side



>Number:         56346
>Category:       kern
>Synopsis:       Listening socket instantly closes if TCP_KEEPALIVE options are set on the server side
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 02 07:55:00 +0000 2021
>Originator:     Szilard Parrag
>Release:        9.2
>Organization:
>Environment:
NetBSD localhost 9.2 NetBSD 9.2 (GENERIC) #0: Wed May 12 13:15:55 UTC 2021  mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64

>Description:
When exectuing the following code the listening socket closes after setting TCP_KEEPALIVE options. This does not happen on Linux, as the values are inherited by the clients/peers.
>How-To-Repeat:
Run the following program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/tcp.h>

void setsockopt_or_fail(int socket, int level, int options_name, const void *option_value, socklen_t option_len){
        int retval = setsockopt(socket, level, options_name, option_value, option_len); 
        if(retval < 0){
                perror("setter failed");
                exit(1);
        }
}


int main(){

        //socket prep
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in server = {0};
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_family = AF_INET;
        server.sin_port = htons(4442);


        int on = 1;
        setsockopt_or_fail(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
        unsigned int a = 10;
        setsockopt_or_fail(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &a, sizeof(a));
        a = 3;
        setsockopt_or_fail(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &a, sizeof(a));
        a = 1;
        setsockopt_or_fail(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &a, sizeof(a));

        //bind
        if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0){
                perror("bind error");
                exit(1);
        }

        //listen

        if(listen(sockfd, 10) < 0){
                perror("listen error");
                exit(1);
        }
        printf("we are listening\n");

        // accept
        for(;;){
                int clientfd = accept(sockfd, NULL, NULL);
                if(clientfd < 0){
                        perror("error during accept");
                        exit(1);
                }
                printf("accepted\n");
                char buff[50];
                while(1){
                        int retval = read(clientfd, &buff, sizeof(buff));

                        if(retval == 0){
                                printf("Connection has finished\n");
                                break;
                        }
                        else if(retval < 0){
                                perror("error reading socket");
                                exit(1);
                        }
                }
                close(clientfd);
        }
        close(sockfd);
}

>Fix:



Home | Main Index | Thread Index | Old Index