From: pcarana Date: Thu, 7 Mar 2019 01:03:45 +0000 (-0600) Subject: Remember connected clients X-Git-Tag: v0.0.2~52^2~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2106f3fda463160611cd4c5f443639738fb08477;p=thirdparty%2FFORT-validator.git Remember connected clients 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). --- diff --git a/src/Makefile.am b/src/Makefile.am index 21449a28..ea022a95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..bb7fa6ac --- /dev/null +++ b/src/clients.c @@ -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 index 00000000..345eaf6d --- /dev/null +++ b/src/clients.h @@ -0,0 +1,23 @@ +#ifndef SRC_CLIENTS_H_ +#define SRC_CLIENTS_H_ + +#include +#include + +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_ */ diff --git a/src/main.c b/src/main.c index 58c209fb..3c327f2b 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include #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: diff --git a/src/rtr/pdu.c b/src/rtr/pdu.c index ffc7413e..992092ea 100644 --- a/src/rtr/pdu.c +++ b/src/rtr/pdu.c @@ -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; diff --git a/src/rtr/pdu.h b/src/rtr/pdu.h index 2c194b5a..225aa828 100644 --- a/src/rtr/pdu.h +++ b/src/rtr/pdu.h @@ -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 diff --git a/src/rtr/rtr.c b/src/rtr/rtr.c index 63b7a02d..81f87956 100644 --- a/src/rtr/rtr.c +++ b/src/rtr/rtr.c @@ -11,6 +11,7 @@ #include #include +#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(¶m, 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(¶m.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