]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Implement error report PDU and send when no data is available
authorpcarana <pc.moreno2099@gmail.com>
Thu, 28 Feb 2019 14:33:33 +0000 (08:33 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Thu, 28 Feb 2019 14:33:33 +0000 (08:33 -0600)
src/rtr/pdu.h
src/rtr/pdu_handler.c
src/rtr/pdu_sender.c
src/rtr/pdu_sender.h
src/rtr/pdu_serializer.c

index 4e5fe9216480a067b36911d27c039241f488f976..95f288cfb8408e4ff4e06d694598b924b237caa8 100644 (file)
@@ -9,11 +9,22 @@
 #define RTR_V0 0
 #define RTR_V1 1
 
-#define CACHE_RESPONSE_PDU_TYPE                3
-#define IPV4_PREFIX_PDU_TYPE           4
-#define IPV6_PREFIX_PDU_TYPE           6
-#define END_OF_DATA_PDU_TYPE           7
-#define CACHE_RESET_PDU_TYPE           8
+#define PDU_TYPE_CACHE_RESPONSE                3
+#define PDU_TYPE_IPV4_PREFIX           4
+#define PDU_TYPE_IPV6_PREFIX           6
+#define PDU_TYPE_END_OF_DATA           7
+#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;
@@ -78,7 +89,9 @@ struct cache_reset_pdu {
 
 struct error_report_pdu {
        struct  pdu_header header;
-       void    *erroneous_pdu;
+       u_int32_t       error_pdu_length;
+       void            *erroneous_pdu;
+       u_int32_t       error_message_length;
        rtr_char        *error_message;
 };
 
index f34aa29bbbe9b7792d7e28c39de359944e17f014..0fec38e1a40dd9b16915b9d93c7f73218fb05a3b 100644 (file)
@@ -59,10 +59,9 @@ handle_serial_query_pdu(int fd, void *pdu)
 
        updates = deltas_db_status(common.start_serial);
        switch (updates) {
-       /* TODO Implement error */
-//     case NO_DATA_AVAILABLE:
+       case NO_DATA_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.4 */
-//             return send_error_pdu;
+               return send_error_report_pdu(&common, ERR_NO_DATA_AVAILABLE, NULL, NULL);
        case DIFF_UNDETERMINED:
                /* https://tools.ietf.org/html/rfc8210#section-8.3 */
                return send_cache_reset_pdu(&common);
@@ -99,10 +98,9 @@ handle_reset_query_pdu(int fd, void *pdu)
 
        updates = deltas_db_status(common.start_serial);
        switch (updates) {
-       /* TODO Implement error */
-//     case NO_DATA_AVAILABLE:
+       case NO_DATA_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.4 */
-//             return send_error_pdu;
+               return send_error_report_pdu(&common, ERR_NO_DATA_AVAILABLE, NULL, NULL);
        case DIFF_AVAILABLE:
                /* https://tools.ietf.org/html/rfc8210#section-8.1 */
                return send_commmon_exchange(&common);
index b6e385af915ac54c071a2997237cacd1b49c96a5..d71635097676a0f100a14c2059fc1a90efba4910 100644 (file)
@@ -61,6 +61,14 @@ length_end_of_data_pdu(struct end_of_data_pdu *pdu)
        return len;
 }
 
+static u_int32_t
+length_error_report_pdu(struct error_report_pdu *pdu)
+{
+       return HEADER_LENGTH +
+           pdu->error_pdu_length + sizeof(pdu->error_pdu_length) +
+           pdu->error_message_length + sizeof(pdu->error_message_length);
+}
+
 static int
 send_response(int fd, char *data, size_t data_len)
 {
@@ -96,7 +104,7 @@ send_cache_reset_pdu(struct sender_common *common)
        size_t len;
 
        /* This PDU has only the header */
-       set_header_values(&pdu.header, common->version, CACHE_RESET_PDU_TYPE, 0);
+       set_header_values(&pdu.header, common->version, PDU_TYPE_CACHE_RESET, 0);
        pdu.header.length = HEADER_LENGTH;
 
        len = serialize_cache_reset_pdu(&pdu, data);
@@ -111,8 +119,8 @@ send_cache_response_pdu(struct sender_common *common)
        size_t len;
 
        /* This PDU has only the header */
-       set_header_values(&pdu.header, common->version,
-           CACHE_RESPONSE_PDU_TYPE, *common->session_id);
+       set_header_values(&pdu.header, common->version, PDU_TYPE_CACHE_RESPONSE,
+           *common->session_id);
        pdu.header.length = HEADER_LENGTH;
 
        len = serialize_cache_response_pdu(&pdu, data);
@@ -127,7 +135,7 @@ send_ipv4_prefix_pdu(struct sender_common *common, struct vrp *vrp)
        char data[BUFFER_SIZE];
        size_t len;
 
-       set_header_values(&pdu.header, common->version, IPV4_PREFIX_PDU_TYPE, 0);
+       set_header_values(&pdu.header, common->version, PDU_TYPE_IPV4_PREFIX, 0);
 
        pdu.flags = vrp->flags;
        pdu.prefix_length = vrp->prefix_length;
@@ -149,7 +157,7 @@ send_ipv6_prefix_pdu(struct sender_common *common, struct vrp *vrp)
        char data[BUFFER_SIZE];
        size_t len;
 
-       set_header_values(&pdu.header, common->version, IPV6_PREFIX_PDU_TYPE, 0);
+       set_header_values(&pdu.header, common->version, PDU_TYPE_IPV6_PREFIX, 0);
 
        pdu.flags = vrp->flags;
        pdu.prefix_length = vrp->prefix_length;
@@ -197,7 +205,8 @@ send_end_of_data_pdu(struct sender_common *common)
        char data[BUFFER_SIZE];
        size_t len;
 
-       set_header_values(&pdu.header, common->version, END_OF_DATA_PDU_TYPE, *common->session_id);
+       set_header_values(&pdu.header, common->version, PDU_TYPE_END_OF_DATA,
+           *common->session_id);
        pdu.serial_number = *common->end_serial;
        if (common->version == RTR_V1) {
                pdu.refresh_interval = config_get_refresh_interval();
@@ -210,3 +219,42 @@ send_end_of_data_pdu(struct sender_common *common)
 
        return send_response(common->fd, data, len);
 }
+
+int
+send_error_report_pdu(struct sender_common *common, u_int16_t code,
+    void *err_pdu, 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,
+           code);
+       if (err_pdu == NULL) {
+               pdu.error_pdu_length = 0;
+               pdu.erroneous_pdu = NULL;
+       } else {
+               /* TODO Really? Or get the PDU header length field */
+               pdu.error_pdu_length = sizeof(*err_pdu);
+               pdu.erroneous_pdu = err_pdu;
+       }
+       if (message == NULL) {
+               pdu.error_message_length = 0;
+               pdu.error_message = NULL;
+       } else {
+               pdu.error_message = malloc(strlen(message) + 1);
+               if (pdu.error_message == NULL) {
+                       warn("Error message couldn't be allocated, removed from PDU");
+                       pdu.error_message_length = 0;
+               } else {
+                       pdu.error_message_length = strlen(message) + 1;
+                       strcpy(pdu.error_message, message);
+               }
+       }
+
+       /* Calculate lengths */
+       pdu.header.length = length_error_report_pdu(&pdu);
+
+       len = serialize_error_report_pdu(&pdu, data);
+       return send_response(common->fd, data, len);
+}
index d91bf40d351f7d8c29e9e3939fc2d63d9b01ef23..607eb2a4654099b0ae94d629e246e8f37ca6d028 100644 (file)
@@ -18,6 +18,7 @@ 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, void *, char *);
 
 
 #endif /* SRC_RTR_PDU_SENDER_H_ */
index 4d6fe665c98248ee1524c867a32c022e4c4d1a23..f35dac7526a48fbb4c68290d0517f2a9ab74584a 100644 (file)
@@ -1,6 +1,7 @@
 #include "pdu_serializer.h"
 
 #include <stdlib.h>
+#include <string.h>
 #include "primitive_writer.h"
 
 void
@@ -112,6 +113,28 @@ serialize_cache_reset_pdu(struct cache_reset_pdu *pdu, char *buf)
 size_t
 serialize_error_report_pdu(struct error_report_pdu *pdu, char *buf)
 {
-       // FIXME Complete me!
-       return 0;
+       size_t head_size;
+       char *ptr, *tmp_ptr;
+       int i;
+
+       head_size = serialize_pdu_header(&pdu->header, pdu->header.error_code, buf);
+
+       ptr = buf + head_size;
+
+       ptr = write_int32(ptr, pdu->error_pdu_length);
+       if (pdu->error_pdu_length > 0) {
+               tmp_ptr = pdu->erroneous_pdu;
+               /* TODO Set only the header of err PDU */
+               while (*tmp_ptr != '\0') {
+                       ptr = write_int8(ptr, *tmp_ptr);
+                       tmp_ptr++;
+               }
+       }
+
+       ptr = write_int32(ptr, pdu->error_message_length);
+       tmp_ptr = pdu->error_message;
+       for (i = 0; i < pdu->error_message_length; i++)
+               ptr = write_int8(ptr, tmp_ptr[i]);
+
+       return ptr - buf;
 }