]> git.proxmox.com Git - mirror_frr.git/blob - pceplib/pcep_msg_objects_encoding.c
Merge pull request #12720 from opensourcerouting/fix/ecommunity_ipv6_missing_token
[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 default:
927 break;
928 }
929 } break;
930
931 default:
932 break;
933 }
934 }
935
936 return index;
937 }
938
939 void encode_ipv6(struct in6_addr *src_ipv6, uint32_t *dst)
940 {
941 memcpy(dst, src_ipv6, sizeof(struct in6_addr));
942 }
943
944 /*
945 * Decoding functions.
946 */
947
948 void pcep_decode_object_hdr(const uint8_t *obj_buf,
949 struct pcep_object_header *obj_hdr)
950 {
951 memset(obj_hdr, 0, sizeof(struct pcep_object_header));
952
953 obj_hdr->object_class = obj_buf[0];
954 obj_hdr->object_type = (obj_buf[1] >> 4) & 0x0f;
955 obj_hdr->flag_p = (obj_buf[1] & OBJECT_HEADER_FLAG_P);
956 obj_hdr->flag_i = (obj_buf[1] & OBJECT_HEADER_FLAG_I);
957 uint16_t net_order_length;
958 memcpy(&net_order_length, obj_buf + 2, sizeof(net_order_length));
959 obj_hdr->encoded_object_length = ntohs(net_order_length);
960 obj_hdr->encoded_object = obj_buf;
961 }
962
963 uint16_t pcep_object_get_length(enum pcep_object_classes object_class,
964 enum pcep_object_types object_type)
965 {
966 uint8_t object_length = pcep_object_class_lengths[object_class];
967 if (object_length == 0) {
968 if (object_class == PCEP_OBJ_CLASS_ENDPOINTS) {
969 if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) {
970 return 12;
971 } else if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
972 return 36;
973 }
974 }
975
976 return 0;
977 }
978
979 return object_length;
980 }
981
982 uint16_t pcep_object_get_length_by_hdr(struct pcep_object_header *object_hdr)
983 {
984 return (pcep_object_get_length(object_hdr->object_class,
985 object_hdr->object_type));
986 }
987
988 bool pcep_object_has_tlvs(struct pcep_object_header *object_hdr)
989 {
990 uint8_t object_length = pcep_object_get_length_by_hdr(object_hdr);
991 if (object_length == 0) {
992 return false;
993 }
994
995 return (object_hdr->encoded_object_length - object_length) > 0;
996 }
997
998 struct pcep_object_header *pcep_decode_object(const uint8_t *obj_buf)
999 {
1000
1001 struct pcep_object_header object_hdr;
1002 /* Only initializes and decodes the Object Header: class, type, flags,
1003 * and length */
1004 pcep_decode_object_hdr(obj_buf, &object_hdr);
1005
1006 if (object_hdr.object_class >= MAX_OBJECT_ENCODER_INDEX) {
1007 pcep_log(LOG_INFO,
1008 "%s: Cannot decode unknown Object class [%d]",
1009 __func__, object_hdr.object_class);
1010 return NULL;
1011 }
1012
1013 object_decoder_funcptr obj_decoder =
1014 object_decoders[object_hdr.object_class];
1015 if (obj_decoder == NULL) {
1016 pcep_log(LOG_INFO,
1017 "%s: No object decoder found for Object class [%d]",
1018 __func__, object_hdr.object_class);
1019 return NULL;
1020 }
1021
1022 /* The object decoders will start decoding the object body, if
1023 * anything from the header is needed, they have the object_hdr */
1024 struct pcep_object_header *object =
1025 obj_decoder(&object_hdr, obj_buf + OBJECT_HEADER_LENGTH);
1026 if (object == NULL) {
1027 pcep_log(LOG_INFO, "%s: Unable to decode Object class [%d].",
1028 __func__, object_hdr.object_class);
1029 return NULL;
1030 }
1031
1032 if (pcep_object_has_tlvs(&object_hdr)) {
1033 object->tlv_list = dll_initialize();
1034 int num_iterations = 0;
1035 uint16_t tlv_index = pcep_object_get_length_by_hdr(&object_hdr);
1036 while ((object->encoded_object_length - tlv_index) > 0
1037 && num_iterations++ < MAX_ITERATIONS) {
1038 struct pcep_object_tlv_header *tlv =
1039 pcep_decode_tlv(obj_buf + tlv_index);
1040 if (tlv == NULL) {
1041 /* TODO should we do anything else here ? */
1042 return object;
1043 }
1044
1045 /* The TLV length does not include the TLV header */
1046 tlv_index += normalize_pcep_tlv_length(
1047 tlv->encoded_tlv_length + TLV_HEADER_LENGTH);
1048 dll_append(object->tlv_list, tlv);
1049 }
1050 }
1051
1052 return object;
1053 }
1054
1055 static struct pcep_object_header *
1056 common_object_create(struct pcep_object_header *hdr, uint16_t new_obj_length)
1057 {
1058 struct pcep_object_header *new_object =
1059 pceplib_malloc(PCEPLIB_MESSAGES, new_obj_length);
1060 memset(new_object, 0, new_obj_length);
1061 memcpy(new_object, hdr, sizeof(struct pcep_object_header));
1062
1063 return new_object;
1064 }
1065
1066 /*
1067 * Decoders
1068 */
1069
1070 struct pcep_object_header *pcep_decode_obj_open(struct pcep_object_header *hdr,
1071 const uint8_t *obj_buf)
1072 {
1073 struct pcep_object_open *obj =
1074 (struct pcep_object_open *)common_object_create(
1075 hdr, sizeof(struct pcep_object_open));
1076
1077 obj->open_version = (obj_buf[0] >> 5) & 0x07;
1078 obj->open_keepalive = obj_buf[1];
1079 obj->open_deadtimer = obj_buf[2];
1080 obj->open_sid = obj_buf[3];
1081
1082 return (struct pcep_object_header *)obj;
1083 }
1084
1085 struct pcep_object_header *pcep_decode_obj_rp(struct pcep_object_header *hdr,
1086 const uint8_t *obj_buf)
1087 {
1088 struct pcep_object_rp *obj =
1089 (struct pcep_object_rp *)common_object_create(
1090 hdr, sizeof(struct pcep_object_rp));
1091
1092 obj->flag_reoptimization = (obj_buf[3] & OBJECT_RP_FLAG_R);
1093 obj->flag_bidirectional = (obj_buf[3] & OBJECT_RP_FLAG_B);
1094 obj->flag_strict = (obj_buf[3] & OBJECT_RP_FLAG_O);
1095 obj->flag_of = (obj_buf[3] & OBJECT_RP_FLAG_OF);
1096 obj->priority = (obj_buf[3] & 0x07);
1097 obj->request_id = ntohl(*((uint32_t *)(obj_buf + 4)));
1098
1099 return (struct pcep_object_header *)obj;
1100 }
1101
1102 struct pcep_object_header *
1103 pcep_decode_obj_notify(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1104 {
1105 struct pcep_object_notify *obj =
1106 (struct pcep_object_notify *)common_object_create(
1107 hdr, sizeof(struct pcep_object_notify));
1108
1109 obj->notification_type = obj_buf[2];
1110 obj->notification_value = obj_buf[3];
1111
1112 return (struct pcep_object_header *)obj;
1113 }
1114
1115 struct pcep_object_header *
1116 pcep_decode_obj_nopath(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1117 {
1118 struct pcep_object_nopath *obj =
1119 (struct pcep_object_nopath *)common_object_create(
1120 hdr, sizeof(struct pcep_object_nopath));
1121
1122 obj->ni = (obj_buf[0] >> 1);
1123 obj->flag_c = (obj_buf[0] & OBJECT_NOPATH_FLAG_C);
1124
1125 return (struct pcep_object_header *)obj;
1126 }
1127
1128 struct pcep_object_header *
1129 pcep_decode_obj_association(struct pcep_object_header *hdr,
1130 const uint8_t *obj_buf)
1131 {
1132 uint16_t *uint16_ptr = (uint16_t *)obj_buf;
1133 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1134
1135 if (hdr->object_type == PCEP_OBJ_TYPE_ASSOCIATION_IPV4) {
1136 struct pcep_object_association_ipv4 *obj =
1137 (struct pcep_object_association_ipv4 *)
1138 common_object_create(
1139 hdr,
1140 sizeof(struct
1141 pcep_object_association_ipv4));
1142 obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R);
1143 obj->association_type = ntohs(uint16_ptr[2]);
1144 obj->association_id = ntohs(uint16_ptr[3]);
1145 obj->src.s_addr = uint32_ptr[2];
1146
1147 return (struct pcep_object_header *)obj;
1148 } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
1149 struct pcep_object_association_ipv6 *obj =
1150 (struct pcep_object_association_ipv6 *)
1151 common_object_create(
1152 hdr,
1153 sizeof(struct
1154 pcep_object_association_ipv6));
1155
1156 obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R);
1157 obj->association_type = ntohs(uint16_ptr[2]);
1158 obj->association_id = ntohs(uint16_ptr[3]);
1159 memcpy(&obj->src, &uint32_ptr[2], sizeof(struct in6_addr));
1160
1161 return (struct pcep_object_header *)obj;
1162 }
1163
1164 return NULL;
1165 }
1166 struct pcep_object_header *
1167 pcep_decode_obj_endpoints(struct pcep_object_header *hdr,
1168 const uint8_t *obj_buf)
1169 {
1170 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1171
1172 if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) {
1173 struct pcep_object_endpoints_ipv4 *obj =
1174 (struct pcep_object_endpoints_ipv4 *)
1175 common_object_create(
1176 hdr,
1177 sizeof(struct
1178 pcep_object_endpoints_ipv4));
1179 obj->src_ipv4.s_addr = uint32_ptr[0];
1180 obj->dst_ipv4.s_addr = uint32_ptr[1];
1181
1182 return (struct pcep_object_header *)obj;
1183 } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) {
1184 struct pcep_object_endpoints_ipv6 *obj =
1185 (struct pcep_object_endpoints_ipv6 *)
1186 common_object_create(
1187 hdr,
1188 sizeof(struct
1189 pcep_object_endpoints_ipv6));
1190
1191 memcpy(&obj->src_ipv6, &uint32_ptr[0], sizeof(struct in6_addr));
1192 memcpy(&obj->dst_ipv6, &uint32_ptr[4], sizeof(struct in6_addr));
1193
1194 return (struct pcep_object_header *)obj;
1195 }
1196
1197 return NULL;
1198 }
1199
1200 struct pcep_object_header *
1201 pcep_decode_obj_bandwidth(struct pcep_object_header *hdr,
1202 const uint8_t *obj_buf)
1203 {
1204 struct pcep_object_bandwidth *obj =
1205 (struct pcep_object_bandwidth *)common_object_create(
1206 hdr, sizeof(struct pcep_object_bandwidth));
1207
1208 uint32_t value = ntohl(*((uint32_t *)obj_buf));
1209 /* Seems like the compiler doesn't correctly copy to the float, so
1210 * memcpy() it */
1211 memcpy(&obj->bandwidth, &value, sizeof(uint32_t));
1212
1213 return (struct pcep_object_header *)obj;
1214 }
1215
1216 struct pcep_object_header *
1217 pcep_decode_obj_metric(struct pcep_object_header *hdr, const uint8_t *obj_buf)
1218 {
1219 struct pcep_object_metric *obj =
1220 (struct pcep_object_metric *)common_object_create(
1221 hdr, sizeof(struct pcep_object_metric));
1222 obj->flag_b = (obj_buf[2] & OBJECT_METRIC_FLAC_B);
1223 obj->flag_c = (obj_buf[2] & OBJECT_METRIC_FLAC_C);
1224 obj->type = obj_buf[3];
1225 uint32_t value = ntohl(*((uint32_t *)(obj_buf + 4)));
1226 /* Seems like the compiler doesn't correctly copy to the float, so
1227 * memcpy() it */
1228 memcpy(&obj->value, &value, sizeof(uint32_t));
1229
1230 return (struct pcep_object_header *)obj;
1231 }
1232
1233 struct pcep_object_header *pcep_decode_obj_lspa(struct pcep_object_header *hdr,
1234 const uint8_t *obj_buf)
1235 {
1236 struct pcep_object_lspa *obj =
1237 (struct pcep_object_lspa *)common_object_create(
1238 hdr, sizeof(struct pcep_object_lspa));
1239 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1240
1241 obj->lspa_exclude_any = ntohl(uint32_ptr[0]);
1242 obj->lspa_include_any = ntohl(uint32_ptr[1]);
1243 obj->lspa_include_all = ntohl(uint32_ptr[2]);
1244 obj->setup_priority = obj_buf[12];
1245 obj->holding_priority = obj_buf[13];
1246 obj->flag_local_protection = (obj_buf[14] & OBJECT_LSPA_FLAG_L);
1247
1248 return (struct pcep_object_header *)obj;
1249 }
1250
1251 struct pcep_object_header *pcep_decode_obj_svec(struct pcep_object_header *hdr,
1252 const uint8_t *obj_buf)
1253 {
1254 struct pcep_object_svec *obj =
1255 (struct pcep_object_svec *)common_object_create(
1256 hdr, sizeof(struct pcep_object_svec));
1257
1258 obj->flag_link_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_L);
1259 obj->flag_node_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_N);
1260 obj->flag_srlg_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_S);
1261
1262 if (hdr->encoded_object_length > LENGTH_2WORDS) {
1263 obj->request_id_list = dll_initialize();
1264 uint16_t index = 1;
1265 uint32_t *uint32_ptr = (uint32_t *)obj_buf;
1266 for (;
1267 index < ((hdr->encoded_object_length - LENGTH_2WORDS) / 4);
1268 index++) {
1269 uint32_t *req_id_ptr = pceplib_malloc(PCEPLIB_MESSAGES,
1270 sizeof(uint32_t));
1271 *req_id_ptr = uint32_ptr[index];
1272 dll_append(obj->request_id_list, req_id_ptr);
1273 }
1274 }
1275
1276 return (struct pcep_object_header *)obj;
1277 }
1278
1279 struct pcep_object_header *pcep_decode_obj_error(struct pcep_object_header *hdr,
1280 const uint8_t *obj_buf)
1281 {
1282 struct pcep_object_error *obj =
1283 (struct pcep_object_error *)common_object_create(
1284 hdr, sizeof(struct pcep_object_error));
1285
1286 obj->error_type = obj_buf[2];
1287 obj->error_value = obj_buf[3];
1288
1289 return (struct pcep_object_header *)obj;
1290 }
1291
1292 struct pcep_object_header *pcep_decode_obj_close(struct pcep_object_header *hdr,
1293 const uint8_t *obj_buf)
1294 {
1295 struct pcep_object_close *obj =
1296 (struct pcep_object_close *)common_object_create(
1297 hdr, sizeof(struct pcep_object_close));
1298
1299 obj->reason = obj_buf[3];
1300
1301 return (struct pcep_object_header *)obj;
1302 }
1303
1304 struct pcep_object_header *pcep_decode_obj_srp(struct pcep_object_header *hdr,
1305 const uint8_t *obj_buf)
1306 {
1307 struct pcep_object_srp *obj =
1308 (struct pcep_object_srp *)common_object_create(
1309 hdr, sizeof(struct pcep_object_srp));
1310
1311 obj->flag_lsp_remove = (obj_buf[3] & OBJECT_SRP_FLAG_R);
1312 obj->srp_id_number = ntohl(*((uint32_t *)(obj_buf + 4)));
1313
1314 return (struct pcep_object_header *)obj;
1315 }
1316
1317 struct pcep_object_header *pcep_decode_obj_lsp(struct pcep_object_header *hdr,
1318 const uint8_t *obj_buf)
1319 {
1320 struct pcep_object_lsp *obj =
1321 (struct pcep_object_lsp *)common_object_create(
1322 hdr, sizeof(struct pcep_object_lsp));
1323
1324 obj->flag_d = (obj_buf[3] & OBJECT_LSP_FLAG_D);
1325 obj->flag_s = (obj_buf[3] & OBJECT_LSP_FLAG_S);
1326 obj->flag_r = (obj_buf[3] & OBJECT_LSP_FLAG_R);
1327 obj->flag_a = (obj_buf[3] & OBJECT_LSP_FLAG_A);
1328 obj->flag_c = (obj_buf[3] & OBJECT_LSP_FLAG_C);
1329 obj->operational_status = ((obj_buf[3] >> 4) & 0x07);
1330 obj->plsp_id = ((ntohl(*((uint32_t *)obj_buf)) >> 12) & 0x000fffff);
1331
1332 return (struct pcep_object_header *)obj;
1333 }
1334
1335 struct pcep_object_header *
1336 pcep_decode_obj_vendor_info(struct pcep_object_header *hdr,
1337 const uint8_t *obj_buf)
1338 {
1339 struct pcep_object_vendor_info *obj =
1340 (struct pcep_object_vendor_info *)common_object_create(
1341 hdr, sizeof(struct pcep_object_vendor_info));
1342
1343 obj->enterprise_number = ntohl(*((uint32_t *)(obj_buf)));
1344 obj->enterprise_specific_info = ntohl(*((uint32_t *)(obj_buf + 4)));
1345 if (obj->enterprise_number == ENTERPRISE_NUMBER_CISCO
1346 && obj->enterprise_specific_info == ENTERPRISE_COLOR_CISCO)
1347 obj->enterprise_specific_info1 =
1348 ntohl(*((uint32_t *)(obj_buf + 8)));
1349 else
1350 obj->enterprise_specific_info1 = 0;
1351
1352 return (struct pcep_object_header *)obj;
1353 }
1354
1355 struct pcep_object_header *
1356 pcep_decode_obj_inter_layer(struct pcep_object_header *hdr,
1357 const uint8_t *obj_buf)
1358 {
1359 struct pcep_object_inter_layer *obj =
1360 (struct pcep_object_inter_layer *)common_object_create(
1361 hdr, sizeof(struct pcep_object_inter_layer));
1362 obj->flag_t = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_T);
1363 obj->flag_m = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_M);
1364 obj->flag_i = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_I);
1365
1366 return (struct pcep_object_header *)obj;
1367 }
1368
1369 struct pcep_object_header *
1370 pcep_decode_obj_switch_layer(struct pcep_object_header *hdr,
1371 const uint8_t *obj_buf)
1372 {
1373 struct pcep_object_switch_layer *obj =
1374 (struct pcep_object_switch_layer *)common_object_create(
1375 hdr, sizeof(struct pcep_object_switch_layer));
1376 obj->switch_layer_rows = dll_initialize();
1377 int num_rows = ((hdr->encoded_object_length - 4) / 4);
1378 uint8_t buf_index = 0;
1379
1380 int i = 0;
1381 for (; i < num_rows; i++) {
1382 struct pcep_object_switch_layer_row *row = pceplib_malloc(
1383 PCEPLIB_MESSAGES,
1384 sizeof(struct pcep_object_switch_layer_row));
1385 row->lsp_encoding_type = obj_buf[buf_index];
1386 row->switching_type = obj_buf[buf_index + 1];
1387 row->flag_i =
1388 (obj_buf[buf_index + 3] & OBJECT_SWITCH_LAYER_FLAG_I);
1389 dll_append(obj->switch_layer_rows, row);
1390
1391 buf_index += LENGTH_1WORD;
1392 }
1393
1394 return (struct pcep_object_header *)obj;
1395 }
1396
1397 struct pcep_object_header *
1398 pcep_decode_obj_req_adap_cap(struct pcep_object_header *hdr,
1399 const uint8_t *obj_buf)
1400 {
1401 struct pcep_object_req_adap_cap *obj =
1402 (struct pcep_object_req_adap_cap *)common_object_create(
1403 hdr, sizeof(struct pcep_object_req_adap_cap));
1404
1405 obj->switching_capability = obj_buf[0];
1406 obj->encoding = obj_buf[1];
1407
1408 return (struct pcep_object_header *)obj;
1409 }
1410
1411 struct pcep_object_header *
1412 pcep_decode_obj_server_ind(struct pcep_object_header *hdr,
1413 const uint8_t *obj_buf)
1414 {
1415 struct pcep_object_server_indication *obj =
1416 (struct pcep_object_server_indication *)common_object_create(
1417 hdr, sizeof(struct pcep_object_server_indication));
1418
1419 obj->switching_capability = obj_buf[0];
1420 obj->encoding = obj_buf[1];
1421
1422 return (struct pcep_object_header *)obj;
1423 }
1424
1425 struct pcep_object_header *
1426 pcep_decode_obj_objective_function(struct pcep_object_header *hdr,
1427 const uint8_t *obj_buf)
1428 {
1429 struct pcep_object_objective_function *obj =
1430 (struct pcep_object_objective_function *)common_object_create(
1431 hdr, sizeof(struct pcep_object_objective_function));
1432
1433 uint16_t *uint16_ptr = (uint16_t *)obj_buf;
1434 obj->of_code = ntohs(*uint16_ptr);
1435
1436 return (struct pcep_object_header *)obj;
1437 }
1438
1439 void set_ro_subobj_fields(struct pcep_object_ro_subobj *subobj, bool flag_l,
1440 uint8_t subobj_type)
1441 {
1442 subobj->flag_subobj_loose_hop = flag_l;
1443 subobj->ro_subobj_type = subobj_type;
1444 }
1445
1446 void decode_ipv6(const uint32_t *src, struct in6_addr *dst_ipv6)
1447 {
1448 memcpy(dst_ipv6, src, sizeof(struct in6_addr));
1449 }
1450 struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr,
1451 const uint8_t *obj_buf)
1452 {
1453 struct pcep_object_ro *obj =
1454 (struct pcep_object_ro *)common_object_create(
1455 hdr, sizeof(struct pcep_object_ro));
1456 obj->sub_objects = dll_initialize();
1457
1458 /* RO Subobject format
1459 *
1460 * 0 1
1461 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1462 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1463 * |L| Type | Length | (Subobject contents) |
1464 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1465 */
1466
1467 uint16_t read_count = 0;
1468 int num_sub_objects = 1;
1469 uint32_t *uint32_ptr;
1470 uint16_t obj_body_length =
1471 hdr->encoded_object_length - OBJECT_HEADER_LENGTH;
1472
1473 while ((obj_body_length - read_count) > OBJECT_RO_SUBOBJ_HEADER_LENGTH
1474 && num_sub_objects < MAX_ITERATIONS) {
1475 num_sub_objects++;
1476 /* Read the Sub-Object Header */
1477 bool flag_l = (obj_buf[read_count] & 0x80);
1478 uint8_t subobj_type = (obj_buf[read_count++] & 0x7f);
1479 uint8_t subobj_length = obj_buf[read_count++];
1480
1481 if (subobj_length <= OBJECT_RO_SUBOBJ_HEADER_LENGTH) {
1482 pcep_log(LOG_INFO,
1483 "%s: Invalid ro subobj type [%d] length [%d]",
1484 __func__, subobj_type, subobj_length);
1485 pceplib_free(PCEPLIB_MESSAGES, obj);
1486 return NULL;
1487 }
1488
1489 switch (subobj_type) {
1490 case RO_SUBOBJ_TYPE_IPV4: {
1491 struct pcep_ro_subobj_ipv4 *ipv4 = pceplib_malloc(
1492 PCEPLIB_MESSAGES,
1493 sizeof(struct pcep_ro_subobj_ipv4));
1494 ipv4->ro_subobj.flag_subobj_loose_hop = flag_l;
1495 ipv4->ro_subobj.ro_subobj_type = subobj_type;
1496 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1497 ipv4->ip_addr.s_addr = *uint32_ptr;
1498 read_count += LENGTH_1WORD;
1499 ipv4->prefix_length = obj_buf[read_count++];
1500 ipv4->flag_local_protection =
1501 (obj_buf[read_count++]
1502 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
1503
1504 dll_append(obj->sub_objects, ipv4);
1505 } break;
1506
1507 case RO_SUBOBJ_TYPE_IPV6: {
1508 struct pcep_ro_subobj_ipv6 *ipv6 = pceplib_malloc(
1509 PCEPLIB_MESSAGES,
1510 sizeof(struct pcep_ro_subobj_ipv6));
1511 ipv6->ro_subobj.flag_subobj_loose_hop = flag_l;
1512 ipv6->ro_subobj.ro_subobj_type = subobj_type;
1513 decode_ipv6((uint32_t *)obj_buf, &ipv6->ip_addr);
1514 read_count += LENGTH_4WORDS;
1515 ipv6->prefix_length = obj_buf[read_count++];
1516 ipv6->flag_local_protection =
1517 (obj_buf[read_count++]
1518 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
1519
1520 dll_append(obj->sub_objects, ipv6);
1521 } break;
1522
1523 case RO_SUBOBJ_TYPE_LABEL: {
1524 struct pcep_ro_subobj_32label *label = pceplib_malloc(
1525 PCEPLIB_MESSAGES,
1526 sizeof(struct pcep_ro_subobj_32label));
1527 label->ro_subobj.flag_subobj_loose_hop = flag_l;
1528 label->ro_subobj.ro_subobj_type = subobj_type;
1529 label->flag_global_label =
1530 (obj_buf[read_count++]
1531 & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL);
1532 label->class_type = obj_buf[read_count++];
1533 label->label = ntohl(obj_buf[read_count]);
1534 read_count += LENGTH_1WORD;
1535
1536 dll_append(obj->sub_objects, label);
1537 } break;
1538
1539 case RO_SUBOBJ_TYPE_UNNUM: {
1540 struct pcep_ro_subobj_unnum *unum = pceplib_malloc(
1541 PCEPLIB_MESSAGES,
1542 sizeof(struct pcep_ro_subobj_unnum));
1543 unum->ro_subobj.flag_subobj_loose_hop = flag_l;
1544 unum->ro_subobj.ro_subobj_type = subobj_type;
1545 set_ro_subobj_fields(
1546 (struct pcep_object_ro_subobj *)unum, flag_l,
1547 subobj_type);
1548 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1549 unum->interface_id = ntohl(uint32_ptr[0]);
1550 unum->router_id.s_addr = uint32_ptr[1];
1551 read_count += 2;
1552
1553 dll_append(obj->sub_objects, unum);
1554 } break;
1555
1556 case RO_SUBOBJ_TYPE_ASN: {
1557 struct pcep_ro_subobj_asn *asn = pceplib_malloc(
1558 PCEPLIB_MESSAGES,
1559 sizeof(struct pcep_ro_subobj_asn));
1560 asn->ro_subobj.flag_subobj_loose_hop = flag_l;
1561 asn->ro_subobj.ro_subobj_type = subobj_type;
1562 uint16_t *uint16_ptr =
1563 (uint16_t *)(obj_buf + read_count);
1564 asn->asn = ntohs(*uint16_ptr);
1565 read_count += 2;
1566
1567 dll_append(obj->sub_objects, asn);
1568 } break;
1569
1570 case RO_SUBOBJ_TYPE_SR: {
1571 /* SR-ERO subobject format
1572 *
1573 * 0 1 2 3 0 1 2 3 4
1574 * 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
1575 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1576 * |L| Type=36 | Length | NT | Flags
1577 * |F|S|C|M|
1578 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1579 * | SID (optional) |
1580 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1581 * // NAI (variable, optional) //
1582 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1583 */
1584
1585 struct pcep_ro_subobj_sr *sr_subobj = pceplib_malloc(
1586 PCEPLIB_MESSAGES,
1587 sizeof(struct pcep_ro_subobj_sr));
1588 sr_subobj->ro_subobj.flag_subobj_loose_hop = flag_l;
1589 sr_subobj->ro_subobj.ro_subobj_type = subobj_type;
1590 dll_append(obj->sub_objects, sr_subobj);
1591
1592 sr_subobj->nai_list = dll_initialize();
1593 sr_subobj->nai_type =
1594 ((obj_buf[read_count++] >> 4) & 0x0f);
1595 sr_subobj->flag_f =
1596 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_F);
1597 sr_subobj->flag_s =
1598 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_S);
1599 sr_subobj->flag_c =
1600 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_C);
1601 sr_subobj->flag_m =
1602 (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_M);
1603 read_count++;
1604
1605 /* If the sid_absent flag is true, then dont decode the
1606 * sid */
1607 uint32_ptr = (uint32_t *)(obj_buf + read_count);
1608 if (sr_subobj->flag_s == false) {
1609 sr_subobj->sid = ntohl(*uint32_ptr);
1610 read_count += LENGTH_1WORD;
1611 uint32_ptr += 1;
1612 }
1613
1614 switch (sr_subobj->nai_type) {
1615 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE: {
1616 struct in_addr *ipv4 =
1617 pceplib_malloc(PCEPLIB_MESSAGES,
1618 sizeof(struct in_addr));
1619 ipv4->s_addr = *uint32_ptr;
1620 dll_append(sr_subobj->nai_list, ipv4);
1621 read_count += LENGTH_1WORD;
1622 } break;
1623
1624 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE: {
1625 struct in6_addr *ipv6 =
1626 pceplib_malloc(PCEPLIB_MESSAGES,
1627 sizeof(struct in6_addr));
1628 decode_ipv6(uint32_ptr, ipv6);
1629 dll_append(sr_subobj->nai_list, ipv6);
1630 read_count += LENGTH_4WORDS;
1631 } break;
1632
1633 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY: {
1634 struct in_addr *ipv4 =
1635 pceplib_malloc(PCEPLIB_MESSAGES,
1636 sizeof(struct in_addr));
1637 ipv4->s_addr = uint32_ptr[0];
1638 dll_append(sr_subobj->nai_list, ipv4);
1639
1640 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1641 sizeof(struct in_addr));
1642 ipv4->s_addr = uint32_ptr[1];
1643 dll_append(sr_subobj->nai_list, ipv4);
1644
1645 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1646 sizeof(struct in_addr));
1647 ipv4->s_addr = uint32_ptr[2];
1648 dll_append(sr_subobj->nai_list, ipv4);
1649
1650 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1651 sizeof(struct in_addr));
1652 ipv4->s_addr = uint32_ptr[3];
1653 dll_append(sr_subobj->nai_list, ipv4);
1654
1655 read_count += LENGTH_4WORDS;
1656 } break;
1657
1658 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY: {
1659 struct in_addr *ipv4 =
1660 pceplib_malloc(PCEPLIB_MESSAGES,
1661 sizeof(struct in_addr));
1662 ipv4->s_addr = uint32_ptr[0];
1663 dll_append(sr_subobj->nai_list, ipv4);
1664
1665 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1666 sizeof(struct in_addr));
1667 ipv4->s_addr = uint32_ptr[1];
1668 dll_append(sr_subobj->nai_list, ipv4);
1669
1670 read_count += LENGTH_2WORDS;
1671 } break;
1672
1673 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY: {
1674 struct in6_addr *ipv6 =
1675 pceplib_malloc(PCEPLIB_MESSAGES,
1676 sizeof(struct in6_addr));
1677 decode_ipv6(uint32_ptr, ipv6);
1678 dll_append(sr_subobj->nai_list, ipv6);
1679
1680 ipv6 = pceplib_malloc(PCEPLIB_MESSAGES,
1681 sizeof(struct in6_addr));
1682 decode_ipv6(uint32_ptr + 4, ipv6);
1683 dll_append(sr_subobj->nai_list, ipv6);
1684
1685 read_count += LENGTH_8WORDS;
1686 } break;
1687
1688 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY: {
1689 struct in6_addr *ipv6 =
1690 pceplib_malloc(PCEPLIB_MESSAGES,
1691 sizeof(struct in6_addr));
1692 decode_ipv6(uint32_ptr, ipv6);
1693 dll_append(sr_subobj->nai_list, ipv6);
1694
1695 struct in_addr *ipv4 =
1696 pceplib_malloc(PCEPLIB_MESSAGES,
1697 sizeof(struct in_addr));
1698 ipv4->s_addr = uint32_ptr[4];
1699 dll_append(sr_subobj->nai_list, ipv4);
1700
1701 ipv6 = pceplib_malloc(PCEPLIB_MESSAGES,
1702 sizeof(struct in6_addr));
1703 decode_ipv6(uint32_ptr + 5, ipv6);
1704 dll_append(sr_subobj->nai_list, ipv6);
1705
1706 ipv4 = pceplib_malloc(PCEPLIB_MESSAGES,
1707 sizeof(struct in_addr));
1708 ipv4->s_addr = uint32_ptr[9];
1709 dll_append(sr_subobj->nai_list, ipv4);
1710
1711 read_count += LENGTH_10WORDS;
1712 } break;
1713
1714 case PCEP_SR_SUBOBJ_NAI_ABSENT:
1715 default:
1716 break;
1717 }
1718 } break;
1719
1720 default:
1721 pcep_log(
1722 LOG_INFO,
1723 "%s: pcep_decode_obj_ro skipping unrecognized sub-object type [%d]",
1724 __func__, subobj_type);
1725 read_count += subobj_length;
1726 break;
1727 }
1728 }
1729
1730 return (struct pcep_object_header *)obj;
1731 }