+static const struct tok lsa_opaque_ri_tlv_values[] = {
+ { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
+ { 0, NULL }
+};
+
+static const struct tok lsa_opaque_ri_tlv_cap_values[] = {
+ { 1, "Reserved" },
+ { 2, "Reserved" },
+ { 4, "Reserved" },
+ { 8, "Reserved" },
+ { 16, "graceful restart capable" },
+ { 32, "graceful restart helper" },
+ { 64, "Stub router support" },
+ { 128, "Traffic engineering" },
+ { 256, "p2p over LAN" },
+ { 512, "path computation server" },
+ { 0, NULL }
+};
+
+static const struct tok ospf_lls_tlv_values[] = {
+ { OSPF_LLS_EO, "Extended Options" },
+ { OSPF_LLS_MD5, "MD5 Authentication" },
+ { 0, NULL }
+};
+
+static const struct tok ospf_lls_eo_options[] = {
+ { OSPF_LLS_EO_LR, "LSDB resync" },
+ { OSPF_LLS_EO_RS, "Restart" },
+ { 0, NULL }
+};
+
+int
+ospf_print_grace_lsa(netdissect_options *ndo,
+ const uint8_t *tptr, u_int ls_length) {
+
+ u_int tlv_type, tlv_length;
+
+
+ while (ls_length > 0) {
+ ND_TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length));
+ return -1;
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
+
+ ND_PRINT((ndo, "\n\t %s TLV (%u), length %u, value: ",
+ tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length));
+
+ if (tlv_length > ls_length) {
+ ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length,
+ ls_length));
+ return -1;
+ }
+
+ /* Infinite loop protection. */
+ if (tlv_type == 0 || tlv_length ==0) {
+ return -1;
+ }
+
+ ND_TCHECK2(*tptr, tlv_length);
+ switch(tlv_type) {
+
+ case LS_OPAQUE_GRACE_TLV_PERIOD:
+ if (tlv_length != 4) {
+ ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length));
+ return -1;
+ }
+ ND_PRINT((ndo, "%us", EXTRACT_32BITS(tptr)));
+ break;
+
+ case LS_OPAQUE_GRACE_TLV_REASON:
+ if (tlv_length != 1) {
+ ND_PRINT((ndo, "\n\t Bogus length %u != 1", tlv_length));
+ return -1;
+ }
+ ND_PRINT((ndo, "%s (%u)",
+ tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr),
+ *tptr));
+ break;
+
+ case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
+ if (tlv_length != 4) {
+ ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length));
+ return -1;
+ }
+ ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
+ break;
+
+ default:
+ if (ndo->ndo_vflag <= 1) {
+ if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
+ return -1;
+ }
+ break;
+
+ }
+ /* in OSPF everything has to be 32-bit aligned, including TLVs */
+ if (tlv_length%4 != 0)
+ tlv_length+=4-(tlv_length%4);
+ ls_length-=tlv_length;
+ tptr+=tlv_length;
+ }
+
+ return 0;
+trunc:
+ return -1;
+}
+
+int
+ospf_print_te_lsa(netdissect_options *ndo,
+ const uint8_t *tptr, u_int ls_length) {
+
+ u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
+ u_int priority_level, te_class, count_srlg;
+ union { /* int to float conversion buffer for several subTLVs */
+ float f;
+ uint32_t i;
+ } bw;
+
+ while (ls_length != 0) {
+ ND_TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length));
+ return -1;
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
+
+ ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u",
+ tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length));
+
+ if (tlv_length > ls_length) {
+ ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length,
+ ls_length));
+ return -1;
+ }
+
+ /* Infinite loop protection. */
+ if (tlv_type == 0 || tlv_length ==0) {
+ return -1;
+ }