]> git.proxmox.com Git - mirror_frr.git/blobdiff - ldpd/notification.c
Merge pull request #2932 from donaldsharp/ferr_fix
[mirror_frr.git] / ldpd / notification.c
index 69d4ab8028d50683bc372313aba6fd21b2238f7f..4a5f3c8fa4bbc9ad2081c184b6c42d413d6837ef 100644 (file)
@@ -38,16 +38,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;
 
@@ -74,6 +66,7 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm)
        if (tcp->nbr) {
                log_msg_notification(1, tcp->nbr, nm);
                nbr_fsm(tcp->nbr, NBR_EVT_PDU_SENT);
+               tcp->nbr->stats.notif_sent++;
        }
 
        evbuf_enqueue(&tcp->wbuf, buf);
@@ -204,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);
@@ -219,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);
@@ -227,13 +237,30 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
                if (nbr->state == NBR_STA_OPENSENT)
                        nbr_start_idtimer(nbr);
 
+               /*
+                * RFC 5036 - Section 3.5.1.1:
+                * "When an LSR receives a Shutdown message during session
+                * initialization, it SHOULD transmit a Shutdown message and
+                * then close the transport connection".
+                */
+               if (nbr->state != NBR_STA_OPER && nm.status_code == S_SHUTDOWN)
+                       send_notification(nbr->tcp, S_SHUTDOWN,
+                           msg.id, msg.type);
+
                nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
                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);
 }