From: pcarana Date: Wed, 10 Apr 2019 22:16:41 +0000 (-0500) Subject: Add multiple changes at PDU and buffers: X-Git-Tag: v0.0.2~49^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a6fd70a363d0685600953aeeed125f79439c8ec;p=thirdparty%2FFORT-validator.git Add multiple changes at PDU and buffers: -Add Router Key PDU (structs, serializer, sender function with pending work to do). -Set buffers as unsigned char buffers. -Prepare to send large PDUs (beta). -Increment default buffer size to 512. --- diff --git a/src/rtr/pdu.c b/src/rtr/pdu.c index 770e52a8..9b7f3d25 100644 --- a/src/rtr/pdu.c +++ b/src/rtr/pdu.c @@ -17,6 +17,7 @@ static int ipv4_prefix_from_stream(struct pdu_header *, int, void *); static int ipv6_prefix_from_stream(struct pdu_header *, int, void *); static int end_of_data_from_stream(struct pdu_header *, int, void *); static int cache_reset_from_stream(struct pdu_header *, int, void *); +static int router_key_from_stream(struct pdu_header *, int, void *); static int error_report_from_stream(struct pdu_header *, int, void *); static void error_report_destroy(void *); @@ -136,6 +137,14 @@ cache_reset_from_stream(struct pdu_header *header, int fd, void *pdu_void) return 0; } +static int +router_key_from_stream(struct pdu_header *header, int fd, void *pdu_void) +{ + struct router_key_pdu *pdu = pdu_void; + memcpy(&pdu->header, header, sizeof(*header)); + return 0; +} + static int error_report_from_stream(struct pdu_header *header, int fd, void *pdu_void) { @@ -197,6 +206,7 @@ DEFINE_METADATA(ipv4_prefix, free); DEFINE_METADATA(ipv6_prefix, free); DEFINE_METADATA(end_of_data, free); DEFINE_METADATA(cache_reset, free); +DEFINE_METADATA(router_key, free); DEFINE_METADATA(error_report, error_report_destroy); struct pdu_metadata const *const pdu_metadatas[] = { @@ -209,7 +219,7 @@ struct pdu_metadata const *const pdu_metadatas[] = { /* 6 */ &ipv6_prefix_meta, /* 7 */ &end_of_data_meta, /* 8 */ &cache_reset_meta, - /* 9 */ NULL, + /* 9 */ &router_key_meta, /* 10 */ &error_report_meta, }; diff --git a/src/rtr/pdu.h b/src/rtr/pdu.h index 3fd76164..8e616463 100644 --- a/src/rtr/pdu.h +++ b/src/rtr/pdu.h @@ -15,6 +15,7 @@ #define PDU_TYPE_IPV6_PREFIX 6 #define PDU_TYPE_END_OF_DATA 7 #define PDU_TYPE_CACHE_RESET 8 +#define PDU_TYPE_ROUTER_KEY 9 #define PDU_TYPE_ERROR_REPORT 10 struct pdu_header { @@ -78,6 +79,15 @@ struct cache_reset_pdu { struct pdu_header header; }; +struct router_key_pdu { + struct pdu_header header; + unsigned char *ski; + size_t ski_len; + u_int32_t asn; + unsigned char *spki; + size_t spki_len; +}; + struct error_report_pdu { struct pdu_header header; u_int32_t error_pdu_length; diff --git a/src/rtr/pdu_handler.c b/src/rtr/pdu_handler.c index 0ec9c4bf..1ded4de8 100644 --- a/src/rtr/pdu_handler.c +++ b/src/rtr/pdu_handler.c @@ -157,6 +157,12 @@ handle_cache_reset_pdu(int fd, void *pdu) return warn_unexpected_pdu(fd, pdu, "Cache Reset"); } +int +handle_router_key_pdu(int fd, void *pdu) +{ + return warn_unexpected_pdu(fd, pdu, "Router Key"); +} + int handle_error_report_pdu(int fd, void *pdu) { diff --git a/src/rtr/pdu_handler.h b/src/rtr/pdu_handler.h index c98f260a..d53c7103 100644 --- a/src/rtr/pdu_handler.h +++ b/src/rtr/pdu_handler.h @@ -12,6 +12,7 @@ int handle_ipv4_prefix_pdu(int, void *); int handle_ipv6_prefix_pdu(int, void *); int handle_end_of_data_pdu(int, void *); int handle_cache_reset_pdu(int, void *); +int handle_router_key_pdu(int, void *); int handle_error_report_pdu(int, void *); #endif /* RTR_PDU_HANDLER_H_ */ diff --git a/src/rtr/pdu_sender.c b/src/rtr/pdu_sender.c index a7bf2e1a..b700545e 100644 --- a/src/rtr/pdu_sender.c +++ b/src/rtr/pdu_sender.c @@ -68,6 +68,13 @@ length_end_of_data_pdu(struct end_of_data_pdu *pdu) return len; } +static u_int32_t +length_router_key_pdu(struct router_key_pdu *pdu) +{ + return HEADER_LENGTH + + pdu->ski_len + sizeof(pdu->asn) + pdu->spki_len; +} + static u_int32_t length_error_report_pdu(struct error_report_pdu *pdu) { @@ -76,28 +83,68 @@ length_error_report_pdu(struct error_report_pdu *pdu) pdu->error_message_length + sizeof(pdu->error_message_length); } +/* + * TODO Needs some testing, this is just a beta version + */ +static int +send_large_response(int fd, struct data_buffer *buffer) +{ + unsigned char *tmp_buffer, *ptr; + size_t buf_size, pending; + int written; + + buf_size = buffer->capacity; + pending = buffer->len; + ptr = buffer->data; + while (pending > 0) { + tmp_buffer = calloc(pending, sizeof(unsigned char)); + if (tmp_buffer == NULL) { + warnx("Couldn't allocate temp buffer"); + return -ENOMEM; + } + memcpy(tmp_buffer, ptr, buf_size); + + written = write(fd, tmp_buffer, buf_size); + free(tmp_buffer); + if (written < 0) { + warnx("Error sending response"); + return -EINVAL; + } + pending -= buf_size; + ptr += buf_size; + buf_size = pending > buffer->capacity ? buffer->capacity : + pending; + } + + return 0; +} + static int -send_response(int fd, char *data, size_t data_len) +send_response(int fd, unsigned char *data, size_t data_len) { struct data_buffer buffer; int error; init_buffer(&buffer); - /* Check for buffer overflow */ - if (data_len > buffer.capacity) { - warnx("Response buffer out of capacity"); - return -EINVAL; - } memcpy(buffer.data, data, data_len); buffer.len = data_len; - error = write(fd, buffer.data, buffer.len); - free_buffer(&buffer); - if (error < 0) { - warnx("Error sending response"); - return -EINVAL; + /* Check for buffer overflow */ + if (data_len <= buffer.capacity) { + error = write(fd, buffer.data, buffer.len); + free_buffer(&buffer); + if (error < 0) { + warnx("Error sending response"); + return -EINVAL; + } + return 0; } + error = send_large_response(fd, &buffer); + free_buffer(&buffer); + if (error) + return error; + return 0; } @@ -105,7 +152,7 @@ int send_serial_notify_pdu(struct sender_common *common) { struct serial_notify_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; set_header_values(&pdu.header, common->version, PDU_TYPE_SERIAL_NOTIFY, @@ -123,7 +170,7 @@ int send_cache_reset_pdu(struct sender_common *common) { struct cache_reset_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; /* This PDU has only the header */ @@ -139,7 +186,7 @@ int send_cache_response_pdu(struct sender_common *common) { struct cache_response_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; /* This PDU has only the header */ @@ -156,7 +203,7 @@ static int send_ipv4_prefix_pdu(struct sender_common *common, struct vrp *vrp) { struct ipv4_prefix_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; set_header_values(&pdu.header, common->version, PDU_TYPE_IPV4_PREFIX, @@ -179,7 +226,7 @@ static int send_ipv6_prefix_pdu(struct sender_common *common, struct vrp *vrp) { struct ipv6_prefix_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; set_header_values(&pdu.header, common->version, PDU_TYPE_IPV6_PREFIX, @@ -198,8 +245,8 @@ send_ipv6_prefix_pdu(struct sender_common *common, struct vrp *vrp) return send_response(common->fd, data, len); } -int -send_payload_pdus(struct sender_common *common) +static int +send_vrps_payload(struct sender_common *common) { struct vrp *vrps, *ptr; unsigned int len; @@ -232,11 +279,86 @@ end: return 0; } +static int +send_router_key_pdu(struct sender_common *common, + struct router_key *router_key) +{ + struct router_key_pdu pdu; + unsigned char data[BUFFER_SIZE]; + size_t len; + u_int16_t reserved; + + if (common->version == RTR_V0) + return 0; + + reserved = 0; + /* Set the flags at the first 8 bits of reserved field */ + reserved += (router_key->flags << 8); + set_header_values(&pdu.header, common->version, PDU_TYPE_ROUTER_KEY, + reserved); + + pdu.ski = router_key->ski; + pdu.ski_len = router_key->ski_len; + pdu.asn = router_key->asn; + pdu.spki = router_key->spki; + pdu.spki_len = router_key->spki_len; + pdu.header.length = length_router_key_pdu(&pdu); + + len = serialize_router_key_pdu(&pdu, data); + + return send_response(common->fd, data, len); +} + +static int +send_keys_payload(struct sender_common *common) +{ + struct router_key *router_keys, *ptr; + unsigned int len; + int error; + + router_keys = malloc(sizeof(struct router_key)); + if (router_keys == NULL) { + warn("Couldn't allocate Router Keys to send PDUs"); + return -ENOMEM; + } + len = get_router_keys_delta(common->start_serial, common->end_serial, + &router_keys); + if (len == 0) + goto end; + + for (ptr = router_keys; (ptr - router_keys) < len; ptr++) { + error = send_router_key_pdu(common, ptr); + if (error) { + free(router_keys); + return error; + } + } +end: + free(router_keys); + return 0; +} + +int +send_payload_pdus(struct sender_common *common) +{ + int error; + + error = send_vrps_payload(common); + if (error) + return error; + + error = send_keys_payload(common); + if (error) + return error; + + return 0; +} + int send_end_of_data_pdu(struct sender_common *common) { struct end_of_data_pdu pdu; - char data[BUFFER_SIZE]; + unsigned char data[BUFFER_SIZE]; size_t len; set_header_values(&pdu.header, common->version, PDU_TYPE_END_OF_DATA, @@ -259,7 +381,7 @@ 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]; + unsigned char data[BUFFER_SIZE]; size_t len; set_header_values(&pdu.header, version, PDU_TYPE_ERROR_REPORT, diff --git a/src/rtr/pdu_serializer.c b/src/rtr/pdu_serializer.c index 3e6220d4..5de4ba82 100644 --- a/src/rtr/pdu_serializer.c +++ b/src/rtr/pdu_serializer.c @@ -19,9 +19,9 @@ free_buffer(struct data_buffer *buffer) static size_t serialize_pdu_header(struct pdu_header *header, u_int16_t union_value, - char *buf) + unsigned char *buf) { - char *ptr; + unsigned char *ptr; ptr = buf; ptr = write_int8(ptr, header->protocol_version); @@ -33,10 +33,10 @@ serialize_pdu_header(struct pdu_header *header, u_int16_t union_value, } size_t -serialize_serial_notify_pdu(struct serial_notify_pdu *pdu, char *buf) +serialize_serial_notify_pdu(struct serial_notify_pdu *pdu, unsigned char *buf) { size_t head_size; - char *ptr; + unsigned char *ptr; head_size = serialize_pdu_header(&pdu->header, pdu->header.session_id, buf); @@ -48,17 +48,18 @@ serialize_serial_notify_pdu(struct serial_notify_pdu *pdu, char *buf) } size_t -serialize_cache_response_pdu(struct cache_response_pdu *pdu, char *buf) +serialize_cache_response_pdu(struct cache_response_pdu *pdu, + unsigned char *buf) { /* No payload to serialize */ return serialize_pdu_header(&pdu->header, pdu->header.session_id, buf); } size_t -serialize_ipv4_prefix_pdu(struct ipv4_prefix_pdu *pdu, char *buf) +serialize_ipv4_prefix_pdu(struct ipv4_prefix_pdu *pdu, unsigned char *buf) { size_t head_size; - char *ptr; + unsigned char *ptr; head_size = serialize_pdu_header(&pdu->header, pdu->header.reserved, buf); @@ -75,10 +76,10 @@ serialize_ipv4_prefix_pdu(struct ipv4_prefix_pdu *pdu, char *buf) } size_t -serialize_ipv6_prefix_pdu(struct ipv6_prefix_pdu *pdu, char *buf) +serialize_ipv6_prefix_pdu(struct ipv6_prefix_pdu *pdu, unsigned char *buf) { size_t head_size; - char *ptr; + unsigned char *ptr; head_size = serialize_pdu_header(&pdu->header, pdu->header.reserved, buf); @@ -95,10 +96,10 @@ serialize_ipv6_prefix_pdu(struct ipv6_prefix_pdu *pdu, char *buf) } size_t -serialize_end_of_data_pdu(struct end_of_data_pdu *pdu, char *buf) +serialize_end_of_data_pdu(struct end_of_data_pdu *pdu, unsigned char *buf) { size_t head_size; - char *ptr; + unsigned char *ptr; head_size = serialize_pdu_header(&pdu->header, pdu->header.session_id, buf); @@ -115,18 +116,48 @@ serialize_end_of_data_pdu(struct end_of_data_pdu *pdu, char *buf) } size_t -serialize_cache_reset_pdu(struct cache_reset_pdu *pdu, char *buf) +serialize_cache_reset_pdu(struct cache_reset_pdu *pdu, unsigned char *buf) { /* No payload to serialize */ return serialize_pdu_header(&pdu->header, pdu->header.reserved, buf); } +/* + * Don't forget to use 'header->reserved' to set flags + */ size_t -serialize_error_report_pdu(struct error_report_pdu *pdu, char *buf) +serialize_router_key_pdu(struct router_key_pdu *pdu, unsigned char *buf) +{ + size_t head_size; + unsigned char *ptr; + int i; + + if (pdu->header.protocol_version == RTR_V0) + return 0; + + head_size = serialize_pdu_header(&pdu->header, pdu->header.reserved, + buf); + + ptr = buf + head_size; + + for (i = 0; i < pdu->ski_len; i++) + ptr = write_int8(ptr, pdu->ski[i]); + + ptr = write_int32(ptr, pdu->asn); + + for (i = 0; i < pdu->spki_len; i++) + ptr = write_int8(ptr, pdu->spki[i]); + + return ptr - buf; +} + +size_t +serialize_error_report_pdu(struct error_report_pdu *pdu, unsigned char *buf) { struct pdu_header *err_pdu_header; size_t head_size; - char *ptr, *tmp_ptr; + unsigned char *ptr; + char *tmp_ptr; int i; head_size = serialize_pdu_header(&pdu->header, pdu->header.error_code, diff --git a/src/rtr/pdu_serializer.h b/src/rtr/pdu_serializer.h index e536ac5d..2c490be5 100644 --- a/src/rtr/pdu_serializer.h +++ b/src/rtr/pdu_serializer.h @@ -3,25 +3,28 @@ #include "pdu.h" -#define BUFFER_SIZE 128 +#define BUFFER_SIZE 512 struct data_buffer { size_t len; size_t capacity; - char *data; + unsigned char *data; }; __BEGIN_DECLS void init_buffer(struct data_buffer *); void free_buffer(struct data_buffer *); -size_t serialize_serial_notify_pdu(struct serial_notify_pdu *, char *); -size_t serialize_cache_response_pdu(struct cache_response_pdu *, char *); -size_t serialize_ipv4_prefix_pdu(struct ipv4_prefix_pdu *, char *); -size_t serialize_ipv6_prefix_pdu(struct ipv6_prefix_pdu *, char *); -size_t serialize_end_of_data_pdu(struct end_of_data_pdu *, char *); -size_t serialize_cache_reset_pdu(struct cache_reset_pdu *, char *); -size_t serialize_error_report_pdu(struct error_report_pdu *, char *); +size_t serialize_serial_notify_pdu(struct serial_notify_pdu *, + unsigned char *); +size_t serialize_cache_response_pdu(struct cache_response_pdu *, + unsigned char *); +size_t serialize_ipv4_prefix_pdu(struct ipv4_prefix_pdu *, unsigned char *); +size_t serialize_ipv6_prefix_pdu(struct ipv6_prefix_pdu *, unsigned char *); +size_t serialize_end_of_data_pdu(struct end_of_data_pdu *, unsigned char *); +size_t serialize_cache_reset_pdu(struct cache_reset_pdu *, unsigned char *); +size_t serialize_router_key_pdu(struct router_key_pdu *, unsigned char *); +size_t serialize_error_report_pdu(struct error_report_pdu *, unsigned char *); __END_DECLS #endif /* SRC_RTR_PDU_SERIALIZER_H_ */ diff --git a/src/rtr/primitive_writer.c b/src/rtr/primitive_writer.c index c2635eaf..bb1a9be4 100644 --- a/src/rtr/primitive_writer.c +++ b/src/rtr/primitive_writer.c @@ -1,15 +1,15 @@ #include "primitive_writer.h" -char * -write_int8(char *buf, u_int8_t value) +unsigned char * +write_int8(unsigned char *buf, u_int8_t value) { buf[0] = value; return buf + 1; } /** Big Endian. */ -char * -write_int16(char *buf, u_int16_t value) +unsigned char * +write_int16(unsigned char *buf, u_int16_t value) { buf[0] = value >> 8; buf[1] = value; @@ -17,8 +17,8 @@ write_int16(char *buf, u_int16_t value) } /** Big Endian. */ -char * -write_int32(char *buf, u_int32_t value) +unsigned char * +write_int32(unsigned char *buf, u_int32_t value) { buf[0] = value >> 24; buf[1] = value >> 16; @@ -27,14 +27,14 @@ write_int32(char *buf, u_int32_t value) return buf + 4; } -char * -write_in_addr(char *buf, struct in_addr value) +unsigned char * +write_in_addr(unsigned char *buf, struct in_addr value) { return write_int32(buf, ntohl(value.s_addr)); } -char * -write_in6_addr(char *buf, struct in6_addr value) +unsigned char * +write_in6_addr(unsigned char *buf, struct in6_addr value) { int i; for (i = 0; i < 16; i++) diff --git a/src/rtr/primitive_writer.h b/src/rtr/primitive_writer.h index 1ecb1c7c..7bed5a71 100644 --- a/src/rtr/primitive_writer.h +++ b/src/rtr/primitive_writer.h @@ -4,11 +4,11 @@ #include __BEGIN_DECLS -char *write_int8(char *, u_int8_t); -char *write_int16(char *, u_int16_t); -char *write_int32(char *, u_int32_t); -char *write_in_addr(char *, struct in_addr); -char *write_in6_addr(char *, struct in6_addr); +unsigned char *write_int8(unsigned char *, u_int8_t); +unsigned char *write_int16(unsigned char *, u_int16_t); +unsigned char *write_int32(unsigned char *, u_int32_t); +unsigned char *write_in_addr(unsigned char *, struct in_addr); +unsigned char *write_in6_addr(unsigned char *, struct in6_addr); __END_DECLS #endif /* RTR_PRIMITIVE_WRITER_H_ */ diff --git a/src/vrps.c b/src/vrps.c index ff3ae7cc..29933f0a 100644 --- a/src/vrps.c +++ b/src/vrps.c @@ -424,6 +424,21 @@ get_vrps_delta(u_int32_t *start_serial, u_int32_t *end_serial, return summary.len; } +/* + * Get the number of updates from serial START_SERIAL to END_SERIAL, set them + * at RESULT. + * + * Return 0 if no updates are available or couldn't be calculated with the + * received values. + */ +unsigned int +get_router_keys_delta(u_int32_t *start_serial, u_int32_t *end_serial, + struct router_key **result) +{ + /* TODO Get deltas diff */ + return 0; +} + void set_vrps_last_modified_date(time_t new_date) { diff --git a/src/vrps.h b/src/vrps.h index f6d4c208..df8c87e2 100644 --- a/src/vrps.h +++ b/src/vrps.h @@ -21,6 +21,15 @@ struct vrp { u_int8_t flags; }; +struct router_key { + u_int8_t flags; + unsigned char *ski; + size_t ski_len; + u_int32_t asn; + unsigned char *spki; + size_t spki_len; +}; + int deltas_db_init(void); struct vrp create_vrp4(u_int32_t, struct in_addr, u_int8_t, u_int8_t); @@ -30,6 +39,8 @@ int deltas_db_create_delta(struct vrp *, unsigned int); int deltas_db_status(u_int32_t *); unsigned int get_vrps_delta(u_int32_t *, u_int32_t *, struct vrp **); +unsigned int get_router_keys_delta(u_int32_t *, u_int32_t *, + struct router_key **); void deltas_db_destroy(void); void set_vrps_last_modified_date(time_t);