Code:  cfm_network_addr_print(netdissect_options *ndo,
                       register const u_char *tptr)
 {
     u_int network_addr_type;
     u_int hexdump =  FALSE;

    /*
     * Altough AFIs are tpically 2 octects wide,
      * 802.1ab specifies that this field width
      * is only once octet
      */
     network_addr_type = *tptr;
     ND_PRINT((ndo, "\n\t  Network Address Type %s (%u)",
            tok2str(af_values, "Unknown", network_addr_type),
           network_addr_type));

    /*
     * Resolve the passed in Address.
      */
     switch(network_addr_type) {
     case AFNUM_INET:
         ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr + 1)));
         break;
 
     case AFNUM_INET6:
         ND_PRINT((ndo, ", %s", ip6addr_string(ndo, tptr + 1)));
         break;
 
    default:
        hexdump = TRUE;
        break;
    }

    return hexdump;
}

Commit Message: CVE-2017-13052/CFM: refine decoding of the Sender ID TLV

In cfm_network_addr_print() add a length argument and use it to validate
the input buffer.

In cfm_print() add a length check for MAC address chassis ID. Supply
cfm_network_addr_print() with the length of its buffer and a correct
pointer to the buffer (it was off-by-one before). Change some error
handling blocks to skip to the next TLV in the current PDU rather than to
stop decoding the PDU. Print the management domain and address contents,
although in hex only so far.

Add some comments to clarify the code flow and to tell exact sections in
IEEE standard documents. Add new error messages and make some existing
messages more specific.

This fixes a buffer over-read discovered by Bhargava Shastry,
SecT/TU Berlin.

Add a test using the capture file supplied by the reporter(s).
CWE ID: CWE-125
 cfm_network_addr_print(netdissect_options *ndo,
                       register const u_char *tptr, const u_int length)
 {
     u_int network_addr_type;
     u_int hexdump =  FALSE;

    /*
     * Altough AFIs are tpically 2 octects wide,
      * 802.1ab specifies that this field width
      * is only once octet
      */
    if (length < 1) {
        ND_PRINT((ndo, "\n\t  Network Address Type (invalid, no data"));
        return hexdump;
    }
    /* The calling function must make any due ND_TCHECK calls. */
     network_addr_type = *tptr;
     ND_PRINT((ndo, "\n\t  Network Address Type %s (%u)",
            tok2str(af_values, "Unknown", network_addr_type),
           network_addr_type));

    /*
     * Resolve the passed in Address.
      */
     switch(network_addr_type) {
     case AFNUM_INET:
        if (length != 1 + 4) {
            ND_PRINT((ndo, "(invalid IPv4 address length %u)", length - 1));
            hexdump = TRUE;
            break;
        }
         ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr + 1)));
         break;
 
     case AFNUM_INET6:
        if (length != 1 + 16) {
            ND_PRINT((ndo, "(invalid IPv6 address length %u)", length - 1));
            hexdump = TRUE;
            break;
        }
         ND_PRINT((ndo, ", %s", ip6addr_string(ndo, tptr + 1)));
         break;
 
    default:
        hexdump = TRUE;
        break;
    }

    return hexdump;
}
