+/* RFC5613 Section 2.2 (w/o the TLVs) */
+static int
+ospf6_print_lls(const u_char *cp, const u_int len)
+{
+ uint16_t llsdatalen;
+
+ if (len == 0)
+ return 0;
+ if (len < OSPF_LLS_HDRLEN)
+ goto trunc;
+ /* Checksum */
+ TCHECK2(*cp, 2);
+ printf("\n\tLLS Checksum 0x%04x", EXTRACT_16BITS(cp));
+ cp += 2;
+ /* LLS Data Length */
+ TCHECK2(*cp, 2);
+ llsdatalen = EXTRACT_16BITS(cp);
+ printf(", Data Length %u", llsdatalen);
+ if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len)
+ goto trunc;
+ cp += 2;
+ /* LLS TLVs */
+ TCHECK2(*cp, llsdatalen - OSPF_LLS_HDRLEN);
+ /* FIXME: code in print-ospf.c can be reused to decode the TLVs */
+
+ return llsdatalen;
+trunc:
+ return -1;
+}
+
+/* RFC6506 Section 4.1 */
+static int
+ospf6_decode_at(const u_char *cp, const u_int len)
+{
+ uint16_t authdatalen;
+
+ if (len == 0)
+ return 0;
+ if (len < OSPF6_AT_HDRLEN)
+ goto trunc;
+ /* Authentication Type */
+ TCHECK2(*cp, 2);
+ printf("\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp)));
+ cp += 2;
+ /* Auth Data Len */
+ TCHECK2(*cp, 2);
+ authdatalen = EXTRACT_16BITS(cp);
+ printf(", Length %u", authdatalen);
+ if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len)
+ goto trunc;
+ cp += 2;
+ /* Reserved */
+ TCHECK2(*cp, 2);
+ cp += 2;
+ /* Security Association ID */
+ TCHECK2(*cp, 2);
+ printf(", SAID %u", EXTRACT_16BITS(cp));
+ cp += 2;
+ /* Cryptographic Sequence Number (High-Order 32 Bits) */
+ TCHECK2(*cp, 4);
+ printf(", CSN 0x%08x", EXTRACT_32BITS(cp));
+ cp += 4;
+ /* Cryptographic Sequence Number (Low-Order 32 Bits) */
+ TCHECK2(*cp, 4);
+ printf(":%08x", EXTRACT_32BITS(cp));
+ cp += 4;
+ /* Authentication Data */
+ TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN);
+ if (vflag > 1)
+ print_unknown_data(cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN);
+ return 0;
+
+trunc:
+ return 1;
+}
+
+/* The trailing data may include LLS and/or AT data (in this specific order).
+ * LLS data may be present only in Hello and DBDesc packets with the L-bit set.
+ * AT data may be present in Hello and DBDesc packets with the AT-bit set or in
+ * any other packet type, thus decode the AT data regardless of the AT-bit.
+ */
+static int
+ospf6_decode_v3_trailer(const struct ospf6hdr *op, const u_char *cp, const unsigned len)
+{
+ int llslen = 0;
+ u_char lls_hello = op->ospf6_type == OSPF_TYPE_HELLO &&
+ op->ospf6_hello.hello_options & OSPF6_OPTION_L;
+ u_char lls_dd = op->ospf6_type == OSPF_TYPE_DD &&
+ op->ospf6_db.db_options & OSPF6_OPTION_L;
+
+ if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(cp, len)) < 0)
+ goto trunc;
+ return ospf6_decode_at(cp + llslen, len - llslen);
+
+trunc:
+ return 1;
+}
+