]>
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);
31 send_init(struct nbr
*nbr
)
37 debug_msg_send("initialization: lsr-id %s", inet_ntoa(nbr
->id
));
39 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ SESS_PRMS_SIZE
+
40 CAP_TLV_DYNAMIC_SIZE
+ CAP_TLV_TWCARD_SIZE
;
41 if ((buf
= ibuf_open(size
)) == NULL
)
44 err
|= gen_ldp_hdr(buf
, size
);
46 err
|= gen_msg_hdr(buf
, MSG_TYPE_INIT
, size
);
47 err
|= gen_init_prms_tlv(buf
, nbr
);
48 err
|= gen_cap_dynamic_tlv(buf
);
49 err
|= gen_cap_twcard_tlv(buf
, 1);
55 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
59 recv_init(struct nbr
*nbr
, char *buf
, uint16_t len
)
62 struct sess_prms_tlv sess
;
66 debug_msg_recv("initialization: lsr-id %s", inet_ntoa(nbr
->id
));
68 memcpy(&msg
, buf
, sizeof(msg
));
72 if (len
< SESS_PRMS_SIZE
) {
73 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
76 memcpy(&sess
, buf
, sizeof(sess
));
77 if (ntohs(sess
.length
) != SESS_PRMS_LEN
) {
78 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
81 if (ntohs(sess
.proto_version
) != LDP_VERSION
) {
82 session_shutdown(nbr
, S_BAD_PROTO_VER
, msg
.id
, msg
.type
);
85 if (ntohs(sess
.keepalive_time
) < MIN_KEEPALIVE
) {
86 session_shutdown(nbr
, S_KEEPALIVE_BAD
, msg
.id
, msg
.type
);
89 if (sess
.lsr_id
!= ldp_rtr_id_get(leconf
) ||
90 ntohs(sess
.lspace_id
) != 0) {
91 session_shutdown(nbr
, S_NO_HELLO
, msg
.id
, msg
.type
);
95 buf
+= SESS_PRMS_SIZE
;
96 len
-= SESS_PRMS_SIZE
;
98 /* Optional Parameters */
104 if (len
< sizeof(tlv
)) {
105 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
109 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
110 tlv_type
= ntohs(tlv
.type
);
111 tlv_len
= ntohs(tlv
.length
);
112 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
113 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
120 * RFC 5561 - Section 6:
121 * "The S-bit of a Capability Parameter in an Initialization
122 * message MUST be 1 and SHOULD be ignored on receipt".
125 case TLV_TYPE_ATMSESSIONPAR
:
126 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
128 case TLV_TYPE_FRSESSION
:
129 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
131 case TLV_TYPE_DYNAMIC_CAP
:
132 if (tlv_len
!= CAP_TLV_DYNAMIC_LEN
) {
133 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
138 if (caps_rcvd
& F_CAP_TLV_RCVD_DYNAMIC
) {
139 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
143 caps_rcvd
|= F_CAP_TLV_RCVD_DYNAMIC
;
145 nbr
->flags
|= F_NBR_CAP_DYNAMIC
;
147 log_debug("%s: lsr-id %s announced the Dynamic "
148 "Capability Announcement capability", __func__
,
151 case TLV_TYPE_TWCARD_CAP
:
152 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
153 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
158 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
159 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
163 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
165 nbr
->flags
|= F_NBR_CAP_TWCARD
;
167 log_debug("%s: lsr-id %s announced the Typed Wildcard "
168 "FEC capability", __func__
, inet_ntoa(nbr
->id
));
171 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
172 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
173 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
174 /* ignore unknown tlv */
181 nbr
->keepalive
= min(nbr_get_keepalive(nbr
->af
, nbr
->id
),
182 ntohs(sess
.keepalive_time
));
184 max_pdu_len
= ntohs(sess
.max_pdu_len
);
186 * RFC 5036 - Section 3.5.3:
187 * "A value of 255 or less specifies the default maximum length of
190 if (max_pdu_len
<= 255)
191 max_pdu_len
= LDP_MAX_LEN
;
192 nbr
->max_pdu_len
= min(max_pdu_len
, LDP_MAX_LEN
);
194 nbr_fsm(nbr
, NBR_EVT_INIT_RCVD
);
200 send_capability(struct nbr
*nbr
, uint16_t capability
, int enable
)
206 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(nbr
->id
));
208 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ CAP_TLV_DYNAMIC_SIZE
;
209 if ((buf
= ibuf_open(size
)) == NULL
)
212 err
|= gen_ldp_hdr(buf
, size
);
213 size
-= LDP_HDR_SIZE
;
214 err
|= gen_msg_hdr(buf
, MSG_TYPE_CAPABILITY
, size
);
216 switch (capability
) {
217 case TLV_TYPE_TWCARD_CAP
:
218 err
|= gen_cap_twcard_tlv(buf
, enable
);
220 case TLV_TYPE_DYNAMIC_CAP
:
222 * RFC 5561 - Section 9:
223 * "An LDP speaker MUST NOT include the Dynamic Capability
224 * Announcement Parameter in Capability messages sent to
229 fatalx("send_capability: unsupported capability");
237 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
238 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
242 recv_capability(struct nbr
*nbr
, char *buf
, uint16_t len
)
248 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(nbr
->id
));
250 memcpy(&msg
, buf
, sizeof(msg
));
254 /* Optional Parameters */
261 if (len
< sizeof(tlv
)) {
262 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
266 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
267 tlv_type
= ntohs(tlv
.type
);
268 tlv_len
= ntohs(tlv
.length
);
269 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
270 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
277 case TLV_TYPE_TWCARD_CAP
:
278 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
279 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
284 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
285 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
289 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
291 memcpy(&reserved
, buf
, sizeof(reserved
));
292 enable
= reserved
& STATE_BIT
;
294 nbr
->flags
|= F_NBR_CAP_TWCARD
;
296 nbr
->flags
&= ~F_NBR_CAP_TWCARD
;
298 log_debug("%s: lsr-id %s %s the Typed Wildcard FEC "
299 "capability", __func__
, inet_ntoa(nbr
->id
),
300 (enable
) ? "announced" : "withdrew");
302 case TLV_TYPE_DYNAMIC_CAP
:
304 * RFC 5561 - Section 9:
305 * "An LDP speaker that receives a Capability message
306 * from a peer that includes the Dynamic Capability
307 * Announcement Parameter SHOULD silently ignore the
308 * parameter and process any other Capability Parameters
313 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
314 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
315 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
316 /* ignore unknown tlv */
323 nbr_fsm(nbr
, NBR_EVT_PDU_RCVD
);
329 gen_init_prms_tlv(struct ibuf
*buf
, struct nbr
*nbr
)
331 struct sess_prms_tlv parms
;
333 memset(&parms
, 0, sizeof(parms
));
334 parms
.type
= htons(TLV_TYPE_COMMONSESSION
);
335 parms
.length
= htons(SESS_PRMS_LEN
);
336 parms
.proto_version
= htons(LDP_VERSION
);
337 parms
.keepalive_time
= htons(nbr_get_keepalive(nbr
->af
, nbr
->id
));
340 parms
.max_pdu_len
= 0;
341 parms
.lsr_id
= nbr
->id
.s_addr
;
344 return (ibuf_add(buf
, &parms
, SESS_PRMS_SIZE
));
348 gen_cap_dynamic_tlv(struct ibuf
*buf
)
350 struct capability_tlv cap
;
352 memset(&cap
, 0, sizeof(cap
));
353 cap
.type
= htons(TLV_TYPE_DYNAMIC_CAP
);
354 cap
.length
= htons(CAP_TLV_DYNAMIC_LEN
);
355 /* the S-bit is always 1 for the Dynamic Capability Announcement */
356 cap
.reserved
= STATE_BIT
;
358 return (ibuf_add(buf
, &cap
, CAP_TLV_DYNAMIC_SIZE
));
362 gen_cap_twcard_tlv(struct ibuf
*buf
, int enable
)
364 struct capability_tlv cap
;
366 memset(&cap
, 0, sizeof(cap
));
367 cap
.type
= htons(TLV_TYPE_TWCARD_CAP
);
368 cap
.length
= htons(CAP_TLV_TWCARD_LEN
);
370 cap
.reserved
= STATE_BIT
;
372 return (ibuf_add(buf
, &cap
, CAP_TLV_TWCARD_SIZE
));