]> git.proxmox.com Git - mirror_frr.git/blobdiff - ldpd/labelmapping.c
ldpd: add missing sanity check in the parsing of label messages
[mirror_frr.git] / ldpd / labelmapping.c
index f53bc8333d7cbd81deb9a9919bff72b38926f4dd..a656626356abe9a9ce8a9fbf18586bc5e38d78cb 100644 (file)
@@ -37,7 +37,7 @@ enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size)
        struct ldp_hdr          *ldp_hdr;
 
        ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
-       ldp_hdr->length = htons(size);
+       ldp_hdr->length = htons(size - LDP_HDR_DEAD_LEN);
        evbuf_enqueue(&nbr->tcp->wbuf, buf);
 }
 
@@ -65,7 +65,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
                        /* real size will be set up later */
                        err |= gen_ldp_hdr(buf, 0);
 
-                       size = LDP_HDR_PDU_LEN;
+                       size = LDP_HDR_SIZE;
                        first = 0;
                }
 
@@ -130,6 +130,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
                }
 
                TAILQ_REMOVE(mh, me, entry);
+               assert(me != TAILQ_FIRST(mh));
                free(me);
        }
 
@@ -319,9 +320,9 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
                                /* do not accept invalid labels */
                                if (label > MPLS_LABEL_MAX ||
                                    (label <= MPLS_LABEL_RESERVED_MAX &&
-                                    label != MPLS_LABEL_IPV4NULL &&
-                                    label != MPLS_LABEL_IPV6NULL &&
-                                    label != MPLS_LABEL_IMPLNULL)) {
+                                    label != MPLS_LABEL_IPV4_EXPLICIT_NULL &&
+                                    label != MPLS_LABEL_IPV6_EXPLICIT_NULL &&
+                                    label != MPLS_LABEL_IMPLICIT_NULL)) {
                                        session_shutdown(nbr, S_BAD_TLV_VAL,
                                            msg.id, msg.type);
                                        goto err;
@@ -395,7 +396,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
                case MAP_TYPE_PREFIX:
                        switch (me->map.fec.prefix.af) {
                        case AF_INET:
-                               if (label == MPLS_LABEL_IPV6NULL) {
+                               if (label == MPLS_LABEL_IPV6_EXPLICIT_NULL) {
                                        session_shutdown(nbr, S_BAD_TLV_VAL,
                                            msg.id, msg.type);
                                        goto err;
@@ -404,7 +405,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
                                        goto next;
                                break;
                        case AF_INET6:
-                               if (label == MPLS_LABEL_IPV4NULL) {
+                               if (label == MPLS_LABEL_IPV4_EXPLICIT_NULL) {
                                        session_shutdown(nbr, S_BAD_TLV_VAL,
                                            msg.id, msg.type);
                                        goto err;
@@ -459,6 +460,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
 
  next:
                TAILQ_REMOVE(&mh, me, entry);
+               assert(me != TAILQ_FIRST(&mh));
                free(me);
        }
 
@@ -721,6 +723,14 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
                /* Prefix Length */
                map->fec.prefix.prefixlen = buf[off];
                off += sizeof(uint8_t);
+               if ((map->fec.prefix.af == AF_IPV4
+                    && map->fec.prefix.prefixlen > IPV4_MAX_PREFIXLEN)
+                   || (map->fec.prefix.af == AF_IPV6
+                       && map->fec.prefix.prefixlen > IPV6_MAX_PREFIXLEN)) {
+                       session_shutdown(nbr, S_BAD_TLV_VAL, msg->id,
+                           msg->type);
+                       return (-1);
+               }
                if (len < off + PREFIX_SIZE(map->fec.prefix.prefixlen)) {
                        session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
                            msg->type);