]> git.lizzy.rs Git - dragonnet.git/commitdiff
Use getaddrinfo and getnameinfo for address parsing
authorElias Fleckenstein <eliasfleckenstein@web.de>
Sun, 17 Apr 2022 15:07:24 +0000 (17:07 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Sun, 17 Apr 2022 15:07:24 +0000 (17:07 +0200)
addr.c
addr.h
listen.c
listen.h
peer.c
peer.h
recv.c
recv_thread.c
send.c

diff --git a/addr.c b/addr.c
index b9a6d378798e6da573221a9bc5181441585b27a8..da8fc2564e5d1f23a6aa172ec92a3b93a8209e5a 100644 (file)
--- a/addr.c
+++ b/addr.c
@@ -1,56 +1,56 @@
-#include <asprintf/asprintf.h>
 #include <dragonnet/addr.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-DragonnetAddr dragonnet_addr_parse_str(char *str)
+struct addrinfo *dragonnet_str2addr(const char *str)
 {
-       DragonnetAddr addr = {0};
-
-       size_t colon_i = 0;
-       for (ssize_t i = strlen(str)-1; i >= 0; --i) {
-               if (str[i] == ':') {
-                       colon_i = i;
-                       break;
-               }
+       const char *port = str + strlen(str) - 1;
+       while (port >= str && *port != ':')
+               port--;
+       port++;
+
+       const char *host_begin = str;
+       if (*host_begin == '[')
+               host_begin++;
+
+       const char *host_end = port - 2;
+       if (host_end >= str && *host_end == ']')
+               host_end--;
+
+       ssize_t host_len = host_end - host_begin + 1;
+       if (host_len < 0)
+               host_len = 0;
+
+       char host[host_len + 1];
+       host[host_len] = '\0';
+       memcpy(host, host_begin, host_len);
+
+       struct addrinfo *result, hints = {0};
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+
+       int err;
+       if ((err = getaddrinfo(host, port, &hints, &result))) {
+               fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
+               return NULL;
        }
 
-       size_t ip_addr_i = 0, port_i = 0;
-       for (size_t i = 0; i < strlen(str); ++i) {
-               if (i < colon_i && str[i] != '[' && str[i] != ']')
-                       addr.ip[ip_addr_i++] = str[i];
-               else if (i > colon_i)
-                       addr.port[port_i++] = str[i];
-       }
-
-       return addr;
-}
-
-char *dragonnet_addr_str(DragonnetAddr addr)
-{
-       char *ptr;
-       asprintf(&ptr, "[%s]:%s", addr.ip, addr.port);
-       return ptr;
+       return result;
 }
 
-DragonnetAddr dragonnet_addr_parse_sock(struct sockaddr_in6 ai_addr)
+char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len)
 {
-       DragonnetAddr addr = {0};
-       sprintf(addr.port, "%d", ntohs(ai_addr.sin6_port));
-       inet_ntop(AF_INET6, &ai_addr.sin6_addr, addr.ip, INET6_ADDRSTRLEN);
+       char host[NI_MAXHOST], port[NI_MAXSERV];
 
-       return addr;
-}
-
-struct sockaddr_in6 dragonnet_addr_sock(DragonnetAddr addr)
-{
-       struct sockaddr_in6 ai_addr = {0};
-       ai_addr.sin6_family = AF_INET6;
-       ai_addr.sin6_flowinfo = 0;
-       ai_addr.sin6_port = htons(atoi(addr.port));
-       inet_pton(AF_INET6, addr.ip, &ai_addr.sin6_addr);
+       int err;
+       if ((err = getnameinfo(addr, addr_len, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICSERV))) {
+               fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err));
+               return NULL;
+       }
 
-       return ai_addr;
+       char str[1 + strlen(host) + 1 + 1 + strlen(port) + 1];
+       sprintf(str, "[%s]:%s", host, port);
+       return strdup(str);
 }
diff --git a/addr.h b/addr.h
index b70ed1f3a006f6b4fa1a78685221ef9cb2dada95..fdffa4a03cf58260158bfeb39263e132bb8bfe37 100644 (file)
--- a/addr.h
+++ b/addr.h
@@ -1,17 +1,11 @@
 #ifndef _DRAGONNET_ADDR_H_
 #define _DRAGONNET_ADDR_H_
 
-#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 
-typedef struct {
-       char ip[INET6_ADDRSTRLEN];
-       char port[6];
-} DragonnetAddr;
-
-DragonnetAddr dragonnet_addr_parse_str(char *addr);
-char *dragonnet_addr_str(DragonnetAddr addr);
-
-DragonnetAddr dragonnet_addr_parse_sock(struct sockaddr_in6 ai_addr);
-struct sockaddr_in6 dragonnet_addr_sock(DragonnetAddr addr);
+struct addrinfo *dragonnet_str2addr(const char *str);
+char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len);
 
 #endif
index b65ca8baea151ab2093a9c1d0bccbd93f8c2dd06..83adba60c9c3f01726dd5f3d96a2bd01758e8e7b 100644 (file)
--- a/listen.c
+++ b/listen.c
@@ -1,5 +1,6 @@
 #define _GNU_SOURCE
 #include <assert.h>
+#include <dragonnet/addr.h>
 #include <dragonnet/listen.h>
 #include <dragonnet/recv.h>
 #include <errno.h>
 // ----
 
 static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock,
-               struct sockaddr_in6 addr, DragonnetListener *l)
+               char *addr, DragonnetListener *l)
 {
        pthread_mutex_init(&p->mtx, NULL);
 
        p->sock = sock;
-       p->laddr = l->laddr;
-       p->raddr = dragonnet_addr_parse_sock(addr);
+       p->address = addr;
        p->on_disconnect = l->on_disconnect;
        p->on_recv = l->on_recv;
        p->on_recv_type = l->on_recv_type;
@@ -30,13 +30,14 @@ static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock,
        return true;
 }
 
-static DragonnetPeer *dragonnet_peer_accept(int sock, struct sockaddr_in6 addr,
+static DragonnetPeer *dragonnet_peer_accept(int sock, char *addr,
                DragonnetListener *l)
 {
        DragonnetPeer *p = malloc(sizeof *p);
        if (!dragonnet_peer_init_accepted(p, sock, addr, l)) {
                pthread_mutex_destroy(&p->mtx);
                free(p);
+               free(addr);
                return NULL;
        }
 
@@ -49,10 +50,15 @@ static DragonnetPeer *dragonnet_peer_accept(int sock, struct sockaddr_in6 addr,
 
 DragonnetListener *dragonnet_listener_new(char *addr)
 {
+       struct addrinfo *info = dragonnet_str2addr(addr);
+       if (!info)
+               return NULL;
+
        DragonnetListener *l = malloc(sizeof *l);
 
        l->active = true;
-       l->sock = socket(AF_INET6, SOCK_STREAM, 0);
+       l->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+       l->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen);
        l->on_connect = NULL;
        l->on_disconnect = NULL;
        l->on_recv = NULL;
@@ -62,19 +68,20 @@ DragonnetListener *dragonnet_listener_new(char *addr)
        if (setsockopt(l->sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr,
                        sizeof so_reuseaddr) < 0) {
                perror("setsockopt");
+               freeaddrinfo(info);
                dragonnet_listener_delete(l);
                return NULL;
        }
 
-       l->laddr = dragonnet_addr_parse_str(addr);
-       struct sockaddr_in6 ai_addr = dragonnet_addr_sock(l->laddr);
-
-       if (bind(l->sock, (const struct sockaddr *) &ai_addr, sizeof ai_addr) < 0) {
+       if (bind(l->sock, info->ai_addr, info->ai_addrlen) < 0) {
                perror("bind");
+               freeaddrinfo(info);
                dragonnet_listener_delete(l);
                return NULL;
        }
 
+       freeaddrinfo(info);
+
        if (listen(l->sock, 10) < 0) {
                perror("listen");
                dragonnet_listener_delete(l);
@@ -93,8 +100,8 @@ static void *listener_main(void *g_listener)
        DragonnetListener *l = (DragonnetListener *) g_listener;
 
        while (l->active) {
-               struct sockaddr_in6 clt_addr;
-               socklen_t clt_addrlen = sizeof clt_addr;
+               struct sockaddr_storage clt_addr;
+               socklen_t clt_addrlen;
 
                int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen);
                if (clt_sock < 0) {
@@ -103,7 +110,8 @@ static void *listener_main(void *g_listener)
                        continue;
                }
 
-               DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addr, l);
+               char *clt_addstr =  dragonnet_addr2str((struct sockaddr *) &clt_addr, clt_addrlen);
+               DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addstr, l);
                if (p == NULL)
                        continue;
 
@@ -134,5 +142,6 @@ void dragonnet_listener_close(DragonnetListener *l)
 void dragonnet_listener_delete(DragonnetListener *l)
 {
        free(l->on_recv_type);
+       free(l->address);
        free(l);
 }
index 8346cccd063fafe5d24863a2ee055fa954254f9b..6d31eaa3b004447be7ad730b0f60e682457fbeb1 100644 (file)
--- a/listen.h
+++ b/listen.h
@@ -6,7 +6,8 @@
 
 typedef struct {
        int sock;
-       DragonnetAddr laddr;
+       char *address;
+
        pthread_t accept_thread;
        bool active;
 
diff --git a/peer.c b/peer.c
index 75eb6abe18876f5059965771e67613a3730a6d4a..ad17be6af59e4824b8cd828c45f732eda7ceff1b 100644 (file)
--- a/peer.c
+++ b/peer.c
@@ -1,4 +1,5 @@
 #include <assert.h>
+#include <dragonnet/addr.h>
 #include <dragonnet/peer.h>
 #include <dragonnet/recv.h>
 #include <dragonnet/recv_thread.h>
@@ -10,28 +11,25 @@ static bool dragonnet_peer_init(DragonnetPeer *p, char *addr)
 {
        pthread_mutex_init(&p->mtx, NULL);
 
-       p->sock = socket(AF_INET6, SOCK_STREAM, 0);
-       p->raddr = dragonnet_addr_parse_str(addr);
-       p->on_disconnect = NULL;
-       p->on_recv = NULL;
-       p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types);
+       struct addrinfo *info = dragonnet_str2addr(addr);
+       if (!info)
+               return false;
+
+       p->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+       p->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen);
 
-       struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr);
-       if (connect(p->sock, (const struct sockaddr *) &sock_addr,
-                       sizeof sock_addr) < 0) {
+       if (connect(p->sock, info->ai_addr, info->ai_addrlen) < 0) {
+               freeaddrinfo(info);
                perror("connect");
                return false;
        }
 
-       struct sockaddr_in6 sock_name;
-       socklen_t sock_namelen = sizeof sock_name;
+       freeaddrinfo(info);
 
-       if (getsockname(p->sock, (struct sockaddr *) &sock_name, &sock_namelen) < 0) {
-               perror("getsockname");
-               return false;
-       }
+       p->on_disconnect = NULL;
+       p->on_recv = NULL;
+       p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types); // fixme: memory leak
 
-       p->laddr = dragonnet_addr_parse_sock(sock_name);
        return true;
 }
 
diff --git a/peer.h b/peer.h
index 8b1a65a68e3a59998901d29938c9bd6adc31c23b..ce6100bc2bb72994923c97839094664ec73e1179 100644 (file)
--- a/peer.h
+++ b/peer.h
@@ -1,7 +1,6 @@
 #ifndef _DRAGONNET_PEER_H_
 #define _DRAGONNET_PEER_H_
 
-#include <dragonnet/addr.h>
 #include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -10,7 +9,8 @@ typedef uint16_t DragonnetTypeId;
 
 typedef struct dragonnet_peer {
        int sock;
-       DragonnetAddr laddr, raddr;
+       char *address;
+
        pthread_t recv_thread;
        pthread_mutex_t mtx;
 
diff --git a/recv.c b/recv.c
index 75a37197b8ab5237adb24bdd795cb5b417ff953d..4cb9be3cc49c5aca149323867ba96a90bb92eca6 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n)
index aefb33548d340b64a7e3b770858ddcf2ce2d3a26..a84e109469ff4f1612bc63404084795ea11f7eb8 100644 (file)
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 void *dragonnet_peer_recv_thread(void *g_peer)
@@ -41,6 +43,7 @@ void *dragonnet_peer_recv_thread(void *g_peer)
                                p->on_disconnect(p);
 
                        close(p->sock);
+                       free(p->address);
 
                        pthread_mutex_destroy(&p->mtx);
                        free(p);
diff --git a/send.c b/send.c
index ce3736670abcd0b2324397d5ba522692a48ca65c..c9dc260d59c4cbc5fc615d31ac88ac474c7e3a22 100644 (file)
--- a/send.c
+++ b/send.c
@@ -3,6 +3,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 
 bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n)
 {