]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/labelmapping.c
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
);
136 enqueue_pdu(nbr
, type
, buf
, size
);
138 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
141 /* Generic function that handles all Label Message types */
143 recv_labelmessage(struct nbr
*nbr
, char *buf
, uint16_t len
, uint16_t type
)
147 uint32_t label
= NO_LABEL
, reqid
= 0;
148 uint32_t pw_status
= 0;
151 uint16_t current_tlv
= 1;
152 struct mapping_entry
*me
;
153 struct mapping_head mh
;
156 memcpy(&msg
, buf
, sizeof(msg
));
161 if (len
< sizeof(ft
)) {
162 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
166 memcpy(&ft
, buf
, sizeof(ft
));
167 if (ntohs(ft
.type
) != TLV_TYPE_FEC
) {
168 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
, msg
.type
);
171 feclen
= ntohs(ft
.length
);
172 if (feclen
> len
- TLV_HDR_SIZE
) {
173 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
177 buf
+= TLV_HDR_SIZE
; /* just advance to the end of the fec header */
182 memset(&map
, 0, sizeof(map
));
185 if ((tlen
= tlv_decode_fec_elm(nbr
, &msg
, buf
, feclen
,
188 if (map
.type
== MAP_TYPE_PWID
&&
189 !(map
.flags
& F_MAP_PW_ID
) &&
190 type
!= MSG_TYPE_LABELWITHDRAW
&&
191 type
!= MSG_TYPE_LABELRELEASE
) {
192 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
,
198 * The Wildcard FEC Element can be used only in the
199 * Label Withdraw and Label Release messages.
201 if (map
.type
== MAP_TYPE_WILDCARD
) {
203 case MSG_TYPE_LABELMAPPING
:
204 case MSG_TYPE_LABELREQUEST
:
205 case MSG_TYPE_LABELABORTREQ
:
206 session_shutdown(nbr
, S_UNKNOWN_FEC
, msg
.id
,
215 * RFC 5561 - Section 4:
216 * "An LDP implementation that supports the Typed Wildcard
217 * FEC Element MUST support its use in Label Request, Label
218 * Withdraw, and Label Release messages".
220 if (map
.type
== MAP_TYPE_TYPED_WCARD
) {
222 case MSG_TYPE_LABELMAPPING
:
223 case MSG_TYPE_LABELABORTREQ
:
224 session_shutdown(nbr
, S_UNKNOWN_FEC
, msg
.id
,
233 * LDP supports the use of multiple FEC Elements per
234 * FEC for the Label Mapping message only.
236 if (type
!= MSG_TYPE_LABELMAPPING
&&
238 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
, msg
.type
);
242 mapping_list_add(&mh
, &map
);
247 } while (feclen
> 0);
249 /* Optional Parameters */
254 uint32_t reqbuf
, labelbuf
, statusbuf
;
256 if (len
< sizeof(tlv
)) {
257 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
261 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
262 tlv_type
= ntohs(tlv
.type
);
263 tlv_len
= ntohs(tlv
.length
);
264 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
265 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
272 * For Label Mapping messages the Label TLV is mandatory and
273 * should appear right after the FEC TLV.
275 if (current_tlv
== 1 && type
== MSG_TYPE_LABELMAPPING
&&
276 !(tlv_type
& TLV_TYPE_GENERICLABEL
)) {
277 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
,
283 case TLV_TYPE_LABELREQUEST
:
285 case MSG_TYPE_LABELMAPPING
:
286 case MSG_TYPE_LABELREQUEST
:
287 if (tlv_len
!= REQID_TLV_LEN
) {
288 session_shutdown(nbr
, S_BAD_TLV_LEN
,
293 flags
|= F_MAP_REQ_ID
;
294 memcpy(&reqbuf
, buf
, sizeof(reqbuf
));
295 reqid
= ntohl(reqbuf
);
302 case TLV_TYPE_HOPCOUNT
:
303 case TLV_TYPE_PATHVECTOR
:
306 case TLV_TYPE_GENERICLABEL
:
308 case MSG_TYPE_LABELMAPPING
:
309 case MSG_TYPE_LABELWITHDRAW
:
310 case MSG_TYPE_LABELRELEASE
:
311 if (tlv_len
!= LABEL_TLV_LEN
) {
312 session_shutdown(nbr
, S_BAD_TLV_LEN
,
317 memcpy(&labelbuf
, buf
, sizeof(labelbuf
));
318 label
= ntohl(labelbuf
);
319 /* do not accept invalid labels */
320 if (label
> MPLS_LABEL_MAX
||
321 (label
<= MPLS_LABEL_RESERVED_MAX
&&
322 label
!= MPLS_LABEL_IPV4NULL
&&
323 label
!= MPLS_LABEL_IPV6NULL
&&
324 label
!= MPLS_LABEL_IMPLNULL
)) {
325 session_shutdown(nbr
, S_BAD_TLV_VAL
,
335 case TLV_TYPE_ATMLABEL
:
336 case TLV_TYPE_FRLABEL
:
338 case MSG_TYPE_LABELMAPPING
:
339 case MSG_TYPE_LABELWITHDRAW
:
340 case MSG_TYPE_LABELRELEASE
:
342 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
351 case TLV_TYPE_STATUS
:
352 if (tlv_len
!= STATUS_TLV_LEN
) {
353 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
359 case TLV_TYPE_PW_STATUS
:
361 case MSG_TYPE_LABELMAPPING
:
362 if (tlv_len
!= PW_STATUS_TLV_LEN
) {
363 session_shutdown(nbr
, S_BAD_TLV_LEN
,
368 flags
|= F_MAP_PW_STATUS
;
369 memcpy(&statusbuf
, buf
, sizeof(statusbuf
));
370 pw_status
= ntohl(statusbuf
);
378 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
379 send_notification_rtlvs(nbr
, S_UNKNOWN_TLV
,
380 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
381 /* ignore unknown tlv */
389 /* notify lde about the received message. */
390 while ((me
= TAILQ_FIRST(&mh
)) != NULL
) {
391 int imsg_type
= IMSG_NONE
;
393 me
->map
.flags
|= flags
;
394 switch (me
->map
.type
) {
395 case MAP_TYPE_PREFIX
:
396 switch (me
->map
.fec
.prefix
.af
) {
398 if (label
== MPLS_LABEL_IPV6NULL
) {
399 session_shutdown(nbr
, S_BAD_TLV_VAL
,
403 if (!nbr
->v4_enabled
)
407 if (label
== MPLS_LABEL_IPV4NULL
) {
408 session_shutdown(nbr
, S_BAD_TLV_VAL
,
412 if (!nbr
->v6_enabled
)
416 fatalx("recv_labelmessage: unknown af");
420 if (label
<= MPLS_LABEL_RESERVED_MAX
) {
421 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
.id
,
425 if (me
->map
.flags
& F_MAP_PW_STATUS
)
426 me
->map
.pw_status
= pw_status
;
431 me
->map
.label
= label
;
432 if (me
->map
.flags
& F_MAP_REQ_ID
)
433 me
->map
.requestid
= reqid
;
435 log_msg_mapping(0, type
, nbr
, &me
->map
);
438 case MSG_TYPE_LABELMAPPING
:
439 imsg_type
= IMSG_LABEL_MAPPING
;
441 case MSG_TYPE_LABELREQUEST
:
442 imsg_type
= IMSG_LABEL_REQUEST
;
444 case MSG_TYPE_LABELWITHDRAW
:
445 imsg_type
= IMSG_LABEL_WITHDRAW
;
447 case MSG_TYPE_LABELRELEASE
:
448 imsg_type
= IMSG_LABEL_RELEASE
;
450 case MSG_TYPE_LABELABORTREQ
:
451 imsg_type
= IMSG_LABEL_ABORT
;
457 ldpe_imsg_compose_lde(imsg_type
, nbr
->peerid
, 0, &me
->map
,
461 TAILQ_REMOVE(&mh
, me
, entry
);
468 mapping_list_clr(&mh
);
473 /* Other TLV related functions */
475 gen_label_tlv(struct ibuf
*buf
, uint32_t label
)
479 lt
.type
= htons(TLV_TYPE_GENERICLABEL
);
480 lt
.length
= htons(LABEL_TLV_LEN
);
481 lt
.label
= htonl(label
);
483 return (ibuf_add(buf
, <
, sizeof(lt
)));
487 gen_reqid_tlv(struct ibuf
*buf
, uint32_t reqid
)
491 rt
.type
= htons(TLV_TYPE_LABELREQUEST
);
492 rt
.length
= htons(REQID_TLV_LEN
);
493 rt
.reqid
= htonl(reqid
);
495 return (ibuf_add(buf
, &rt
, sizeof(rt
)));
499 gen_pw_status_tlv(struct ibuf
*buf
, uint32_t status
)
501 struct pw_status_tlv st
;
503 st
.type
= htons(TLV_TYPE_PW_STATUS
);
504 st
.length
= htons(PW_STATUS_TLV_LEN
);
505 st
.value
= htonl(status
);
507 return (ibuf_add(buf
, &st
, sizeof(st
)));
511 len_fec_tlv(struct map
*map
)
513 uint16_t len
= TLV_HDR_SIZE
;
516 case MAP_TYPE_WILDCARD
:
517 len
+= FEC_ELM_WCARD_LEN
;
519 case MAP_TYPE_PREFIX
:
520 len
+= FEC_ELM_PREFIX_MIN_LEN
+
521 PREFIX_SIZE(map
->fec
.prefix
.prefixlen
);
524 len
+= FEC_PWID_ELM_MIN_LEN
;
525 if (map
->flags
& F_MAP_PW_ID
)
526 len
+= PW_STATUS_TLV_LEN
;
527 if (map
->flags
& F_MAP_PW_IFMTU
)
528 len
+= FEC_SUBTLV_IFMTU_SIZE
;
529 if (map
->flags
& F_MAP_PW_STATUS
)
530 len
+= PW_STATUS_TLV_SIZE
;
532 case MAP_TYPE_TYPED_WCARD
:
533 len
+= FEC_ELM_TWCARD_MIN_LEN
;
534 switch (map
->fec
.twcard
.type
) {
535 case MAP_TYPE_PREFIX
:
537 len
+= sizeof(uint16_t);
540 fatalx("len_fec_tlv: unexpected fec type");
544 fatalx("len_fec_tlv: unexpected fec type");
551 gen_fec_tlv(struct ibuf
*buf
, struct map
*map
)
554 uint16_t family
, len
, pw_type
, ifmtu
;
555 uint8_t pw_len
= 0, twcard_len
;
556 uint32_t group_id
, pwid
;
559 ft
.type
= htons(TLV_TYPE_FEC
);
562 case MAP_TYPE_WILDCARD
:
563 ft
.length
= htons(sizeof(uint8_t));
564 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
565 err
|= ibuf_add(buf
, &map
->type
, sizeof(map
->type
));
567 case MAP_TYPE_PREFIX
:
568 len
= PREFIX_SIZE(map
->fec
.prefix
.prefixlen
);
569 ft
.length
= htons(sizeof(map
->type
) + sizeof(family
) +
570 sizeof(map
->fec
.prefix
.prefixlen
) + len
);
571 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
572 err
|= ibuf_add(buf
, &map
->type
, sizeof(map
->type
));
573 switch (map
->fec
.prefix
.af
) {
575 family
= htons(AF_IPV4
);
578 family
= htons(AF_IPV6
);
581 fatalx("gen_fec_tlv: unknown af");
584 err
|= ibuf_add(buf
, &family
, sizeof(family
));
585 err
|= ibuf_add(buf
, &map
->fec
.prefix
.prefixlen
,
586 sizeof(map
->fec
.prefix
.prefixlen
));
588 err
|= ibuf_add(buf
, &map
->fec
.prefix
.prefix
, len
);
591 if (map
->flags
& F_MAP_PW_ID
)
592 pw_len
+= FEC_PWID_SIZE
;
593 if (map
->flags
& F_MAP_PW_IFMTU
)
594 pw_len
+= FEC_SUBTLV_IFMTU_SIZE
;
596 len
= FEC_PWID_ELM_MIN_LEN
+ pw_len
;
598 ft
.length
= htons(len
);
599 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
601 err
|= ibuf_add(buf
, &map
->type
, sizeof(uint8_t));
602 pw_type
= map
->fec
.pwid
.type
;
603 if (map
->flags
& F_MAP_PW_CWORD
)
604 pw_type
|= CONTROL_WORD_FLAG
;
605 pw_type
= htons(pw_type
);
606 err
|= ibuf_add(buf
, &pw_type
, sizeof(uint16_t));
607 err
|= ibuf_add(buf
, &pw_len
, sizeof(uint8_t));
608 group_id
= htonl(map
->fec
.pwid
.group_id
);
609 err
|= ibuf_add(buf
, &group_id
, sizeof(uint32_t));
610 if (map
->flags
& F_MAP_PW_ID
) {
611 pwid
= htonl(map
->fec
.pwid
.pwid
);
612 err
|= ibuf_add(buf
, &pwid
, sizeof(uint32_t));
614 if (map
->flags
& F_MAP_PW_IFMTU
) {
617 stlv
.type
= SUBTLV_IFMTU
;
618 stlv
.length
= FEC_SUBTLV_IFMTU_SIZE
;
619 err
|= ibuf_add(buf
, &stlv
, sizeof(uint16_t));
621 ifmtu
= htons(map
->fec
.pwid
.ifmtu
);
622 err
|= ibuf_add(buf
, &ifmtu
, sizeof(uint16_t));
625 case MAP_TYPE_TYPED_WCARD
:
626 len
= FEC_ELM_TWCARD_MIN_LEN
;
627 switch (map
->fec
.twcard
.type
) {
628 case MAP_TYPE_PREFIX
:
630 len
+= sizeof(uint16_t);
633 fatalx("gen_fec_tlv: unexpected fec type");
635 ft
.length
= htons(len
);
636 err
|= ibuf_add(buf
, &ft
, sizeof(ft
));
637 err
|= ibuf_add(buf
, &map
->type
, sizeof(uint8_t));
638 err
|= ibuf_add(buf
, &map
->fec
.twcard
.type
, sizeof(uint8_t));
640 switch (map
->fec
.twcard
.type
) {
641 case MAP_TYPE_PREFIX
:
642 twcard_len
= sizeof(uint16_t);
643 err
|= ibuf_add(buf
, &twcard_len
, sizeof(uint8_t));
645 switch (map
->fec
.twcard
.u
.prefix_af
) {
647 family
= htons(AF_IPV4
);
650 family
= htons(AF_IPV6
);
653 fatalx("gen_fec_tlv: unknown af");
657 err
|= ibuf_add(buf
, &family
, sizeof(uint16_t));
660 twcard_len
= sizeof(uint16_t);
661 err
|= ibuf_add(buf
, &twcard_len
, sizeof(uint8_t));
662 pw_type
= htons(map
->fec
.twcard
.u
.pw_type
);
663 err
|= ibuf_add(buf
, &pw_type
, sizeof(uint16_t));
666 fatalx("gen_fec_tlv: unexpected fec type");
677 tlv_decode_fec_elm(struct nbr
*nbr
, struct ldp_msg
*msg
, char *buf
,
678 uint16_t len
, struct map
*map
)
681 uint8_t pw_len
, twcard_len
;
684 off
+= sizeof(uint8_t);
687 case MAP_TYPE_WILDCARD
:
688 if (len
== FEC_ELM_WCARD_LEN
)
691 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
->id
,
696 case MAP_TYPE_PREFIX
:
697 if (len
< FEC_ELM_PREFIX_MIN_LEN
) {
698 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
704 memcpy(&map
->fec
.prefix
.af
, buf
+ off
,
705 sizeof(map
->fec
.prefix
.af
));
706 off
+= sizeof(map
->fec
.prefix
.af
);
707 map
->fec
.prefix
.af
= ntohs(map
->fec
.prefix
.af
);
708 switch (map
->fec
.prefix
.af
) {
710 map
->fec
.prefix
.af
= AF_INET
;
713 map
->fec
.prefix
.af
= AF_INET6
;
716 send_notification(nbr
->tcp
, S_UNSUP_ADDR
, msg
->id
,
722 map
->fec
.prefix
.prefixlen
= buf
[off
];
723 off
+= sizeof(uint8_t);
724 if (len
< off
+ PREFIX_SIZE(map
->fec
.prefix
.prefixlen
)) {
725 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
731 memset(&map
->fec
.prefix
.prefix
, 0,
732 sizeof(map
->fec
.prefix
.prefix
));
733 memcpy(&map
->fec
.prefix
.prefix
, buf
+ off
,
734 PREFIX_SIZE(map
->fec
.prefix
.prefixlen
));
736 /* Just in case... */
737 ldp_applymask(map
->fec
.prefix
.af
, &map
->fec
.prefix
.prefix
,
738 &map
->fec
.prefix
.prefix
, map
->fec
.prefix
.prefixlen
);
740 return (off
+ PREFIX_SIZE(map
->fec
.prefix
.prefixlen
));
742 if (len
< FEC_PWID_ELM_MIN_LEN
) {
743 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
749 memcpy(&map
->fec
.pwid
.type
, buf
+ off
, sizeof(uint16_t));
750 map
->fec
.pwid
.type
= ntohs(map
->fec
.pwid
.type
);
751 if (map
->fec
.pwid
.type
& CONTROL_WORD_FLAG
) {
752 map
->flags
|= F_MAP_PW_CWORD
;
753 map
->fec
.pwid
.type
&= ~CONTROL_WORD_FLAG
;
755 off
+= sizeof(uint16_t);
759 off
+= sizeof(uint8_t);
761 if (len
!= FEC_PWID_ELM_MIN_LEN
+ pw_len
) {
762 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
768 memcpy(&map
->fec
.pwid
.group_id
, buf
+ off
, sizeof(uint32_t));
769 map
->fec
.pwid
.group_id
= ntohl(map
->fec
.pwid
.group_id
);
770 off
+= sizeof(uint32_t);
776 if (pw_len
< sizeof(uint32_t)) {
777 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
782 memcpy(&map
->fec
.pwid
.pwid
, buf
+ off
, sizeof(uint32_t));
783 map
->fec
.pwid
.pwid
= ntohl(map
->fec
.pwid
.pwid
);
784 map
->flags
|= F_MAP_PW_ID
;
785 off
+= sizeof(uint32_t);
786 pw_len
-= sizeof(uint32_t);
788 /* Optional Interface Parameter Sub-TLVs */
792 if (pw_len
< sizeof(stlv
)) {
793 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
798 memcpy(&stlv
, buf
+ off
, sizeof(stlv
));
799 if (stlv
.length
> pw_len
) {
800 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
807 if (stlv
.length
!= FEC_SUBTLV_IFMTU_SIZE
) {
808 session_shutdown(nbr
, S_BAD_TLV_LEN
,
812 memcpy(&map
->fec
.pwid
.ifmtu
, buf
+ off
+
813 SUBTLV_HDR_SIZE
, sizeof(uint16_t));
814 map
->fec
.pwid
.ifmtu
= ntohs(map
->fec
.pwid
.ifmtu
);
815 map
->flags
|= F_MAP_PW_IFMTU
;
822 pw_len
-= stlv
.length
;
826 case MAP_TYPE_TYPED_WCARD
:
827 if (len
< FEC_ELM_TWCARD_MIN_LEN
) {
828 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
833 memcpy(&map
->fec
.twcard
.type
, buf
+ off
, sizeof(uint8_t));
834 off
+= sizeof(uint8_t);
835 memcpy(&twcard_len
, buf
+ off
, sizeof(uint8_t));
836 off
+= sizeof(uint8_t);
837 if (len
!= FEC_ELM_TWCARD_MIN_LEN
+ twcard_len
) {
838 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
843 switch (map
->fec
.twcard
.type
) {
844 case MAP_TYPE_PREFIX
:
845 if (twcard_len
!= sizeof(uint16_t)) {
846 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
851 memcpy(&map
->fec
.twcard
.u
.prefix_af
, buf
+ off
,
853 map
->fec
.twcard
.u
.prefix_af
=
854 ntohs(map
->fec
.twcard
.u
.prefix_af
);
855 off
+= sizeof(uint16_t);
857 switch (map
->fec
.twcard
.u
.prefix_af
) {
859 map
->fec
.twcard
.u
.prefix_af
= AF_INET
;
862 map
->fec
.twcard
.u
.prefix_af
= AF_INET6
;
865 session_shutdown(nbr
, S_BAD_TLV_VAL
, msg
->id
,
871 if (twcard_len
!= sizeof(uint16_t)) {
872 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
->id
,
877 memcpy(&map
->fec
.twcard
.u
.pw_type
, buf
+ off
,
879 map
->fec
.twcard
.u
.pw_type
=
880 ntohs(map
->fec
.twcard
.u
.pw_type
);
881 /* ignore the reserved bit as per RFC 6667 */
882 map
->fec
.twcard
.u
.pw_type
&= ~PW_TWCARD_RESERVED_BIT
;
883 off
+= sizeof(uint16_t);
886 send_notification(nbr
->tcp
, S_UNKNOWN_FEC
, msg
->id
,
893 send_notification(nbr
->tcp
, S_UNKNOWN_FEC
, msg
->id
, msg
->type
);
901 log_msg_mapping(int out
, uint16_t msg_type
, struct nbr
*nbr
, struct map
*map
)
903 debug_msg(out
, "%s: lsr-id %s, fec %s, label %s", msg_name(msg_type
),
904 inet_ntoa(nbr
->id
), log_map(map
), log_label(map
->label
));