]> git.proxmox.com Git - mirror_frr.git/blob - pceplib/pcep_msg_objects_encoding.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / pceplib / pcep_msg_objects_encoding.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 /*
25 * Encoding and decoding for PCEP Objects.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "pcep_msg_objects.h"
36 #include "pcep_msg_encoding.h"
37 #include "pcep_utils_logging.h"
38 #include "pcep_utils_memory.h"
39
40 void write_object_header(struct pcep_object_header *object_hdr,
41 uint16_t object_length, uint8_t *buf);
42 void pcep_decode_object_hdr(const uint8_t *obj_buf,
43 struct pcep_object_header *obj_hdr);
44 void set_ro_subobj_fields(struct pcep_object_ro_subobj *subobj, bool flag_l,
45 uint8_t subobj_type);
46
47 /*
48 * forward declarations for initialize_object_encoders()
49 */
50 uint16_t pcep_encode_obj_open(struct pcep_object_header *obj,
51 struct pcep_versioning *versioning, uint8_t *buf);
52 uint16_t pcep_encode_obj_rp(struct pcep_object_header *obj,
53 struct pcep_versioning *versioning, uint8_t *buf);
54 uint16_t pcep_encode_obj_nopath(struct pcep_object_header *obj,
55 struct pcep_versioning *versioning,
56 uint8_t *buf);
57 uint16_t pcep_encode_obj_endpoints(struct pcep_object_header *obj,
58 struct pcep_versioning *versioning,
59 uint8_t *buf);
60 uint16_t pcep_encode_obj_association(struct pcep_object_header *obj,
61 struct pcep_versioning *versioning,
62 uint8_t *buf);
63 uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header *obj,
64 struct pcep_versioning *versioning,
65 uint8_t *buf);
66 uint16_t pcep_encode_obj_metric(struct pcep_object_header *obj,
67 struct pcep_versioning *versioning,
68 uint8_t *buf);
69 uint16_t pcep_encode_obj_ro(struct pcep_object_header *obj,
70 struct pcep_versioning *versioning, uint8_t *buf);
71 uint16_t pcep_encode_obj_lspa(struct pcep_object_header *obj,
72 struct pcep_versioning *versioning, uint8_t *buf);
73 uint16_t pcep_encode_obj_svec(struct pcep_object_header *obj,
74 struct pcep_versioning *versioning, uint8_t *buf);
75 uint16_t pcep_encode_obj_notify(struct pcep_object_header *obj,
76 struct pcep_versioning *versioning,
77 uint8_t *buf);
78 uint16_t pcep_encode_obj_error(struct pcep_object_header *error,
79 struct pcep_versioning *versioning,
80 uint8_t *buf);
81 uint16_t pcep_encode_obj_close(struct pcep_object_header *close,
82 struct pcep_versioning *versioning,
83 uint8_t *buf);
84 uint16_t pcep_encode_obj_srp(struct pcep_object_header *obj,
85 struct pcep_versioning *versioning, uint8_t *buf);
86 uint16_t pcep_encode_obj_lsp(struct pcep_object_header *obj,
87 struct pcep_versioning *versioning, uint8_t *buf);
88 uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header *obj,
89 struct pcep_versioning *versioning,
90 uint8_t *buf);
91 uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header *obj,
92 struct pcep_versioning *versioning,
93 uint8_t *buf);
94 uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header *obj,
95 struct pcep_versioning *versioning,
96 uint8_t *buf);
97 uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header *obj,
98 struct pcep_versioning *versioning,
99 uint8_t *buf);
100 uint16_t pcep_encode_obj_server_ind(struct pcep_object_header *obj,
101 struct pcep_versioning *versioning,
102 uint8_t *buf);
103 uint16_t pcep_encode_obj_objective_function(struct pcep_object_header *obj,
104 struct pcep_versioning *versioning,
105 uint8_t *buf);
106 typedef uint16_t (*object_encoder_funcptr)(struct pcep_object_header *,
107 struct pcep_versioning *versioning,
108 uint8_t *buf);
109
110 #define MAX_OBJECT_ENCODER_INDEX 64
111
112 #define PCEP_ENCODERS_ARGS \
113 struct pcep_object_header *, struct pcep_versioning *versioning, \
114 uint8_t *buf
115 uint16_t (*const object_encoders[MAX_OBJECT_ENCODER_INDEX])(
116 PCEP_ENCODERS_ARGS) = {
117 [PCEP_OBJ_CLASS_OPEN] = pcep_encode_obj_open,
118 [PCEP_OBJ_CLASS_RP] = pcep_encode_obj_rp,
119 [PCEP_OBJ_CLASS_NOPATH] = pcep_encode_obj_nopath,
120 [PCEP_OBJ_CLASS_ENDPOINTS] = pcep_encode_obj_endpoints,
121 [PCEP_OBJ_CLASS_BANDWIDTH] = pcep_encode_obj_bandwidth,
122 [PCEP_OBJ_CLASS_METRIC] = pcep_encode_obj_metric,
123 [PCEP_OBJ_CLASS_ERO] = pcep_encode_obj_ro,
124 [PCEP_OBJ_CLASS_RRO] = pcep_encode_obj_ro,
125 [PCEP_OBJ_CLASS_LSPA] = pcep_encode_obj_lspa,
126 [PCEP_OBJ_CLASS_IRO] = pcep_encode_obj_ro,
127 [PCEP_OBJ_CLASS_SVEC] = pcep_encode_obj_svec,
128 [PCEP_OBJ_CLASS_NOTF] = pcep_encode_obj_notify,
129 [PCEP_OBJ_CLASS_ERROR] = pcep_encode_obj_error,
130 [PCEP_OBJ_CLASS_CLOSE] = pcep_encode_obj_close,
131 [PCEP_OBJ_CLASS_LSP] = pcep_encode_obj_lsp,
132 [PCEP_OBJ_CLASS_SRP] = pcep_encode_obj_srp,
133 [PCEP_OBJ_CLASS_ASSOCIATION] = pcep_encode_obj_association,
134 [PCEP_OBJ_CLASS_INTER_LAYER] = pcep_encode_obj_inter_layer,
135 [PCEP_OBJ_CLASS_SWITCH_LAYER] = pcep_encode_obj_switch_layer,
136 [PCEP_OBJ_CLASS_REQ_ADAP_CAP] = pcep_encode_obj_req_adap_cap,
137 [PCEP_OBJ_CLASS_SERVER_IND] = pcep_encode_obj_server_ind,
138 [PCEP_OBJ_CLASS_VENDOR_INFO] = pcep_encode_obj_vendor_info,
139 [PCEP_OBJ_CLASS_OF] = pcep_encode_obj_objective_function,
140 };
141 /*
142 * forward declarations for initialize_object_decoders()
143 */
144 struct pcep_object_header *pcep_decode_obj_open(struct pcep_object_header *hdr,
145 const uint8_t *buf);
146 struct pcep_object_header *pcep_decode_obj_rp(struct pcep_object_header *hdr,
147 const uint8_t *buf);
148 struct pcep_object_header *
149 pcep_decode_obj_nopath(struct pcep_object_header *hdr, const uint8_t *buf);
150 struct pcep_object_header *
151 pcep_decode_obj_endpoints(struct pcep_object_header *hdr, const uint8_t *buf);
152 struct pcep_object_header *
153 pcep_decode_obj_association(struct pcep_object_header *hdr, const uint8_t *buf);
154 struct pcep_object_header *
155 pcep_decode_obj_bandwidth(struct pcep_object_header *hdr, const uint8_t *buf);
156 struct pcep_object_header *
157 pcep_decode_obj_metric(struct pcep_object_header *hdr, const uint8_t *buf);
158 struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr,
159 const uint8_t *buf);
160 struct pcep_object_header *pcep_decode_obj_lspa(struct pcep_object_header *hdr,
161 const uint8_t *buf);
162 struct pcep_object_header *pcep_decode_obj_svec(struct pcep_object_header *hdr,
163 const uint8_t *buf);
164 struct pcep_object_header *
165 pcep_decode_obj_notify(struct pcep_object_header *hdr, const uint8_t *buf);
166 struct pcep_object_header *pcep_decode_obj_error(struct pcep_object_header *hdr,
167 const uint8_t *buf);
168 struct pcep_object_header *pcep_decode_obj_close(struct pcep_object_header *hdr,
169 const uint8_t *buf);
170 struct pcep_object_header *pcep_decode_obj_srp(struct pcep_object_header *hdr,
171 const uint8_t *buf);
172 struct pcep_object_header *pcep_decode_obj_lsp(struct pcep_object_header *hdr,
173 const uint8_t *buf);
174 struct pcep_object_header *
175 pcep_decode_obj_vendor_info(struct pcep_object_header *hdr, const uint8_t *buf);
176 struct pcep_object_header *
177 pcep_decode_obj_inter_layer(struct pcep_object_header *hdr, const uint8_t *buf);
178 struct pcep_object_header *
179 pcep_decode_obj_switch_layer(struct pcep_object_header *hdr,
180 const uint8_t *buf);
181 struct pcep_object_header *
182 pcep_decode_obj_req_adap_cap(struct pcep_object_header *hdr,
183 const uint8_t *buf);
184 struct pcep_object_header *
185 pcep_decode_obj_server_ind(struct pcep_object_header *hdr, const uint8_t *buf);
186 struct pcep_object_header *
187 pcep_decode_obj_objective_function(struct pcep_object_header *hdr,
188 const uint8_t *buf);
189 typedef struct pcep_object_header *(*object_decoder_funcptr)(
190 struct pcep_object_header *, const uint8_t *buf);
191
192 #define PCEP_DECODERS_ARGS struct pcep_object_header *, const uint8_t *buf
193
194 struct pcep_object_header *(*const object_decoders[MAX_OBJECT_ENCODER_INDEX])(
195 PCEP_DECODERS_ARGS) = {
196 [PCEP_OBJ_CLASS_OPEN] = pcep_decode_obj_open,
197 [PCEP_OBJ_CLASS_RP] = pcep_decode_obj_rp,
198 [PCEP_OBJ_CLASS_NOPATH] = pcep_decode_obj_nopath,
199 [PCEP_OBJ_CLASS_ENDPOINTS] = pcep_decode_obj_endpoints,
200 [PCEP_OBJ_CLASS_BANDWIDTH] = pcep_decode_obj_bandwidth,
201 [PCEP_OBJ_CLASS_METRIC] = pcep_decode_obj_metric,
202 [PCEP_OBJ_CLASS_ERO] = pcep_decode_obj_ro,
203 [PCEP_OBJ_CLASS_RRO] = pcep_decode_obj_ro,
204 [PCEP_OBJ_CLASS_LSPA] = pcep_decode_obj_lspa,
205 [PCEP_OBJ_CLASS_IRO] = pcep_decode_obj_ro,
206 [PCEP_OBJ_CLASS_SVEC] = pcep_decode_obj_svec,
207 [PCEP_OBJ_CLASS_NOTF] = pcep_decode_obj_notify,
208 [PCEP_OBJ_CLASS_ERROR] = pcep_decode_obj_error,
209 [PCEP_OBJ_CLASS_CLOSE] = pcep_decode_obj_close,
210 [PCEP_OBJ_CLASS_LSP] = pcep_decode_obj_lsp,
211 [PCEP_OBJ_CLASS_SRP] = pcep_decode_obj_srp,
212 [PCEP_OBJ_CLASS_ASSOCIATION] = pcep_decode_obj_association,
213 [PCEP_OBJ_CLASS_INTER_LAYER] = pcep_decode_obj_inter_layer,
214 [PCEP_OBJ_CLASS_SWITCH_LAYER] = pcep_decode_obj_switch_layer,
215 [PCEP_OBJ_CLASS_REQ_ADAP_CAP] = pcep_decode_obj_req_adap_cap,
216 [PCEP_OBJ_CLASS_SERVER_IND] = pcep_decode_obj_server_ind,
217 [PCEP_OBJ_CLASS_VENDOR_INFO] = pcep_decode_obj_vendor_info,
218 [PCEP_OBJ_CLASS_OF] = pcep_decode_obj_objective_function,
219 };
220
221 /* Object lengths, including the Object Header.
222 * Used by pcep_object_get_length() and pcep_object_has_tlvs() */
223 static uint8_t pcep_object_class_lengths[] = {
224 0, /* Object class 0 unused */
225 8, /* PCEP_OBJ_CLASS_OPEN = 1 */
226 12, /* PCEP_OBJ_CLASS_RP = 2 */
227 16, /* PCEP_OBJ_CLASS_NOPATH = 3, includes 8 for mandatory TLV */
228 0, /* PCEP_OBJ_CLASS_ENDPOINTS = 4, could be ipv4 or ipv6, setting to 0
229 */
230 8, /* PCEP_OBJ_CLASS_BANDWIDTH = 5 */
231 12, /* PCEP_OBJ_CLASS_METRIC = 6 */
232 0, /* PCEP_OBJ_CLASS_ERO = 7, setting 0, ROs cannot have TLVs */
233 0, /* PCEP_OBJ_CLASS_RRO = 8, setting 0, ROs cannot have TLVs */
234 20, /* PCEP_OBJ_CLASS_LSPA = 9 */
235 0, /* PCEP_OBJ_CLASS_IRO = 10, setting 0, ROs cannot have TLVs */
236 0, /* PCEP_OBJ_CLASS_SVEC = 11, SVECs cannot have TLVs */
237 8, /* PCEP_OBJ_CLASS_NOTF = 12 */
238 8, /* PCEP_OBJ_CLASS_ERROR = 13 */
239 0, /* Object class 14 unused */
240 8, /* PCEP_OBJ_CLASS_CLOSE = 15 */
241 0, 0, 0, 0, 0, /* Object classes 16 - 20 are not used */
242 8, /* PCEP_OBJ_CLASS_OF = 21 */
243 0, 0, 0, 0, 0, /* Object classes 22 - 26 are not used */
244 0, 0, 0, 0, 0, /* Object classes 27 - 31 are not used */
245 8, /* PCEP_OBJ_CLASS_LSP = 32 */
246 12, /* PCEP_OBJ_CLASS_SRP = 33 */
247 12, /* PCEP_OBJ_CLASS_VENDOR_INFO = 34 */
248 0, /* Object class 35 unused */
249 0, /* PCEP_OBJ_CLASS_INTER_LAYER = 36, cannot have TLVs */
250 0, /* PCEP_OBJ_CLASS_SWITCH_LAYER = 37, cannot have TLVs */
251 0, /* PCEP_OBJ_CLASS_REQ_ADAP_CAP = 38, cannot have TLVs*/
252 8, /* PCEP_OBJ_CLASS_SERVER_IND = 39 */
253 0, /* PCEP_OBJ_CLASS_ASSOCIATION = 40, cannot have TLVs */
254 };
255
256 /*
257 * The TLVs can have strange length values, since they do not include padding in
258 * the TLV header length, but that extra padding must be taken into account by
259 * the enclosing object by rounding up to the next 4 byte boundary.
260 * Example returned lengths:
261 * normalize_length(4) = 4, normalize_length(5) = 8, normalize_length(6)
262 * = 8, normalize_length(7) = 8, normalize_length(8) = 8
263 * normalize_length(9) = 12, normalize_length(10) = 12, normalize_length(11) =
264 * 12, normalize_length(12) = 12, normalize_length(13) = 13...
265 */
266 uint16_t normalize_pcep_tlv_length(uint16_t length)
267 {
268 return (length % 4 == 0) ? length : (length + (4 - (length % 4)));
269 }
270
271 /*
272 * Encoding functions
273 */
274 uint16_t pcep_encode_object(struct pcep_object_header *object_hdr,
275 struct pcep_versioning *versioning, uint8_t *buf)
276 {
277
278 if (object_hdr->object_class >= MAX_OBJECT_ENCODER_INDEX) {
279 pcep_log(LOG_INFO,
280 "%s: Cannot encode unknown Object class [%d]",
281 __func__, object_hdr->object_class);
282 return 0;
283 }
284
285 object_encoder_funcptr obj_encoder =
286 object_encoders[object_hdr->object_class];
287 if (obj_encoder == NULL) {
288 pcep_log(LOG_INFO,
289 "%s: No object encoder found for Object class [%d]",
290 __func__, object_hdr->object_class);
291 return 0;
292 }
293
294 uint16_t object_length = OBJECT_HEADER_LENGTH
295 + obj_encoder(object_hdr, versioning,
296 buf + OBJECT_HEADER_LENGTH);
297 double_linked_list_node *node =
298 (object_hdr->tlv_list == NULL ? NULL
299 : object_hdr->tlv_list->head);
300 for (; node != NULL; node = node->next_node) {
301 /* Returns the length of the TLV, including the TLV header */
302 object_length += pcep_encode_tlv(
303 (struct pcep_object_tlv_header *)node->data, versioning,
304 buf + object_length);
305 }
306 object_length = normalize_pcep_tlv_length(object_length);
307 write_object_header(object_hdr, object_length, buf);
308 object_hdr->encoded_object = buf;
309 object_hdr->encoded_object_length = object_length;
310
311 return object_length;
312 }
313
314
315 /* Object Header
316 *
317 * 0 1 2 3
318 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
319 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320 * | Object-Class | OT |Res|P|I| Object Length (bytes) |
321 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
322 * | |
323 * // (Object body) //
324 * | |
325 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
326 *
327 */
328
329 void write_object_header(struct pcep_object_header *object_hdr,
330 uint16_t object_length, uint8_t *buf)
331 {
332 buf[0] = object_hdr->object_class;
333 buf[1] = ((object_hdr->object_type << 4)
334 | (object_hdr->flag_p ? OBJECT_HEADER_FLAG_P : 0x00)
335 | (object_hdr->flag_i ? OBJECT_HEADER_FLAG_I : 0x00));
336 uint16_t net_order_length = htons(object_length);
337 memcpy(buf + 2, &net_order_length, sizeof(net_order_length));
338 }
339
340
341 /*
342 * Functions to encode objects
343 * - they will be passed a pointer to a buffer to write the object body,
344 * which is past the object header.
345 * - they should return the object body length, not including the object header
346 * length.
347 */
348
349 uint16_t pcep_encode_obj_open(struct pcep_object_header *hdr,
350 struct pcep_versioning *versioning,
351 uint8_t *obj_body_buf)
352 {
353 (void)versioning;
354 struct pcep_object_open *open = (struct pcep_object_open *)hdr;
355 obj_body_buf[0] = (open->open_version << 5) & 0xe0;
356 obj_body_buf[1] = open->open_keepalive;
357 obj_body_buf[2] = open->open_deadtimer;
358 obj_body_buf[3] = open->open_sid;
359
360 return LENGTH_1WORD;
361 }
362
363 uint16_t pcep_encode_obj_rp(struct pcep_object_header *hdr,
364 struct pcep_versioning *versioning,
365 uint8_t *obj_body_buf)
366 {
367 (void)versioning;
368 struct pcep_object_rp *rp = (struct pcep_object_rp *)hdr;
369 obj_body_buf[3] = ((rp->flag_strict ? OBJECT_RP_FLAG_O : 0x00)
370 | (rp->flag_bidirectional ? OBJECT_RP_FLAG_B : 0x00)
371 | (rp->flag_reoptimization ? OBJECT_RP_FLAG_R : 0x00)
372 | (rp->flag_of ? OBJECT_RP_FLAG_OF : 0x00)
373 | (rp->priority & 0x07));
374 uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4);
375 *uint32_ptr = htonl(rp->request_id);
376
377 return LENGTH_2WORDS;
378 }
379
380 uint16_t pcep_encode_obj_notify(struct pcep_object_header *hdr,
381 struct pcep_versioning *versioning,
382 uint8_t *obj_body_buf)
383 {
384 (void)versioning;
385 struct pcep_object_notify *notify = (struct pcep_object_notify *)hdr;
386 obj_body_buf[2] = notify->notification_type;
387 obj_body_buf[3] = notify->notification_value;
388
389 return LENGTH_1WORD;
390 }
391
392 uint16_t pcep_encode_obj_nopath(struct pcep_object_header *hdr,
393 struct pcep_versioning *versioning,
394 uint8_t *obj_body_buf)
395 {
396 (void)versioning;
397 struct pcep_object_nopath *nopath = (struct pcep_object_nopath *)hdr;
398 obj_body_buf[0] = nopath->ni;
399 obj_body_buf[1] = ((nopath->flag_c) ? OBJECT_NOPATH_FLAG_C : 0x00);
400
401 return LENGTH_1WORD;
402 }
403
404 uint16_t pcep_encode_obj_association(struct pcep_object_header *hdr,
405 struct pcep_versioning *versioning,
406 uint8_t *obj_body_buf)
407 {
408 (void)versioning;
409 uint16_t *uint16_ptr = (uint16_t *)obj_body_buf;
410 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
411 if (hdr->object_type == PCEP_OBJ_TYPE_ASSOCIATION_IPV4) {
412 struct pcep_object_association_ipv4 *ipv4 =
413 (struct pcep_object_association_ipv4 *)hdr;
414 obj_body_buf[3] =
415 (ipv4->R_flag ? OBJECT_ASSOCIATION_FLAG_R : 0x00);
416 uint16_ptr[2] = htons(ipv4->association_type);
417 uint16_ptr[3] = htons(ipv4->association_id);
418 uint32_ptr[2] = ipv4->src.s_addr;
419
420 return LENGTH_3WORDS;
421 } else {
422 struct pcep_object_association_ipv6 *ipv6 =
423 (struct pcep_object_association_ipv6 *)hdr;
424 obj_body_buf[3] =
425 (ipv6->R_flag ? OBJECT_ASSOCIATION_FLAG_R : 0x00);
426 uint16_ptr[2] = htons(ipv6->association_type);
427 uint16_ptr[3] = htons(ipv6->association_id);
428 memcpy(uint32_ptr, &ipv6->src, sizeof(struct in6_addr));
429
430 return LENGTH_6WORDS;
431 }
432 }
433
434 uint16_t pcep_encode_obj_endpoints(struct pcep_object_header *hdr,
435 struct pcep_versioning *versioning,
436 uint8_t *obj_body_buf)
437 {
438 (void)versioning;
439 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
440 if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) {
441 struct pcep_object_endpoints_ipv4 *ipv4 =
442 (struct pcep_object_endpoints_ipv4 *)hdr;
443 uint32_ptr[0] = ipv4->src_ipv4.s_addr;
444 uint32_ptr[1] = ipv4->dst_ipv4.s_addr;
445
446 return LENGTH_2WORDS;
447 } else {
448 struct pcep_object_endpoints_ipv6 *ipv6 =
449 (struct pcep_object_endpoints_ipv6 *)hdr;
450 memcpy(uint32_ptr, &ipv6->src_ipv6, sizeof(struct in6_addr));
451 memcpy(&uint32_ptr[4], &ipv6->dst_ipv6,
452 sizeof(struct in6_addr));
453
454 return LENGTH_8WORDS;
455 }
456 }
457
458 uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header *hdr,
459 struct pcep_versioning *versioning,
460 uint8_t *obj_body_buf)
461 {
462 (void)versioning;
463 struct pcep_object_bandwidth *bandwidth =
464 (struct pcep_object_bandwidth *)hdr;
465 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
466 /* Seems like the compiler doesn't correctly copy the float, so memcpy()
467 * it */
468 memcpy(uint32_ptr, &(bandwidth->bandwidth), sizeof(uint32_t));
469 *uint32_ptr = htonl(*uint32_ptr);
470
471 return LENGTH_1WORD;
472 }
473
474 uint16_t pcep_encode_obj_metric(struct pcep_object_header *hdr,
475 struct pcep_versioning *versioning,
476 uint8_t *obj_body_buf)
477 {
478 (void)versioning;
479 struct pcep_object_metric *metric = (struct pcep_object_metric *)hdr;
480 obj_body_buf[2] = ((metric->flag_c ? OBJECT_METRIC_FLAC_C : 0x00)
481 | (metric->flag_b ? OBJECT_METRIC_FLAC_B : 0x00));
482 obj_body_buf[3] = metric->type;
483 uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4);
484 /* Seems like the compiler doesn't correctly copy the float, so memcpy()
485 * it */
486 memcpy(uint32_ptr, &(metric->value), sizeof(uint32_t));
487 *uint32_ptr = htonl(*uint32_ptr);
488
489 return LENGTH_2WORDS;
490 }
491
492 uint16_t pcep_encode_obj_lspa(struct pcep_object_header *hdr,
493 struct pcep_versioning *versioning,
494 uint8_t *obj_body_buf)
495 {
496 (void)versioning;
497 struct pcep_object_lspa *lspa = (struct pcep_object_lspa *)hdr;
498 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
499 uint32_ptr[0] = htonl(lspa->lspa_exclude_any);
500 uint32_ptr[1] = htonl(lspa->lspa_include_any);
501 uint32_ptr[2] = htonl(lspa->lspa_include_all);
502 obj_body_buf[12] = lspa->setup_priority;
503 obj_body_buf[13] = lspa->holding_priority;
504 obj_body_buf[14] =
505 (lspa->flag_local_protection ? OBJECT_LSPA_FLAG_L : 0x00);
506
507 return LENGTH_4WORDS;
508 }
509
510 uint16_t pcep_encode_obj_svec(struct pcep_object_header *hdr,
511 struct pcep_versioning *versioning,
512 uint8_t *obj_body_buf)
513 {
514 (void)versioning;
515 struct pcep_object_svec *svec = (struct pcep_object_svec *)hdr;
516 obj_body_buf[3] =
517 ((svec->flag_srlg_diverse ? OBJECT_SVEC_FLAG_S : 0x00)
518 | (svec->flag_node_diverse ? OBJECT_SVEC_FLAG_N : 0x00)
519 | (svec->flag_link_diverse ? OBJECT_SVEC_FLAG_L : 0x00));
520
521 if (svec->request_id_list == NULL) {
522 return LENGTH_1WORD;
523 }
524
525 int index = 1;
526 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
527 double_linked_list_node *node = svec->request_id_list->head;
528 for (; node != NULL; node = node->next_node) {
529 uint32_ptr[index++] = htonl(*((uint32_t *)(node->data)));
530 }
531
532 return LENGTH_1WORD
533 + (svec->request_id_list->num_entries * sizeof(uint32_t));
534 }
535
536 uint16_t pcep_encode_obj_error(struct pcep_object_header *hdr,
537 struct pcep_versioning *versioning,
538 uint8_t *obj_body_buf)
539 {
540 (void)versioning;
541 struct pcep_object_error *error = (struct pcep_object_error *)hdr;
542 obj_body_buf[2] = error->error_type;
543 obj_body_buf[3] = error->error_value;
544
545 return LENGTH_1WORD;
546 }
547
548 uint16_t pcep_encode_obj_close(struct pcep_object_header *hdr,
549 struct pcep_versioning *versioning,
550 uint8_t *obj_body_buf)
551 {
552 (void)versioning;
553 struct pcep_object_close *close = (struct pcep_object_close *)hdr;
554 obj_body_buf[3] = close->reason;
555
556 return LENGTH_1WORD;
557 }
558
559 uint16_t pcep_encode_obj_srp(struct pcep_object_header *hdr,
560 struct pcep_versioning *versioning,
561 uint8_t *obj_body_buf)
562 {
563 (void)versioning;
564 struct pcep_object_srp *srp = (struct pcep_object_srp *)hdr;
565 obj_body_buf[3] = (srp->flag_lsp_remove ? OBJECT_SRP_FLAG_R : 0x00);
566 uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4);
567 *uint32_ptr = htonl(srp->srp_id_number);
568
569 return LENGTH_2WORDS;
570 }
571
572 uint16_t pcep_encode_obj_lsp(struct pcep_object_header *hdr,
573 struct pcep_versioning *versioning,
574 uint8_t *obj_body_buf)
575 {
576 (void)versioning;
577 struct pcep_object_lsp *lsp = (struct pcep_object_lsp *)hdr;
578 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
579 uint32_ptr[0] = htonl((lsp->plsp_id << 12) & 0xfffff000);
580 obj_body_buf[3] = ((lsp->flag_c ? OBJECT_LSP_FLAG_C : 0x00)
581 | ((lsp->operational_status << 4) & 0x70)
582 | (lsp->flag_a ? OBJECT_LSP_FLAG_A : 0x00)
583 | (lsp->flag_r ? OBJECT_LSP_FLAG_R : 0x00)
584 | (lsp->flag_s ? OBJECT_LSP_FLAG_S : 0x00)
585 | (lsp->flag_d ? OBJECT_LSP_FLAG_D : 0x00));
586
587 return LENGTH_1WORD;
588 }
589
590 uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header *hdr,
591 struct pcep_versioning *versioning,
592 uint8_t *obj_body_buf)
593 {
594 (void)versioning;
595 struct pcep_object_vendor_info *obj =
596 (struct pcep_object_vendor_info *)hdr;
597 uint32_t *uint32_ptr = (uint32_t *)obj_body_buf;
598 uint32_ptr[0] = htonl(obj->enterprise_number);
599 uint32_ptr[1] = htonl(obj->enterprise_specific_info);
600
601 return LENGTH_2WORDS;
602 }
603
604 uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header *hdr,
605 struct pcep_versioning *versioning,
606 uint8_t *obj_body_buf)
607 {
608 (void)versioning;
609 struct pcep_object_inter_layer *obj =
610 (struct pcep_object_inter_layer *)hdr;
611 obj_body_buf[3] = ((obj->flag_i ? OBJECT_INTER_LAYER_FLAG_I : 0x00)
612 | (obj->flag_m ? OBJECT_INTER_LAYER_FLAG_M : 0x00)
613 | (obj->flag_t ? OBJECT_INTER_LAYER_FLAG_T : 0x00));
614
615 return LENGTH_1WORD;
616 }
617
618 uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header *hdr,
619 struct pcep_versioning *versioning,
620 uint8_t *obj_body_buf)
621 {
622 (void)versioning;
623 struct pcep_object_switch_layer *obj =
624 (struct pcep_object_switch_layer *)hdr;
625 uint8_t buf_index = 0;
626
627 double_linked_list_node *node = obj->switch_layer_rows->head;
628 while (node != NULL) {
629 struct pcep_object_switch_layer_row *row = node->data;
630 if (row == NULL) {
631 break;
632 }
633
634 obj_body_buf[buf_index] = row->lsp_encoding_type;
635 obj_body_buf[buf_index + 1] = row->switching_type;
636 obj_body_buf[buf_index + 3] =
637 (row->flag_i ? OBJECT_SWITCH_LAYER_FLAG_I : 0x00);
638
639 buf_index += LENGTH_1WORD;
640 }
641
642 return buf_index;
643 }
644
645 uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header *hdr,
646 struct pcep_versioning *versioning,
647 uint8_t *obj_body_buf)
648 {
649 (void)versioning;
650 struct pcep_object_req_adap_cap *obj =
651 (struct pcep_object_req_adap_cap *)hdr;
652
653 obj_body_buf[0] = obj->switching_capability;
654 obj_body_buf[1] = obj->encoding;
655
656 return LENGTH_1WORD;
657 }
658
659 uint16_t pcep_encode_obj_server_ind(struct pcep_object_header *hdr,
660 struct pcep_versioning *versioning,
661 uint8_t *obj_body_buf)
662 {
663 (void)versioning;
664 struct pcep_object_server_indication *obj =
665 (struct pcep_object_server_indication *)hdr;
666
667 obj_body_buf[0] = obj->switching_capability;
668 obj_body_buf[1] = obj->encoding;
669
670 return LENGTH_1WORD;
671 }
672
673 uint16_t pcep_encode_obj_objective_function(struct pcep_object_header *hdr,
674 struct pcep_versioning *versioning,
675 uint8_t *obj_body_buf)
676 {
677 (void)versioning;
678 struct pcep_object_objective_function *obj =
679 (struct pcep_object_objective_function *)hdr;
680
681 uint16_t *uint16_ptr = (uint16_t *)obj_body_buf;
682 *uint16_ptr = htons(obj->of_code);
683
684 return LENGTH_1WORD;
685 }
686
687 uint16_t pcep_encode_obj_ro(struct pcep_object_header *hdr,
688 struct pcep_versioning *versioning,
689 uint8_t *obj_body_buf)
690 {
691 (void)versioning;
692 struct pcep_object_ro *ro = (struct pcep_object_ro *)hdr;
693 if (ro == NULL || ro->sub_objects == NULL) {
694 return 0;
695 }
696
697 /* RO Subobject format
698 *
699 * 0 1
700 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
701 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
702 * |L| Type | Length | (Subobject contents) |
703 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
704 */
705
706 uint16_t index = 0;
707 double_linked_list_node *node = ro->sub_objects->head;
708 for (; node != NULL; node = node->next_node) {
709 struct pcep_object_ro_subobj *ro_subobj = node->data;
710 obj_body_buf[index++] =
711 ((ro_subobj->flag_subobj_loose_hop ? 0x80 : 0x00)
712 | (ro_subobj->ro_subobj_type));
713 /* The length will be written below, depending on the subobj
714 * type */
715 uint8_t *length_ptr = &(obj_body_buf[index++]);
716 uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + index);
717
718 /* - The index has already been incremented past the header,
719 * and now points to the ro_subobj body. Below it just needs
720 * to be incremented past the body.
721 *
722 * - Each section below needs to write the total length,
723 * including the 2 byte subobj header. */
724
725 switch (ro_subobj->ro_subobj_type) {
726 case RO_SUBOBJ_TYPE_IPV4: {
727 struct pcep_ro_subobj_ipv4 *ipv4 =
728 (struct pcep_ro_subobj_ipv4 *)ro_subobj;
729 uint32_ptr[0] = ipv4->ip_addr.s_addr;
730 index += LENGTH_1WORD;
731 obj_body_buf[index++] = ipv4->prefix_length;
732 obj_body_buf[index++] =
733 (ipv4->flag_local_protection
734 ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
735 : 0x00);
736 *length_ptr = LENGTH_2WORDS;
737 } break;
738
739 case RO_SUBOBJ_TYPE_IPV6: {
740 struct pcep_ro_subobj_ipv6 *ipv6 =
741 (struct pcep_ro_subobj_ipv6 *)ro_subobj;
742 encode_ipv6(&ipv6->ip_addr, uint32_ptr);
743 index += LENGTH_4WORDS;
744 obj_body_buf[index++] = ipv6->prefix_length;
745 obj_body_buf[index++] =
746 (ipv6->flag_local_protection
747 ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
748 : 0x00);
749 *length_ptr = LENGTH_5WORDS;
750 } break;
751
752 case RO_SUBOBJ_TYPE_LABEL: {
753 struct pcep_ro_subobj_32label *label =
754 (struct pcep_ro_subobj_32label *)ro_subobj;
755 obj_body_buf[index++] =
756 (label->flag_global_label
757 ? OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL
758 : 0x00);
759 obj_body_buf[index++] = label->class_type;
760 uint32_ptr = (uint32_t *)(obj_body_buf + index);
761 *uint32_ptr = htonl(label->label);
762 *length_ptr = LENGTH_2WORDS;
763 index += LENGTH_1WORD;
764 } break;
765
766 case RO_SUBOBJ_TYPE_UNNUM: {
767 struct pcep_ro_subobj_unnum *unum =
768 (struct pcep_ro_subobj_unnum *)ro_subobj;
769 index += 2; /* increment past 2 reserved bytes */
770 uint32_ptr = (uint32_t *)(obj_body_buf + index);
771 uint32_ptr[0] = unum->router_id.s_addr;
772 uint32_ptr[1] = htonl(unum->interface_id);
773 *length_ptr = LENGTH_3WORDS;
774 index += LENGTH_2WORDS;
775 } break;
776
777 case RO_SUBOBJ_TYPE_ASN: {
778 struct pcep_ro_subobj_asn *asn =
779 (struct pcep_ro_subobj_asn *)ro_subobj;
780 uint16_t *uint16_ptr =
781 (uint16_t *)(obj_body_buf + index);
782 *uint16_ptr = htons(asn->asn);
783 *length_ptr = LENGTH_1WORD;
784 index += 2;
785 } break;
786
787 case RO_SUBOBJ_TYPE_SR: {
788 /* SR-ERO subobject format
789 *
790 * 0 1 2 3 0 1 2 3 4
791 * 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
792 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
793 * |L| Type=36 | Length | NT | Flags
794 * |F|S|C|M|
795 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
796 * | SID (optional) |
797 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
798 * // NAI (variable, optional) //
799 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
800 */
801
802 struct pcep_ro_subobj_sr *sr_subobj =
803 (struct pcep_ro_subobj_sr *)ro_subobj;
804 obj_body_buf[index++] =
805 ((sr_subobj->nai_type << 4) & 0xf0);
806 obj_body_buf[index++] =
807 ((sr_subobj->flag_f ? OBJECT_SUBOBJ_SR_FLAG_F
808 : 0x00)
809 | (sr_subobj->flag_s ? OBJECT_SUBOBJ_SR_FLAG_S
810 : 0x00)
811 | (sr_subobj->flag_c ? OBJECT_SUBOBJ_SR_FLAG_C
812 : 0x00)
813 | (sr_subobj->flag_m ? OBJECT_SUBOBJ_SR_FLAG_M
814 : 0x00));
815 uint32_ptr = (uint32_t *)(obj_body_buf + index);
816 /* Start with LENGTH_1WORD for the SubObj HDR + NT +
817 * Flags */
818 uint8_t sr_base_length = LENGTH_1WORD;
819 /* If the sid_absent flag is true, then dont convert the
820 * sid */
821 if (sr_subobj->flag_s == false) {
822 uint32_ptr[0] = htonl(sr_subobj->sid);
823 index += LENGTH_1WORD;
824 uint32_ptr = (uint32_t *)(obj_body_buf + index);
825 sr_base_length += LENGTH_1WORD;
826 }
827
828 /* The lengths below need to include:
829 * - sr_base_length: set above to include SR SubObj Hdr
830 * and the SID if present
831 * - Number of bytes written to the NAI
832 * The index will only be incremented below by the
833 * number of bytes written to the NAI, since the RO SR
834 * subobj header and the SID have already been written.
835 */
836
837 double_linked_list_node *nai_node =
838 (sr_subobj->nai_list == NULL
839 ? NULL
840 : sr_subobj->nai_list->head);
841 if (nai_node == NULL) {
842 if (sr_subobj->nai_type
843 == PCEP_SR_SUBOBJ_NAI_ABSENT) {
844 *length_ptr = sr_base_length;
845 continue;
846 } else {
847 return 0;
848 }
849 }
850 switch (sr_subobj->nai_type) {
851 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE:
852 uint32_ptr[0] =
853 ((struct in_addr *)nai_node->data)
854 ->s_addr;
855 *length_ptr = sr_base_length + LENGTH_1WORD;
856 index += LENGTH_1WORD;
857 break;
858
859 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE:
860 encode_ipv6((struct in6_addr *)nai_node->data,
861 uint32_ptr);
862 *length_ptr = sr_base_length + LENGTH_4WORDS;
863 index += LENGTH_4WORDS;
864 break;
865
866 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY:
867 uint32_ptr[0] =
868 ((struct in_addr *)nai_node->data)
869 ->s_addr;
870 nai_node = nai_node->next_node;
871 uint32_ptr[1] =
872 ((struct in_addr *)nai_node->data)
873 ->s_addr;
874 nai_node = nai_node->next_node;
875 uint32_ptr[2] =
876 ((struct in_addr *)nai_node->data)
877 ->s_addr;
878 nai_node = nai_node->next_node;
879 uint32_ptr[3] =
880 ((struct in_addr *)nai_node->data)
881 ->s_addr;
882 *length_ptr = sr_base_length + LENGTH_4WORDS;
883 index += LENGTH_4WORDS;
884 break;
885
886 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY:
887 uint32_ptr[0] =
888 ((struct in_addr *)nai_node->data)
889 ->s_addr;
890 nai_node = nai_node->next_node;
891 uint32_ptr[1] =
892 ((struct in_addr *)nai_node->data)
893 ->s_addr;
894 *length_ptr = sr_base_length + LENGTH_2WORDS;
895 index += LENGTH_2WORDS;
896 break;
897
898 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY:
899 encode_ipv6((struct in6_addr *)nai_node->data,
900 uint32_ptr);
901 nai_node = nai_node->next_node;
902 encode_ipv6((struct in6_addr *)nai_node->data,
903 uint32_ptr + 4);
904 *length_ptr = sr_base_length + LENGTH_8WORDS;
905 index += LENGTH_8WORDS;
906 break;
907
908 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY:
909 encode_ipv6((struct in6_addr *)nai_node->data,
910 uint32_ptr);
911 nai_node = nai_node->next_node;
912 uint32_ptr[4] =
913 ((struct in_addr *)nai_node->data)
914 ->s_addr;
915 nai_node = nai_node->next_node;
916 encode_ipv6((struct in6_addr *)nai_node->data,
917 uint32_ptr + 5);
918 nai_node = nai_node->next_node;
919 uint32_ptr[9] =
920 ((struct in_addr *)nai_node->data)
921 ->s_addr;
922 *length_ptr = sr_base_length + LENGTH_10WORDS;
923 index += LENGTH_10WORDS;
924 break;
925
926 case PCEP_SR_SUBOBJ_NAI_ABSENT:
927 case PCEP_SR_SUBOBJ_NAI_UNKNOWN:
928 break;
929 }
930 } break;
931
932 case RO_SUBOBJ_UNKNOWN:
933 break;
934 }
935 }
936
937 return index;
938 }
939
940 void encode_ipv6(struct in6_addr *src_ipv6, uint32_t *dst)
941 {
942 memcpy(dst, src_ipv6, sizeof(struct in6_addr));
943 }
944
945 /*
946 * Decoding functions.
947 */
948
949 void pcep_decode_object_hdr(const uint8_t *obj_buf,
950 struct pcep_object_header *obj_hdr)
951 {
952 memset(obj_hdr, 0, sizeof(struct pcep_object_header));
953
954 obj_hdr->object_class = obj_buf[0];
955 obj_hdr->object_type = (obj_buf[1] >> 4) & 0x0f;
956 obj_hdr->flag_p = (obj_buf[1] & OBJECT_HEADER_FLAG_P);
957 obj_hdr->flag_i = (obj_buf[1] & OBJECT_HEADER_FLAG_I);
958 uint16_t net_order_length;
959 memcpy(&net_order_length, obj_buf + 2, sizeof(net_order_length));
960 obj_hdr->encoded_object_length = ntohs(net_order_length);
961 obj_hdr->encoded_object = obj_buf;
962 }
963
964 uint16_t pcep_object_get_length(enum pcep_object_classes object_class,
965 enum pcep_object_types object_type)
966 {
967 uint8_t object_length = pcep_object_class_lengths[object_class];
968 if (object_length == 0) {
969 if (object_class == PCEP_OBJ_CLASS_ENDPOINTS) {
970 if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) {
971 return 12;
972 } else if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
973 return 36;
974 }
975 }
976
977 return 0;
978 }
979
980 return object_length;
981 }
982
983 uint16_t pcep_object_get_length_by_hdr(struct pcep_object_header *object_hdr)
984 {
985 return (pcep_object_get_length(object_hdr->object_class,
986 object_hdr->object_type));
987 }
988
989 bool pcep_object_has_tlvs(struct pcep_object_header *object_hdr)
990 {
991 uint8_t object_length = pcep_object_get_length_by_hdr(object_hdr);
992 if (object_length == 0) {
993 return false;
994 }
995
996 return (object_hdr->encoded_object_length - object_length) > 0;
997 }
998
999 struct pcep_object_header *pcep_decode_object(const uint8_t *obj_buf)
1000 {
1001
1002 struct pcep_object_header object_hdr;
1003 /* Only initializes and decodes the Object Header: class, type, flags,
1004 * and length */
1005 pcep_decode_object_hdr(obj_buf, &object_hdr);
1006
1007 if (object_hdr.object_class >= MAX_OBJECT_ENCODER_INDEX) {
1008 pcep_log(LOG_INFO,
1009 "%s: Cannot decode unknown Object class [%d]",
1010 __func__, object_hdr.object_class);
1011 return NULL;
1012 }
1013
1014 object_decoder_funcptr obj_decoder =
1015 object_decoders[object_hdr.object_class];
1016 if (obj_decoder == NULL) {
1017 pcep_log(LOG_INFO,
1018 "%s: No object decoder found for Object class [%d]",
1019 __func__, object_hdr.object_class);
1020 return NULL;
1021 }
1022
1023 /* The object decoders will start decoding the object body, if
1024 * anything from the header is needed, they have the object_hdr */
1025 struct pcep_object_header *object =
1026 obj_decoder(&object_hdr, obj_buf + OBJECT_HEADER_LENGTH);
1027 if (object == NULL) {
1028 pcep_log(LOG_INFO, "%s: Unable to decode Object class [%d].",
1029 __func__, object_hdr.object_class);
1030 return NULL;
1031 }
1032
1033 if (pcep_object_has_tlvs(&object_hdr)) {
1034 object->tlv_list = dll_initialize();
1035 int num_iterations = 0;
1036 uint16_t tlv_index = pcep_object_get_length_by_hdr(&object_hdr);
1037 while ((object->encoded_object_length - tlv_index) > 0
1038 && num_iterations++ < MAX_ITERATIONS) {
1039 struct pcep_object_tlv_header *tlv =
1040 pcep_decode_tlv(obj_buf + tlv_index);
1041 if (tlv == NULL) {
1042 /* TODO should we do anything else here ? */
1043 return object;
1044 }
1045
1046 /* The TLV length does not include the TLV header */
1047 tlv_index += normalize_pcep_tlv_length(
1048 tlv->encoded_tlv_length + TLV_HEADER_LENGTH);
1049 dll_append(object->tlv_list, tlv);
1050 }
1051 }
1052
1053 return object;
1054 }
1055
1056 static struct pcep_object_header *
1057 common_object_create(struct pcep_object_header *hdr, uint16_t new_obj_length)
1058 {
1059 struct pcep_object_header *new_object =
1060 pceplib_malloc(PCEPLIB_MESSAGES, new_obj_length);
1061 memset(new_object, 0, new_obj_length);
1062 memcpy(new_object, hdr, sizeof(struct pcep_object_header));
1063
1064 return new_object;
1065 }
1066
1067 /*
1068 * Decoders
1069 */
1070
1071 struct pcep_object_header *pcep_decode_obj_open(struct pcep_object_header *hdr,
1072 const uint8_t *obj_buf)
1073 {
1074 struct pcep_object_open *obj =
1075 (struct pcep_object_open *)common_object_create(
1076 hdr, sizeof(struct pcep_object_open));
1077
1078 obj->open_version = (obj_buf[0] >> 5) & 0x07;
1079 obj->open_keepalive = obj_buf[1];
1080 obj->open_deadtimer = obj_buf[2];
1081 obj->open_sid = obj_buf[3];
1082
1083 return (struct pcep_object_header *)obj;
1084 }
1085
1086 struct pcep_object_header *pcep_decode_obj_rp(struct pcep_object_header *hdr,
1087 const uint8_t *obj_buf)
1088 {
1089 struct pcep_object_rp *obj =
1090 (struct pcep_object_rp *)common_object_create(
1091 hdr, sizeof(struct pcep_object_rp));
1092
1093 obj->flag_reoptimization = (obj_buf[3] & OBJECT_RP_FLAG_R);
1094 obj->flag_bidirectional = (obj_buf[3] & OBJECT_RP_FLAG_B);
1095 obj->flag_strict = (obj_buf[3] & OBJECT_RP_FLAG_O);
1096 obj->flag_of = (obj_buf[3] & OBJECT_RP_FLAG_OF);
1097 obj->priority = (obj_buf[3] & 0x07);
1098 obj->request_id = ntohl(*((uint32_t *)(obj_buf + 4)));
1099
1100 return (struct pcep_object_header *)obj;
1101 }
1102
1103 struct pcep_object_header *
1104 pcep_decode_obj_notify(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1105 {
1106 struct pcep_object_notify *obj =
1107 (struct pcep_object_notify *)common_object_create(
1108 hdr, sizeof(struct pcep_object_notify));
1109
1110 obj->notification_type = obj_buf[2];
1111 obj->notification_value = obj_buf[3];
1112
1113 return (struct pcep_object_header *)obj;
1114 }
1115
1116 struct pcep_object_header *
1117 pcep_decode_obj_nopath(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1118 {
1119 struct pcep_object_nopath *obj =
1120 (struct pcep_object_nopath *)common_object_create(
1121 hdr, sizeof(struct pcep_object_nopath));
1122
1123 obj->ni = (obj_buf[0] >> 1);
1124 obj->flag_c = (obj_buf[0] & OBJECT_NOPATH_FLAG_C);
1125
1126 return (struct pcep_object_header *)obj;
1127 }
1128
1129 struct pcep_object_header *
1130 pcep_decode_obj_association(struct pcep_object_header *hdr,
1131 const uint8_t *obj_buf)
1132 {
1133 uint16_t *uint16_ptr = (uint16_t *)obj_buf;
1134 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1135
1136 if (hdr->object_type == PCEP_OBJ_TYPE_ASSOCIATION_IPV4) {
1137 struct pcep_object_association_ipv4 *obj =
1138 (struct pcep_object_association_ipv4 *)
1139 common_object_create(
1140 hdr,
1141 sizeof(struct
1142 pcep_object_association_ipv4));
1143 obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R);
1144 obj->association_type = ntohs(uint16_ptr[2]);
1145 obj->association_id = ntohs(uint16_ptr[3]);
1146 obj->src.s_addr = uint32_ptr[2];
1147
1148 return (struct pcep_object_header *)obj;
1149 } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
1150 struct pcep_object_association_ipv6 *obj =
1151 (struct pcep_object_association_ipv6 *)
1152 common_object_create(
1153 hdr,
1154 sizeof(struct
1155 pcep_object_association_ipv6));
1156
1157 obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R);
1158 obj->association_type = ntohs(uint16_ptr[2]);
1159 obj->association_id = ntohs(uint16_ptr[3]);
1160 memcpy(&obj->src, &uint32_ptr[2], sizeof(struct in6_addr));
1161
1162 return (struct pcep_object_header *)obj;
1163 }
1164
1165 return NULL;
1166 }
1167 struct pcep_object_header *
1168 pcep_decode_obj_endpoints(struct pcep_object_header *hdr,
1169 const uint8_t *obj_buf)
1170 {
1171 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1172
1173 if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) {
1174 struct pcep_object_endpoints_ipv4 *obj =
1175 (struct pcep_object_endpoints_ipv4 *)
1176 common_object_create(
1177 hdr,
1178 sizeof(struct
1179 pcep_object_endpoints_ipv4));
1180 obj->src_ipv4.s_addr = uint32_ptr[0];
1181 obj->dst_ipv4.s_addr = uint32_ptr[1];
1182
1183 return (struct pcep_object_header *)obj;
1184 } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
1185 struct pcep_object_endpoints_ipv6 *obj =
1186 (struct pcep_object_endpoints_ipv6 *)
1187 common_object_create(
1188 hdr,
1189 sizeof(struct
1190 pcep_object_endpoints_ipv6));
1191
1192 memcpy(&obj->src_ipv6, &uint32_ptr[0], sizeof(struct in6_addr));
1193 memcpy(&obj->dst_ipv6, &uint32_ptr[4], sizeof(struct in6_addr));
1194
1195 return (struct pcep_object_header *)obj;
1196 }
1197
1198 return NULL;
1199 }
1200
1201 struct pcep_object_header *
1202 pcep_decode_obj_bandwidth(struct pcep_object_header *hdr,
1203 const uint8_t *obj_buf)
1204 {
1205 struct pcep_object_bandwidth *obj =
1206 (struct pcep_object_bandwidth *)common_object_create(
1207 hdr, sizeof(struct pcep_object_bandwidth));
1208
1209 uint32_t value = ntohl(*((uint32_t *)obj_buf));
1210 /* Seems like the compiler doesn't correctly copy to the float, so
1211 * memcpy() it */
1212 memcpy(&obj->bandwidth, &value, sizeof(uint32_t));
1213
1214 return (struct pcep_object_header *)obj;
1215 }
1216
1217 struct pcep_object_header *
1218 pcep_decode_obj_metric(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1219 {
1220 struct pcep_object_metric *obj =
1221 (struct pcep_object_metric *)common_object_create(
1222 hdr, sizeof(struct pcep_object_metric));
1223 obj->flag_b = (obj_buf[2] & OBJECT_METRIC_FLAC_B);
1224 obj->flag_c = (obj_buf[2] & OBJECT_METRIC_FLAC_C);
1225 obj->type = obj_buf[3];
1226 uint32_t value = ntohl(*((uint32_t *)(obj_buf + 4)));
1227 /* Seems like the compiler doesn't correctly copy to the float, so
1228 * memcpy() it */
1229 memcpy(&obj->value, &value, sizeof(uint32_t));
1230
1231 return (struct pcep_object_header *)obj;
1232 }
1233
1234 struct pcep_object_header *pcep_decode_obj_lspa(struct pcep_object_header *hdr,
1235 const uint8_t *obj_buf)
1236 {
1237 struct pcep_object_lspa *obj =
1238 (struct pcep_object_lspa *)common_object_create(
1239 hdr, sizeof(struct pcep_object_lspa));
1240 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1241
1242 obj->lspa_exclude_any = ntohl(uint32_ptr[0]);
1243 obj->lspa_include_any = ntohl(uint32_ptr[1]);
1244 obj->lspa_include_all = ntohl(uint32_ptr[2]);
1245 obj->setup_priority = obj_buf[12];
1246 obj->holding_priority = obj_buf[13];
1247 obj->flag_local_protection = (obj_buf[14] & OBJECT_LSPA_FLAG_L);
1248
1249 return (struct pcep_object_header *)obj;
1250 }
1251
1252 struct pcep_object_header *pcep_decode_obj_svec(struct pcep_object_header *hdr,
1253 const uint8_t *obj_buf)
1254 {
1255 struct pcep_object_svec *obj =
1256 (struct pcep_object_svec *)common_object_create(
1257 hdr, sizeof(struct pcep_object_svec));
1258
1259 obj->flag_link_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_L);
1260 obj->flag_node_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_N);
1261 obj->flag_srlg_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_S);
1262
1263 if (hdr->encoded_object_length > LENGTH_2WORDS) {
1264 obj->request_id_list = dll_initialize();
1265 uint16_t index = 1;
1266 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1267 for (;
1268 index < ((hdr->encoded_object_length - LENGTH_2WORDS) / 4);
1269 index++) {
1270 uint32_t *req_id_ptr = pceplib_malloc(PCEPLIB_MESSAGES,
1271 sizeof(uint32_t));
1272 *req_id_ptr = uint32_ptr[index];
1273 dll_append(obj->request_id_list, req_id_ptr);
1274 }
1275 }
1276
1277 return (struct pcep_object_header *)obj;
1278 }
1279
1280 struct pcep_object_header *pcep_decode_obj_error(struct pcep_object_header *hdr,
1281 const uint8_t *obj_buf)
1282 {
1283 struct pcep_object_error *obj =
1284 (struct pcep_object_error *)common_object_create(
1285 hdr, sizeof(struct pcep_object_error));
1286
1287 obj->error_type = obj_buf[2];
1288 obj->error_value = obj_buf[3];
1289
1290 return (struct pcep_object_header *)obj;
1291 }
1292
1293 struct pcep_object_header *pcep_decode_obj_close(struct pcep_object_header *hdr,
1294 const uint8_t *obj_buf)
1295 {
1296 struct pcep_object_close *obj =
1297 (struct pcep_object_close *)common_object_create(
1298 hdr, sizeof(struct pcep_object_close));
1299
1300 obj->reason = obj_buf[3];
1301
1302 return (struct pcep_object_header *)obj;
1303 }
1304
1305 struct pcep_object_header *pcep_decode_obj_srp(struct pcep_object_header *hdr,
1306 const uint8_t *obj_buf)
1307 {
1308 struct pcep_object_srp *obj =
1309 (struct pcep_object_srp *)common_object_create(
1310 hdr, sizeof(struct pcep_object_srp));
1311
1312 obj->flag_lsp_remove = (obj_buf[3] & OBJECT_SRP_FLAG_R);
1313 obj->srp_id_number = ntohl(*((uint32_t *)(obj_buf + 4)));
1314
1315 return (struct pcep_object_header *)obj;
1316 }
1317
1318 struct pcep_object_header *pcep_decode_obj_lsp(struct pcep_object_header *hdr,
1319 const uint8_t *obj_buf)
1320 {
1321 struct pcep_object_lsp *obj =
1322 (struct pcep_object_lsp *)common_object_create(
1323 hdr, sizeof(struct pcep_object_lsp));
1324
1325 obj->flag_d = (obj_buf[3] & OBJECT_LSP_FLAG_D);
1326 obj->flag_s = (obj_buf[3] & OBJECT_LSP_FLAG_S);
1327 obj->flag_r = (obj_buf[3] & OBJECT_LSP_FLAG_R);
1328 obj->flag_a = (obj_buf[3] & OBJECT_LSP_FLAG_A);
1329 obj->flag_c = (obj_buf[3] & OBJECT_LSP_FLAG_C);
1330 obj->operational_status = ((obj_buf[3] >> 4) & 0x07);
1331 obj->plsp_id = ((ntohl(*((uint32_t *)obj_buf)) >> 12) & 0x000fffff);
1332
1333 return (struct pcep_object_header *)obj;
1334 }
1335
1336 struct pcep_object_header *
1337 pcep_decode_obj_vendor_info(struct pcep_object_header *hdr,
1338 const uint8_t *obj_buf)
1339 {
1340 struct pcep_object_vendor_info *obj =
1341 (struct pcep_object_vendor_info *)common_object_create(
1342 hdr, sizeof(struct pcep_object_vendor_info));
1343
1344 obj->enterprise_number = ntohl(*((uint32_t *)(obj_buf)));
1345 obj->enterprise_specific_info = ntohl(*((uint32_t *)(obj_buf + 4)));
1346 if (obj->enterprise_number == ENTERPRISE_NUMBER_CISCO
1347 && obj->enterprise_specific_info == ENTERPRISE_COLOR_CISCO)
1348 obj->enterprise_specific_info1 =
1349 ntohl(*((uint32_t *)(obj_buf + 8)));
1350 else
1351 obj->enterprise_specific_info1 = 0;
1352
1353 return (struct pcep_object_header *)obj;
1354 }
1355
1356 struct pcep_object_header *
1357 pcep_decode_obj_inter_layer(struct pcep_object_header *hdr,
1358 const uint8_t *obj_buf)
1359 {
1360 struct pcep_object_inter_layer *obj =
1361 (struct pcep_object_inter_layer *)common_object_create(
1362 hdr, sizeof(struct pcep_object_inter_layer));
1363 obj->flag_t = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_T);
1364 obj->flag_m = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_M);
1365 obj->flag_i = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_I);
1366
1367 return (struct pcep_object_header *)obj;
1368 }
1369
1370 struct pcep_object_header *
1371 pcep_decode_obj_switch_layer(struct pcep_object_header *hdr,
1372 const uint8_t *obj_buf)
1373 {
1374 struct pcep_object_switch_layer *obj =
1375 (struct pcep_object_switch_layer *)common_object_create(
1376 hdr, sizeof(struct pcep_object_switch_layer));
1377 obj->switch_layer_rows = dll_initialize();
1378 int num_rows = ((hdr->encoded_object_length - 4) / 4);
1379 uint8_t buf_index = 0;
1380
1381 int i = 0;
1382 for (; i < num_rows; i++) {
1383 struct pcep_object_switch_layer_row *row = pceplib_malloc(
1384 PCEPLIB_MESSAGES,
1385 sizeof(struct pcep_object_switch_layer_row));
1386 row->lsp_encoding_type = obj_buf[buf_index];
1387 row->switching_type = obj_buf[buf_index + 1];
1388 row->flag_i =
1389 (obj_buf[buf_index + 3] & OBJECT_SWITCH_LAYER_FLAG_I);
1390 dll_append(obj->switch_layer_rows, row);
1391
1392 buf_index += LENGTH_1WORD;
1393 }
1394
1395 return (struct pcep_object_header *)obj;
1396 }
1397
1398 struct pcep_object_header *
1399 pcep_decode_obj_req_adap_cap(struct pcep_object_header *hdr,
1400 const uint8_t *obj_buf)
1401 {
1402 struct pcep_object_req_adap_cap *obj =
1403 (struct pcep_object_req_adap_cap *)common_object_create(
1404 hdr, sizeof(struct pcep_object_req_adap_cap));
1405
1406 obj->switching_capability = obj_buf[0];
1407 obj->encoding = obj_buf[1];
1408
1409 return (struct pcep_object_header *)obj;
1410 }
1411
1412 struct pcep_object_header *
1413 pcep_decode_obj_server_ind(struct pcep_object_header *hdr,
1414 const uint8_t *obj_buf)
1415 {
1416 struct pcep_object_server_indication *obj =
1417 (struct pcep_object_server_indication *)common_object_create(
1418 hdr, sizeof(struct pcep_object_server_indication));
1419
1420 obj->switching_capability = obj_buf[0];
1421 obj->encoding = obj_buf[1];
1422
1423 return (struct pcep_object_header *)obj;
1424 }
1425
1426 struct pcep_object_header *
1427 pcep_decode_obj_objective_function(struct pcep_object_header *hdr,
1428 const uint8_t *obj_buf)
1429 {
1430 struct pcep_object_objective_function *obj =
1431 (struct pcep_object_objective_function *)common_object_create(
1432 hdr, sizeof(struct pcep_object_objective_function));
1433
1434 uint16_t *uint16_ptr = (uint16_t *)obj_buf;
1435 obj->of_code = ntohs(*uint16_ptr);
1436
1437 return (struct pcep_object_header *)obj;
1438 }
1439
1440 void set_ro_subobj_fields(struct pcep_object_ro_subobj *subobj, bool flag_l,
1441 uint8_t subobj_type)
1442 {
1443 subobj->flag_subobj_loose_hop = flag_l;
1444 subobj->ro_subobj_type = subobj_type;
1445 }
1446
1447 void decode_ipv6(const uint32_t *src, struct in6_addr *dst_ipv6)
1448 {
1449 memcpy(dst_ipv6, src, sizeof(struct in6_addr));
1450 }
1451 struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr,
1452 const uint8_t *obj_buf)
1453 {
1454 struct pcep_object_ro *obj =
1455 (struct pcep_object_ro *)common_object_create(
1456 hdr, sizeof(struct pcep_object_ro));
1457 obj->sub_objects = dll_initialize();
1458
1459 /* RO Subobject format
1460 *
1461 * 0 1
1462 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1463 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1464 * |L| Type | Length | (Subobject contents) |
1465 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1466 */
1467
1468 uint16_t read_count = 0;
1469 int num_sub_objects = 1;
1470 uint32_t *uint32_ptr;
1471 uint16_t obj_body_length =
1472 hdr->encoded_object_length - OBJECT_HEADER_LENGTH;
1473
1474 while ((obj_body_length - read_count) > OBJECT_RO_SUBOBJ_HEADER_LENGTH
1475 && num_sub_objects < MAX_ITERATIONS) {
1476 num_sub_objects++;
1477 /* Read the Sub-Object Header */
1478 bool flag_l = (obj_buf[read_count] & 0x80);
1479 uint8_t subobj_type = (obj_buf[read_count++] & 0x7f);
1480 uint8_t subobj_length = obj_buf[read_count++];
1481
1482 if (subobj_length <= OBJECT_RO_SUBOBJ_HEADER_LENGTH) {
1483 pcep_log(LOG_INFO,
1484 "%s: Invalid ro subobj type [%d] length [%d]",
1485 __func__, subobj_type, subobj_length);
1486 pceplib_free(PCEPLIB_MESSAGES, obj);
1487 return NULL;
1488 }
1489
1490 switch (subobj_type) {
1491 case RO_SUBOBJ_TYPE_IPV4: {
1492 struct pcep_ro_subobj_ipv4 *ipv4 = pceplib_malloc(
1493 PCEPLIB_MESSAGES,
1494 sizeof(struct pcep_ro_subobj_ipv4));
1495 ipv4->ro_subobj.flag_subobj_loose_hop = flag_l;
1496 ipv4->ro_subobj.ro_subobj_type = subobj_type;
1497 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1498 ipv4->ip_addr.s_addr = *uint32_ptr;
1499 read_count += LENGTH_1WORD;
1500 ipv4->prefix_length = obj_buf[read_count++];
1501 ipv4->flag_local_protection =
1502 (obj_buf[read_count++]
1503 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
1504
1505 dll_append(obj->sub_objects, ipv4);
1506 } break;
1507
1508 case RO_SUBOBJ_TYPE_IPV6: {
1509 struct pcep_ro_subobj_ipv6 *ipv6 = pceplib_malloc(
1510 PCEPLIB_MESSAGES,
1511 sizeof(struct pcep_ro_subobj_ipv6));
1512 ipv6->ro_subobj.flag_subobj_loose_hop = flag_l;
1513 ipv6->ro_subobj.ro_subobj_type = subobj_type;
1514 decode_ipv6((uint32_t *)obj_buf, &ipv6->ip_addr);
1515 read_count += LENGTH_4WORDS;
1516 ipv6->prefix_length = obj_buf[read_count++];
1517 ipv6->flag_local_protection =
1518 (obj_buf[read_count++]
1519 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
1520
1521 dll_append(obj->sub_objects, ipv6);
1522 } break;
1523
1524 case RO_SUBOBJ_TYPE_LABEL: {
1525 struct pcep_ro_subobj_32label *label = pceplib_malloc(
1526 PCEPLIB_MESSAGES,
1527 sizeof(struct pcep_ro_subobj_32label));
1528 label->ro_subobj.flag_subobj_loose_hop = flag_l;
1529 label->ro_subobj.ro_subobj_type = subobj_type;
1530 label->flag_global_label =
1531 (obj_buf[read_count++]
1532 & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL);
1533 label->class_type = obj_buf[read_count++];
1534 label->label = ntohl(obj_buf[read_count]);
1535 read_count += LENGTH_1WORD;
1536
1537 dll_append(obj->sub_objects, label);
1538 } break;
1539
1540 case RO_SUBOBJ_TYPE_UNNUM: {
1541 struct pcep_ro_subobj_unnum *unum = pceplib_malloc(
1542 PCEPLIB_MESSAGES,
1543 sizeof(struct pcep_ro_subobj_unnum));
1544 unum->ro_subobj.flag_subobj_loose_hop = flag_l;
1545 unum->ro_subobj.ro_subobj_type = subobj_type;
1546 set_ro_subobj_fields(
1547 (struct pcep_object_ro_subobj *)unum, flag_l,
1548 subobj_type);
1549 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1550 unum->interface_id = ntohl(uint32_ptr[0]);
1551 unum->router_id.s_addr = uint32_ptr[1];
1552 read_count += 2;
1553
1554 dll_append(obj->sub_objects, unum);
1555 } break;
1556
1557 case RO_SUBOBJ_TYPE_ASN: {
1558 struct pcep_ro_subobj_asn *asn = pceplib_malloc(
1559 PCEPLIB_MESSAGES,
1560 sizeof(struct pcep_ro_subobj_asn));
1561 asn->ro_subobj.flag_subobj_loose_hop = flag_l;
1562 asn->ro_subobj.ro_subobj_type = subobj_type;
1563 uint16_t *uint16_ptr =
1564 (uint16_t *)(obj_buf + read_count);
1565 asn->asn = ntohs(*uint16_ptr);
1566 read_count += 2;
1567
1568 dll_append(obj->sub_objects, asn);
1569 } break;
1570
1571 case RO_SUBOBJ_TYPE_SR: {
1572 /* SR-ERO subobject format
1573 *
1574 * 0 1 2 3 0 1 2 3 4
1575 * 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1576 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1577 * |L| Type=36 | Length | NT | Flags
1578 * |F|S|C|M|
1579 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1580 * | SID (optional) |
1581 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1582 * // NAI (variable, optional) //
1583 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1584 */
1585
1586 struct pcep_ro_subobj_sr *sr_subobj = pceplib_malloc(
1587 PCEPLIB_MESSAGES,
1588 sizeof(struct pcep_ro_subobj_sr));
1589 sr_subobj->ro_subobj.flag_subobj_loose_hop = flag_l;
1590 sr_subobj->ro_subobj.ro_subobj_type = subobj_type;
1591 dll_append(obj->sub_objects, sr_subobj);
1592
1593 sr_subobj->nai_list = dll_initialize();
1594 sr_subobj->nai_type =
1595 ((obj_buf[read_count++] >> 4) & 0x0f);
1596 sr_subobj->flag_f =
1597 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_F);
1598 sr_subobj->flag_s =
1599 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_S);
1600 sr_subobj->flag_c =
1601 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_C);
1602 sr_subobj->flag_m =
1603 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_M);
1604 read_count++;
1605
1606 /* If the sid_absent flag is true, then dont decode the
1607 * sid */
1608 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1609 if (sr_subobj->flag_s == false) {
1610 sr_subobj->sid = ntohl(*uint32_ptr);
1611 read_count += LENGTH_1WORD;
1612 uint32_ptr += 1;
1613 }
1614
1615 switch (sr_subobj->nai_type) {
1616 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE: {
1617 struct in_addr *ipv4 =
1618 pceplib_malloc(PCEPLIB_MESSAGES,
1619 sizeof(struct in_addr));
1620 ipv4->s_addr = *uint32_ptr;
1621 dll_append(sr_subobj->nai_list, ipv4);
1622 read_count += LENGTH_1WORD;
1623 } break;
1624
1625 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE: {
1626 struct in6_addr *ipv6 =
1627 pceplib_malloc(PCEPLIB_MESSAGES,
1628 sizeof(struct in6_addr));
1629 decode_ipv6(uint32_ptr, ipv6);
1630 dll_append(sr_subobj->nai_list, ipv6);
1631 read_count += LENGTH_4WORDS;
1632 } break;
1633
1634 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY: {
1635 struct in_addr *ipv4 =
1636 pceplib_malloc(PCEPLIB_MESSAGES,
1637 sizeof(struct in_addr));
1638 ipv4->s_addr = uint32_ptr[0];
1639 dll_append(sr_subobj->nai_list, ipv4);
1640
1641 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1642 sizeof(struct in_addr));
1643 ipv4->s_addr = uint32_ptr[1];
1644 dll_append(sr_subobj->nai_list, ipv4);
1645
1646 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1647 sizeof(struct in_addr));
1648 ipv4->s_addr = uint32_ptr[2];
1649 dll_append(sr_subobj->nai_list, ipv4);
1650
1651 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1652 sizeof(struct in_addr));
1653 ipv4->s_addr = uint32_ptr[3];
1654 dll_append(sr_subobj->nai_list, ipv4);
1655
1656 read_count += LENGTH_4WORDS;
1657 } break;
1658
1659 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY: {
1660 struct in_addr *ipv4 =
1661 pceplib_malloc(PCEPLIB_MESSAGES,
1662 sizeof(struct in_addr));
1663 ipv4->s_addr = uint32_ptr[0];
1664 dll_append(sr_subobj->nai_list, ipv4);
1665
1666 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1667 sizeof(struct in_addr));
1668 ipv4->s_addr = uint32_ptr[1];
1669 dll_append(sr_subobj->nai_list, ipv4);
1670
1671 read_count += LENGTH_2WORDS;
1672 } break;
1673
1674 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY: {
1675 struct in6_addr *ipv6 =
1676 pceplib_malloc(PCEPLIB_MESSAGES,
1677 sizeof(struct in6_addr));
1678 decode_ipv6(uint32_ptr, ipv6);
1679 dll_append(sr_subobj->nai_list, ipv6);
1680
1681 ipv6 = pceplib_malloc(PCEPLIB_MESSAGES,
1682 sizeof(struct in6_addr));
1683 decode_ipv6(uint32_ptr + 4, ipv6);
1684 dll_append(sr_subobj->nai_list, ipv6);
1685
1686 read_count += LENGTH_8WORDS;
1687 } break;
1688
1689 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY: {
1690 struct in6_addr *ipv6 =
1691 pceplib_malloc(PCEPLIB_MESSAGES,
1692 sizeof(struct in6_addr));
1693 decode_ipv6(uint32_ptr, ipv6);
1694 dll_append(sr_subobj->nai_list, ipv6);
1695
1696 struct in_addr *ipv4 =
1697 pceplib_malloc(PCEPLIB_MESSAGES,
1698 sizeof(struct in_addr));
1699 ipv4->s_addr = uint32_ptr[4];
1700 dll_append(sr_subobj->nai_list, ipv4);
1701
1702 ipv6 = pceplib_malloc(PCEPLIB_MESSAGES,
1703 sizeof(struct in6_addr));
1704 decode_ipv6(uint32_ptr + 5, ipv6);
1705 dll_append(sr_subobj->nai_list, ipv6);
1706
1707 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1708 sizeof(struct in_addr));
1709 ipv4->s_addr = uint32_ptr[9];
1710 dll_append(sr_subobj->nai_list, ipv4);
1711
1712 read_count += LENGTH_10WORDS;
1713 } break;
1714
1715 case PCEP_SR_SUBOBJ_NAI_ABSENT:
1716 case PCEP_SR_SUBOBJ_NAI_UNKNOWN:
1717 break;
1718 }
1719 } break;
1720
1721 default:
1722 pcep_log(
1723 LOG_INFO,
1724 "%s: pcep_decode_obj_ro skipping unrecognized sub-object type [%d]",
1725 __func__, subobj_type);
1726 read_count += subobj_length;
1727 break;
1728 }
1729 }
1730
1731 return (struct pcep_object_header *)obj;
1732 }