]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
IPv6 and DNS support
authorElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Mar 2021 10:14:06 +0000 (11:14 +0100)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Mar 2021 10:14:06 +0000 (11:14 +0100)
client.c
server.c
util.c
util.h

index 5bce71841f19b64da3c6ef808f46958d6c4718b2..dd48e307261979888f4665cc12ffd75a555631ed 100644 (file)
--- a/client.c
+++ b/client.c
@@ -4,6 +4,7 @@
 #include <arpa/inet.h>
 #include <unistd.h>
 #include <errno.h>
+#include <netdb.h>
 #include "client.h"
 #include "signal.h"
 #include "util.h"
@@ -146,6 +147,23 @@ int main(int argc, char **argv)
 {
        program_name = argv[0];
 
+       if (argc < 3)
+               internal_error("missing address or port");
+
+       struct addrinfo hints = {
+               .ai_family = AF_UNSPEC,                 // support both IPv4 and IPv6
+               .ai_socktype = SOCK_STREAM,
+               .ai_protocol = 0,
+               .ai_flags = AI_NUMERICSERV,
+       };
+
+       struct addrinfo *info = NULL;
+
+       int gai_state = getaddrinfo(argv[1], argv[2], &hints, &info);
+
+       if (gai_state != 0)
+               internal_error(gai_strerror(gai_state));
+
        Client client = {
                .fd = -1,
                .map = NULL,
@@ -155,28 +173,16 @@ int main(int argc, char **argv)
 
        pthread_mutex_init(&client.mtx, NULL);
 
-       client.fd = socket(AF_INET, SOCK_STREAM, 0);
+       client.fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
 
        if (client.fd == -1)
                syscall_error("socket");
 
-       if (argc <= 1)
-               internal_error("missing address");
-
-       struct in_addr addr_buf;
-
-       if (inet_aton(argv[1], &addr_buf) == 0)
-               internal_error("invalid address");
-
-       struct sockaddr_in addr = {
-               .sin_family = AF_INET,
-               .sin_port = get_port_from_args(argc, argv, 2),
-               .sin_addr = addr_buf,
-       };
-
-       if (connect(client.fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+       if (connect(client.fd, info->ai_addr, info->ai_addrlen) == -1)
                syscall_error("connect");
 
+       freeaddrinfo(info);
+
        init_signal_handlers();
 
        client.map = map_create();
index eec407c89ff661429e992f81628fa2ebfebae135..94364d239e0a2e2fc721188098022f9f867f0edf 100644 (file)
--- a/server.c
+++ b/server.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <netdb.h>
 #include "server.h"
 #include "signal.h"
 #include "util.h"
@@ -68,10 +69,10 @@ static void *reciever_thread(void *clientptr)
 
 static void accept_client(Server *srv)
 {
-       struct sockaddr_in client_addr_buf = {0};
-       socklen_t client_addrlen = sizeof(client_addr_buf);
+       struct sockaddr_storage client_address = {0};
+       socklen_t client_addrlen = sizeof(client_address);
 
-       int fd = accept(srv->sockfd, (struct sockaddr *) &client_addr_buf, &client_addrlen);
+       int fd = accept(srv->sockfd, (struct sockaddr *)&client_address, &client_addrlen);
 
        if (fd == -1) {
                if (errno == EINTR)
@@ -85,7 +86,7 @@ static void accept_client(Server *srv)
        client->state = CS_CREATED;
        client->fd = fd;
        client->name = NULL;
-       client->address = address_string(&client_addr_buf);
+       client->address = address_string((struct sockaddr_in6 *) &client_address);
 
        printf("Connected %s\n", client->address);
 
@@ -99,34 +100,47 @@ int main(int argc, char **argv)
 {
        program_name = argv[0];
 
+       if (argc < 2)
+               internal_error("missing port");
+
+       struct addrinfo hints = {
+               .ai_family = AF_INET6,
+               .ai_socktype = SOCK_STREAM,
+               .ai_protocol = 0,
+               .ai_flags = AI_NUMERICSERV | AI_PASSIVE,
+       };
+
+       struct addrinfo *info = NULL;
+
+       int gai_state = getaddrinfo(NULL, argv[1], &hints, &info);
+
+       if (gai_state != 0)
+               internal_error(gai_strerror(gai_state));
+
        Server server = {
                .sockfd = -1,
                .map = NULL,
                .clients = linked_list_create(),
        };
 
-       server.sockfd = socket(AF_INET, SOCK_STREAM, 0);
+       server.sockfd = socket(info->ai_family, info->ai_socktype, 0);
 
        if (server.sockfd == -1)
                syscall_error("socket");
 
-       struct sockaddr_in srv_addr = {
-               .sin_family = AF_INET,
-               .sin_port = get_port_from_args(argc, argv, 1),
-               .sin_addr = {.s_addr = INADDR_ANY},
-       };
-
        int flag = 1;
 
        if (setsockopt(server.sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, 4) == -1)
                syscall_error("setsockopt");
 
-       if (bind(server.sockfd, (struct sockaddr *) &srv_addr, sizeof(srv_addr)) == -1)
+       if (bind(server.sockfd, info->ai_addr, info->ai_addrlen) == -1)
                syscall_error("bind");
 
        if (listen(server.sockfd, 3) == -1)
                syscall_error("listen");
 
+       freeaddrinfo(info);
+
        init_signal_handlers();
 
        server.map = map_create(NULL);
diff --git a/util.c b/util.c
index d7c6650487ecd94f094270fe186e828c740e57cd..e8c9e3a386d45aac8f8e70efb404ac2753d2e5c6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <limits.h>
 #include <unistd.h>
 #include <string.h>
 #include "util.h"
@@ -19,20 +18,6 @@ void internal_error(const char *err)
        exit(EXIT_FAILURE);
 }
 
-
-unsigned short get_port_from_args(int argc, char **argv, int index)
-{
-       if (argc <= index)
-               internal_error("missing port");
-
-       unsigned int port = atoi(argv[index]);
-
-       if (port == 0 || port > USHRT_MAX)
-               internal_error("invalid port");
-
-       return htons(port);
-}
-
 char *read_string(int fd, size_t bufsiz)
 {
        char buf[bufsiz + 1];
@@ -51,12 +36,16 @@ char *read_string(int fd, size_t bufsiz)
        return strdup(buf);
 }
 
-char *address_string(struct sockaddr_in *addr)
+char *address_string(struct sockaddr_in6 *addr)
 {
-       char *str_addr = inet_ntoa(addr->sin_addr);
-       char str_port[5];
-       sprintf(str_port, "%d", ntohs(addr->sin_port));
-       char *address = malloc(strlen(str_addr) + 1 + strlen(str_port) + 1);
-       sprintf(address, "%s:%s", str_addr, str_port);
-       return address;
+       char address[INET6_ADDRSTRLEN] = {0};
+       char port[6] = {0};
+
+       if (inet_ntop(addr->sin6_family, &addr->sin6_addr, address, INET6_ADDRSTRLEN) == NULL)
+               perror("inet_ntop");
+       sprintf(port, "%d", ntohs(addr->sin6_port));
+
+       char *result = malloc(strlen(address) + 1 + strlen(port) + 1);
+       sprintf(result, "%s:%s", address, port);
+       return result;
 }
diff --git a/util.h b/util.h
index 5dfae4a0ceb6a9ba132939bed3cdd9d88f98d7d1..ed53816b902f78576cd78f20290de4ef14b6122d 100644 (file)
--- a/util.h
+++ b/util.h
@@ -11,8 +11,7 @@ extern const char *program_name;
 
 void syscall_error(const char *err);
 void internal_error(const char *err);
-u16 get_port_from_args(int argc, char **argv, int index);
 char *read_string(int fd, size_t bufsiz);
-char *address_string(struct sockaddr_in *addr);
+char *address_string(struct sockaddr_in6 *addr);
 
 #endif