+/*
+ * this is the common IS-REACH decoder it is called
+ * from various EXTD-IS REACH style TLVs (22,24,222)
+ */
+
+static int
+isis_print_ext_is_reach (const u_int8_t *tptr,const char *ident, int tlv) {
+
+ char ident_buffer[20];
+ int subt,subl,tslen;
+ int proc_bytes = 0; /* how many bytes did we process ? */
+
+ if (!TTEST2(*tptr, NODE_ID_LEN))
+ return(0);
+
+ printf("%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN));
+ tptr+=(NODE_ID_LEN);
+
+ if (tlv != TLV_IS_ALIAS_ID) {
+ if (!TTEST2(*tptr, 3))
+ return(0);
+ printf(", Metric: %d",EXTRACT_24BITS(tptr));
+ tptr+=3;
+ }
+
+ if (!TTEST2(*tptr, 1))
+ return(0);
+ tslen=*(tptr++); /* read out subTLV length */
+ proc_bytes=NODE_ID_LEN+3+1;
+ printf(", %ssub-TLVs present",tslen ? "" : "no ");
+ if (tslen) {
+ printf(" (%u)",tslen);
+ while (tslen>0) {
+ if (!TTEST2(*tptr,2))
+ return(0);
+ subt=*(tptr++);
+ subl=*(tptr++);
+ /* prepend the ident string */
+ snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
+ if(!isis_print_is_reach_subtlv(tptr,subt,subl,ident_buffer))
+ return(0);
+ tptr+=subl;
+ tslen-=(subl+2);
+ proc_bytes+=(subl+2);
+ }
+ }
+ return(proc_bytes);
+}
+
+/*
+ * this is the common Multi Topology ID decoder
+ * it is called from various MT-TLVs (222,229,235,237)
+ */
+
+static int
+isis_print_mtid (const u_int8_t *tptr,const char *ident) {
+
+ if (!TTEST2(*tptr, 2))
+ return(0);
+
+ printf("%s%s",
+ ident,
+ tok2str(isis_mt_values,
+ "Reserved for IETF Consensus",
+ ISIS_MASK_MTID(EXTRACT_16BITS(tptr))));
+
+ printf(" Topology (0x%03x), Flags: [%s]",
+ ISIS_MASK_MTID(EXTRACT_16BITS(tptr)),
+ bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr))));
+
+ return(2);
+}
+
+/*
+ * this is the common extended IP reach decoder
+ * it is called from TLVs (135,235,236,237)
+ * we process the TLV and optional subTLVs and return
+ * the amount of processed bytes
+ */
+
+static int
+isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi) {
+
+ char ident_buffer[20];
+ u_int8_t prefix[16]; /* shared copy buffer for IPv4 and IPv6 prefixes */
+ u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen;
+
+ if (!TTEST2(*tptr, 4))
+ return (0);
+ metric = EXTRACT_32BITS(tptr);
+ processed=4;
+ tptr+=4;
+
+ if (afi == IPV4) {
+ if (!TTEST2(*tptr, 1)) /* fetch status byte */
+ return (0);
+ status_byte=*(tptr++);
+ bit_length = status_byte&0x3f;
+ processed++;
+#ifdef INET6
+ } else if (afi == IPV6) {
+ if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
+ return (0);
+ status_byte=*(tptr++);
+ bit_length=*(tptr++);
+ processed+=2;
+#endif
+ } else
+ return (0); /* somebody is fooling us */
+
+ byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
+
+ if (!TTEST2(*tptr, byte_length))
+ return (0);
+ memset(prefix, 0, 16); /* clear the copy buffer */
+ memcpy(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */
+ tptr+=byte_length;
+ processed+=byte_length;
+
+ if (afi == IPV4)
+ printf("%sIPv4 prefix: %15s/%u",
+ ident,
+ ipaddr_string(prefix),
+ bit_length);
+#ifdef INET6
+ if (afi == IPV6)
+ printf("%sIPv6 prefix: %s/%u",
+ ident,
+ ip6addr_string(prefix),
+ bit_length);
+#endif
+
+ printf(", Distribution: %s, Metric: %u",
+ ISIS_MASK_TLV_EXT_IP_UPDOWN(status_byte) ? "down" : "up",
+ metric);
+
+ if (afi == IPV4 && ISIS_MASK_TLV_EXT_IP_SUBTLV(status_byte))
+ printf(", sub-TLVs present");
+#ifdef INET6
+ if (afi == IPV6)
+ printf(", %s%s",
+ ISIS_MASK_TLV_EXT_IP6_IE(status_byte) ? "External" : "Internal",
+ ISIS_MASK_TLV_EXT_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
+#endif
+
+ if ((ISIS_MASK_TLV_EXT_IP_SUBTLV(status_byte) && afi == IPV4) ||
+ (ISIS_MASK_TLV_EXT_IP6_SUBTLV(status_byte) && afi == IPV6)) {
+ /* assume that one prefix can hold more
+ than one subTLV - therefore the first byte must reflect
+ the aggregate bytecount of the subTLVs for this prefix
+ */
+ if (!TTEST2(*tptr, 1))
+ return (0);
+ sublen=*(tptr++);
+ processed+=sublen+1;
+ printf(" (%u)",sublen); /* print out subTLV length */
+
+ while (sublen>0) {
+ if (!TTEST2(*tptr,2))
+ return (0);
+ subtlvtype=*(tptr++);
+ subtlvlen=*(tptr++);
+ /* prepend the ident string */
+ snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
+ if(!isis_print_ip_reach_subtlv(tptr,subtlvtype,subtlvlen,ident_buffer))
+ return(0);
+ tptr+=subtlvlen;
+ sublen-=(subtlvlen+2);
+ }
+ }
+ return (processed);
+}
+