]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Use Error PDUs handling methods and prepare to send other error PDUs
authorpcarana <pc.moreno2099@gmail.com>
Mon, 11 Mar 2019 17:52:36 +0000 (11:52 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Mon, 11 Mar 2019 17:52:36 +0000 (11:52 -0600)
Send Unexpected Protocol Version when needed.
Simplify 'send_error_report_pdu' call.
Remove error codes definitions from 'pdu.h'.
Send Unsupported PDU error when such PDUs arrive to the server.
Try to close socket when a fatal Error PDU is received.
Log errno when there's an error sending a response.

src/clients.c
src/rtr/pdu.c
src/rtr/pdu.h
src/rtr/pdu_handler.c
src/rtr/pdu_sender.c
src/rtr/pdu_sender.h
src/rtr/rtr.c

index 4495e3edd6ae86d613894a66cdcc5e2c22c1aadb..6e5ee9921bb3127c00b0b5afb7da3c4b4b641361 100644 (file)
@@ -32,14 +32,13 @@ 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)
+static struct client *
+get_client(struct sockaddr_storage *addr)
 {
        struct client *ptr;
 
        ARRAYLIST_FOREACH(clients_db, ptr)
-               if (ptr->rtr_version == rtr_version &&
-                   ptr->sin_family == addr->ss_family) {
+               if (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)
@@ -78,14 +77,28 @@ create_client(int fd, struct sockaddr_storage *addr, u_int8_t rtr_version)
        return clients_db_add_client(client);
 }
 
+/*
+ * If the ADDR isn't already stored, store it; otherwise update its file
+ * descriptor.
+ *
+ * Return the creation/update result.
+ *
+ * Code error -EINVAL will be returned when a client exists but its RTR version
+ * isn't the same as in the DB.
+ */
 int
 update_client(int fd, struct sockaddr_storage *addr, u_int8_t rtr_version)
 {
        struct client *client;
-       client = get_client(addr, rtr_version);
+       client = get_client(addr);
 
        if (client == NULL)
                return create_client(fd, addr, rtr_version);
+
+       /* TODO Isn't ready to handle distinct version on clients reconnection */
+       if (client->rtr_version != rtr_version)
+               return -EINVAL;
+
        client->fd = fd;
        return 0;
 }
index 992092eaeefe69f2216db074496e03e8b2230a9b..0660d283dec955db3141d981f7f10375acb7f3c3 100644 (file)
@@ -160,9 +160,6 @@ error_report_from_stream(struct pdu_header *header, int fd, void *pdu_void)
                return error;
        }
 
-       warnx("Error report received from stream. Code %d. Message %s.",
-           pdu->header.error_code,
-           strlen(pdu->error_message) == 0 ? "**empty**" : pdu->error_message);
        return 0;
 }
 
index 225aa82892f3f72454820b2d31700441fae7dbdc..3fd761644024533d66d2c4f7e145c96be77fed53 100644 (file)
 #define PDU_TYPE_CACHE_RESET           8
 #define PDU_TYPE_ERROR_REPORT          10
 
-#define ERR_CORRUPT_DATA                       0
-#define ERR_INTERNAL_ERROR                     1
-#define ERR_NO_DATA_AVAILABLE          2
-#define ERR_INVALID_REQUEST                    3
-#define ERR_UNSUP_PROTO_VERSION                4
-#define ERR_UNSUP_PDU_TYPE                     5
-#define ERR_WITHDRAWAL_UNKNOWN         6
-#define ERR_DUPLICATE_ANNOUNCE         7
-#define UNEXPECTED_PROTO_VERSION       8
-
 struct pdu_header {
        u_int8_t        protocol_version;
        u_int8_t        pdu_type;
index 6627e4534a1e1f4c3adcdd454cc53286e1b1881e..26756d20038b56b744001cafd9588d39984f7539 100644 (file)
@@ -3,25 +3,27 @@
 #include <err.h>
 #include <errno.h>
 #include <stddef.h>
+#include <unistd.h>
 
+#include "err_pdu.h"
 #include "pdu.h"
 #include "pdu_sender.h"
 #include "vrps.h"
 
-static int warn_unexpected_pdu(char *);
-
 static int
-warn_unexpected_pdu(char *pdu_name)
+warn_unexpected_pdu(int fd, void *pdu, char *pdu_name)
 {
-       warnx("RTR servers are not expected to receive %s PDUs, but we got one anyway (Closing socket.)",
-           pdu_name);
+       struct pdu_header *pdu_header = pdu;
+       warnx("Unexpected %s PDU received", pdu_name);
+       err_pdu_send(fd, pdu_header->protocol_version, ERR_PDU_UNSUP_PDU_TYPE,
+           pdu_header, "Unexpected PDU received");
        return -EINVAL;
 }
 
 int
 handle_serial_notify_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("Serial Notify");
+       return warn_unexpected_pdu(fd, pdu, "Serial Notify");
 }
 
 static int
@@ -63,7 +65,7 @@ handle_serial_query_pdu(int fd, void *pdu)
        version = received->header.protocol_version;
        session_id = current_session_id(version);
        if (received->header.session_id != session_id)
-               return send_error_report_pdu(&common, ERR_CORRUPT_DATA, NULL, NULL);
+               return err_pdu_send(fd, version, ERR_PDU_CORRUPT_DATA, NULL, NULL);
 
        current_serial = last_serial_number();
        init_sender_common(&common, fd, version, &session_id,
@@ -73,7 +75,8 @@ handle_serial_query_pdu(int fd, void *pdu)
        switch (updates) {
        case NO_DATA_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.4 */
-               return send_error_report_pdu(&common, ERR_NO_DATA_AVAILABLE, NULL, NULL);
+               return err_pdu_send(fd, version, ERR_PDU_NO_DATA_AVAILABLE, NULL,
+                   NULL);
        case DIFF_UNDETERMINED:
                /* https://tools.ietf.org/html/rfc8210#section-8.3 */
                return send_cache_reset_pdu(&common);
@@ -120,7 +123,8 @@ handle_reset_query_pdu(int fd, void *pdu)
        switch (updates) {
        case NO_DATA_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.4 */
-               return send_error_report_pdu(&common, ERR_NO_DATA_AVAILABLE, NULL, NULL);
+               return err_pdu_send(fd, version, ERR_PDU_NO_DATA_AVAILABLE, NULL,
+                   NULL);
        case DIFF_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.1 */
                return send_commmon_exchange(&common);
@@ -134,42 +138,43 @@ handle_reset_query_pdu(int fd, void *pdu)
 int
 handle_cache_response_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("Cache Response");
+       return warn_unexpected_pdu(fd, pdu, "Cache Response");
 }
 
 int
 handle_ipv4_prefix_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("IPv4 Prefix");
+       return warn_unexpected_pdu(fd, pdu, "IPv4 Prefix");
 }
 
 int
 handle_ipv6_prefix_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("IPv6 Prefix");
+       return warn_unexpected_pdu(fd, pdu, "IPv6 Prefix");
 }
 
 int
 handle_end_of_data_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("End of Data");
+       return warn_unexpected_pdu(fd, pdu, "End of Data");
 }
 
 int
 handle_cache_reset_pdu(int fd, void *pdu)
 {
-       return warn_unexpected_pdu("Cache Reset");
+       return warn_unexpected_pdu(fd, pdu, "Cache Reset");
 }
 
 int
 handle_error_report_pdu(int fd, void *pdu)
 {
        struct error_report_pdu *received = pdu;
-       struct sender_common common;
 
-       init_sender_common(&common, fd, received->header.protocol_version,
-               NULL, NULL, NULL);
+       if (err_pdu_is_fatal(received->header.error_code)) {
+               warnx("Fatal error report PDU received, closing socket.");
+               close(fd);
+       }
+       err_pdu_log(received->header.error_code, received->error_message);
 
-       /* TODO complete handler */
        return 0;
 }
index e46fc62c7c54a9e8946ae59b0832d80a45008a62..49ac4914e8795d33926176d7a79f087b04a2591c 100644 (file)
@@ -94,10 +94,7 @@ send_response(int fd, char *data, size_t data_len)
        error = write(fd, buffer.data, buffer.len);
        free_buffer(&buffer);
        if (error < 0) {
-               err(error, "Error sending response");
-               /*
-                * TODO Send error PDU here depending on error type?
-                */
+               err(errno, "Error sending response");
                return error;
        }
 
@@ -247,14 +244,14 @@ send_end_of_data_pdu(struct sender_common *common)
 }
 
 int
-send_error_report_pdu(struct sender_common *common, u_int16_t code,
-    struct pdu_header *err_pdu_header, char *message)
+send_error_report_pdu(int fd, u_int8_t version, u_int16_t code,
+struct pdu_header *err_pdu_header, char *message)
 {
        struct error_report_pdu pdu;
        char data[BUFFER_SIZE];
        size_t len;
 
-       set_header_values(&pdu.header, common->version, PDU_TYPE_ERROR_REPORT,
+       set_header_values(&pdu.header, version, PDU_TYPE_ERROR_REPORT,
            code);
 
        pdu.error_pdu_length = 0;
@@ -279,5 +276,5 @@ send_error_report_pdu(struct sender_common *common, u_int16_t code,
 
        len = serialize_error_report_pdu(&pdu, data);
        free(pdu.error_message);
-       return send_response(common->fd, data, len);
+       return send_response(fd, data, len);
 }
index 9a0b85f286965d6afa858eeeb09a232545ad81e9..db228c8d7eb16696be96abde8f35d0102aa9db8a 100644 (file)
@@ -20,8 +20,8 @@ int send_cache_reset_pdu(struct sender_common *);
 int send_cache_response_pdu(struct sender_common *);
 int send_payload_pdus(struct sender_common *);
 int send_end_of_data_pdu(struct sender_common *);
-int send_error_report_pdu(struct sender_common *, u_int16_t,
-    struct pdu_header *, char *);
+int send_error_report_pdu(int, u_int8_t, u_int16_t, struct pdu_header *,
+    char *);
 
 
 #endif /* SRC_RTR_PDU_SENDER_H_ */
index 3b9fac4911abd7d04f3e28ee4a2e670b9e845061..23d8aeab4d1efa4d7d1be20b97515c1e68c018b7 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "clients.h"
 #include "configuration.h"
+#include "err_pdu.h"
 #include "pdu.h"
 
 /*
@@ -124,10 +125,17 @@ client_thread_cb(void *param_void)
                if (err)
                        return NULL;
 
+               /* Protocol Version Negotiation isn't necessary (for now) */
                /* RTR Version ready, now update client */
                err = update_client(param.client_fd, &param.client_addr, rtr_version);
-               if (err)
+               if (err) {
+                       if (err == -EINVAL) {
+                               err_pdu_send(param.client_fd, rtr_version,
+                                   ERR_PDU_UNEXPECTED_PROTO_VERSION,
+                                   (struct pdu_header *) pdu, NULL);
+                       }
                        return NULL;
+               }
 
                err = meta->handle(param.client_fd, pdu);
                meta->destructor(pdu);