]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Remember connected clients
authorpcarana <pc.moreno2099@gmail.com>
Thu, 7 Mar 2019 01:03:45 +0000 (19:03 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Thu, 7 Mar 2019 01:03:45 +0000 (19:03 -0600)
Use sockaddr_storage to fetch both IPv4 & 6 socket info.
Fetch the RTR version when the PDU is loaded.
Expose client data for later use (Serial Notify PDU).

src/Makefile.am
src/clients.c [new file with mode: 0644]
src/clients.h [new file with mode: 0644]
src/main.c
src/rtr/pdu.c
src/rtr/pdu.h
src/rtr/rtr.c

index 21449a288ac7b3df44bca45937672bf362b7d40e..ea022a95e7cd4e0b16e771e0a85e1d421b44693f 100644 (file)
@@ -6,6 +6,7 @@ bin_PROGRAMS = rtr_server
 rtr_server_SOURCES = main.c
 rtr_server_SOURCES += address.c address.h
 rtr_server_SOURCES += array_list.h
+rtr_server_SOURCES += clients.c clients.h
 rtr_server_SOURCES += common.c common.h
 rtr_server_SOURCES += configuration.c configuration.h
 rtr_server_SOURCES += csv.c csv.h
diff --git a/src/clients.c b/src/clients.c
new file mode 100644 (file)
index 0000000..bb7fa6a
--- /dev/null
@@ -0,0 +1,106 @@
+#include "clients.h"
+
+#include "array_list.h"
+
+#define SADDR_IN(addr) ((struct sockaddr_in *)addr)
+#define SADDR_IN6(addr) ((struct sockaddr_in6 *)addr)
+
+ARRAY_LIST(clientsdb, struct client)
+
+struct clientsdb *clients_db;
+
+int
+clients_db_init(void)
+{
+       int error;
+
+       clients_db = malloc(sizeof(struct clientsdb));
+       if (clients_db == NULL) {
+               err(-ENOMEM, "Clients DB couldn't be allocated");
+               return -ENOMEM;
+       }
+       error = clientsdb_init(clients_db);
+       if (error)
+               err(error, "Clients DB couldn't be initialized");
+
+       return error;
+}
+
+static int
+clients_db_add_client(struct client *client)
+{
+       return clientsdb_add(clients_db, client);
+}
+
+static struct client
+*get_client(struct sockaddr_storage *addr, u_int8_t rtr_version)
+{
+       struct client *ptr;
+
+       ARRAYLIST_FOREACH(clients_db, ptr)
+               if (ptr->rtr_version == rtr_version &&
+                   ptr->sin_family == addr->ss_family) {
+                       if (ptr->sin_family == AF_INET) {
+                               if (ptr->sin_addr.s_addr == SADDR_IN(addr)->sin_addr.s_addr &&
+                                   ptr->sin_port == SADDR_IN(addr)->sin_port)
+                                       return ptr;
+                       } else if (ptr->sin_family == AF_INET6)
+                               if (IN6_ARE_ADDR_EQUAL(ptr->sin6_addr.s6_addr32, SADDR_IN6(addr)->sin6_addr.s6_addr32) &&
+                                   ptr->sin_port == SADDR_IN6(addr)->sin6_port)
+                                       return ptr;
+               }
+
+       return NULL;
+}
+
+static int
+create_client(struct sockaddr_storage *addr, u_int8_t rtr_version,
+    time_t ttl)
+{
+       struct client *client;
+
+       client = malloc(sizeof(struct client));
+       if (client == NULL) {
+               err(-ENOMEM, "Couldn't allocate client");
+               return -ENOMEM;
+       }
+
+       client->sin_family = addr->ss_family;
+       if (addr->ss_family == AF_INET) {
+               client->sin_addr = SADDR_IN(addr)->sin_addr;
+               client->sin_port = SADDR_IN(addr)->sin_port;
+       } else if (addr->ss_family == AF_INET6) {
+               client->sin6_addr = SADDR_IN6(addr)->sin6_addr;
+               client->sin_port = SADDR_IN6(addr)->sin6_port;
+       }
+       client->rtr_version = rtr_version;
+       client->expiration = time(NULL) + ttl;
+
+       return clients_db_add_client(client);
+}
+
+int
+update_client(struct sockaddr_storage *addr, u_int8_t rtr_version,
+    time_t ttl)
+{
+       struct client *client;
+       client = get_client(addr, rtr_version);
+
+       if (client == NULL)
+               return create_client(addr, rtr_version, ttl);
+       client->expiration = time(NULL) + ttl;
+       return 0;
+}
+
+static void
+client_destroy(struct client *client)
+{
+       free(client);
+}
+
+void
+clients_db_destroy(void)
+{
+       clientsdb_cleanup(clients_db, client_destroy);
+       free(clients_db);
+}
diff --git a/src/clients.h b/src/clients.h
new file mode 100644 (file)
index 0000000..345eaf6
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef SRC_CLIENTS_H_
+#define SRC_CLIENTS_H_
+
+#include <arpa/inet.h>
+#include <time.h>
+
+struct client {
+       sa_family_t sin_family;
+       union {
+               struct in_addr sin_addr;
+               struct in6_addr sin6_addr;
+       };
+       in_port_t sin_port;
+       u_int8_t rtr_version;
+       /* TODO forget clients when the expiration time is reached */
+       time_t expiration;
+};
+
+int clients_db_init(void);
+int update_client(struct sockaddr_storage *, u_int8_t, time_t);
+void clients_db_destroy(void);
+
+#endif /* SRC_CLIENTS_H_ */
index 58c209fb0ad0d7535ac72614fcac5f3f88fff7be..3c327f2b60f3494fb2d27c8fb0db7bf2f2a7903d 100644 (file)
@@ -4,6 +4,7 @@
 #include <unistd.h>
 
 #include "rtr/rtr.h"
+#include "clients.h"
 #include "configuration.h"
 #include "csv.h"
 #include "updates_daemon.h"
@@ -49,16 +50,22 @@ main(int argc, char *argv[])
        if (err)
                goto end1;
 
-       err = csv_parse_vrps_file();
+       err = clients_db_init();
        if (err)
                goto end2;
 
+       err = csv_parse_vrps_file();
+       if (err)
+               goto end3;
+
        err = updates_daemon_init();
        if (err)
-               goto end2;
+               goto end3;
 
        err = rtr_listen();
 
+end3:
+       clients_db_destroy();
 end2:
        deltas_db_destroy();
 end1:
index ffc7413eba728542f9eaf012b2f06f6df5530711..992092eaeefe69f2216db074496e03e8b2230a9b 100644 (file)
@@ -21,7 +21,8 @@ static int    error_report_from_stream(struct pdu_header *, int, void *);
 static void    error_report_destroy(void *);
 
 int
-pdu_load(int fd, void **pdu, struct pdu_metadata const **metadata)
+pdu_load(int fd, void **pdu, struct pdu_metadata const **metadata,
+    u_int8_t *rtr_version)
 {
        struct pdu_header header;
        struct pdu_metadata const *meta;
@@ -44,6 +45,7 @@ pdu_load(int fd, void **pdu, struct pdu_metadata const **metadata)
                free(*pdu);
                return err;
        }
+       *rtr_version = header.protocol_version;
 
        if (metadata)
                *metadata = meta;
@@ -139,6 +141,7 @@ error_report_from_stream(struct pdu_header *header, int fd, void *pdu_void)
 {
        struct error_report_pdu *pdu = pdu_void;
        u_int32_t sub_pdu_len; /* TODO use this for something */
+       u_int8_t rtr_version;
        int error;
 
        memcpy(&pdu->header, header, sizeof(*header));
@@ -147,7 +150,7 @@ error_report_from_stream(struct pdu_header *header, int fd, void *pdu_void)
        if (error)
                return error;
 
-       error = pdu_load(fd, &pdu->erroneous_pdu, NULL);
+       error = pdu_load(fd, &pdu->erroneous_pdu, NULL, &rtr_version);
        if (error)
                return -EINVAL;
 
index 2c194b5ae32884421e42b7ff70ffeb5820c1b1d1..225aa82892f3f72454820b2d31700441fae7dbdc 100644 (file)
@@ -104,7 +104,7 @@ struct pdu_metadata {
 };
 
 __BEGIN_DECLS
-int pdu_load(int, void **, struct pdu_metadata const **);
+int pdu_load(int, void **, struct pdu_metadata const **, u_int8_t *);
 struct pdu_metadata const *pdu_get_metadata(u_int8_t);
 struct pdu_header *pdu_get_header(void *);
 __END_DECLS
index 63b7a02de4dc850f0eff1970d45c5ecf5410b411..81f8795629ad233e92e1c49ff22ef43448a49f86 100644 (file)
@@ -11,6 +11,7 @@
 #include <unistd.h>
 #include <arpa/inet.h>
 
+#include "clients.h"
 #include "configuration.h"
 #include "pdu.h"
 
@@ -55,6 +56,7 @@ create_server_socket(void)
  */
 struct thread_param {
        int     client_fd;
+       struct sockaddr_storage client_addr;
 };
 
 enum verdict {
@@ -112,12 +114,18 @@ client_thread_cb(void *param_void)
        struct pdu_metadata const *meta;
        void *pdu;
        int err;
+       u_int8_t rtr_version;
 
        memcpy(&param, param_void, sizeof(param));
        free(param_void); /* Ha. */
 
        while (true) { /* For each PDU... */
-               err = pdu_load(param.client_fd, &pdu, &meta);
+               err = pdu_load(param.client_fd, &pdu, &meta, &rtr_version);
+               if (err)
+                       return NULL;
+
+               /* RTR Version ready, now update client */
+               err = update_client(&param.client_addr, rtr_version, 3600);
                if (err)
                        return NULL;
 
@@ -137,7 +145,7 @@ static int
 handle_client_connections(int server_fd)
 {
        int client_fd;
-       struct sockaddr_in client_addr;
+       struct sockaddr_storage client_addr;
        socklen_t sizeof_client_addr;
        struct thread_param *arg;
        pthread_t thread;
@@ -171,6 +179,7 @@ handle_client_connections(int server_fd)
                        continue;
                }
                arg->client_fd = client_fd;
+               arg->client_addr = client_addr;
 
                /*
                 * FIXME Handle session IDs, serial IDs, protocol version