]>
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 %s", inet_ntoa(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 %s", inet_ntoa(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 %s announced the Dynamic "
150 "Capability Announcement capability", __func__
,
153 case TLV_TYPE_TWCARD_CAP
:
154 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
155 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
160 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
161 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
165 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
167 nbr
->flags
|= F_NBR_CAP_TWCARD
;
169 log_debug("%s: lsr-id %s announced the Typed Wildcard "
170 "FEC capability", __func__
, inet_ntoa(nbr
->id
));
172 case TLV_TYPE_UNOTIF_CAP
:
173 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
174 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
179 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
180 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
184 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
186 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
188 log_debug("%s: lsr-id %s announced the Unrecognized "
189 "Notification capability", __func__
,
193 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
194 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
195 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
196 /* ignore unknown tlv */
203 nbr
->keepalive
= min(nbr_get_keepalive(nbr
->af
, nbr
->id
),
204 ntohs(sess
.keepalive_time
));
206 max_pdu_len
= ntohs(sess
.max_pdu_len
);
208 * RFC 5036 - Section 3.5.3:
209 * "A value of 255 or less specifies the default maximum length of
212 if (max_pdu_len
<= 255)
213 max_pdu_len
= LDP_MAX_LEN
;
214 nbr
->max_pdu_len
= min(max_pdu_len
, LDP_MAX_LEN
);
216 nbr_fsm(nbr
, NBR_EVT_INIT_RCVD
);
222 send_capability(struct nbr
*nbr
, uint16_t capability
, int enable
)
228 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(nbr
->id
));
230 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ CAP_TLV_DYNAMIC_SIZE
;
231 if ((buf
= ibuf_open(size
)) == NULL
)
234 err
|= gen_ldp_hdr(buf
, size
);
235 size
-= LDP_HDR_SIZE
;
236 err
|= gen_msg_hdr(buf
, MSG_TYPE_CAPABILITY
, size
);
238 switch (capability
) {
239 case TLV_TYPE_TWCARD_CAP
:
240 err
|= gen_cap_twcard_tlv(buf
, enable
);
242 case TLV_TYPE_UNOTIF_CAP
:
243 err
|= gen_cap_unotif_tlv(buf
, enable
);
245 case TLV_TYPE_DYNAMIC_CAP
:
247 * RFC 5561 - Section 9:
248 * "An LDP speaker MUST NOT include the Dynamic Capability
249 * Announcement Parameter in Capability messages sent to
254 fatalx("send_capability: unsupported capability");
262 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
263 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
264 nbr
->stats
.capability_sent
++;
268 recv_capability(struct nbr
*nbr
, char *buf
, uint16_t len
)
274 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(nbr
->id
));
276 memcpy(&msg
, buf
, sizeof(msg
));
280 /* Optional Parameters */
287 if (len
< sizeof(tlv
)) {
288 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
292 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
293 tlv_type
= ntohs(tlv
.type
);
294 tlv_len
= ntohs(tlv
.length
);
295 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
296 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
303 case TLV_TYPE_TWCARD_CAP
:
304 if (tlv_len
!= CAP_TLV_TWCARD_LEN
) {
305 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
310 if (caps_rcvd
& F_CAP_TLV_RCVD_TWCARD
) {
311 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
315 caps_rcvd
|= F_CAP_TLV_RCVD_TWCARD
;
317 memcpy(&reserved
, buf
, sizeof(reserved
));
318 enable
= reserved
& STATE_BIT
;
320 nbr
->flags
|= F_NBR_CAP_TWCARD
;
322 nbr
->flags
&= ~F_NBR_CAP_TWCARD
;
324 log_debug("%s: lsr-id %s %s the Typed Wildcard FEC "
325 "capability", __func__
, inet_ntoa(nbr
->id
),
326 (enable
) ? "announced" : "withdrew");
328 case TLV_TYPE_UNOTIF_CAP
:
329 if (tlv_len
!= CAP_TLV_UNOTIF_LEN
) {
330 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
335 if (caps_rcvd
& F_CAP_TLV_RCVD_UNOTIF
) {
336 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
340 caps_rcvd
|= F_CAP_TLV_RCVD_UNOTIF
;
342 memcpy(&reserved
, buf
, sizeof(reserved
));
343 enable
= reserved
& STATE_BIT
;
345 nbr
->flags
|= F_NBR_CAP_UNOTIF
;
347 nbr
->flags
&= ~F_NBR_CAP_UNOTIF
;
349 log_debug("%s: lsr-id %s %s the Unrecognized "
350 "Notification capability", __func__
,
351 inet_ntoa(nbr
->id
), (enable
) ? "announced" :
354 case TLV_TYPE_DYNAMIC_CAP
:
356 * RFC 5561 - Section 9:
357 * "An LDP speaker that receives a Capability message
358 * from a peer that includes the Dynamic Capability
359 * Announcement Parameter SHOULD silently ignore the
360 * parameter and process any other Capability Parameters
365 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
366 send_notification_rtlvs(nbr
, S_UNSSUPORTDCAP
,
367 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
368 /* ignore unknown tlv */
375 nbr_fsm(nbr
, NBR_EVT_PDU_RCVD
);
381 gen_init_prms_tlv(struct ibuf
*buf
, struct nbr
*nbr
)
383 struct sess_prms_tlv parms
;
385 memset(&parms
, 0, sizeof(parms
));
386 parms
.type
= htons(TLV_TYPE_COMMONSESSION
);
387 parms
.length
= htons(SESS_PRMS_LEN
);
388 parms
.proto_version
= htons(LDP_VERSION
);
389 parms
.keepalive_time
= htons(nbr_get_keepalive(nbr
->af
, nbr
->id
));
392 parms
.max_pdu_len
= 0;
393 parms
.lsr_id
= nbr
->id
.s_addr
;
396 return (ibuf_add(buf
, &parms
, SESS_PRMS_SIZE
));
400 gen_cap_dynamic_tlv(struct ibuf
*buf
)
402 struct capability_tlv cap
;
404 memset(&cap
, 0, sizeof(cap
));
405 cap
.type
= htons(TLV_TYPE_DYNAMIC_CAP
);
406 cap
.length
= htons(CAP_TLV_DYNAMIC_LEN
);
407 /* the S-bit is always 1 for the Dynamic Capability Announcement */
408 cap
.reserved
= STATE_BIT
;
410 return (ibuf_add(buf
, &cap
, CAP_TLV_DYNAMIC_SIZE
));
414 gen_cap_twcard_tlv(struct ibuf
*buf
, int enable
)
416 struct capability_tlv cap
;
418 memset(&cap
, 0, sizeof(cap
));
419 cap
.type
= htons(TLV_TYPE_TWCARD_CAP
);
420 cap
.length
= htons(CAP_TLV_TWCARD_LEN
);
422 cap
.reserved
= STATE_BIT
;
424 return (ibuf_add(buf
, &cap
, CAP_TLV_TWCARD_SIZE
));
428 gen_cap_unotif_tlv(struct ibuf
*buf
, int enable
)
430 struct capability_tlv cap
;
432 memset(&cap
, 0, sizeof(cap
));
433 cap
.type
= htons(TLV_TYPE_UNOTIF_CAP
);
434 cap
.length
= htons(CAP_TLV_UNOTIF_LEN
);
436 cap
.reserved
= STATE_BIT
;
438 return (ibuf_add(buf
, &cap
, CAP_TLV_UNOTIF_SIZE
));