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?