]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/init.c
1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
13 #include "ldp_debug.h"
15 static int gen_init_prms_tlv(struct ibuf
*, struct nbr
*);
16 static int gen_cap_dynamic_tlv(struct ibuf
*);
17 static int gen_cap_twcard_tlv(struct ibuf
*, int);
18 static int gen_cap_unotif_tlv(struct ibuf
*, int);
21 send_init(struct nbr
*nbr
)
27 debug_msg_send("initialization: lsr-id %pI4", &nbr
->id
);
29 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ SESS_PRMS_SIZE
+
30 CAP_TLV_DYNAMIC_SIZE
+ CAP_TLV_TWCARD_SIZE
+ CAP_TLV_UNOTIF_SIZE
;
31 if ((buf
= ibuf_open(size
)) == NULL
)
34 err
|= gen_ldp_hdr(buf
, size
);
36 err
|= gen_msg_hdr(buf
, MSG_TYPE_INIT
, size
);
37 err
|= gen_init_prms_tlv(buf
, nbr
);
38 err
|= gen_cap_dynamic_tlv(buf
);
39 err
|= gen_cap_twcard_tlv(buf
, 1);
40 err
|= gen_cap_unotif_tlv(buf
, 1);
46 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
50 recv_init(struct nbr
*nbr
, char *buf
, uint16_t len
)
53 struct sess_prms_tlv sess
;
57 debug_msg_recv("initialization: lsr-id %pI4", &nbr
->id
);
59 memcpy(&msg
, buf
, sizeof(msg
));
63 if (len
< SESS_PRMS_SIZE
) {
64 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
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
);
72 if (ntohs(sess
.proto_version
) != LDP_VERSION
) {
73 session_shutdown(nbr
, S_BAD_PROTO_VER
, msg
.id
, msg
.type
);
76 if (ntohs(sess
.keepalive_time
) < MIN_KEEPALIVE
) {
77 session_shutdown(nbr
, S_KEEPALIVE_BAD
, msg
.id
, msg
.type
);
80 if (sess
.lsr_id
!= ldp_rtr_id_get(leconf
) ||
81 ntohs(sess
.lspace_id
) != 0) {
82 session_shutdown(nbr
, S_NO_HELLO
, msg
.id
, msg
.type
);
86 buf
+= SESS_PRMS_SIZE
;
87 len
-= SESS_PRMS_SIZE
;
89 /* Optional Parameters */
95 if (len
< sizeof(tlv
)) {
96 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
100 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
101 tlv_type
= ntohs(tlv
.type
);
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
);
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".
116 case TLV_TYPE_ATMSESSIONPAR
:
117 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
119 case TLV_TYPE_FRSESSION
:
120 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
122 case TLV_TYPE_DYNAMIC_CAP
:
123 if (tlv_len
!= CAP_TLV_DYNAMIC_LEN
) {
124 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
129 if (caps_rcvd
& F_CAP_TLV_RCVD_DYNAMIC
) {
130 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
134 caps_rcvd
|= F_CAP_TLV_RCVD_DYNAMIC
;
136 nbr
->flags
|= F_NBR_CAP_DYNAMIC
;
138 log_debug("%s: lsr-id %pI4 announced the Dynamic Capability Announcement capability", __func__
,
141 case TLV_TYPE_TWCARD_CAP
:
142 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
143 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
148 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
149 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
153 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
155 nbr
->flags
|= F_NBR_CAP_TWCARD
;
157 log_debug("%s: lsr-id %pI4 announced the Typed Wildcard FEC capability", __func__
, &nbr
->id
);
159 case TLV_TYPE_UNOTIF_CAP
:
160 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
161 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
166 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
167 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
171 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
173 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
175 log_debug("%s: lsr-id %pI4 announced the Unrecognized Notification capability", __func__
,
179 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
180 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
181 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
182 /* ignore unknown tlv */
189 nbr
->keepalive
= MIN(nbr_get_keepalive(nbr
->af
, nbr
->id
),
190 ntohs(sess
.keepalive_time
));
192 max_pdu_len
= ntohs(sess
.max_pdu_len
);
194 * RFC 5036 - Section 3.5.3:
195 * "A value of 255 or less specifies the default maximum length of
198 if (max_pdu_len
<= 255)
199 max_pdu_len
= LDP_MAX_LEN
;
200 nbr
->max_pdu_len
= MIN(max_pdu_len
, LDP_MAX_LEN
);
202 nbr_fsm(nbr
, NBR_EVT_INIT_RCVD
);
208 send_capability(struct nbr
*nbr
, uint16_t capability
, int enable
)
214 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
216 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ CAP_TLV_DYNAMIC_SIZE
;
217 if ((buf
= ibuf_open(size
)) == NULL
)
220 err
|= gen_ldp_hdr(buf
, size
);
221 size
-= LDP_HDR_SIZE
;
222 err
|= gen_msg_hdr(buf
, MSG_TYPE_CAPABILITY
, size
);
224 switch (capability
) {
225 case TLV_TYPE_TWCARD_CAP
:
226 err
|= gen_cap_twcard_tlv(buf
, enable
);
228 case TLV_TYPE_UNOTIF_CAP
:
229 err
|= gen_cap_unotif_tlv(buf
, enable
);
231 case TLV_TYPE_DYNAMIC_CAP
:
233 * RFC 5561 - Section 9:
234 * "An LDP speaker MUST NOT include the Dynamic Capability
235 * Announcement Parameter in Capability messages sent to
240 fatalx("send_capability: unsupported capability");
248 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
249 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
250 nbr
->stats
.capability_sent
++;
254 recv_capability(struct nbr
*nbr
, char *buf
, uint16_t len
)
260 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
262 memcpy(&msg
, buf
, sizeof(msg
));
266 /* Optional Parameters */
273 if (len
< sizeof(tlv
)) {
274 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
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
);
289 case TLV_TYPE_TWCARD_CAP
:
290 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
291 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
296 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
297 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
301 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
303 memcpy(&reserved
, buf
, sizeof(reserved
));
304 enable
= reserved
& STATE_BIT
;
306 nbr
->flags
|= F_NBR_CAP_TWCARD
;
308 nbr
->flags
&= ~F_NBR_CAP_TWCARD
;
310 log_debug("%s: lsr-id %pI4 %s the Typed Wildcard FEC capability", __func__
, &nbr
->id
,
311 (enable
) ? "announced" : "withdrew");
313 case TLV_TYPE_UNOTIF_CAP
:
314 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
315 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
320 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
321 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
325 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
327 memcpy(&reserved
, buf
, sizeof(reserved
));
328 enable
= reserved
& STATE_BIT
;
330 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
332 nbr
->flags
&= ~F_NBR_CAP_UNOTIF
;
334 log_debug("%s: lsr-id %pI4 %s the Unrecognized Notification capability", __func__
,
335 &nbr
->id
, (enable
) ? "announced" :
338 case TLV_TYPE_DYNAMIC_CAP
:
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
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 */
359 nbr_fsm(nbr
, NBR_EVT_PDU_RCVD
);
365 gen_init_prms_tlv(struct ibuf
*buf
, struct nbr
*nbr
)
367 struct sess_prms_tlv parms
;
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
));
376 parms
.max_pdu_len
= 0;
377 parms
.lsr_id
= nbr
->id
.s_addr
;
380 return (ibuf_add(buf
, &parms
, SESS_PRMS_SIZE
));
384 gen_cap_dynamic_tlv(struct ibuf
*buf
)
386 struct capability_tlv cap
;
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
;
394 return (ibuf_add(buf
, &cap
, CAP_TLV_DYNAMIC_SIZE
));
398 gen_cap_twcard_tlv(struct ibuf
*buf
, int enable
)
400 struct capability_tlv cap
;
402 memset(&cap
, 0, sizeof(cap
));
403 cap
.type
= htons(TLV_TYPE_TWCARD_CAP
);
404 cap
.length
= htons(CAP_TLV_TWCARD_LEN
);
406 cap
.reserved
= STATE_BIT
;
408 return (ibuf_add(buf
, &cap
, CAP_TLV_TWCARD_SIZE
));
412 gen_cap_unotif_tlv(struct ibuf
*buf
, int enable
)
414 struct capability_tlv cap
;
416 memset(&cap
, 0, sizeof(cap
));
417 cap
.type
= htons(TLV_TYPE_UNOTIF_CAP
);
418 cap
.length
= htons(CAP_TLV_UNOTIF_LEN
);
420 cap
.reserved
= STATE_BIT
;
422 return (ibuf_add(buf
, &cap
, CAP_TLV_UNOTIF_SIZE
));