From: pcarana Date: Mon, 11 Mar 2019 17:52:36 +0000 (-0600) Subject: Use Error PDUs handling methods and prepare to send other error PDUs X-Git-Tag: v0.0.2~52^2~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3002d1d1a13ea5d809d56ca0c89fcd49148b4311;p=thirdparty%2FFORT-validator.git Use Error PDUs handling methods and prepare to send other error PDUs 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. --- diff --git a/src/clients.c b/src/clients.c index 4495e3ed..6e5ee992 100644 --- a/src/clients.c +++ b/src/clients.c @@ -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; } diff --git a/src/rtr/pdu.c b/src/rtr/pdu.c index 992092ea..0660d283 100644 --- a/src/rtr/pdu.c +++ b/src/rtr/pdu.c @@ -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; } diff --git a/src/rtr/pdu.h b/src/rtr/pdu.h index 225aa828..3fd76164 100644 --- a/src/rtr/pdu.h +++ b/src/rtr/pdu.h @@ -17,16 +17,6 @@ #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; diff --git a/src/rtr/pdu_handler.c b/src/rtr/pdu_handler.c index 6627e453..26756d20 100644 --- a/src/rtr/pdu_handler.c +++ b/src/rtr/pdu_handler.c @@ -3,25 +3,27 @@ #include #include #include +#include +#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; } diff --git a/src/rtr/pdu_sender.c b/src/rtr/pdu_sender.c index e46fc62c..49ac4914 100644 --- a/src/rtr/pdu_sender.c +++ b/src/rtr/pdu_sender.c @@ -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); } diff --git a/src/rtr/pdu_sender.h b/src/rtr/pdu_sender.h index 9a0b85f2..db228c8d 100644 --- a/src/rtr/pdu_sender.h +++ b/src/rtr/pdu_sender.h @@ -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_ */ diff --git a/src/rtr/rtr.c b/src/rtr/rtr.c index 3b9fac49..23d8aeab 100644 --- a/src/rtr/rtr.c +++ b/src/rtr/rtr.c @@ -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, ¶m.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);