]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/init.c
Merge pull request #12908 from opensourcerouting/fix/memory_leak_path_attributes
[mirror_frr.git] / ldpd / init.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: ISC
8429abe0
RW
2/* $OpenBSD$ */
3
4/*
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
8429abe0
RW
6 */
7
eac6e3f0 8#include <zebra.h>
8429abe0
RW
9
10#include "ldpd.h"
11#include "ldpe.h"
12#include "log.h"
eac6e3f0 13#include "ldp_debug.h"
8429abe0
RW
14
15static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
8819fc38 16static int gen_cap_dynamic_tlv(struct ibuf *);
d4afb819 17static int gen_cap_twcard_tlv(struct ibuf *, int);
257799cd 18static int gen_cap_unotif_tlv(struct ibuf *, int);
8429abe0
RW
19
20void
21send_init(struct nbr *nbr)
22{
23 struct ibuf *buf;
24 uint16_t size;
25 int err = 0;
26
903a7226 27 debug_msg_send("initialization: lsr-id %pI4", &nbr->id);
8429abe0 28
8819fc38 29 size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
257799cd 30 CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE + CAP_TLV_UNOTIF_SIZE;
8429abe0
RW
31 if ((buf = ibuf_open(size)) == NULL)
32 fatal(__func__);
33
34 err |= gen_ldp_hdr(buf, size);
35 size -= LDP_HDR_SIZE;
36 err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
8429abe0 37 err |= gen_init_prms_tlv(buf, nbr);
8819fc38 38 err |= gen_cap_dynamic_tlv(buf);
d4afb819 39 err |= gen_cap_twcard_tlv(buf, 1);
257799cd 40 err |= gen_cap_unotif_tlv(buf, 1);
8429abe0
RW
41 if (err) {
42 ibuf_free(buf);
43 return;
44 }
45
46 evbuf_enqueue(&nbr->tcp->wbuf, buf);
47}
48
49int
50recv_init(struct nbr *nbr, char *buf, uint16_t len)
51{
52 struct ldp_msg msg;
53 struct sess_prms_tlv sess;
54 uint16_t max_pdu_len;
8819fc38 55 int caps_rcvd = 0;
8429abe0 56
903a7226 57 debug_msg_recv("initialization: lsr-id %pI4", &nbr->id);
8429abe0
RW
58
59 memcpy(&msg, buf, sizeof(msg));
60 buf += LDP_MSG_SIZE;
61 len -= LDP_MSG_SIZE;
62
63 if (len < SESS_PRMS_SIZE) {
64 session_shutdown(nbr, S_BAD_MSG_LEN, msg.id, msg.type);
65 return (-1);
66 }
67 memcpy(&sess, buf, sizeof(sess));
68 if (ntohs(sess.length) != SESS_PRMS_LEN) {
69 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
70 return (-1);
71 }
72 if (ntohs(sess.proto_version) != LDP_VERSION) {
73 session_shutdown(nbr, S_BAD_PROTO_VER, msg.id, msg.type);
74 return (-1);
75 }
76 if (ntohs(sess.keepalive_time) < MIN_KEEPALIVE) {
77 session_shutdown(nbr, S_KEEPALIVE_BAD, msg.id, msg.type);
78 return (-1);
79 }
eac6e3f0 80 if (sess.lsr_id != ldp_rtr_id_get(leconf) ||
8429abe0
RW
81 ntohs(sess.lspace_id) != 0) {
82 session_shutdown(nbr, S_NO_HELLO, msg.id, msg.type);
83 return (-1);
84 }
85
86 buf += SESS_PRMS_SIZE;
87 len -= SESS_PRMS_SIZE;
88
89 /* Optional Parameters */
90 while (len > 0) {
91 struct tlv tlv;
8819fc38 92 uint16_t tlv_type;
8429abe0
RW
93 uint16_t tlv_len;
94
95 if (len < sizeof(tlv)) {
96 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
97 return (-1);
98 }
99
100 memcpy(&tlv, buf, TLV_HDR_SIZE);
8819fc38 101 tlv_type = ntohs(tlv.type);
8429abe0
RW
102 tlv_len = ntohs(tlv.length);
103 if (tlv_len + TLV_HDR_SIZE > len) {
104 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
105 return (-1);
106 }
107 buf += TLV_HDR_SIZE;
108 len -= TLV_HDR_SIZE;
109
8819fc38
RW
110 /*
111 * RFC 5561 - Section 6:
112 * "The S-bit of a Capability Parameter in an Initialization
113 * message MUST be 1 and SHOULD be ignored on receipt".
114 */
115 switch (tlv_type) {
8429abe0
RW
116 case TLV_TYPE_ATMSESSIONPAR:
117 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
118 return (-1);
119 case TLV_TYPE_FRSESSION:
120 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
121 return (-1);
8819fc38
RW
122 case TLV_TYPE_DYNAMIC_CAP:
123 if (tlv_len != CAP_TLV_DYNAMIC_LEN) {
124 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
125 msg.type);
126 return (-1);
127 }
128
129 if (caps_rcvd & F_CAP_TLV_RCVD_DYNAMIC) {
130 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
131 msg.type);
132 return (-1);
133 }
134 caps_rcvd |= F_CAP_TLV_RCVD_DYNAMIC;
135
136 nbr->flags |= F_NBR_CAP_DYNAMIC;
137
903a7226
MS
138 log_debug("%s: lsr-id %pI4 announced the Dynamic Capability Announcement capability", __func__,
139 &nbr->id);
8819fc38 140 break;
d4afb819
RW
141 case TLV_TYPE_TWCARD_CAP:
142 if (tlv_len != CAP_TLV_TWCARD_LEN) {
143 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
144 msg.type);
145 return (-1);
146 }
147
148 if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
149 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
150 msg.type);
151 return (-1);
152 }
153 caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
154
155 nbr->flags |= F_NBR_CAP_TWCARD;
156
903a7226 157 log_debug("%s: lsr-id %pI4 announced the Typed Wildcard FEC capability", __func__, &nbr->id);
d4afb819 158 break;
257799cd
RW
159 case TLV_TYPE_UNOTIF_CAP:
160 if (tlv_len != CAP_TLV_UNOTIF_LEN) {
161 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
162 msg.type);
163 return (-1);
164 }
165
166 if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) {
167 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
168 msg.type);
169 return (-1);
170 }
171 caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF;
172
173 nbr->flags |= F_NBR_CAP_UNOTIF;
174
903a7226
MS
175 log_debug("%s: lsr-id %pI4 announced the Unrecognized Notification capability", __func__,
176 &nbr->id);
257799cd 177 break;
8429abe0
RW
178 default:
179 if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
8819fc38
RW
180 send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
181 msg.id, msg.type, tlv_type, tlv_len, buf);
8429abe0
RW
182 /* ignore unknown tlv */
183 break;
184 }
185 buf += tlv_len;
186 len -= tlv_len;
187 }
188
7a8ce9d5 189 nbr->keepalive = MIN(nbr_get_keepalive(nbr->af, nbr->id),
8429abe0
RW
190 ntohs(sess.keepalive_time));
191
192 max_pdu_len = ntohs(sess.max_pdu_len);
193 /*
194 * RFC 5036 - Section 3.5.3:
195 * "A value of 255 or less specifies the default maximum length of
196 * 4096 octets".
197 */
198 if (max_pdu_len <= 255)
199 max_pdu_len = LDP_MAX_LEN;
7a8ce9d5 200 nbr->max_pdu_len = MIN(max_pdu_len, LDP_MAX_LEN);
8429abe0
RW
201
202 nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
203
204 return (0);
205}
206
8819fc38
RW
207void
208send_capability(struct nbr *nbr, uint16_t capability, int enable)
209{
210 struct ibuf *buf;
211 uint16_t size;
212 int err = 0;
213
903a7226 214 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
8819fc38
RW
215
216 size = LDP_HDR_SIZE + LDP_MSG_SIZE + CAP_TLV_DYNAMIC_SIZE;
217 if ((buf = ibuf_open(size)) == NULL)
218 fatal(__func__);
219
220 err |= gen_ldp_hdr(buf, size);
221 size -= LDP_HDR_SIZE;
222 err |= gen_msg_hdr(buf, MSG_TYPE_CAPABILITY, size);
223
224 switch (capability) {
d4afb819
RW
225 case TLV_TYPE_TWCARD_CAP:
226 err |= gen_cap_twcard_tlv(buf, enable);
227 break;
257799cd
RW
228 case TLV_TYPE_UNOTIF_CAP:
229 err |= gen_cap_unotif_tlv(buf, enable);
230 break;
8819fc38
RW
231 case TLV_TYPE_DYNAMIC_CAP:
232 /*
233 * RFC 5561 - Section 9:
234 * "An LDP speaker MUST NOT include the Dynamic Capability
235 * Announcement Parameter in Capability messages sent to
236 * its peers".
237 */
238 /* FALLTHROUGH */
239 default:
240 fatalx("send_capability: unsupported capability");
241 }
242
243 if (err) {
244 ibuf_free(buf);
245 return;
246 }
247
248 evbuf_enqueue(&nbr->tcp->wbuf, buf);
249 nbr_fsm(nbr, NBR_EVT_PDU_SENT);
0f7b5df9 250 nbr->stats.capability_sent++;
8819fc38
RW
251}
252
253int
254recv_capability(struct nbr *nbr, char *buf, uint16_t len)
255{
256 struct ldp_msg msg;
d4afb819
RW
257 int enable = 0;
258 int caps_rcvd = 0;
8819fc38 259
903a7226 260 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
8819fc38
RW
261
262 memcpy(&msg, buf, sizeof(msg));
263 buf += LDP_MSG_SIZE;
264 len -= LDP_MSG_SIZE;
265
266 /* Optional Parameters */
267 while (len > 0) {
268 struct tlv tlv;
269 uint16_t tlv_type;
270 uint16_t tlv_len;
d4afb819 271 uint8_t reserved;
8819fc38
RW
272
273 if (len < sizeof(tlv)) {
274 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
275 return (-1);
276 }
277
278 memcpy(&tlv, buf, TLV_HDR_SIZE);
279 tlv_type = ntohs(tlv.type);
280 tlv_len = ntohs(tlv.length);
281 if (tlv_len + TLV_HDR_SIZE > len) {
282 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
283 return (-1);
284 }
285 buf += TLV_HDR_SIZE;
286 len -= TLV_HDR_SIZE;
287
288 switch (tlv_type) {
d4afb819
RW
289 case TLV_TYPE_TWCARD_CAP:
290 if (tlv_len != CAP_TLV_TWCARD_LEN) {
291 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
292 msg.type);
293 return (-1);
294 }
295
296 if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
297 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
298 msg.type);
299 return (-1);
300 }
301 caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
302
303 memcpy(&reserved, buf, sizeof(reserved));
304 enable = reserved & STATE_BIT;
305 if (enable)
306 nbr->flags |= F_NBR_CAP_TWCARD;
307 else
308 nbr->flags &= ~F_NBR_CAP_TWCARD;
309
903a7226 310 log_debug("%s: lsr-id %pI4 %s the Typed Wildcard FEC capability", __func__, &nbr->id,
d4afb819
RW
311 (enable) ? "announced" : "withdrew");
312 break;
257799cd
RW
313 case TLV_TYPE_UNOTIF_CAP:
314 if (tlv_len != CAP_TLV_UNOTIF_LEN) {
315 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
316 msg.type);
317 return (-1);
318 }
319
320 if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) {
321 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
322 msg.type);
323 return (-1);
324 }
325 caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF;
326
327 memcpy(&reserved, buf, sizeof(reserved));
328 enable = reserved & STATE_BIT;
329 if (enable)
330 nbr->flags |= F_NBR_CAP_UNOTIF;
331 else
332 nbr->flags &= ~F_NBR_CAP_UNOTIF;
333
903a7226
MS
334 log_debug("%s: lsr-id %pI4 %s the Unrecognized Notification capability", __func__,
335 &nbr->id, (enable) ? "announced" :
257799cd
RW
336 "withdrew");
337 break;
8819fc38
RW
338 case TLV_TYPE_DYNAMIC_CAP:
339 /*
340 * RFC 5561 - Section 9:
341 * "An LDP speaker that receives a Capability message
342 * from a peer that includes the Dynamic Capability
343 * Announcement Parameter SHOULD silently ignore the
344 * parameter and process any other Capability Parameters
345 * in the message".
346 */
347 /* FALLTHROUGH */
348 default:
349 if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
350 send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
351 msg.id, msg.type, tlv_type, tlv_len, buf);
352 /* ignore unknown tlv */
353 break;
354 }
355 buf += tlv_len;
356 len -= tlv_len;
357 }
358
359 nbr_fsm(nbr, NBR_EVT_PDU_RCVD);
360
361 return (0);
362}
363
8429abe0
RW
364static int
365gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr)
366{
367 struct sess_prms_tlv parms;
368
369 memset(&parms, 0, sizeof(parms));
370 parms.type = htons(TLV_TYPE_COMMONSESSION);
371 parms.length = htons(SESS_PRMS_LEN);
372 parms.proto_version = htons(LDP_VERSION);
373 parms.keepalive_time = htons(nbr_get_keepalive(nbr->af, nbr->id));
374 parms.reserved = 0;
375 parms.pvlim = 0;
376 parms.max_pdu_len = 0;
377 parms.lsr_id = nbr->id.s_addr;
378 parms.lspace_id = 0;
379
380 return (ibuf_add(buf, &parms, SESS_PRMS_SIZE));
381}
8819fc38
RW
382
383static int
384gen_cap_dynamic_tlv(struct ibuf *buf)
385{
386 struct capability_tlv cap;
387
388 memset(&cap, 0, sizeof(cap));
389 cap.type = htons(TLV_TYPE_DYNAMIC_CAP);
390 cap.length = htons(CAP_TLV_DYNAMIC_LEN);
391 /* the S-bit is always 1 for the Dynamic Capability Announcement */
392 cap.reserved = STATE_BIT;
393
394 return (ibuf_add(buf, &cap, CAP_TLV_DYNAMIC_SIZE));
395}
d4afb819
RW
396
397static int
398gen_cap_twcard_tlv(struct ibuf *buf, int enable)
399{
400 struct capability_tlv cap;
401
402 memset(&cap, 0, sizeof(cap));
403 cap.type = htons(TLV_TYPE_TWCARD_CAP);
404 cap.length = htons(CAP_TLV_TWCARD_LEN);
405 if (enable)
406 cap.reserved = STATE_BIT;
407
408 return (ibuf_add(buf, &cap, CAP_TLV_TWCARD_SIZE));
409}
257799cd
RW
410
411static int
412gen_cap_unotif_tlv(struct ibuf *buf, int enable)
413{
414 struct capability_tlv cap;
415
416 memset(&cap, 0, sizeof(cap));
417 cap.type = htons(TLV_TYPE_UNOTIF_CAP);
418 cap.length = htons(CAP_TLV_UNOTIF_LEN);
419 if (enable)
420 cap.reserved = STATE_BIT;
421
422 return (ibuf_add(buf, &cap, CAP_TLV_UNOTIF_SIZE));
423}