]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/init.c
4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #include "ldp_debug.h"
26 static int gen_init_prms_tlv(struct ibuf
*, struct nbr
*);
27 static int gen_cap_dynamic_tlv(struct ibuf
*);
28 static int gen_cap_twcard_tlv(struct ibuf
*, int);
29 static int gen_cap_unotif_tlv(struct ibuf
*, int);
32 send_init(struct nbr
*nbr
)
38 debug_msg_send("initialization: lsr-id %pI4", &nbr
->id
);
40 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ SESS_PRMS_SIZE
+
41 CAP_TLV_DYNAMIC_SIZE
+ CAP_TLV_TWCARD_SIZE
+ CAP_TLV_UNOTIF_SIZE
;
42 if ((buf
= ibuf_open(size
)) == NULL
)
45 err
|= gen_ldp_hdr(buf
, size
);
47 err
|= gen_msg_hdr(buf
, MSG_TYPE_INIT
, size
);
48 err
|= gen_init_prms_tlv(buf
, nbr
);
49 err
|= gen_cap_dynamic_tlv(buf
);
50 err
|= gen_cap_twcard_tlv(buf
, 1);
51 err
|= gen_cap_unotif_tlv(buf
, 1);
57 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
61 recv_init(struct nbr
*nbr
, char *buf
, uint16_t len
)
64 struct sess_prms_tlv sess
;
68 debug_msg_recv("initialization: lsr-id %pI4", &nbr
->id
);
70 memcpy(&msg
, buf
, sizeof(msg
));
74 if (len
< SESS_PRMS_SIZE
) {
75 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
78 memcpy(&sess
, buf
, sizeof(sess
));
79 if (ntohs(sess
.length
) != SESS_PRMS_LEN
) {
80 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
83 if (ntohs(sess
.proto_version
) != LDP_VERSION
) {
84 session_shutdown(nbr
, S_BAD_PROTO_VER
, msg
.id
, msg
.type
);
87 if (ntohs(sess
.keepalive_time
) < MIN_KEEPALIVE
) {
88 session_shutdown(nbr
, S_KEEPALIVE_BAD
, msg
.id
, msg
.type
);
91 if (sess
.lsr_id
!= ldp_rtr_id_get(leconf
) ||
92 ntohs(sess
.lspace_id
) != 0) {
93 session_shutdown(nbr
, S_NO_HELLO
, msg
.id
, msg
.type
);
97 buf
+= SESS_PRMS_SIZE
;
98 len
-= SESS_PRMS_SIZE
;
100 /* Optional Parameters */
106 if (len
< sizeof(tlv
)) {
107 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
111 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
112 tlv_type
= ntohs(tlv
.type
);
113 tlv_len
= ntohs(tlv
.length
);
114 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
115 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
122 * RFC 5561 - Section 6:
123 * "The S-bit of a Capability Parameter in an Initialization
124 * message MUST be 1 and SHOULD be ignored on receipt".
127 case TLV_TYPE_ATMSESSIONPAR
:
128 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
130 case TLV_TYPE_FRSESSION
:
131 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
133 case TLV_TYPE_DYNAMIC_CAP
:
134 if (tlv_len
!= CAP_TLV_DYNAMIC_LEN
) {
135 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
140 if (caps_rcvd
& F_CAP_TLV_RCVD_DYNAMIC
) {
141 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
145 caps_rcvd
|= F_CAP_TLV_RCVD_DYNAMIC
;
147 nbr
->flags
|= F_NBR_CAP_DYNAMIC
;
149 log_debug("%s: lsr-id %pI4 announced the Dynamic Capability Announcement capability", __func__
,
152 case TLV_TYPE_TWCARD_CAP
:
153 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
154 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
159 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
160 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
164 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
166 nbr
->flags
|= F_NBR_CAP_TWCARD
;
168 log_debug("%s: lsr-id %pI4 announced the Typed Wildcard FEC capability", __func__
, &nbr
->id
);
170 case TLV_TYPE_UNOTIF_CAP
:
171 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
172 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
177 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
178 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
182 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
184 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
186 log_debug("%s: lsr-id %pI4 announced the Unrecognized Notification capability", __func__
,
190 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
191 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
192 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
193 /* ignore unknown tlv */
200 nbr
->keepalive
= MIN(nbr_get_keepalive(nbr
->af
, nbr
->id
),
201 ntohs(sess
.keepalive_time
));
203 max_pdu_len
= ntohs(sess
.max_pdu_len
);
205 * RFC 5036 - Section 3.5.3:
206 * "A value of 255 or less specifies the default maximum length of
209 if (max_pdu_len
<= 255)
210 max_pdu_len
= LDP_MAX_LEN
;
211 nbr
->max_pdu_len
= MIN(max_pdu_len
, LDP_MAX_LEN
);
213 nbr_fsm(nbr
, NBR_EVT_INIT_RCVD
);
219 send_capability(struct nbr
*nbr
, uint16_t capability
, int enable
)
225 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
227 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ CAP_TLV_DYNAMIC_SIZE
;
228 if ((buf
= ibuf_open(size
)) == NULL
)
231 err
|= gen_ldp_hdr(buf
, size
);
232 size
-= LDP_HDR_SIZE
;
233 err
|= gen_msg_hdr(buf
, MSG_TYPE_CAPABILITY
, size
);
235 switch (capability
) {
236 case TLV_TYPE_TWCARD_CAP
:
237 err
|= gen_cap_twcard_tlv(buf
, enable
);
239 case TLV_TYPE_UNOTIF_CAP
:
240 err
|= gen_cap_unotif_tlv(buf
, enable
);
242 case TLV_TYPE_DYNAMIC_CAP
:
244 * RFC 5561 - Section 9:
245 * "An LDP speaker MUST NOT include the Dynamic Capability
246 * Announcement Parameter in Capability messages sent to
251 fatalx("send_capability: unsupported capability");
259 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
260 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
261 nbr
->stats
.capability_sent
++;
265 recv_capability(struct nbr
*nbr
, char *buf
, uint16_t len
)
271 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
273 memcpy(&msg
, buf
, sizeof(msg
));
277 /* Optional Parameters */
284 if (len
< sizeof(tlv
)) {
285 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
289 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
290 tlv_type
= ntohs(tlv
.type
);
291 tlv_len
= ntohs(tlv
.length
);
292 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
293 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
300 case TLV_TYPE_TWCARD_CAP
:
301 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
302 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
307 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
308 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
312 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
314 memcpy(&reserved
, buf
, sizeof(reserved
));
315 enable
= reserved
& STATE_BIT
;
317 nbr
->flags
|= F_NBR_CAP_TWCARD
;
319 nbr
->flags
&= ~F_NBR_CAP_TWCARD
;
321 log_debug("%s: lsr-id %pI4 %s the Typed Wildcard FEC capability", __func__
, &nbr
->id
,
322 (enable
) ? "announced" : "withdrew");
324 case TLV_TYPE_UNOTIF_CAP
:
325 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
326 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
331 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
332 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
336 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
338 memcpy(&reserved
, buf
, sizeof(reserved
));
339 enable
= reserved
& STATE_BIT
;
341 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
343 nbr
->flags
&= ~F_NBR_CAP_UNOTIF
;
345 log_debug("%s: lsr-id %pI4 %s the Unrecognized Notification capability", __func__
,
346 &nbr
->id
, (enable
) ? "announced" :
349 case TLV_TYPE_DYNAMIC_CAP
:
351 * RFC 5561 - Section 9:
352 * "An LDP speaker that receives a Capability message
353 * from a peer that includes the Dynamic Capability
354 * Announcement Parameter SHOULD silently ignore the
355 * parameter and process any other Capability Parameters
360 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
361 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
362 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
363 /* ignore unknown tlv */
370 nbr_fsm(nbr
, NBR_EVT_PDU_RCVD
);
376 gen_init_prms_tlv(struct ibuf
*buf
, struct nbr
*nbr
)
378 struct sess_prms_tlv parms
;
380 memset(&parms
, 0, sizeof(parms
));
381 parms
.type
= htons(TLV_TYPE_COMMONSESSION
);
382 parms
.length
= htons(SESS_PRMS_LEN
);
383 parms
.proto_version
= htons(LDP_VERSION
);
384 parms
.keepalive_time
= htons(nbr_get_keepalive(nbr
->af
, nbr
->id
));
387 parms
.max_pdu_len
= 0;
388 parms
.lsr_id
= nbr
->id
.s_addr
;
391 return (ibuf_add(buf
, &parms
, SESS_PRMS_SIZE
));
395 gen_cap_dynamic_tlv(struct ibuf
*buf
)
397 struct capability_tlv cap
;
399 memset(&cap
, 0, sizeof(cap
));
400 cap
.type
= htons(TLV_TYPE_DYNAMIC_CAP
);
401 cap
.length
= htons(CAP_TLV_DYNAMIC_LEN
);
402 /* the S-bit is always 1 for the Dynamic Capability Announcement */
403 cap
.reserved
= STATE_BIT
;
405 return (ibuf_add(buf
, &cap
, CAP_TLV_DYNAMIC_SIZE
));
409 gen_cap_twcard_tlv(struct ibuf
*buf
, int enable
)
411 struct capability_tlv cap
;
413 memset(&cap
, 0, sizeof(cap
));
414 cap
.type
= htons(TLV_TYPE_TWCARD_CAP
);
415 cap
.length
= htons(CAP_TLV_TWCARD_LEN
);
417 cap
.reserved
= STATE_BIT
;
419 return (ibuf_add(buf
, &cap
, CAP_TLV_TWCARD_SIZE
));
423 gen_cap_unotif_tlv(struct ibuf
*buf
, int enable
)
425 struct capability_tlv cap
;
427 memset(&cap
, 0, sizeof(cap
));
428 cap
.type
= htons(TLV_TYPE_UNOTIF_CAP
);
429 cap
.length
= htons(CAP_TLV_UNOTIF_LEN
);
431 cap
.reserved
= STATE_BIT
;
433 return (ibuf_add(buf
, &cap
, CAP_TLV_UNOTIF_SIZE
));