From dc542a393b530d7a48835f4d49722d5de65ab602 Mon Sep 17 00:00:00 2001 From: Tobias Girstmair Date: Mon, 28 Dec 2020 17:18:22 +0100 Subject: [PATCH] use getaddrinfo() for transparent ipv4/6 support introduces a malloc :( --- ircpipe.c | 69 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/ircpipe.c b/ircpipe.c index 4652864..ad66e92 100644 --- a/ircpipe.c +++ b/ircpipe.c @@ -1,5 +1,4 @@ -#define _POSIX_C_SOURCE 200809L /* getopt(>=2), gethostbyname(>=200809L), dprintf(>=200809L), strtok_r(*) */ -#define _DEFAULT_SOURCE /* herror(*) */ +#define _POSIX_C_SOURCE 200809L /* getopt(>=2), dprintf(>=200809L), strtok_r(*), getaddrinfo(>=200112L) */ #include #include #include @@ -8,22 +7,25 @@ #include #include #include -#ifndef NO_TLS +#include + +#ifndef WITHOUT_TLS #include #include #endif -#define DEFAULT_PORT 6667 #define DEFAULT_PING 60000 /*ms*/ #define DEFAULT_TIMEOUT 2000 /*ms*/ -#define DEFAULT_TLS 0 /*off*/ +#define DEFAULT_TLS NO_TLS +#define DEFAULT_PORT_PLAIN "6667" +#define DEFAULT_PORT_TLS "6697" #define POLL_TIMEOUT 100 #define STR_(x) #x #define STR(x) STR_(x) #define OR_DIE < 0 && (perror(__FILE__ ":" STR(__LINE__)), exit(1), 0) -#define OR_DIE_h == NULL && (herror(__FILE__ ":" STR(__LINE__)), exit(1), 0) +#define OR_DIE_gai(err) if (err) {fprintf(stderr, __FILE__ ":" STR(__LINE__) ": %s\n", gai_strerror(err));exit(1);} enum pass_type_e { NO_PASSWD, @@ -31,26 +33,44 @@ enum pass_type_e { SASL_PLAIN_PASSWD, }; +enum tls_use_e { + NO_TLS, + USE_TLS, + INSECURE_TLS, +}; + void irc_help(const char *exe, const int code) { fprintf(stderr, "Usage: %s [-n NICK] [-j CHAN] HOST [PORT]\n", exe); exit(code); } -int irc_connect(const char *host, const unsigned short port) { +int irc_connect(const char *host, const char *port) { int sockfd; - struct sockaddr_in addr = {0}; - struct hostent *host_e; + struct addrinfo *results, *r; + + fprintf(stderr, "%s : %s\n", host,port); + int err = getaddrinfo(host, port, NULL, &results); OR_DIE_gai(err); /*unable to resolve*/ - host_e = gethostbyname(host); host_e OR_DIE_h; + for (r = results; r != NULL; r = r->ai_next) { + sockfd = socket(r->ai_family, SOCK_STREAM, 0); + if (sockfd < 0) continue; /* try next; todo: should check errno */ - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr = *((struct in_addr *)host_e->h_addr_list[0]); + if (connect(sockfd, r->ai_addr, r->ai_addrlen) == 0) + break; /* successfully connected */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd OR_DIE; - /* tls here */ - /* connect timeout here */ - connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) OR_DIE; + close(sockfd); /* failed, try next addr */ + } + + if (r == NULL) { + /* all failed; abort. */ + sockfd = -1; + } else { + /* connection established. */ + /* tls here */ + /* connect timeout here */ + } + + freeaddrinfo(results); return sockfd; } @@ -191,10 +211,10 @@ void irc_cleanup(const int sockfd) { int main(int argc, char **argv) { char *host = NULL; + char *port = NULL; char *nick = NULL; char *pass = NULL; char *chan = NULL; - unsigned short port = DEFAULT_PORT; size_t ping_iv = DEFAULT_PING; /* interval between outgoing pings */ size_t resp_to = DEFAULT_TIMEOUT; /* how long to wait for command response (connect, ping, auth, ...) */ int tls = DEFAULT_TLS; @@ -207,13 +227,14 @@ int main(int argc, char **argv) { pass = getenv("IRC_PASSWD"); - while ((opt = getopt(argc, argv, "n:j:psh")) != -1) { + while ((opt = getopt(argc, argv, "n:j:pPsSkh")) != -1) { switch (opt) { case 'n': nick = optarg; break; case 'p': pass_type = SERVER_PASSWD; break; case 'P': pass_type = SASL_PLAIN_PASSWD; break; - case 's': tls = 1; break; - case 'S': tls = 0; break; + case 's': tls = USE_TLS; break; + case 'S': tls = NO_TLS; break; + case 'k': tls = INSECURE_TLS; break; case 'j': chan = optarg; break; default: irc_help(argv[0], opt != 'h'); } @@ -226,7 +247,11 @@ int main(int argc, char **argv) { irc_help(argv[0], 1); } if (optind < argc) { - port = atoi(argv[optind++]); + port = argv[optind++]; + } else { + port = (tls == NO_TLS) + ? DEFAULT_PORT_PLAIN + : DEFAULT_PORT_TLS; } if (optind < argc) { /* too many positional arguments */ -- 2.39.3