]> git.proxmox.com Git - mirror_frr.git/blame - pceplib/pcep_msg_messages.c
Merge pull request #11194 from donaldsharp/untrusted
[mirror_frr.git] / pceplib / pcep_msg_messages.c
CommitLineData
74971473
JG
1/*
2 * This file is part of the PCEPlib, a PCEP protocol library.
3 *
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 * Author : Brady Johnson <brady@voltanet.io>
20 *
21 */
22
23
24/*
25 * This is the implementation of a High Level PCEP message API.
26 */
27
1f8031f7
DL
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
74971473
JG
32#include <string.h>
33#include <arpa/inet.h>
34#include <stdarg.h>
35#include <unistd.h>
36
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"
43
44static struct pcep_message *
45pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type,
46 double_linked_list *obj_list)
47{
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);
57
58 return message;
59}
60
61static struct pcep_message *
62pcep_msg_create_common(enum pcep_message_types msg_type)
63{
64 return pcep_msg_create_common_with_obj_list(msg_type, NULL);
65}
66
67struct pcep_message *pcep_msg_create_open(uint8_t keepalive, uint8_t deadtimer,
68 uint8_t sid)
69{
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));
73
74 return message;
75}
76
77struct pcep_message *
78pcep_msg_create_open_with_tlvs(uint8_t keepalive, uint8_t deadtimer,
79 uint8_t sid, double_linked_list *tlv_list)
80{
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));
84
85 return message;
86}
87
88
89struct pcep_message *
90pcep_msg_create_request(struct pcep_object_rp *rp,
91 struct pcep_object_endpoints_ipv4 *endpoints,
92 double_linked_list *object_list)
93{
94 if ((rp == NULL) || (endpoints == NULL)) {
95 return NULL;
96 }
97
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);
102
103 return message;
104}
105
106struct pcep_message *
107pcep_msg_create_request_ipv6(struct pcep_object_rp *rp,
108 struct pcep_object_endpoints_ipv6 *endpoints,
109 double_linked_list *object_list)
110{
111 if ((rp == NULL) || (endpoints == NULL)) {
112 return NULL;
113 }
114
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);
119
120 return message;
121}
122
123struct pcep_message *pcep_msg_create_reply(struct pcep_object_rp *rp,
124 double_linked_list *object_list)
125{
126 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
127 PCEP_TYPE_PCREP, object_list);
128
129 if (rp != NULL) {
130 dll_prepend(message->obj_list, rp);
131 }
132
133 return message;
134}
135
136struct pcep_message *pcep_msg_create_close(uint8_t reason)
137{
138 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_CLOSE);
139 dll_append(message->obj_list, pcep_obj_create_close(reason));
140
141 return message;
142}
143
144struct pcep_message *pcep_msg_create_error(uint8_t error_type,
145 uint8_t error_value)
146{
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));
150
151 return message;
152}
153
154struct pcep_message *
155pcep_msg_create_error_with_objects(uint8_t error_type, uint8_t error_value,
156 double_linked_list *object_list)
157{
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));
162
163 return message;
164}
165
166struct pcep_message *pcep_msg_create_keepalive()
167{
168 return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE));
169}
170
171struct pcep_message *
172pcep_msg_create_report(double_linked_list *state_report_object_list)
173{
174 return (state_report_object_list == NULL
175 ? NULL
176 : pcep_msg_create_common_with_obj_list(
177 PCEP_TYPE_REPORT, state_report_object_list));
178}
179
180struct pcep_message *
181pcep_msg_create_update(double_linked_list *update_request_object_list)
182{
183 if (update_request_object_list == NULL) {
184 pcep_log(
185 LOG_INFO,
186 "%s: pcep_msg_create_update NULL update_request_object_list",
187 __func__);
188 return NULL;
189 }
190
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) {
194 pcep_log(
195 LOG_INFO,
196 "%s: pcep_msg_create_update there must be at least 3 update objects",
197 __func__);
198 return NULL;
199 }
200
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;
204
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). */
210 pcep_log(
211 LOG_INFO,
212 "%s: pcep_msg_create_update missing mandatory first SRP object",
213 __func__);
214 return NULL;
215 }
216
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). */
224 pcep_log(
225 LOG_INFO,
226 "%s: pcep_msg_create_update missing mandatory second LSP object",
227 __func__);
228 return NULL;
229 }
230
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). */
238 pcep_log(
239 LOG_INFO,
240 "%s: pcep_msg_create_update missing mandatory third ERO object",
241 __func__);
242 return NULL;
243 }
244
245 return (pcep_msg_create_common_with_obj_list(
246 PCEP_TYPE_UPDATE, update_request_object_list));
247}
248
249struct pcep_message *
250pcep_msg_create_initiate(double_linked_list *lsp_object_list)
251{
252 if (lsp_object_list == NULL) {
253 pcep_log(
254 LOG_INFO,
255 "%s: pcep_msg_create_initiate NULL update_request_object_list",
256 __func__);
257 return NULL;
258 }
259
260 /* There must be at least 2 objects: SRP and LSP. */
261 if (lsp_object_list->num_entries < 2) {
262 pcep_log(
263 LOG_INFO,
264 "%s: pcep_msg_create_initiate there must be at least 2 objects",
265 __func__);
266 return NULL;
267 }
268
269 double_linked_list_node *node = lsp_object_list->head;
270 struct pcep_object_header *obj_hdr =
271 (struct pcep_object_header *)node->data;
272
273 /* Check for the mandatory first SRP object */
274 if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
275 pcep_log(
276 LOG_INFO,
277 "%s: pcep_msg_create_initiate missing mandatory first SRP object",
278 __func__);
279 return NULL;
280 }
281
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) {
286 pcep_log(
287 LOG_INFO,
288 "%s: pcep_msg_create_initiate missing mandatory second LSP object",
289 __func__);
290 return NULL;
291 }
292
293 return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE,
294 lsp_object_list));
295}
296
297struct pcep_message *pcep_msg_create_notify(struct pcep_object_notify *notify,
298 double_linked_list *object_list)
299{
300 if (notify == NULL) {
301 pcep_log(LOG_INFO,
302 "%s: pcep_msg_create_notify NULL notify object",
303 __func__);
304 return NULL;
305 }
306
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);
310
311 return message;
312}