]> git.proxmox.com Git - mirror_frr.git/blame - pceplib/pcep_msg_tools.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pceplib / pcep_msg_tools.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: LGPL-2.1-or-later
74971473
JG
2/*
3 * This file is part of the PCEPlib, a PCEP protocol library.
4 *
5 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 *
74971473
JG
7 * Author : Brady Johnson <brady@voltanet.io>
8 *
9 */
10
11
1f8031f7
DL
12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif
15
74971473
JG
16#include <errno.h>
17#include <stdio.h>
18#include <string.h>
19#include <unistd.h>
20
21#include "pcep_msg_tools.h"
22#include "pcep_msg_encoding.h"
23#include "pcep_utils_logging.h"
24#include "pcep_utils_memory.h"
25
26static const char *message_type_strs[] = {"NOT_IMPLEMENTED0",
27 "OPEN",
28 "KEEPALIVE",
29 "PCREQ",
30 "PCREP",
31 "PCNOTF",
32 "ERROR",
33 "CLOSE",
34 "NOT_IMPLEMENTED8",
35 "NOT_IMPLEMENTED9",
36 "REPORT",
37 "UPDATE",
38 "INITIATE",
39 "UNKOWN_MESSAGE_TYPE"};
40
41static const char *object_class_strs[] = {"NOT_IMPLEMENTED0",
42 "OPEN",
43 "RP",
44 "NOPATH",
45 "ENDPOINTS",
46 "BANDWIDTH",
47 "METRIC",
48 "ERO",
49 "RRO",
50 "LSPA",
51 "IRO",
52 "SVEC",
53 "NOTF",
54 "ERROR",
55 "NOT_IMPLEMENTED14",
56 "CLOSE",
57 "NOT_IMPLEMENTED16",
58 "NOT_IMPLEMENTED17",
59 "NOT_IMPLEMENTED18",
60 "NOT_IMPLEMENTED19",
61 "NOT_IMPLEMENTED20",
62 "OBJECTIVE_FUNCTION",
63 "NOT_IMPLEMENTED22",
64 "NOT_IMPLEMENTED23",
65 "NOT_IMPLEMENTED24",
66 "NOT_IMPLEMENTED25",
67 "NOT_IMPLEMENTED26",
68 "NOT_IMPLEMENTED27",
69 "NOT_IMPLEMENTED28",
70 "NOT_IMPLEMENTED29",
71 "NOT_IMPLEMENTED30",
72 "NOT_IMPLEMENTED31",
73 "LSP",
74 "SRP",
75 "VENDOR_INFO",
76 "NOT_IMPLEMENTED35",
77 "INTER_LAYER",
78 "SWITCH_LAYER",
79 "REQ_ADAP_CAP",
80 "SERVER_IND",
81 "ASSOCIATION", /* 40 */
82 "UNKNOWN_MESSAGE_TYPE"};
83
84
85double_linked_list *pcep_msg_read(int sock_fd)
86{
87 int ret;
7ed8c4b1 88 uint8_t buffer[PCEP_MESSAGE_LENGTH] = {0};
74971473
JG
89 uint16_t buffer_read = 0;
90
91
7ed8c4b1 92 ret = read(sock_fd, &buffer, PCEP_MESSAGE_LENGTH);
74971473
JG
93
94 if (ret < 0) {
95 pcep_log(
96 LOG_INFO,
97 "%s: pcep_msg_read: Failed to read from socket fd [%d] errno [%d %s]",
98 __func__, sock_fd, errno, strerror(errno));
99 return NULL;
100 } else if (ret == 0) {
101 pcep_log(LOG_INFO, "%s: pcep_msg_read: Remote shutdown fd [%d]",
102 __func__, sock_fd);
103 return NULL;
104 }
105
106 double_linked_list *msg_list = dll_initialize();
107 struct pcep_message *msg = NULL;
108
7ed8c4b1 109 while (((uint16_t)ret - buffer_read) >= MESSAGE_HEADER_LENGTH) {
74971473
JG
110
111 /* Get the Message header, validate it, and return the msg
112 * length */
7ed8c4b1 113 int32_t msg_length =
74971473 114 pcep_decode_validate_msg_header(buffer + buffer_read);
7ed8c4b1 115 if (msg_length < 0 || msg_length > PCEP_MESSAGE_LENGTH) {
74971473
JG
116 /* If the message header is invalid, we cant keep
117 * reading since the length may be invalid */
118 pcep_log(
119 LOG_INFO,
120 "%s: pcep_msg_read: Received an invalid message fd [%d]",
121 __func__, sock_fd);
122 return msg_list;
123 }
124
7ed8c4b1 125 /* Check if the msg_length is longer than what was read,
74971473 126 * in which case, we need to read the rest of the message. */
7ed8c4b1
JG
127 if ((ret - buffer_read) < msg_length) {
128 int read_len = (msg_length - (ret - buffer_read));
74971473
JG
129 int read_ret = 0;
130 pcep_log(
131 LOG_INFO,
132 "%s: pcep_msg_read: Message not fully read! Trying to read %d bytes more, fd [%d]",
133 __func__, read_len, sock_fd);
134
b8cc7b62 135 if (PCEP_MESSAGE_LENGTH - ret - buffer_read >= read_len)
7ed8c4b1
JG
136 read_ret =
137 read(sock_fd, &buffer[ret], read_len);
138 else {
139 pcep_log(
140 LOG_ERR,
141 "%s: Trying to read size (%d) offset (%d) in a buff of size (%d)",
b8cc7b62
QY
142 __func__, read_len, ret,
143 PCEP_MESSAGE_LENGTH);
7ed8c4b1
JG
144 return msg_list;
145 }
74971473
JG
146
147 if (read_ret != read_len) {
148 pcep_log(
149 LOG_INFO,
150 "%s: pcep_msg_read: Did not manage to read enough data (%d != %d) fd [%d]",
151 __func__, read_ret, read_len, sock_fd);
152 return msg_list;
153 }
154 }
155
156 msg = pcep_decode_message(buffer + buffer_read);
7ed8c4b1 157 buffer_read += msg_length;
74971473
JG
158
159 if (msg == NULL) {
160 return msg_list;
161 } else {
162 dll_append(msg_list, msg);
163 }
164 }
165
166 return msg_list;
167}
168
169struct pcep_message *pcep_msg_get(double_linked_list *msg_list, uint8_t type)
170{
171 if (msg_list == NULL) {
172 return NULL;
173 }
174
175 double_linked_list_node *node;
176 for (node = msg_list->head; node != NULL; node = node->next_node) {
177 if (((struct pcep_message *)node->data)->msg_header->type
178 == type) {
179 return (struct pcep_message *)node->data;
180 }
181 }
182
183 return NULL;
184}
185
186struct pcep_message *pcep_msg_get_next(double_linked_list *list,
187 struct pcep_message *current,
188 uint8_t type)
189{
190 if (list == NULL || current == NULL) {
191 return NULL;
192 }
193
194 if (list->head == NULL) {
195 return NULL;
196 }
197
198 double_linked_list_node *node;
199 for (node = list->head; node != NULL; node = node->next_node) {
200 if (node->data == current) {
201 continue;
202 }
203
204 if (((struct pcep_message *)node->data)->msg_header->type
205 == type) {
206 return (struct pcep_message *)node->data;
207 }
208 }
209
210 return NULL;
211}
212
213struct pcep_object_header *pcep_obj_get(double_linked_list *list,
214 uint8_t object_class)
215{
216 if (list == NULL) {
217 return NULL;
218 }
219
220 if (list->head == NULL) {
221 return NULL;
222 }
223
224 double_linked_list_node *obj_item;
225 for (obj_item = list->head; obj_item != NULL;
226 obj_item = obj_item->next_node) {
227 if (((struct pcep_object_header *)obj_item->data)->object_class
228 == object_class) {
229 return (struct pcep_object_header *)obj_item->data;
230 }
231 }
232
233 return NULL;
234}
235
236struct pcep_object_header *pcep_obj_get_next(double_linked_list *list,
237 struct pcep_object_header *current,
238 uint8_t object_class)
239{
240 if (list == NULL || current == NULL) {
241 return NULL;
242 }
243
244 if (list->head == NULL) {
245 return NULL;
246 }
247
248 double_linked_list_node *node;
249 for (node = list->head; node != NULL; node = node->next_node) {
250 if (node->data == current) {
251 continue;
252 }
253
254 if (((struct pcep_object_header *)node->data)->object_class
255 == object_class) {
256 return (struct pcep_object_header *)node->data;
257 }
258 }
259
260 return NULL;
261}
262
263void pcep_obj_free_tlv(struct pcep_object_tlv_header *tlv)
264{
265 /* Specific TLV freeing */
266 switch (tlv->type) {
267 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID:
268 if (((struct pcep_object_tlv_speaker_entity_identifier *)tlv)
269 ->speaker_entity_id_list
270 != NULL) {
271 dll_destroy_with_data_memtype(
272 ((struct
273 pcep_object_tlv_speaker_entity_identifier *)
274 tlv)
275 ->speaker_entity_id_list,
276 PCEPLIB_MESSAGES);
277 }
278 break;
279
280 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
281 if (((struct pcep_object_tlv_path_setup_type_capability *)tlv)
282 ->pst_list
283 != NULL) {
284 dll_destroy_with_data_memtype(
285 ((struct
286 pcep_object_tlv_path_setup_type_capability *)
287 tlv)
288 ->pst_list,
289 PCEPLIB_MESSAGES);
290 }
291
292 if (((struct pcep_object_tlv_path_setup_type_capability *)tlv)
293 ->sub_tlv_list
294 != NULL) {
295 dll_destroy_with_data_memtype(
296 ((struct
297 pcep_object_tlv_path_setup_type_capability *)
298 tlv)
299 ->sub_tlv_list,
300 PCEPLIB_MESSAGES);
301 }
302 break;
303
fdfa6ecf
DS
304 case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
305 case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
306 case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
307 case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
308 case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
309 case PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS:
310 case PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS:
311 case PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE:
312 case PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC:
313 case PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION:
314 case PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY:
315 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE:
316 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
317 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
318 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
319 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
320 case PCEP_OBJ_TLV_TYPE_UNKNOWN:
321 case PCEP_OBJ_TYPE_CISCO_BSID:
322 case PCEP_OBJ_TLV_TYPE_ARBITRARY:
74971473
JG
323 break;
324 }
325
326 pceplib_free(PCEPLIB_MESSAGES, tlv);
327}
328
329void pcep_obj_free_object(struct pcep_object_header *obj)
330{
331 /* Iterate the TLVs and free each one */
332 if (obj->tlv_list != NULL) {
333 struct pcep_object_tlv_header *tlv;
334 while ((tlv = (struct pcep_object_tlv_header *)
335 dll_delete_first_node(obj->tlv_list))
336 != NULL) {
337 pcep_obj_free_tlv(tlv);
338 }
339
340 dll_destroy(obj->tlv_list);
341 }
342
343 /* Specific object freeing */
344 switch (obj->object_class) {
345 case PCEP_OBJ_CLASS_ERO:
346 case PCEP_OBJ_CLASS_IRO:
347 case PCEP_OBJ_CLASS_RRO: {
348 if (((struct pcep_object_ro *)obj)->sub_objects != NULL) {
349 double_linked_list_node *node =
350 ((struct pcep_object_ro *)obj)
351 ->sub_objects->head;
352 for (; node != NULL; node = node->next_node) {
353 struct pcep_object_ro_subobj *ro_subobj =
354 (struct pcep_object_ro_subobj *)
355 node->data;
356 if (ro_subobj->ro_subobj_type
357 == RO_SUBOBJ_TYPE_SR) {
358 if (((struct pcep_ro_subobj_sr *)
359 ro_subobj)
360 ->nai_list
361 != NULL) {
362 dll_destroy_with_data_memtype(
363 ((struct
364 pcep_ro_subobj_sr *)
365 ro_subobj)
366 ->nai_list,
367 PCEPLIB_MESSAGES);
368 }
369 }
370 }
371 dll_destroy_with_data_memtype(
372 ((struct pcep_object_ro *)obj)->sub_objects,
373 PCEPLIB_MESSAGES);
374 }
375 } break;
376
377 case PCEP_OBJ_CLASS_SVEC:
378 if (((struct pcep_object_svec *)obj)->request_id_list != NULL) {
379 dll_destroy_with_data_memtype(
380 ((struct pcep_object_svec *)obj)
381 ->request_id_list,
382 PCEPLIB_MESSAGES);
383 }
384 break;
385
386 case PCEP_OBJ_CLASS_SWITCH_LAYER:
387 if (((struct pcep_object_switch_layer *)obj)->switch_layer_rows
388 != NULL) {
389 dll_destroy_with_data_memtype(
390 ((struct pcep_object_switch_layer *)obj)
391 ->switch_layer_rows,
392 PCEPLIB_MESSAGES);
393 }
394 break;
395
fdfa6ecf
DS
396 case PCEP_OBJ_CLASS_OPEN:
397 case PCEP_OBJ_CLASS_RP:
398 case PCEP_OBJ_CLASS_NOPATH:
399 case PCEP_OBJ_CLASS_ENDPOINTS:
400 case PCEP_OBJ_CLASS_BANDWIDTH:
401 case PCEP_OBJ_CLASS_METRIC:
402 case PCEP_OBJ_CLASS_LSPA:
403 case PCEP_OBJ_CLASS_NOTF:
404 case PCEP_OBJ_CLASS_ERROR:
405 case PCEP_OBJ_CLASS_CLOSE:
406 case PCEP_OBJ_CLASS_OF:
407 case PCEP_OBJ_CLASS_LSP:
408 case PCEP_OBJ_CLASS_SRP:
409 case PCEP_OBJ_CLASS_VENDOR_INFO:
410 case PCEP_OBJ_CLASS_INTER_LAYER:
411 case PCEP_OBJ_CLASS_REQ_ADAP_CAP:
412 case PCEP_OBJ_CLASS_SERVER_IND:
413 case PCEP_OBJ_CLASS_ASSOCIATION:
414 case PCEP_OBJ_CLASS_MAX:
74971473
JG
415 break;
416 }
417
418 pceplib_free(PCEPLIB_MESSAGES, obj);
419}
420
421void pcep_msg_free_message(struct pcep_message *message)
422{
423 /* Iterate the objects and free each one */
424 if (message->obj_list != NULL) {
425 struct pcep_object_header *obj;
426 while ((obj = (struct pcep_object_header *)
427 dll_delete_first_node(message->obj_list))
428 != NULL) {
429 pcep_obj_free_object(obj);
430 }
431
432 dll_destroy(message->obj_list);
433 }
434
435 if (message->msg_header != NULL) {
436 pceplib_free(PCEPLIB_MESSAGES, message->msg_header);
437 }
438
439 if (message->encoded_message != NULL) {
440 pceplib_free(PCEPLIB_MESSAGES, message->encoded_message);
441 }
442
443 pceplib_free(PCEPLIB_MESSAGES, message);
444}
445
446void pcep_msg_free_message_list(double_linked_list *list)
447{
448 /* Iterate the messages and free each one */
449 struct pcep_message *msg;
450 while ((msg = (struct pcep_message *)dll_delete_first_node(list))
451 != NULL) {
452 pcep_msg_free_message(msg);
453 }
454
455 dll_destroy(list);
456}
457
458const char *get_message_type_str(uint8_t type)
459{
460 uint8_t msg_type =
461 (type > PCEP_TYPE_INITIATE) ? PCEP_TYPE_INITIATE + 1 : type;
462
463 return message_type_strs[msg_type];
464}
465
466const char *get_object_class_str(uint8_t class)
467{
468 uint8_t object_class =
469 (class > PCEP_OBJ_CLASS_SRP) ? PCEP_OBJ_CLASS_SRP + 1 : class;
470
471 return object_class_strs[object_class];
472}
473
474/* Expecting a list of struct pcep_message pointers */
475void pcep_msg_print(double_linked_list *msg_list)
476{
477 double_linked_list_node *node;
478 for (node = msg_list->head; node != NULL; node = node->next_node) {
479 struct pcep_message *msg = (struct pcep_message *)node->data;
480 pcep_log(LOG_INFO, "%s: PCEP_MSG %s", __func__,
481 get_message_type_str(msg->msg_header->type));
482
483 double_linked_list_node *obj_node =
484 (msg->obj_list == NULL ? NULL : msg->obj_list->head);
485 for (; obj_node != NULL; obj_node = obj_node->next_node) {
486 struct pcep_object_header *obj_header =
487 ((struct pcep_object_header *)obj_node->data);
488 pcep_log(
489 LOG_INFO, "%s: PCEP_OBJ %s", __func__,
490 get_object_class_str(obj_header->object_class));
491 }
492 }
493}
494
495int pcep_msg_send(int sock_fd, struct pcep_message *msg)
496{
497 if (msg == NULL) {
498 return 0;
499 }
7ed8c4b1
JG
500 int msg_length = ntohs(msg->encoded_message_length);
501 if (msg_length > PCEP_MESSAGE_LENGTH) {
502 pcep_log(LOG_ERR, "%s: Not sended, size(% d) exceed max(% d) ",
503 __func__, msg_length, PCEP_MESSAGE_LENGTH);
504 return 0;
505 }
74971473 506
7ed8c4b1 507 return write(sock_fd, msg->encoded_message, msg_length);
74971473 508}