4 * Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include "ldp_debug.h"
29 static void enqueue_pdu(struct nbr
*, uint16_t, struct ibuf
*, uint16_t);
30 static int gen_label_tlv(struct ibuf
*, uint32_t);
31 static int gen_reqid_tlv(struct ibuf
*, uint32_t);
32 static void log_msg_mapping(int, uint16_t, struct nbr
*, struct map
*);
35 enqueue_pdu(struct nbr
*nbr
, uint16_t type
, struct ibuf
*buf
, uint16_t size
)
37 struct ldp_hdr
*ldp_hdr
;
39 ldp_hdr
= ibuf_seek(buf
, 0, sizeof(struct ldp_hdr
));
40 ldp_hdr
->length
= htons(size
);
41 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
44 /* Generic function that handles all Label Message types */
46 send_labelmessage(struct nbr
*nbr
, uint16_t type
, struct mapping_head
*mh
)
48 struct ibuf
*buf
= NULL
;
49 struct mapping_entry
*me
;
50 uint16_t msg_size
, size
= 0;
58 while ((me
= TAILQ_FIRST(mh
)) != NULL
) {
61 if ((buf
= ibuf_open(nbr
->max_pdu_len
+
62 LDP_HDR_DEAD_LEN
)) == NULL
)
65 /* real size will be set up later */
66 err
|= gen_ldp_hdr(buf
, 0);
68 size
= LDP_HDR_PDU_LEN
;
73 msg_size
= LDP_MSG_SIZE
;
74 msg_size
+= len_fec_tlv(&me
->map
);
75 if (me
->map
.label
!= NO_LABEL
)
76 msg_size
+= LABEL_TLV_SIZE
;
77 if (me
->map
.flags
& F_MAP_REQ_ID
)
78 msg_size
+= REQID_TLV_SIZE
;
79 if (me
->map
.flags
& F_MAP_STATUS
)
80 msg_size
+= STATUS_SIZE
;
82 /* maximum pdu length exceeded, we need a new ldp pdu */
83 if (size
+ msg_size
> nbr
->max_pdu_len
) {
84 enqueue_pdu(nbr
, type
, buf
, size
);
91 /* append message and tlvs */
92 err
|= gen_msg_hdr(buf
, type
, msg_size
);
93 err
|= gen_fec_tlv(buf
, &me
->map
);
94 if (me
->map
.label
!= NO_LABEL
)
95 err
|= gen_label_tlv(buf
, me
->map
.label
);
96 if (me
->map
.flags
& F_MAP_REQ_ID
)
97 err
|= gen_reqid_tlv(buf
, me
->map
.requestid
);
98 if (me
->map
.flags
& F_MAP_PW_STATUS
)
99 err
|= gen_pw_status_tlv(buf
, me
->map
.pw_status
);
100 if (me
->map
.flags
& F_MAP_STATUS
)
101 err
|= gen_status_tlv(buf
, me
->map
.st
.status_code
,
102 me
->map
.st
.msg_id
, me
->map
.st
.msg_type
);
105 mapping_list_clr(mh
);
109 log_msg_mapping(1, type
, nbr
, &me
->map
);
111 /* no errors - update per neighbor message counters */
113 case MSG_TYPE_LABELMAPPING
:
114 nbr
->stats
.labelmap_sent
++;
116 case MSG_TYPE_LABELREQUEST
:
117 nbr
->stats
.labelreq_sent
++;
119 case MSG_TYPE_LABELWITHDRAW
:
120 nbr
->stats
.labelwdraw_sent
++;
122 case MSG_TYPE_LABELRELEASE
:
123 nbr
->stats
.labelrel_sent
++;
125 case MSG_TYPE_LABELABORTREQ
:
126 nbr
->stats
.labelabreq_sent
++;
132 TAILQ_REMOVE(mh
, me
, entry
);
133 assert(me
!= TAILQ_FIRST(mh
));
137 enqueue_pdu(nbr
, type
, buf
, size
);
139 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
142 /* Generic function that handles all Label Message types */
144 recv_labelmessage(struct nbr
*nbr
, char *buf
, uint16_t len
, uint16_t type
)
148 uint32_t label
= NO_LABEL
, reqid
= 0;
149 uint32_t pw_status
= 0;
152 uint16_t current_tlv
= 1;
153 struct mapping_entry
*me
;
154 struct mapping_head mh
;
157 memcpy(&msg
, buf
, sizeof(msg
));
162 if (len
< sizeof(ft
)) {
163 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
167 memcpy(&ft
, buf
, sizeof(ft
));
168 if (ntohs(ft
.type
) != TLV_TYPE_FEC
) {
169 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
, msg
.type
);
172 feclen
= ntohs(ft
.length
);
173 if (feclen
> len
- TLV_HDR_SIZE
) {
174 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
178 buf
+= TLV_HDR_SIZE
; /* just advance to the end of the fec header */
183 memset(&map
, 0, sizeof(map
));
186 if ((tlen
= tlv_decode_fec_elm(nbr
, &msg
, buf
, feclen
,
189 if (map
.type
== MAP_TYPE_PWID
&&
190 !(map
.flags
& F_MAP_PW_ID
) &&
191 type
!= MSG_TYPE_LABELWITHDRAW
&&
192 type
!= MSG_TYPE_LABELRELEASE
) {
193 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
,
199 * The Wildcard FEC Element can be used only in the
200 * Label Withdraw and Label Release messages.
202 if (map
.type
== MAP_TYPE_WILDCARD
) {
204 case MSG_TYPE_LABELMAPPING
:
205 case MSG_TYPE_LABELREQUEST
:
206 case MSG_TYPE_LABELABORTREQ
:
207 session_shutdown(nbr
, S_UNKNOWN_FEC
, msg
.id
,
216 * RFC 5561 - Section 4:
217 * "An LDP implementation that supports the Typed Wildcard
218 * FEC Element MUST support its use in Label Request, Label
219 * Withdraw, and Label Release messages".
221 if (map
.type
== MAP_TYPE_TYPED_WCARD
) {
223 case MSG_TYPE_LABELMAPPING
:
224 case MSG_TYPE_LABELABORTREQ
:
225 session_shutdown(nbr
, S_UNKNOWN_FEC
, msg
.id
,
234 * LDP supports the use of multiple FEC Elements per
235 * FEC for the Label Mapping message only.
237 if (type
!= MSG_TYPE_LABELMAPPING
&&
239 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
243 mapping_list_add(&mh
, &map
);
248 } while (feclen
> 0);
250 /* Optional Parameters */
255 uint32_t reqbuf
, labelbuf
, statusbuf
;
257 if (len
< sizeof(tlv
)) {
258 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
262 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
263 tlv_type
= ntohs(tlv
.type
);
264 tlv_len
= ntohs(tlv
.length
);
265 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
266 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
273 * For Label Mapping messages the Label TLV is mandatory and
274 * should appear right after the FEC TLV.
276 if (current_tlv
== 1 && type
== MSG_TYPE_LABELMAPPING
&&
277 !(tlv_type
& TLV_TYPE_GENERICLABEL
)) {
278 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
,
284 case TLV_TYPE_LABELREQUEST
:
286 case MSG_TYPE_LABELMAPPING
:
287 case MSG_TYPE_LABELREQUEST
:
288 if (tlv_len
!= REQID_TLV_LEN
) {
289 session_shutdown(nbr
, S_BAD_TLV_LEN
,
294 flags
|= F_MAP_REQ_ID
;
295 memcpy(&reqbuf
, buf
, sizeof(reqbuf
));
296 reqid
= ntohl(reqbuf
);
303 case TLV_TYPE_HOPCOUNT
:
304 case TLV_TYPE_PATHVECTOR
:
307 case TLV_TYPE_GENERICLABEL
:
309 case MSG_TYPE_LABELMAPPING
:
310 case MSG_TYPE_LABELWITHDRAW
:
311 case MSG_TYPE_LABELRELEASE
:
312 if (tlv_len
!= LABEL_TLV_LEN
) {
313 session_shutdown(nbr
, S_BAD_TLV_LEN
,
318 memcpy(&labelbuf
, buf
, sizeof(labelbuf
));
319 label
= ntohl(labelbuf
);
320 /* do not accept invalid labels */
321 if (label
> MPLS_LABEL_MAX
||
322 (label
<= MPLS_LABEL_RESERVED_MAX
&&
323 label
!= MPLS_LABEL_IPV4_EXPLICIT_NULL
&&
324 label
!= MPLS_LABEL_IPV6_EXPLICIT_NULL
&&
325 label
!= MPLS_LABEL_IMPLICIT_NULL
)) {
326 session_shutdown(nbr
, S_BAD_TLV_VAL
,
336 case TLV_TYPE_ATMLABEL
:
337 case TLV_TYPE_FRLABEL
:
339 case MSG_TYPE_LABELMAPPING
:
340 case MSG_TYPE_LABELWITHDRAW
:
341 case MSG_TYPE_LABELRELEASE
:
343 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
352 case TLV_TYPE_STATUS
:
353 if (tlv_len
!= STATUS_TLV_LEN
) {
354 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
360 case TLV_TYPE_PW_STATUS
:
362 case MSG_TYPE_LABELMAPPING
:
363 if (tlv_len
!= PW_STATUS_TLV_LEN
) {
364 session_shutdown(nbr
, S_BAD_TLV_LEN
,
369 flags
|= F_MAP_PW_STATUS
;
370 memcpy(&statusbuf
, buf
, sizeof(statusbuf
));
371 pw_status
= ntohl(statusbuf
);
379 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
380 send_notification_rtlvs(nbr
, S_UNKNOWN_TLV
,
381 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
382 /* ignore unknown tlv */
390 /* notify lde about the received message. */
391 while ((me
= TAILQ_FIRST(&mh
)) != NULL
) {
392 int imsg_type
= IMSG_NONE
;
394 me
->map
.flags
|= flags
;
395 switch (me
->map
.type
) {
396 case MAP_TYPE_PREFIX
:
397 switch (me
->map
.fec
.prefix
.af
) {
399 if (label
== MPLS_LABEL_IPV6_EXPLICIT_NULL
) {
400 session_shutdown(nbr
, S_BAD_TLV_VAL
,
404 if (!nbr
->v4_enabled
)
408 if (label
== MPLS_LABEL_IPV4_EXPLICIT_NULL
) {
409 session_shutdown(nbr
, S_BAD_TLV_VAL
,
413 if (!nbr
->v6_enabled
)
417 fatalx("recv_labelmessage: unknown af");
421 if (label
<= MPLS_LABEL_RESERVED_MAX
) {
422 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
426 if (me
->map
.flags
& F_MAP_PW_STATUS
)
427 me
->map
.pw_status
= pw_status
;
432 me
->map
.label
= label
;
433 if (me
->map
.flags
& F_MAP_REQ_ID
)
434 me
->map
.requestid
= reqid
;
436 log_msg_mapping(0, type
, nbr
, &me
->map
);
439 case MSG_TYPE_LABELMAPPING
:
440 imsg_type
= IMSG_LABEL_MAPPING
;
442 case MSG_TYPE_LABELREQUEST
:
443 imsg_type
= IMSG_LABEL_REQUEST
;
445 case MSG_TYPE_LABELWITHDRAW
:
446 imsg_type
= IMSG_LABEL_WITHDRAW
;
448 case MSG_TYPE_LABELRELEASE
:
449 imsg_type
= IMSG_LABEL_RELEASE
;
451 case MSG_TYPE_LABELABORTREQ
:
452 imsg_type
= IMSG_LABEL_ABORT
;
458 ldpe_imsg_compose_lde(imsg_type
, nbr
->peerid
, 0, &me
->map
,
462 TAILQ_REMOVE(&mh
, me
, entry
);
463 assert(me
!= TAILQ_FIRST(&mh
));
470 mapping_list_clr(&mh
);
475 /* Other TLV related functions */
477 gen_label_tlv(struct ibuf
*buf
, uint32_t label
)
481 lt
.type
= htons(TLV_TYPE_GENERICLABEL
);
482 lt
.length
= htons(LABEL_TLV_LEN
);
483 lt
.label
= htonl(label
);
485 return (ibuf_add(buf
, <
, sizeof(lt
)));
489 gen_reqid_tlv(struct ibuf
*buf
, uint32_t reqid
)
493 rt
.type
= htons(TLV_TYPE_LABELREQUEST
);
494 rt
.length
= htons(REQID_TLV_LEN
);
495 rt
.reqid
= htonl(reqid
);
497 return (ibuf_add(buf
, &rt
, sizeof(rt
)));
501 gen_pw_status_tlv(struct ibuf
*buf
, uint32_t status
)
503 struct pw_status_tlv st
;
505 st
.type
= htons(TLV_TYPE_PW_STATUS
);
506 st
.length
= htons(PW_STATUS_TLV_LEN
);
507 st
.value
= htonl(status
);
509 return (ibuf_add(buf
, &st
, sizeof(st
)));
513 len_fec_tlv(struct map
*map
)
515 uint16_t len
= TLV_HDR_SIZE
;
518 case MAP_TYPE_WILDCARD
:
519 len
+= FEC_ELM_WCARD_LEN
;
521 case MAP_TYPE_PREFIX
:
522 len
+= FEC_ELM_PREFIX_MIN_LEN
+
523 PREFIX_SIZE(map
->fec
.prefix
.prefixlen
);
526 len
+= FEC_PWID_ELM_MIN_LEN
;
527 if (map
->flags
& F_MAP_PW_ID
)
528 len
+= PW_STATUS_TLV_LEN
;
529 if (map
->flags
& F_MAP_PW_IFMTU
)
530 len
+= FEC_SUBTLV_IFMTU_SIZE
;
531 if (map
->flags
& F_MAP_PW_STATUS
)
532 len
+= PW_STATUS_TLV_SIZE
;
534 case MAP_TYPE_TYPED_WCARD
:
535 len
+= FEC_ELM_TWCARD_MIN_LEN
;
536 switch (map
->fec
.twcard
.type
) {
537 case MAP_TYPE_PREFIX
:
539 len
+= sizeof(uint16_t);
542 fatalx("len_fec_tlv: unexpected fec type");
546 fatalx("len_fec_tlv: unexpected fec type");
553 gen_fec_tlv(struct ibuf
*buf
, struct map
*map
)
556 uint16_t family
, len
, pw_type
, ifmtu
;
557 uint8_t pw_len
= 0, twcard_len
;
558 uint32_t group_id
, pwid
;
561 ft
.type
= htons(TLV_TYPE_FEC
);
564 case MAP_TYPE_WILDCARD
:
565 ft
.length
= htons(sizeof(uint8_t));
566 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
567 err
|= ibuf_add(buf
, &map
->type
, sizeof(map
->type
));
569 case MAP_TYPE_PREFIX
:
570 len
= PREFIX_SIZE(map
->fec
.prefix
.prefixlen
);
571 ft
.length
= htons(sizeof(map
->type
) + sizeof(family
) +
572 sizeof(map
->fec
.prefix
.prefixlen
) + len
);
573 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
574 err
|= ibuf_add(buf
, &map
->type
, sizeof(map
->type
));
575 switch (map
->fec
.prefix
.af
) {
577 family
= htons(AF_IPV4
);
580 family
= htons(AF_IPV6
);
583 fatalx("gen_fec_tlv: unknown af");
586 err
|= ibuf_add(buf
, &family
, sizeof(family
));
587 err
|= ibuf_add(buf
, &map
->fec
.prefix
.prefixlen
,
588 sizeof(map
->fec
.prefix
.prefixlen
));
590 err
|= ibuf_add(buf
, &map
->fec
.prefix
.prefix
, len
);
593 if (map
->flags
& F_MAP_PW_ID
)
594 pw_len
+= FEC_PWID_SIZE
;
595 if (map
->flags
& F_MAP_PW_IFMTU
)
596 pw_len
+= FEC_SUBTLV_IFMTU_SIZE
;
598 len
= FEC_PWID_ELM_MIN_LEN
+ pw_len
;
600 ft
.length
= htons(len
);
601 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
603 err
|= ibuf_add(buf
, &map
->type
, sizeof(uint8_t));
604 pw_type
= map
->fec
.pwid
.type
;
605 if (map
->flags
& F_MAP_PW_CWORD
)
606 pw_type
|= CONTROL_WORD_FLAG
;
607 pw_type
= htons(pw_type
);
608 err
|= ibuf_add(buf
, &pw_type
, sizeof(uint16_t));
609 err
|= ibuf_add(buf
, &pw_len
, sizeof(uint8_t));
610 group_id
= htonl(map
->fec
.pwid
.group_id
);
611 err
|= ibuf_add(buf
, &group_id
, sizeof(uint32_t));
612 if (map
->flags
& F_MAP_PW_ID
) {
613 pwid
= htonl(map
->fec
.pwid
.pwid
);
614 err
|= ibuf_add(buf
, &pwid
, sizeof(uint32_t));
616 if (map
->flags
& F_MAP_PW_IFMTU
) {
619 stlv
.type
= SUBTLV_IFMTU
;
620 stlv
.length
= FEC_SUBTLV_IFMTU_SIZE
;
621 err
|= ibuf_add(buf
, &stlv
, sizeof(uint16_t));
623 ifmtu
= htons(map
->fec
.pwid
.ifmtu
);
624 err
|= ibuf_add(buf
, &ifmtu
, sizeof(uint16_t));
627 case MAP_TYPE_TYPED_WCARD
:
628 len
= FEC_ELM_TWCARD_MIN_LEN
;
629 switch (map
->fec
.twcard
.type
) {
630 case MAP_TYPE_PREFIX
:
632 len
+= sizeof(uint16_t);
635 fatalx("gen_fec_tlv: unexpected fec type");
637 ft
.length
= htons(len
);
638 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
639 err
|= ibuf_add(buf
, &map
->type
, sizeof(uint8_t));
640 err
|= ibuf_add(buf
, &map
->fec
.twcard
.type
, sizeof(uint8_t));
642 switch (map
->fec
.twcard
.type
) {
643 case MAP_TYPE_PREFIX
:
644 twcard_len
= sizeof(uint16_t);
645 err
|= ibuf_add(buf
, &twcard_len
, sizeof(uint8_t));
647 switch (map
->fec
.twcard
.u
.prefix_af
) {
649 family
= htons(AF_IPV4
);
652 family
= htons(AF_IPV6
);
655 fatalx("gen_fec_tlv: unknown af");
659 err
|= ibuf_add(buf
, &family
, sizeof(uint16_t));
662 twcard_len
= sizeof(uint16_t);
663 err
|= ibuf_add(buf
, &twcard_len
, sizeof(uint8_t));
664 pw_type
= htons(map
->fec
.twcard
.u
.pw_type
);
665 err
|= ibuf_add(buf
, &pw_type
, sizeof(uint16_t));
668 fatalx("gen_fec_tlv: unexpected fec type");
679 tlv_decode_fec_elm(struct nbr
*nbr
, struct ldp_msg
*msg
, char *buf
,
680 uint16_t len
, struct map
*map
)
683 uint8_t pw_len
, twcard_len
;
686 off
+= sizeof(uint8_t);
689 case MAP_TYPE_WILDCARD
:
690 if (len
== FEC_ELM_WCARD_LEN
)
693 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
->id
,
698 case MAP_TYPE_PREFIX
:
699 if (len
< FEC_ELM_PREFIX_MIN_LEN
) {
700 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
706 memcpy(&map
->fec
.prefix
.af
, buf
+ off
,
707 sizeof(map
->fec
.prefix
.af
));
708 off
+= sizeof(map
->fec
.prefix
.af
);
709 map
->fec
.prefix
.af
= ntohs(map
->fec
.prefix
.af
);
710 switch (map
->fec
.prefix
.af
) {
712 map
->fec
.prefix
.af
= AF_INET
;
715 map
->fec
.prefix
.af
= AF_INET6
;
718 send_notification(nbr
->tcp
, S_UNSUP_ADDR
, msg
->id
,
724 map
->fec
.prefix
.prefixlen
= buf
[off
];
725 off
+= sizeof(uint8_t);
726 if (len
< off
+ PREFIX_SIZE(map
->fec
.prefix
.prefixlen
)) {
727 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
733 memset(&map
->fec
.prefix
.prefix
, 0,
734 sizeof(map
->fec
.prefix
.prefix
));
735 memcpy(&map
->fec
.prefix
.prefix
, buf
+ off
,
736 PREFIX_SIZE(map
->fec
.prefix
.prefixlen
));
738 /* Just in case... */
739 ldp_applymask(map
->fec
.prefix
.af
, &map
->fec
.prefix
.prefix
,
740 &map
->fec
.prefix
.prefix
, map
->fec
.prefix
.prefixlen
);
742 return (off
+ PREFIX_SIZE(map
->fec
.prefix
.prefixlen
));
744 if (len
< FEC_PWID_ELM_MIN_LEN
) {
745 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
751 memcpy(&map
->fec
.pwid
.type
, buf
+ off
, sizeof(uint16_t));
752 map
->fec
.pwid
.type
= ntohs(map
->fec
.pwid
.type
);
753 if (map
->fec
.pwid
.type
& CONTROL_WORD_FLAG
) {
754 map
->flags
|= F_MAP_PW_CWORD
;
755 map
->fec
.pwid
.type
&= ~CONTROL_WORD_FLAG
;
757 off
+= sizeof(uint16_t);
761 off
+= sizeof(uint8_t);
763 if (len
!= FEC_PWID_ELM_MIN_LEN
+ pw_len
) {
764 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
770 memcpy(&map
->fec
.pwid
.group_id
, buf
+ off
, sizeof(uint32_t));
771 map
->fec
.pwid
.group_id
= ntohl(map
->fec
.pwid
.group_id
);
772 off
+= sizeof(uint32_t);
778 if (pw_len
< sizeof(uint32_t)) {
779 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
784 memcpy(&map
->fec
.pwid
.pwid
, buf
+ off
, sizeof(uint32_t));
785 map
->fec
.pwid
.pwid
= ntohl(map
->fec
.pwid
.pwid
);
786 map
->flags
|= F_MAP_PW_ID
;
787 off
+= sizeof(uint32_t);
788 pw_len
-= sizeof(uint32_t);
790 /* Optional Interface Parameter Sub-TLVs */
794 if (pw_len
< sizeof(stlv
)) {
795 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
800 memcpy(&stlv
, buf
+ off
, sizeof(stlv
));
801 if (stlv
.length
> pw_len
) {
802 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
809 if (stlv
.length
!= FEC_SUBTLV_IFMTU_SIZE
) {
810 session_shutdown(nbr
, S_BAD_TLV_LEN
,
814 memcpy(&map
->fec
.pwid
.ifmtu
, buf
+ off
+
815 SUBTLV_HDR_SIZE
, sizeof(uint16_t));
816 map
->fec
.pwid
.ifmtu
= ntohs(map
->fec
.pwid
.ifmtu
);
817 map
->flags
|= F_MAP_PW_IFMTU
;
824 pw_len
-= stlv
.length
;
828 case MAP_TYPE_TYPED_WCARD
:
829 if (len
< FEC_ELM_TWCARD_MIN_LEN
) {
830 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
835 memcpy(&map
->fec
.twcard
.type
, buf
+ off
, sizeof(uint8_t));
836 off
+= sizeof(uint8_t);
837 memcpy(&twcard_len
, buf
+ off
, sizeof(uint8_t));
838 off
+= sizeof(uint8_t);
839 if (len
!= FEC_ELM_TWCARD_MIN_LEN
+ twcard_len
) {
840 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
845 switch (map
->fec
.twcard
.type
) {
846 case MAP_TYPE_PREFIX
:
847 if (twcard_len
!= sizeof(uint16_t)) {
848 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
853 memcpy(&map
->fec
.twcard
.u
.prefix_af
, buf
+ off
,
855 map
->fec
.twcard
.u
.prefix_af
=
856 ntohs(map
->fec
.twcard
.u
.prefix_af
);
857 off
+= sizeof(uint16_t);
859 switch (map
->fec
.twcard
.u
.prefix_af
) {
861 map
->fec
.twcard
.u
.prefix_af
= AF_INET
;
864 map
->fec
.twcard
.u
.prefix_af
= AF_INET6
;
867 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
->id
,
873 if (twcard_len
!= sizeof(uint16_t)) {
874 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
879 memcpy(&map
->fec
.twcard
.u
.pw_type
, buf
+ off
,
881 map
->fec
.twcard
.u
.pw_type
=
882 ntohs(map
->fec
.twcard
.u
.pw_type
);
883 /* ignore the reserved bit as per RFC 6667 */
884 map
->fec
.twcard
.u
.pw_type
&= ~PW_TWCARD_RESERVED_BIT
;
885 off
+= sizeof(uint16_t);
888 send_notification(nbr
->tcp
, S_UNKNOWN_FEC
, msg
->id
,
895 send_notification(nbr
->tcp
, S_UNKNOWN_FEC
, msg
->id
, msg
->type
);
903 log_msg_mapping(int out
, uint16_t msg_type
, struct nbr
*nbr
, struct map
*map
)
905 debug_msg(out
, "%s: lsr-id %s, fec %s, label %s", msg_name(msg_type
),
906 inet_ntoa(nbr
->id
), log_map(map
), log_label(map
->label
));