summaryrefslogtreecommitdiffstats
path: root/pceplib/pcep_msg_messages.c
diff options
context:
space:
mode:
Diffstat (limited to 'pceplib/pcep_msg_messages.c')
-rw-r--r--pceplib/pcep_msg_messages.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/pceplib/pcep_msg_messages.c b/pceplib/pcep_msg_messages.c
new file mode 100644
index 0000000..9bbfc53
--- /dev/null
+++ b/pceplib/pcep_msg_messages.c
@@ -0,0 +1,312 @@
+/*
+ * This file is part of the PCEPlib, a PCEP protocol library.
+ *
+ * Copyright (C) 2020 Volta Networks https://voltanet.io/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Author : Brady Johnson <brady@voltanet.io>
+ *
+ */
+
+
+/*
+ * This is the implementation of a High Level PCEP message API.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_msg_messages.h"
+#include "pcep_msg_objects.h"
+#include "pcep_utils_double_linked_list.h"
+#include "pcep_utils_logging.h"
+#include "pcep_utils_memory.h"
+
+static struct pcep_message *
+pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type,
+ double_linked_list *obj_list)
+{
+ struct pcep_message *message =
+ pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message));
+ memset(message, 0, sizeof(struct pcep_message));
+ message->msg_header = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_message_header));
+ memset(message->msg_header, 0, sizeof(struct pcep_message_header));
+ message->msg_header->type = msg_type;
+ message->msg_header->pcep_version = PCEP_MESSAGE_HEADER_VERSION;
+ message->obj_list = ((obj_list == NULL) ? dll_initialize() : obj_list);
+
+ return message;
+}
+
+static struct pcep_message *
+pcep_msg_create_common(enum pcep_message_types msg_type)
+{
+ return pcep_msg_create_common_with_obj_list(msg_type, NULL);
+}
+
+struct pcep_message *pcep_msg_create_open(uint8_t keepalive, uint8_t deadtimer,
+ uint8_t sid)
+{
+ struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN);
+ dll_append(message->obj_list,
+ pcep_obj_create_open(keepalive, deadtimer, sid, NULL));
+
+ return message;
+}
+
+struct pcep_message *
+pcep_msg_create_open_with_tlvs(uint8_t keepalive, uint8_t deadtimer,
+ uint8_t sid, double_linked_list *tlv_list)
+{
+ struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN);
+ dll_append(message->obj_list,
+ pcep_obj_create_open(keepalive, deadtimer, sid, tlv_list));
+
+ return message;
+}
+
+
+struct pcep_message *
+pcep_msg_create_request(struct pcep_object_rp *rp,
+ struct pcep_object_endpoints_ipv4 *endpoints,
+ double_linked_list *object_list)
+{
+ if ((rp == NULL) || (endpoints == NULL)) {
+ return NULL;
+ }
+
+ struct pcep_message *message = pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_PCREQ, object_list);
+ dll_prepend(message->obj_list, endpoints);
+ dll_prepend(message->obj_list, rp);
+
+ return message;
+}
+
+struct pcep_message *
+pcep_msg_create_request_ipv6(struct pcep_object_rp *rp,
+ struct pcep_object_endpoints_ipv6 *endpoints,
+ double_linked_list *object_list)
+{
+ if ((rp == NULL) || (endpoints == NULL)) {
+ return NULL;
+ }
+
+ struct pcep_message *message = pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_PCREQ, object_list);
+ dll_prepend(message->obj_list, endpoints);
+ dll_prepend(message->obj_list, rp);
+
+ return message;
+}
+
+struct pcep_message *pcep_msg_create_reply(struct pcep_object_rp *rp,
+ double_linked_list *object_list)
+{
+ struct pcep_message *message = pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_PCREP, object_list);
+
+ if (rp != NULL) {
+ dll_prepend(message->obj_list, rp);
+ }
+
+ return message;
+}
+
+struct pcep_message *pcep_msg_create_close(uint8_t reason)
+{
+ struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_CLOSE);
+ dll_append(message->obj_list, pcep_obj_create_close(reason));
+
+ return message;
+}
+
+struct pcep_message *pcep_msg_create_error(uint8_t error_type,
+ uint8_t error_value)
+{
+ struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_ERROR);
+ dll_append(message->obj_list,
+ pcep_obj_create_error(error_type, error_value));
+
+ return message;
+}
+
+struct pcep_message *
+pcep_msg_create_error_with_objects(uint8_t error_type, uint8_t error_value,
+ double_linked_list *object_list)
+{
+ struct pcep_message *message = pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_ERROR, object_list);
+ dll_prepend(message->obj_list,
+ pcep_obj_create_error(error_type, error_value));
+
+ return message;
+}
+
+struct pcep_message *pcep_msg_create_keepalive()
+{
+ return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE));
+}
+
+struct pcep_message *
+pcep_msg_create_report(double_linked_list *state_report_object_list)
+{
+ return (state_report_object_list == NULL
+ ? NULL
+ : pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_REPORT, state_report_object_list));
+}
+
+struct pcep_message *
+pcep_msg_create_update(double_linked_list *update_request_object_list)
+{
+ if (update_request_object_list == NULL) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_update NULL update_request_object_list",
+ __func__);
+ return NULL;
+ }
+
+ /* There must be at least 3 objects:
+ * These 3 are mandatory: SRP, LSP, and ERO. The ERO may be empty */
+ if (update_request_object_list->num_entries < 3) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_update there must be at least 3 update objects",
+ __func__);
+ return NULL;
+ }
+
+ double_linked_list_node *node = update_request_object_list->head;
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)node->data;
+
+ /* Check for the mandatory first SRP object */
+ if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
+ /* If the SRP object is missing, the receiving PCC MUST send a
+ * PCErr message with Error-type=6 (Mandatory Object missing)
+ * and Error-value=10 (SRP object missing). */
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_update missing mandatory first SRP object",
+ __func__);
+ return NULL;
+ }
+
+ /* Check for the mandatory 2nd LSP object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) {
+ /* If the LSP object is missing, the receiving PCC MUST send a
+ * PCErr message with Error-type=6 (Mandatory Object missing)
+ * and Error-value=8 (LSP object missing). */
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_update missing mandatory second LSP object",
+ __func__);
+ return NULL;
+ }
+
+ /* Check for the mandatory 3rd ERO object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ if (obj_hdr->object_class != PCEP_OBJ_CLASS_ERO) {
+ /* If the ERO object is missing, the receiving PCC MUST send a
+ * PCErr message with Error-type=6 (Mandatory Object missing)
+ * and Error-value=9 (ERO object missing). */
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_update missing mandatory third ERO object",
+ __func__);
+ return NULL;
+ }
+
+ return (pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_UPDATE, update_request_object_list));
+}
+
+struct pcep_message *
+pcep_msg_create_initiate(double_linked_list *lsp_object_list)
+{
+ if (lsp_object_list == NULL) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_initiate NULL update_request_object_list",
+ __func__);
+ return NULL;
+ }
+
+ /* There must be at least 2 objects: SRP and LSP. */
+ if (lsp_object_list->num_entries < 2) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_initiate there must be at least 2 objects",
+ __func__);
+ return NULL;
+ }
+
+ double_linked_list_node *node = lsp_object_list->head;
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)node->data;
+
+ /* Check for the mandatory first SRP object */
+ if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_initiate missing mandatory first SRP object",
+ __func__);
+ return NULL;
+ }
+
+ /* Check for the mandatory 2nd LSP object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) {
+ pcep_log(
+ LOG_INFO,
+ "%s: pcep_msg_create_initiate missing mandatory second LSP object",
+ __func__);
+ return NULL;
+ }
+
+ return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE,
+ lsp_object_list));
+}
+
+struct pcep_message *pcep_msg_create_notify(struct pcep_object_notify *notify,
+ double_linked_list *object_list)
+{
+ if (notify == NULL) {
+ pcep_log(LOG_INFO,
+ "%s: pcep_msg_create_notify NULL notify object",
+ __func__);
+ return NULL;
+ }
+
+ struct pcep_message *message = pcep_msg_create_common_with_obj_list(
+ PCEP_TYPE_PCNOTF, object_list);
+ dll_prepend(message->obj_list, notify);
+
+ return message;
+}