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