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