-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.
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 *);
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)
{
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[] = {
/* 6 */ &ipv6_prefix_meta,
/* 7 */ &end_of_data_meta,
/* 8 */ &cache_reset_meta,
- /* 9 */ NULL,
+ /* 9 */ &router_key_meta,
/* 10 */ &error_report_meta,
};
#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 {
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;
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)
{
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_ */
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)
{
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;
}
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,
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 */
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 */
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,
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,
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;
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,
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,
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);
}
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);
}
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);
}
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);
}
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);
}
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,
#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_ */
#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;
}
/** 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;
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++)
#include <netinet/in.h>
__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_ */
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)
{
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);
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);