1

When calling connect in my program below, it fails with errno of 22 (EINVAL).

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

int main(int argc, char** argv) {
    if(argc != 3) { /* usage */
        fprintf(stderr, "usage: talk address port\n");
        return EXIT_FAILURE;
    }

    char* address = argv[1];
    char* port = argv[2];

    struct addrinfo hints;
    struct addrinfo *servinfo;
    struct addrinfo *clientinfo;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    int gai_res = getaddrinfo(address, port, &hints, &servinfo);

    if(gai_res) {
        fprintf(stderr, "Failed to resolve remote address: %s\n",
            gai_strerror(gai_res));
        return EXIT_FAILURE;
    }

    gai_res = getaddrinfo(NULL, port, &hints, &clientinfo);

    if(gai_res) {
        fprintf(stderr, "Failed to resolve local address: %s\n",
            gai_strerror(gai_res));
        return EXIT_FAILURE;
    }


    int socket_fd = socket(servinfo->ai_family, servinfo->ai_socktype,
        servinfo->ai_protocol);

    if(socket_fd == -1) {
        fprintf(stderr, "Failed to open socket to remote host: %s\n",
            strerror(errno));
        freeaddrinfo(servinfo);
        return EXIT_FAILURE;
    }

    int bind_res = bind(socket_fd, clientinfo->ai_addr, clientinfo->ai_addrlen);

    if(bind_res == -1) {
        fprintf(stderr, "Failed to bind to socket: %s\n", strerror(errno));
        freeaddrinfo(servinfo);
        return EXIT_FAILURE;
    }

    int connect_res = connect(socket_fd, servinfo->ai_addr,
        servinfo->ai_addrlen);

    if(connect_res == -1) {
        fprintf(stderr, "Failed to connect to socket: %s\n", strerror(errno));
        freeaddrinfo(servinfo);
        return EXIT_FAILURE;
    }

    ssize_t bytes_sent = send(socket_fd, "Hello", 7, 0);

    if(bytes_sent == -1) {
        fprintf(stderr, "Failed to send to remote host: %s\n", strerror(errno));
        freeaddrinfo(servinfo);
        return EXIT_FAILURE;
    }

    printf("Sent message to %s on port %s\n", address, port);

    close(socket_fd);
    freeaddrinfo(servinfo);

    return EXIT_SUCCESS;
}

$ gcc talk.c -Wall -Wextra -Wshadow -pedantic -std=gnu99 -g3 -o talk
$ ./talk 192.168.0.16 3301
Failed to connect to socket: Invalid argument

When I inspect the contents of servinfo in GDB, everything seems fine:

$ gdb talk -q
Reading symbols from talk...done.
(gdb) b main.c:63
Breakpoint 1 at 0x13fb: file main.c, line 63.
(gdb) run 192.168.0.16 3301
Starting program: /home/foo/dev/tmp/talk/talk 192.168.0.16 3301

Breakpoint 1, main (argc=3, argv=0x7fffffffe328) at main.c:63
63      int connect_res = connect(socket_fd, servinfo->ai_addr,
(gdb) p servinfo
$1 = (struct addrinfo *) 0x555555559260
(gdb) p *servinfo
$2 = {ai_flags = 0, ai_family = 2, ai_socktype = 2, ai_protocol = 17, ai_addrlen = 16, ai_addr = 0x555555559290, ai_canonname = 0x0, ai_next = 0x0}
(gdb) p servinfo->ai_addr
$3 = (struct sockaddr *) 0x555555559290
(gdb) p *(servinfo->ai_addr)
$4 = {sa_family = 2, sa_data = "\f\345\300\250\000\020\000\000\000\000\000\000\000"}

Note that calling connect on UDP sockets is well-defined and is done (in this case, at least) to allow easy use of send and recv (rather than their datagram counterparts).

Which of the parameters to connect would be invalid in this case?

jmcph4
  • 197
  • 2
  • 8
  • Not an answer but your message "Failed to connect to socket" is not correct. You failed to connect *this socket* to a remote *address.* – user207421 Sep 01 '20 at 10:19
  • I've compiled and run your program, seems to work ok. Is this Linux? `strace` output might help. – Mark Nunberg Sep 01 '20 at 12:50
  • Cast `servinfo->ai_addr` to `struct sockaddr_in*` and make sure its `sin_addr` and `sin_port` fields are correct. – Remy Lebeau Sep 01 '20 at 23:38
  • I suggest there is something wrong with the port. Try setting `hints.ai_flags = AI_NUMERICSERV;` to force it to be treated as numeric, and check the value you get back to ensure it isn't zero. – user207421 Sep 02 '20 at 03:34
  • @MarkNunberg This is running on OpenBSD 6.7. – jmcph4 Sep 06 '20 at 03:52

0 Answers0