0

Was trying to implement a TCP echo server with C, and came across this code while searching the web and was trying to compile it. It shows some error related to socket.h

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <error.h>
#include <strings.h>
#include <unistd.h>

#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024

int main(int argc, char **argv)
{
    struct sockaddr_in server;
    struct sockaddr_in client;
    int sock;
    int new;
    int sockaddr_len = sizeof(struct sockaddr_in);
    int data_len;
    char data[MAX_DATA];

    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
    {
        perror("server socket: ");
        exit(-1);

    }
    server.sin_family=AF_INET;
    server.sin_port=htons(atoi(argv[1]));
    server.sin_addr.s_addr=INADDR_ANY;
    bzero(&server.sin_zero, 0);

    if((bind(sock, (struct sockaddr *)&server, sockaddr_len)) == ERROR)
    {
        perror("bind: ");
        exit(-1);

    }
    if((listen(sock, MAX_CLIENTS)) == ERROR)
    {
        perror("listen");
        exit(-1);

    }
    while(1)
    {
        if((new = accept(sock, (struct sockaddr *)&client, sockaddr_len)) == ERROR)
        {
            perror("accept");
            exit(-1);
        }
        printf("New Client connected from port no %d and IP %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
        data_len = 1;
        while(data_len)
        {
            data_len = recv(new, data, MAX_DATA, 0);
            if(data_len)
            {
                send(new, data, data_len, 0);
                data[data_len] = '\0';
                printf("Sent mesg: %s", data);
            }
        }
        printf("Client disconnected\n");
        close(new);
    }
    close(sock);
}

While compiling in Linux using gcc (Debian 8.3.0-6) 8.3.0 following warnings/errors are thrown,

tcp_srv.c: In function ‘main’:
tcp_srv.c:50:54: warning: passing argument 3 of ‘accept’ makes pointer from integer without a cast [-Wint-conversion]
   if((new = accept(sock, (struct sockaddr *)&client, sockaddr_len)) == ERROR)
                                                      ^~~~~~~~~~~~
In file included from tcp_srv.c:4:
/usr/include/x86_64-linux-gnu/sys/socket.h:233:28: note: expected ‘socklen_t * restrict’ {aka ‘unsigned int * restrict’} but argument is of type ‘int’
      socklen_t *__restrict __addr_len);

The binary upon execution is giving a Segmentation fault which I assume due to this error. Tried googling this error but couldn't get any solutions as such.

akbharath
  • 3
  • 5
  • 1
    Hi @akbharath - If you look at the man page for accept the error is correct - https://man7.org/linux/man-pages/man2/accept.2.html - `int accept(int sockfd, struct sockaddr *restrict addr,socklen_t *restrict addrlen);` Is it possible you forget an `&` on sockaddr_len - i.e. `&sockaddr_len` – Mr R Apr 15 '21 at 19:10
  • `data[data_len] = '\0';` <<-- you are addressing out-of-bounds here data_len could be equal to MAX_DATA) – wildplasser Apr 15 '21 at 19:38
  • `while(data_len)` Data_len will be -1 on error, causing the loop to run until infilnity. – wildplasser Apr 15 '21 at 19:40

1 Answers1

0

accept prototype is:

     int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);

and manual says:

The address_len is a value-result parameter; it should initially contain the amount of space pointed to by address; on return it will contain the actual length (in bytes) of the address returned.

Third argument must be pointer to a socklen_t thus:

if((new = accept(sock, (struct sockaddr *)&client, &sockaddr_len)) == ERROR)
    
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69