diff options
-rw-r--r-- | usr.sbin/ldpd/init.c | 69 | ||||
-rw-r--r-- | usr.sbin/ldpd/labelmapping.c | 74 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde.c | 42 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde.h | 5 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde_lib.c | 45 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldp.h | 10 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.8 | 12 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/logmsg.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/notification.c | 42 |
11 files changed, 256 insertions, 54 deletions
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c index 6905c906530..a19d1daa87d 100644 --- a/usr.sbin/ldpd/init.c +++ b/usr.sbin/ldpd/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.36 2017/03/04 00:09:17 renato Exp $ */ +/* $OpenBSD: init.c,v 1.37 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -27,6 +27,7 @@ static int gen_init_prms_tlv(struct ibuf *, struct nbr *); static int gen_cap_dynamic_tlv(struct ibuf *); static int gen_cap_twcard_tlv(struct ibuf *, int); +static int gen_cap_unotif_tlv(struct ibuf *, int); void send_init(struct nbr *nbr) @@ -38,7 +39,7 @@ send_init(struct nbr *nbr) log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE + - CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE; + CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE + CAP_TLV_UNOTIF_SIZE; if ((buf = ibuf_open(size)) == NULL) fatal(__func__); @@ -48,6 +49,7 @@ send_init(struct nbr *nbr) err |= gen_init_prms_tlv(buf, nbr); err |= gen_cap_dynamic_tlv(buf); err |= gen_cap_twcard_tlv(buf, 1); + err |= gen_cap_unotif_tlv(buf, 1); if (err) { ibuf_free(buf); return; @@ -168,6 +170,26 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len) log_debug("%s: lsr-id %s announced the Typed Wildcard " "FEC capability", __func__, inet_ntoa(nbr->id)); break; + case TLV_TYPE_UNOTIF_CAP: + if (tlv_len != CAP_TLV_UNOTIF_LEN) { + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, + msg.type); + return (-1); + } + + if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) { + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, + msg.type); + return (-1); + } + caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF; + + nbr->flags |= F_NBR_CAP_UNOTIF; + + log_debug("%s: lsr-id %s announced the Unrecognized " + "Notification capability", __func__, + inet_ntoa(nbr->id)); + break; default: if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) send_notification_rtlvs(nbr, S_UNSSUPORTDCAP, @@ -218,6 +240,9 @@ send_capability(struct nbr *nbr, uint16_t capability, int enable) case TLV_TYPE_TWCARD_CAP: err |= gen_cap_twcard_tlv(buf, enable); break; + case TLV_TYPE_UNOTIF_CAP: + err |= gen_cap_unotif_tlv(buf, enable); + break; case TLV_TYPE_DYNAMIC_CAP: /* * RFC 5561 - Section 9: @@ -300,6 +325,32 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len) "capability", __func__, inet_ntoa(nbr->id), (enable) ? "announced" : "withdrew"); break; + case TLV_TYPE_UNOTIF_CAP: + if (tlv_len != CAP_TLV_UNOTIF_LEN) { + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, + msg.type); + return (-1); + } + + if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) { + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, + msg.type); + return (-1); + } + caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF; + + memcpy(&reserved, buf, sizeof(reserved)); + enable = reserved & STATE_BIT; + if (enable) + nbr->flags |= F_NBR_CAP_UNOTIF; + else + nbr->flags &= ~F_NBR_CAP_UNOTIF; + + log_debug("%s: lsr-id %s %s the Unrecognized " + "Notification capability", __func__, + inet_ntoa(nbr->id), (enable) ? "announced" : + "withdrew"); + break; case TLV_TYPE_DYNAMIC_CAP: /* * RFC 5561 - Section 9: @@ -372,3 +423,17 @@ gen_cap_twcard_tlv(struct ibuf *buf, int enable) return (ibuf_add(buf, &cap, CAP_TLV_TWCARD_SIZE)); } + +static int +gen_cap_unotif_tlv(struct ibuf *buf, int enable) +{ + struct capability_tlv cap; + + memset(&cap, 0, sizeof(cap)); + cap.type = htons(TLV_TYPE_UNOTIF_CAP); + cap.length = htons(CAP_TLV_UNOTIF_LEN); + if (enable) + cap.reserved = STATE_BIT; + + return (ibuf_add(buf, &cap, CAP_TLV_UNOTIF_SIZE)); +} diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c index 17b2db940f8..cfafb4366c0 100644 --- a/usr.sbin/ldpd/labelmapping.c +++ b/usr.sbin/ldpd/labelmapping.c @@ -1,4 +1,4 @@ -/* $OpenBSD: labelmapping.c,v 1.67 2017/03/04 00:12:25 renato Exp $ */ +/* $OpenBSD: labelmapping.c,v 1.68 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org> @@ -75,36 +75,8 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) } /* calculate size */ - msg_size = LDP_MSG_SIZE + TLV_HDR_SIZE; - switch (me->map.type) { - case MAP_TYPE_WILDCARD: - msg_size += FEC_ELM_WCARD_LEN; - break; - case MAP_TYPE_PREFIX: - msg_size += FEC_ELM_PREFIX_MIN_LEN + - PREFIX_SIZE(me->map.fec.prefix.prefixlen); - break; - case MAP_TYPE_PWID: - msg_size += FEC_PWID_ELM_MIN_LEN; - if (me->map.flags & F_MAP_PW_ID) - msg_size += PW_STATUS_TLV_LEN; - if (me->map.flags & F_MAP_PW_IFMTU) - msg_size += FEC_SUBTLV_IFMTU_SIZE; - if (me->map.flags & F_MAP_PW_STATUS) - msg_size += PW_STATUS_TLV_SIZE; - break; - case MAP_TYPE_TYPED_WCARD: - msg_size += FEC_ELM_TWCARD_MIN_LEN; - switch (me->map.fec.twcard.type) { - case MAP_TYPE_PREFIX: - case MAP_TYPE_PWID: - msg_size += sizeof(uint16_t); - break; - default: - fatalx("send_labelmessage: unexpected fec type"); - } - break; - } + msg_size = LDP_MSG_SIZE; + msg_size += len_fec_tlv(&me->map); if (me->map.label != NO_LABEL) msg_size += LABEL_TLV_SIZE; if (me->map.flags & F_MAP_REQ_ID) @@ -551,6 +523,46 @@ gen_pw_status_tlv(struct ibuf *buf, uint32_t status) return (ibuf_add(buf, &st, sizeof(st))); } +uint16_t +len_fec_tlv(struct map *map) +{ + uint16_t len = TLV_HDR_SIZE; + + switch (map->type) { + case MAP_TYPE_WILDCARD: + len += FEC_ELM_WCARD_LEN; + break; + case MAP_TYPE_PREFIX: + len += FEC_ELM_PREFIX_MIN_LEN + + PREFIX_SIZE(map->fec.prefix.prefixlen); + break; + case MAP_TYPE_PWID: + len += FEC_PWID_ELM_MIN_LEN; + if (map->flags & F_MAP_PW_ID) + len += PW_STATUS_TLV_LEN; + if (map->flags & F_MAP_PW_IFMTU) + len += FEC_SUBTLV_IFMTU_SIZE; + if (map->flags & F_MAP_PW_STATUS) + len += PW_STATUS_TLV_SIZE; + break; + case MAP_TYPE_TYPED_WCARD: + len += FEC_ELM_TWCARD_MIN_LEN; + switch (map->fec.twcard.type) { + case MAP_TYPE_PREFIX: + case MAP_TYPE_PWID: + len += sizeof(uint16_t); + break; + default: + fatalx("len_fec_tlv: unexpected fec type"); + } + break; + default: + fatalx("len_fec_tlv: unexpected fec type"); + } + + return (len); +} + int gen_fec_tlv(struct ibuf *buf, struct map *map) { diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c index 2ce30c9e5c0..e6b45719700 100644 --- a/usr.sbin/ldpd/lde.c +++ b/usr.sbin/ldpd/lde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lde.c,v 1.72 2017/03/04 00:12:26 renato Exp $ */ +/* $OpenBSD: lde.c,v 1.73 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -313,6 +313,13 @@ lde_dispatch_imsg(int fd, short event, void *bula) case S_PW_STATUS: l2vpn_recv_pw_status(ln, &nm); break; + case S_ENDOFLIB: + /* + * Do nothing for now. Should be useful in + * the future when we implement LDP-IGP + * Synchronization (RFC 5443) and Graceful + * Restart (RFC 3478). + */ default: break; } @@ -990,6 +997,38 @@ lde_send_notification(struct lde_nbr *ln, uint32_t status_code, uint32_t msg_id, &nm, sizeof(nm)); } +void +lde_send_notification_eol_prefix(struct lde_nbr *ln, int af) +{ + struct notify_msg nm; + + memset(&nm, 0, sizeof(nm)); + nm.status_code = S_ENDOFLIB; + nm.fec.type = MAP_TYPE_TYPED_WCARD; + nm.fec.fec.twcard.type = MAP_TYPE_PREFIX; + nm.fec.fec.twcard.u.prefix_af = af; + nm.flags |= F_NOTIF_FEC; + + lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, + &nm, sizeof(nm)); +} + +void +lde_send_notification_eol_pwid(struct lde_nbr *ln, uint16_t pw_type) +{ + struct notify_msg nm; + + memset(&nm, 0, sizeof(nm)); + nm.status_code = S_ENDOFLIB; + nm.fec.type = MAP_TYPE_TYPED_WCARD; + nm.fec.fec.twcard.type = MAP_TYPE_PWID; + nm.fec.fec.twcard.u.pw_type = pw_type; + nm.flags |= F_NOTIF_FEC; + + lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, + &nm, sizeof(nm)); +} + static __inline int lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b) { @@ -1007,6 +1046,7 @@ lde_nbr_new(uint32_t peerid, struct lde_nbr *new) ln->id = new->id; ln->v4_enabled = new->v4_enabled; ln->v6_enabled = new->v6_enabled; + ln->flags = new->flags; ln->peerid = peerid; fec_init(&ln->recv_map); fec_init(&ln->sent_map); diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h index 785236ef372..ec76293560f 100644 --- a/usr.sbin/ldpd/lde.h +++ b/usr.sbin/ldpd/lde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lde.h,v 1.48 2017/03/04 00:12:26 renato Exp $ */ +/* $OpenBSD: lde.h,v 1.49 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -87,6 +87,7 @@ struct lde_nbr { struct in_addr id; int v4_enabled; /* announce/process v4 msgs */ int v6_enabled; /* announce/process v6 msgs */ + int flags; /* capabilities */ struct fec_tree recv_req; struct fec_tree sent_req; struct fec_tree recv_map; @@ -146,6 +147,8 @@ void lde_send_labelrelease(struct lde_nbr *, struct fec_node *, struct map *, uint32_t); void lde_send_notification(struct lde_nbr *, uint32_t, uint32_t, uint16_t); +void lde_send_notification_eol_prefix(struct lde_nbr *, int); +void lde_send_notification_eol_pwid(struct lde_nbr *, uint16_t); struct lde_nbr *lde_nbr_find_by_lsrid(struct in_addr); struct lde_nbr *lde_nbr_find_by_addr(int, union ldpd_addr *); struct lde_map *lde_map_add(struct lde_nbr *, struct fec_node *, int); diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c index 254f71bd896..5b58205eee9 100644 --- a/usr.sbin/ldpd/lde_lib.c +++ b/usr.sbin/ldpd/lde_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lde_lib.c,v 1.68 2017/03/04 00:12:26 renato Exp $ */ +/* $OpenBSD: lde_lib.c,v 1.69 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -26,6 +26,7 @@ #include "ldpd.h" #include "lde.h" +#include "ldpe.h" #include "log.h" static __inline int fec_compare(struct fec *, struct fec *); @@ -215,6 +216,22 @@ fec_snap(struct lde_nbr *ln) } lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0); + + /* + * RFC 5919 - Section 4: + * "An LDP speaker that conforms to this specification SHOULD signal + * completion of its label advertisements to a peer by means of a + * Notification message, if its peer has advertised the Unrecognized + * Notification capability during session establishment. The LDP + * speaker SHOULD send the Notification message (per Forwarding + * Equivalence Class (FEC) Type) to a peer even if the LDP speaker has + * zero Label bindings to advertise to that peer". + */ + if (ln->flags & F_NBR_CAP_UNOTIF) { + lde_send_notification_eol_prefix(ln, AF_INET); + lde_send_notification_eol_prefix(ln, AF_INET6); + lde_send_notification_eol_pwid(ln, PW_TYPE_WILDCARD); + } } static void @@ -612,6 +629,32 @@ lde_check_request_wcard(struct map *map, struct lde_nbr *ln) /* LRq.9: perform LSR label distribution */ lde_send_labelmapping(ln, fn, 1); } + + /* + * RFC 5919 - Section 5.3: + * "When an LDP speaker receives a Label Request message for a Typed + * Wildcard FEC (e.g., a particular FEC Element Type) from a peer, the + * LDP speaker determines the set of bindings (as per any local + * filtering policy) to advertise to the peer for the FEC type specified + * by the request. Assuming the peer had advertised the Unrecognized + * Notification capability at session initialization time, the speaker + * should send the peer an End-of-LIB Notification for the FEC type when + * it completes advertisement of the permitted bindings". + */ + if (ln->flags & F_NBR_CAP_UNOTIF) { + switch (map->fec.twcard.type) { + case MAP_TYPE_PREFIX: + lde_send_notification_eol_prefix(ln, + map->fec.twcard.u.prefix_af); + break; + case MAP_TYPE_PWID: + lde_send_notification_eol_pwid(ln, + map->fec.twcard.u.pw_type); + break; + default: + break; + } + } } void diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h index 1ce18242fa4..ef6374c7f9a 100644 --- a/usr.sbin/ldpd/ldp.h +++ b/usr.sbin/ldpd/ldp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldp.h,v 1.40 2017/03/04 00:12:26 renato Exp $ */ +/* $OpenBSD: ldp.h,v 1.41 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -103,6 +103,8 @@ #define TLV_TYPE_DYNAMIC_CAP 0x8506 /* RFC 5918 */ #define TLV_TYPE_TWCARD_CAP 0x850B +/* RFC 5919 */ +#define TLV_TYPE_UNOTIF_CAP 0x8603 /* RFC 7552 */ #define TLV_TYPE_DUALSTACK 0x8701 @@ -206,6 +208,8 @@ struct hello_prms_opt16_tlv { #define S_WITHDRAW_MTHD 0x0000002B /* RFC 5561 */ #define S_UNSSUPORTDCAP 0x0000002E +/* RFC 5919 */ +#define S_ENDOFLIB 0x0000002F /* RFC 7552 */ #define S_TRANS_MISMTCH 0x80000032 #define S_DS_NONCMPLNCE 0x80000033 @@ -246,6 +250,7 @@ struct capability_tlv { #define F_CAP_TLV_RCVD_DYNAMIC 0x01 #define F_CAP_TLV_RCVD_TWCARD 0x02 +#define F_CAP_TLV_RCVD_UNOTIF 0x04 #define CAP_TLV_DYNAMIC_SIZE 5 #define CAP_TLV_DYNAMIC_LEN 1 @@ -253,6 +258,9 @@ struct capability_tlv { #define CAP_TLV_TWCARD_SIZE 5 #define CAP_TLV_TWCARD_LEN 1 +#define CAP_TLV_UNOTIF_SIZE 5 +#define CAP_TLV_UNOTIF_LEN 1 + #define AF_IPV4 0x1 #define AF_IPV6 0x2 diff --git a/usr.sbin/ldpd/ldpd.8 b/usr.sbin/ldpd/ldpd.8 index 87e5535ec2f..de74fcfa553 100644 --- a/usr.sbin/ldpd/ldpd.8 +++ b/usr.sbin/ldpd/ldpd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ldpd.8,v 1.20 2017/03/04 00:12:26 renato Exp $ +.\" $OpenBSD: ldpd.8,v 1.21 2017/03/04 00:15:35 renato Exp $ .\" .\" Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> .\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -152,6 +152,16 @@ socket used for communication with .Re .Pp .Rs +.%A R. Asati +.%A P. Mohapatra +.%A E. Chen +.%A B. Thomas +.%D August 2010 +.%R RFC 5919 +.%T Signaling LDP Label Advertisement Completion +.Re +.Pp +.Rs .%A K. Raza .%A S. Boutros .%A C. Pignataro diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h index 10dd050c7e6..cc9882d6c22 100644 --- a/usr.sbin/ldpd/ldpe.h +++ b/usr.sbin/ldpd/ldpe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpe.h,v 1.73 2017/03/04 00:09:17 renato Exp $ */ +/* $OpenBSD: ldpe.h,v 1.74 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -106,6 +106,7 @@ struct nbr { #define F_NBR_GTSM_NEGOTIATED 0x01 #define F_NBR_CAP_DYNAMIC 0x02 #define F_NBR_CAP_TWCARD 0x04 +#define F_NBR_CAP_UNOTIF 0x08 RB_HEAD(nbr_id_head, nbr); RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare) @@ -179,6 +180,7 @@ int recv_address(struct nbr *, char *, uint16_t); void send_labelmessage(struct nbr *, uint16_t, struct mapping_head *); int recv_labelmessage(struct nbr *, char *, uint16_t, uint16_t); int gen_pw_status_tlv(struct ibuf *, uint32_t); +uint16_t len_fec_tlv(struct map *); int gen_fec_tlv(struct ibuf *, struct map *); int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *, uint16_t, struct map *); diff --git a/usr.sbin/ldpd/logmsg.c b/usr.sbin/ldpd/logmsg.c index 539d875993c..b8a75369726 100644 --- a/usr.sbin/ldpd/logmsg.c +++ b/usr.sbin/ldpd/logmsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: logmsg.c,v 1.5 2017/03/04 00:12:26 renato Exp $ */ +/* $OpenBSD: logmsg.c,v 1.6 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -423,6 +423,8 @@ status_code_name(uint32_t status) return ("Label Withdraw PW Status Method"); case S_UNSSUPORTDCAP: return ("Unsupported Capability"); + case S_ENDOFLIB: + return ("End-of-LIB"); case S_TRANS_MISMTCH: return ("Transport Connection Mismatch"); case S_DS_NONCMPLNCE: diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c index 361cf5660e2..37d7260fcfb 100644 --- a/usr.sbin/ldpd/neighbor.c +++ b/usr.sbin/ldpd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.78 2016/09/03 16:07:08 renato Exp $ */ +/* $OpenBSD: neighbor.c,v 1.79 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -740,6 +740,7 @@ nbr_act_session_operational(struct nbr *nbr) lde_nbr.id = nbr->id; lde_nbr.v4_enabled = nbr->v4_enabled; lde_nbr.v6_enabled = nbr->v6_enabled; + lde_nbr.flags = nbr->flags; return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &lde_nbr, sizeof(lde_nbr))); } diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c index 962a1fea78c..afda48f8416 100644 --- a/usr.sbin/ldpd/notification.c +++ b/usr.sbin/ldpd/notification.c @@ -1,4 +1,4 @@ -/* $OpenBSD: notification.c,v 1.45 2017/03/04 00:06:10 renato Exp $ */ +/* $OpenBSD: notification.c,v 1.46 2017/03/04 00:15:35 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -39,16 +39,8 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm) size = LDP_HDR_SIZE + LDP_MSG_SIZE + STATUS_SIZE; if (nm->flags & F_NOTIF_PW_STATUS) size += PW_STATUS_TLV_SIZE; - if (nm->flags & F_NOTIF_FEC) { - size += TLV_HDR_SIZE; - switch (nm->fec.type) { - case MAP_TYPE_PWID: - size += FEC_PWID_ELM_MIN_LEN; - if (nm->fec.flags & F_MAP_PW_ID) - size += sizeof(uint32_t); - break; - } - } + if (nm->flags & F_NOTIF_FEC) + size += len_fec_tlv(&nm->fec); if (nm->flags & F_NOTIF_RETURNED_TLVS) size += TLV_HDR_SIZE * 2 + nm->rtlvs.length; @@ -205,7 +197,9 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len) len -= tlv_len; } - if (nm.status_code == S_PW_STATUS) { + /* sanity checks */ + switch (nm.status_code) { + case S_PW_STATUS: if (!(nm.flags & (F_NOTIF_PW_STATUS|F_NOTIF_FEC))) { send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type); @@ -220,6 +214,21 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len) msg.id, msg.type); return (-1); } + break; + case S_ENDOFLIB: + if (!(nm.flags & F_NOTIF_FEC)) { + send_notification(nbr->tcp, S_MISS_MSG, + msg.id, msg.type); + return (-1); + } + if (nm.fec.type != MAP_TYPE_TYPED_WCARD) { + send_notification(nbr->tcp, S_BAD_TLV_VAL, + msg.id, msg.type); + return (-1); + } + break; + default: + break; } log_msg_notification(0, nbr, &nm); @@ -232,9 +241,16 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len) return (-1); } - if (nm.status_code == S_PW_STATUS) + /* lde needs to know about a few notification messages */ + switch (nm.status_code) { + case S_PW_STATUS: + case S_ENDOFLIB: ldpe_imsg_compose_lde(IMSG_NOTIFICATION, nbr->peerid, 0, &nm, sizeof(nm)); + break; + default: + break; + } return (0); } |