2 * This file is part of the PCEPlib, a PCEP protocol library.
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * Author : Brady Johnson <brady@voltanet.io>
25 * This is the implementation of a High Level PCEP message API.
33 #include <arpa/inet.h>
37 #include "pcep_msg_encoding.h"
38 #include "pcep_msg_messages.h"
39 #include "pcep_msg_objects.h"
40 #include "pcep_utils_double_linked_list.h"
41 #include "pcep_utils_logging.h"
42 #include "pcep_utils_memory.h"
44 static struct pcep_message
*
45 pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type
,
46 double_linked_list
*obj_list
)
48 struct pcep_message
*message
=
49 pceplib_malloc(PCEPLIB_MESSAGES
, sizeof(struct pcep_message
));
50 memset(message
, 0, sizeof(struct pcep_message
));
51 message
->msg_header
= pceplib_malloc(
52 PCEPLIB_MESSAGES
, sizeof(struct pcep_message_header
));
53 memset(message
->msg_header
, 0, sizeof(struct pcep_message_header
));
54 message
->msg_header
->type
= msg_type
;
55 message
->msg_header
->pcep_version
= PCEP_MESSAGE_HEADER_VERSION
;
56 message
->obj_list
= ((obj_list
== NULL
) ? dll_initialize() : obj_list
);
61 static struct pcep_message
*
62 pcep_msg_create_common(enum pcep_message_types msg_type
)
64 return pcep_msg_create_common_with_obj_list(msg_type
, NULL
);
67 struct pcep_message
*pcep_msg_create_open(uint8_t keepalive
, uint8_t deadtimer
,
70 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_OPEN
);
71 dll_append(message
->obj_list
,
72 pcep_obj_create_open(keepalive
, deadtimer
, sid
, NULL
));
78 pcep_msg_create_open_with_tlvs(uint8_t keepalive
, uint8_t deadtimer
,
79 uint8_t sid
, double_linked_list
*tlv_list
)
81 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_OPEN
);
82 dll_append(message
->obj_list
,
83 pcep_obj_create_open(keepalive
, deadtimer
, sid
, tlv_list
));
90 pcep_msg_create_request(struct pcep_object_rp
*rp
,
91 struct pcep_object_endpoints_ipv4
*endpoints
,
92 double_linked_list
*object_list
)
94 if ((rp
== NULL
) || (endpoints
== NULL
)) {
98 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
99 PCEP_TYPE_PCREQ
, object_list
);
100 dll_prepend(message
->obj_list
, endpoints
);
101 dll_prepend(message
->obj_list
, rp
);
106 struct pcep_message
*
107 pcep_msg_create_request_ipv6(struct pcep_object_rp
*rp
,
108 struct pcep_object_endpoints_ipv6
*endpoints
,
109 double_linked_list
*object_list
)
111 if ((rp
== NULL
) || (endpoints
== NULL
)) {
115 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
116 PCEP_TYPE_PCREQ
, object_list
);
117 dll_prepend(message
->obj_list
, endpoints
);
118 dll_prepend(message
->obj_list
, rp
);
123 struct pcep_message
*pcep_msg_create_reply(struct pcep_object_rp
*rp
,
124 double_linked_list
*object_list
)
126 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
127 PCEP_TYPE_PCREP
, object_list
);
130 dll_prepend(message
->obj_list
, rp
);
136 struct pcep_message
*pcep_msg_create_close(uint8_t reason
)
138 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_CLOSE
);
139 dll_append(message
->obj_list
, pcep_obj_create_close(reason
));
144 struct pcep_message
*pcep_msg_create_error(uint8_t error_type
,
147 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_ERROR
);
148 dll_append(message
->obj_list
,
149 pcep_obj_create_error(error_type
, error_value
));
154 struct pcep_message
*
155 pcep_msg_create_error_with_objects(uint8_t error_type
, uint8_t error_value
,
156 double_linked_list
*object_list
)
158 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
159 PCEP_TYPE_ERROR
, object_list
);
160 dll_prepend(message
->obj_list
,
161 pcep_obj_create_error(error_type
, error_value
));
166 struct pcep_message
*pcep_msg_create_keepalive()
168 return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE
));
171 struct pcep_message
*
172 pcep_msg_create_report(double_linked_list
*state_report_object_list
)
174 return (state_report_object_list
== NULL
176 : pcep_msg_create_common_with_obj_list(
177 PCEP_TYPE_REPORT
, state_report_object_list
));
180 struct pcep_message
*
181 pcep_msg_create_update(double_linked_list
*update_request_object_list
)
183 if (update_request_object_list
== NULL
) {
186 "%s: pcep_msg_create_update NULL update_request_object_list",
191 /* There must be at least 3 objects:
192 * These 3 are mandatory: SRP, LSP, and ERO. The ERO may be empty */
193 if (update_request_object_list
->num_entries
< 3) {
196 "%s: pcep_msg_create_update there must be at least 3 update objects",
201 double_linked_list_node
*node
= update_request_object_list
->head
;
202 struct pcep_object_header
*obj_hdr
=
203 (struct pcep_object_header
*)node
->data
;
205 /* Check for the mandatory first SRP object */
206 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_SRP
) {
207 /* If the SRP object is missing, the receiving PCC MUST send a
208 * PCErr message with Error-type=6 (Mandatory Object missing)
209 * and Error-value=10 (SRP object missing). */
212 "%s: pcep_msg_create_update missing mandatory first SRP object",
217 /* Check for the mandatory 2nd LSP object */
218 node
= node
->next_node
;
219 obj_hdr
= (struct pcep_object_header
*)node
->data
;
220 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_LSP
) {
221 /* If the LSP object is missing, the receiving PCC MUST send a
222 * PCErr message with Error-type=6 (Mandatory Object missing)
223 * and Error-value=8 (LSP object missing). */
226 "%s: pcep_msg_create_update missing mandatory second LSP object",
231 /* Check for the mandatory 3rd ERO object */
232 node
= node
->next_node
;
233 obj_hdr
= (struct pcep_object_header
*)node
->data
;
234 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_ERO
) {
235 /* If the ERO object is missing, the receiving PCC MUST send a
236 * PCErr message with Error-type=6 (Mandatory Object missing)
237 * and Error-value=9 (ERO object missing). */
240 "%s: pcep_msg_create_update missing mandatory third ERO object",
245 return (pcep_msg_create_common_with_obj_list(
246 PCEP_TYPE_UPDATE
, update_request_object_list
));
249 struct pcep_message
*
250 pcep_msg_create_initiate(double_linked_list
*lsp_object_list
)
252 if (lsp_object_list
== NULL
) {
255 "%s: pcep_msg_create_initiate NULL update_request_object_list",
260 /* There must be at least 2 objects: SRP and LSP. */
261 if (lsp_object_list
->num_entries
< 2) {
264 "%s: pcep_msg_create_initiate there must be at least 2 objects",
269 double_linked_list_node
*node
= lsp_object_list
->head
;
270 struct pcep_object_header
*obj_hdr
=
271 (struct pcep_object_header
*)node
->data
;
273 /* Check for the mandatory first SRP object */
274 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_SRP
) {
277 "%s: pcep_msg_create_initiate missing mandatory first SRP object",
282 /* Check for the mandatory 2nd LSP object */
283 node
= node
->next_node
;
284 obj_hdr
= (struct pcep_object_header
*)node
->data
;
285 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_LSP
) {
288 "%s: pcep_msg_create_initiate missing mandatory second LSP object",
293 return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE
,
297 struct pcep_message
*pcep_msg_create_notify(struct pcep_object_notify
*notify
,
298 double_linked_list
*object_list
)
300 if (notify
== NULL
) {
302 "%s: pcep_msg_create_notify NULL notify object",
307 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
308 PCEP_TYPE_PCNOTF
, object_list
);
309 dll_prepend(message
->obj_list
, notify
);