]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: LGPL-2.1-or-later |
74971473 JG |
2 | /* |
3 | * This file is part of the PCEPlib, a PCEP protocol library. | |
4 | * | |
5 | * Copyright (C) 2020 Volta Networks https://voltanet.io/ | |
6 | * | |
74971473 JG |
7 | * Author : Brady Johnson <brady@voltanet.io> |
8 | * | |
9 | */ | |
10 | ||
11 | ||
12 | /* | |
13 | * This is the implementation of a High Level PCEP message API. | |
14 | */ | |
15 | ||
1f8031f7 DL |
16 | #ifdef HAVE_CONFIG_H |
17 | #include "config.h" | |
18 | #endif | |
19 | ||
74971473 JG |
20 | #include <string.h> |
21 | #include <arpa/inet.h> | |
22 | #include <stdarg.h> | |
23 | #include <unistd.h> | |
24 | ||
25 | #include "pcep_msg_encoding.h" | |
26 | #include "pcep_msg_messages.h" | |
27 | #include "pcep_msg_objects.h" | |
28 | #include "pcep_utils_double_linked_list.h" | |
29 | #include "pcep_utils_logging.h" | |
30 | #include "pcep_utils_memory.h" | |
31 | ||
32 | static struct pcep_message * | |
33 | pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type, | |
34 | double_linked_list *obj_list) | |
35 | { | |
36 | struct pcep_message *message = | |
37 | pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message)); | |
38 | memset(message, 0, sizeof(struct pcep_message)); | |
39 | message->msg_header = pceplib_malloc( | |
40 | PCEPLIB_MESSAGES, sizeof(struct pcep_message_header)); | |
41 | memset(message->msg_header, 0, sizeof(struct pcep_message_header)); | |
42 | message->msg_header->type = msg_type; | |
43 | message->msg_header->pcep_version = PCEP_MESSAGE_HEADER_VERSION; | |
44 | message->obj_list = ((obj_list == NULL) ? dll_initialize() : obj_list); | |
45 | ||
46 | return message; | |
47 | } | |
48 | ||
49 | static struct pcep_message * | |
50 | pcep_msg_create_common(enum pcep_message_types msg_type) | |
51 | { | |
52 | return pcep_msg_create_common_with_obj_list(msg_type, NULL); | |
53 | } | |
54 | ||
55 | struct pcep_message *pcep_msg_create_open(uint8_t keepalive, uint8_t deadtimer, | |
56 | uint8_t sid) | |
57 | { | |
58 | struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN); | |
59 | dll_append(message->obj_list, | |
60 | pcep_obj_create_open(keepalive, deadtimer, sid, NULL)); | |
61 | ||
62 | return message; | |
63 | } | |
64 | ||
65 | struct pcep_message * | |
66 | pcep_msg_create_open_with_tlvs(uint8_t keepalive, uint8_t deadtimer, | |
67 | uint8_t sid, double_linked_list *tlv_list) | |
68 | { | |
69 | struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN); | |
70 | dll_append(message->obj_list, | |
71 | pcep_obj_create_open(keepalive, deadtimer, sid, tlv_list)); | |
72 | ||
73 | return message; | |
74 | } | |
75 | ||
76 | ||
77 | struct pcep_message * | |
78 | pcep_msg_create_request(struct pcep_object_rp *rp, | |
79 | struct pcep_object_endpoints_ipv4 *endpoints, | |
80 | double_linked_list *object_list) | |
81 | { | |
82 | if ((rp == NULL) || (endpoints == NULL)) { | |
83 | return NULL; | |
84 | } | |
85 | ||
86 | struct pcep_message *message = pcep_msg_create_common_with_obj_list( | |
87 | PCEP_TYPE_PCREQ, object_list); | |
88 | dll_prepend(message->obj_list, endpoints); | |
89 | dll_prepend(message->obj_list, rp); | |
90 | ||
91 | return message; | |
92 | } | |
93 | ||
94 | struct pcep_message * | |
95 | pcep_msg_create_request_ipv6(struct pcep_object_rp *rp, | |
96 | struct pcep_object_endpoints_ipv6 *endpoints, | |
97 | double_linked_list *object_list) | |
98 | { | |
99 | if ((rp == NULL) || (endpoints == NULL)) { | |
100 | return NULL; | |
101 | } | |
102 | ||
103 | struct pcep_message *message = pcep_msg_create_common_with_obj_list( | |
104 | PCEP_TYPE_PCREQ, object_list); | |
105 | dll_prepend(message->obj_list, endpoints); | |
106 | dll_prepend(message->obj_list, rp); | |
107 | ||
108 | return message; | |
109 | } | |
110 | ||
111 | struct pcep_message *pcep_msg_create_reply(struct pcep_object_rp *rp, | |
112 | double_linked_list *object_list) | |
113 | { | |
114 | struct pcep_message *message = pcep_msg_create_common_with_obj_list( | |
115 | PCEP_TYPE_PCREP, object_list); | |
116 | ||
117 | if (rp != NULL) { | |
118 | dll_prepend(message->obj_list, rp); | |
119 | } | |
120 | ||
121 | return message; | |
122 | } | |
123 | ||
124 | struct pcep_message *pcep_msg_create_close(uint8_t reason) | |
125 | { | |
126 | struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_CLOSE); | |
127 | dll_append(message->obj_list, pcep_obj_create_close(reason)); | |
128 | ||
129 | return message; | |
130 | } | |
131 | ||
132 | struct pcep_message *pcep_msg_create_error(uint8_t error_type, | |
133 | uint8_t error_value) | |
134 | { | |
135 | struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_ERROR); | |
136 | dll_append(message->obj_list, | |
137 | pcep_obj_create_error(error_type, error_value)); | |
138 | ||
139 | return message; | |
140 | } | |
141 | ||
142 | struct pcep_message * | |
143 | pcep_msg_create_error_with_objects(uint8_t error_type, uint8_t error_value, | |
144 | double_linked_list *object_list) | |
145 | { | |
146 | struct pcep_message *message = pcep_msg_create_common_with_obj_list( | |
147 | PCEP_TYPE_ERROR, object_list); | |
148 | dll_prepend(message->obj_list, | |
149 | pcep_obj_create_error(error_type, error_value)); | |
150 | ||
151 | return message; | |
152 | } | |
153 | ||
2816045a | 154 | struct pcep_message *pcep_msg_create_keepalive(void) |
74971473 JG |
155 | { |
156 | return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE)); | |
157 | } | |
158 | ||
159 | struct pcep_message * | |
160 | pcep_msg_create_report(double_linked_list *state_report_object_list) | |
161 | { | |
162 | return (state_report_object_list == NULL | |
163 | ? NULL | |
164 | : pcep_msg_create_common_with_obj_list( | |
165 | PCEP_TYPE_REPORT, state_report_object_list)); | |
166 | } | |
167 | ||
168 | struct pcep_message * | |
169 | pcep_msg_create_update(double_linked_list *update_request_object_list) | |
170 | { | |
171 | if (update_request_object_list == NULL) { | |
172 | pcep_log( | |
173 | LOG_INFO, | |
174 | "%s: pcep_msg_create_update NULL update_request_object_list", | |
175 | __func__); | |
176 | return NULL; | |
177 | } | |
178 | ||
179 | /* There must be at least 3 objects: | |
180 | * These 3 are mandatory: SRP, LSP, and ERO. The ERO may be empty */ | |
181 | if (update_request_object_list->num_entries < 3) { | |
182 | pcep_log( | |
183 | LOG_INFO, | |
184 | "%s: pcep_msg_create_update there must be at least 3 update objects", | |
185 | __func__); | |
186 | return NULL; | |
187 | } | |
188 | ||
189 | double_linked_list_node *node = update_request_object_list->head; | |
190 | struct pcep_object_header *obj_hdr = | |
191 | (struct pcep_object_header *)node->data; | |
192 | ||
193 | /* Check for the mandatory first SRP object */ | |
194 | if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) { | |
195 | /* If the SRP object is missing, the receiving PCC MUST send a | |
196 | * PCErr message with Error-type=6 (Mandatory Object missing) | |
197 | * and Error-value=10 (SRP object missing). */ | |
198 | pcep_log( | |
199 | LOG_INFO, | |
200 | "%s: pcep_msg_create_update missing mandatory first SRP object", | |
201 | __func__); | |
202 | return NULL; | |
203 | } | |
204 | ||
205 | /* Check for the mandatory 2nd LSP object */ | |
206 | node = node->next_node; | |
207 | obj_hdr = (struct pcep_object_header *)node->data; | |
208 | if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) { | |
209 | /* If the LSP object is missing, the receiving PCC MUST send a | |
210 | * PCErr message with Error-type=6 (Mandatory Object missing) | |
211 | * and Error-value=8 (LSP object missing). */ | |
212 | pcep_log( | |
213 | LOG_INFO, | |
214 | "%s: pcep_msg_create_update missing mandatory second LSP object", | |
215 | __func__); | |
216 | return NULL; | |
217 | } | |
218 | ||
219 | /* Check for the mandatory 3rd ERO object */ | |
220 | node = node->next_node; | |
221 | obj_hdr = (struct pcep_object_header *)node->data; | |
222 | if (obj_hdr->object_class != PCEP_OBJ_CLASS_ERO) { | |
223 | /* If the ERO object is missing, the receiving PCC MUST send a | |
224 | * PCErr message with Error-type=6 (Mandatory Object missing) | |
225 | * and Error-value=9 (ERO object missing). */ | |
226 | pcep_log( | |
227 | LOG_INFO, | |
228 | "%s: pcep_msg_create_update missing mandatory third ERO object", | |
229 | __func__); | |
230 | return NULL; | |
231 | } | |
232 | ||
233 | return (pcep_msg_create_common_with_obj_list( | |
234 | PCEP_TYPE_UPDATE, update_request_object_list)); | |
235 | } | |
236 | ||
237 | struct pcep_message * | |
238 | pcep_msg_create_initiate(double_linked_list *lsp_object_list) | |
239 | { | |
240 | if (lsp_object_list == NULL) { | |
241 | pcep_log( | |
242 | LOG_INFO, | |
243 | "%s: pcep_msg_create_initiate NULL update_request_object_list", | |
244 | __func__); | |
245 | return NULL; | |
246 | } | |
247 | ||
248 | /* There must be at least 2 objects: SRP and LSP. */ | |
249 | if (lsp_object_list->num_entries < 2) { | |
250 | pcep_log( | |
251 | LOG_INFO, | |
252 | "%s: pcep_msg_create_initiate there must be at least 2 objects", | |
253 | __func__); | |
254 | return NULL; | |
255 | } | |
256 | ||
257 | double_linked_list_node *node = lsp_object_list->head; | |
258 | struct pcep_object_header *obj_hdr = | |
259 | (struct pcep_object_header *)node->data; | |
260 | ||
261 | /* Check for the mandatory first SRP object */ | |
262 | if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) { | |
263 | pcep_log( | |
264 | LOG_INFO, | |
265 | "%s: pcep_msg_create_initiate missing mandatory first SRP object", | |
266 | __func__); | |
267 | return NULL; | |
268 | } | |
269 | ||
270 | /* Check for the mandatory 2nd LSP object */ | |
271 | node = node->next_node; | |
272 | obj_hdr = (struct pcep_object_header *)node->data; | |
273 | if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) { | |
274 | pcep_log( | |
275 | LOG_INFO, | |
276 | "%s: pcep_msg_create_initiate missing mandatory second LSP object", | |
277 | __func__); | |
278 | return NULL; | |
279 | } | |
280 | ||
281 | return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE, | |
282 | lsp_object_list)); | |
283 | } | |
284 | ||
285 | struct pcep_message *pcep_msg_create_notify(struct pcep_object_notify *notify, | |
286 | double_linked_list *object_list) | |
287 | { | |
288 | if (notify == NULL) { | |
289 | pcep_log(LOG_INFO, | |
290 | "%s: pcep_msg_create_notify NULL notify object", | |
291 | __func__); | |
292 | return NULL; | |
293 | } | |
294 | ||
295 | struct pcep_message *message = pcep_msg_create_common_with_obj_list( | |
296 | PCEP_TYPE_PCNOTF, object_list); | |
297 | dll_prepend(message->obj_list, notify); | |
298 | ||
299 | return message; | |
300 | } |