xref: /netbsd-src/external/bsd/tcpdump/dist/print-ospf.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
30f74e101Schristos  *	The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  *
210f74e101Schristos  * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
220f74e101Schristos  */
230f74e101Schristos 
2411b3aaa1Schristos #include <sys/cdefs.h>
250f74e101Schristos #ifndef lint
26*26ba0b50Schristos __RCSID("$NetBSD: print-ospf.c,v 1.11 2024/09/02 16:15:32 christos Exp $");
270f74e101Schristos #endif
280f74e101Schristos 
29dc860a36Sspz /* \summary: Open Shortest Path First (OSPF) printer */
30dc860a36Sspz 
31c74ad251Schristos #include <config.h>
320f74e101Schristos 
33c74ad251Schristos #include "netdissect-stdinc.h"
340f74e101Schristos 
35fdccd7e4Schristos #include "netdissect.h"
360f74e101Schristos #include "addrtoname.h"
370f74e101Schristos #include "extract.h"
380f74e101Schristos #include "gmpls.h"
390f74e101Schristos 
400f74e101Schristos #include "ospf.h"
410f74e101Schristos 
420f74e101Schristos 
43870189d2Schristos static const struct tok ospf_option_values[] = {
44c74ad251Schristos 	{ OSPF_OPTION_MT,	"MultiTopology" }, /* draft-ietf-ospf-mt-09 */
450f74e101Schristos 	{ OSPF_OPTION_E,	"External" },
460f74e101Schristos 	{ OSPF_OPTION_MC,	"Multicast" },
470f74e101Schristos 	{ OSPF_OPTION_NP,	"NSSA" },
480f74e101Schristos 	{ OSPF_OPTION_L,	"LLS" },
490f74e101Schristos 	{ OSPF_OPTION_DC,	"Demand Circuit" },
500f74e101Schristos 	{ OSPF_OPTION_O,	"Opaque" },
510f74e101Schristos 	{ OSPF_OPTION_DN,	"Up/Down" },
520f74e101Schristos 	{ 0,			NULL }
530f74e101Schristos };
540f74e101Schristos 
55870189d2Schristos static const struct tok ospf_authtype_values[] = {
560f74e101Schristos 	{ OSPF_AUTH_NONE,	"none" },
570f74e101Schristos 	{ OSPF_AUTH_SIMPLE,	"simple" },
580f74e101Schristos 	{ OSPF_AUTH_MD5,	"MD5" },
590f74e101Schristos 	{ 0,			NULL }
600f74e101Schristos };
610f74e101Schristos 
62870189d2Schristos static const struct tok ospf_rla_flag_values[] = {
630f74e101Schristos 	{ RLA_FLAG_B,		"ABR" },
640f74e101Schristos 	{ RLA_FLAG_E,		"ASBR" },
65c74ad251Schristos 	{ RLA_FLAG_V,		"Virtual" },
66c74ad251Schristos 	{ RLA_FLAG_W,		"Wildcard" },
67c74ad251Schristos 	{ RLA_FLAG_NT,		"Nt" },
68c74ad251Schristos 	{ RLA_FLAG_H,		"Host" },
690f74e101Schristos 	{ 0,			NULL }
700f74e101Schristos };
710f74e101Schristos 
72870189d2Schristos static const struct tok type2str[] = {
730f74e101Schristos 	{ OSPF_TYPE_HELLO,	"Hello" },
740f74e101Schristos 	{ OSPF_TYPE_DD,		"Database Description" },
750f74e101Schristos 	{ OSPF_TYPE_LS_REQ,	"LS-Request" },
760f74e101Schristos 	{ OSPF_TYPE_LS_UPDATE,	"LS-Update" },
770f74e101Schristos 	{ OSPF_TYPE_LS_ACK,	"LS-Ack" },
780f74e101Schristos 	{ 0,			NULL }
790f74e101Schristos };
800f74e101Schristos 
81870189d2Schristos static const struct tok lsa_values[] = {
820f74e101Schristos 	{ LS_TYPE_ROUTER,       "Router" },
830f74e101Schristos 	{ LS_TYPE_NETWORK,      "Network" },
840f74e101Schristos 	{ LS_TYPE_SUM_IP,       "Summary" },
850f74e101Schristos 	{ LS_TYPE_SUM_ABR,      "ASBR Summary" },
860f74e101Schristos 	{ LS_TYPE_ASE,          "External" },
870f74e101Schristos 	{ LS_TYPE_GROUP,        "Multicast Group" },
880f74e101Schristos 	{ LS_TYPE_NSSA,         "NSSA" },
890f74e101Schristos 	{ LS_TYPE_OPAQUE_LL,    "Link Local Opaque" },
900f74e101Schristos 	{ LS_TYPE_OPAQUE_AL,    "Area Local Opaque" },
910f74e101Schristos 	{ LS_TYPE_OPAQUE_DW,    "Domain Wide Opaque" },
920f74e101Schristos 	{ 0,			NULL }
930f74e101Schristos };
940f74e101Schristos 
95870189d2Schristos static const struct tok ospf_dd_flag_values[] = {
960f74e101Schristos 	{ OSPF_DB_INIT,	        "Init" },
970f74e101Schristos 	{ OSPF_DB_MORE,	        "More" },
980f74e101Schristos 	{ OSPF_DB_MASTER,	"Master" },
990f74e101Schristos     { OSPF_DB_RESYNC,	"OOBResync" },
1000f74e101Schristos 	{ 0,			NULL }
1010f74e101Schristos };
1020f74e101Schristos 
103870189d2Schristos static const struct tok lsa_opaque_values[] = {
1040f74e101Schristos 	{ LS_OPAQUE_TYPE_TE,    "Traffic Engineering" },
1050f74e101Schristos 	{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
1060f74e101Schristos 	{ LS_OPAQUE_TYPE_RI,    "Router Information" },
1070f74e101Schristos 	{ 0,			NULL }
1080f74e101Schristos };
1090f74e101Schristos 
110870189d2Schristos static const struct tok lsa_opaque_te_tlv_values[] = {
1110f74e101Schristos 	{ LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
1120f74e101Schristos 	{ LS_OPAQUE_TE_TLV_LINK,   "Link" },
1130f74e101Schristos 	{ 0,			NULL }
1140f74e101Schristos };
1150f74e101Schristos 
116870189d2Schristos static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
1170f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE,            "Link Type" },
1180f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID,              "Link ID" },
1190f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP,             "Local Interface IP address" },
1200f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP,            "Remote Interface IP address" },
1210f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC,            "Traffic Engineering Metric" },
1220f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW,               "Maximum Bandwidth" },
1230f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW,           "Maximum Reservable Bandwidth" },
1240f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW,             "Unreserved Bandwidth" },
1250f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP,          "Administrative Group" },
1260f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
1270f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
1280f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR,    "Interface Switching Capability" },
1290f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP,    "Shared Risk Link Group" },
1300f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS,       "Bandwidth Constraints" },
1310f74e101Schristos 	{ 0,			NULL }
1320f74e101Schristos };
1330f74e101Schristos 
134870189d2Schristos static const struct tok lsa_opaque_grace_tlv_values[] = {
1350f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_PERIOD,             "Grace Period" },
1360f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_REASON,             "Graceful restart Reason" },
1370f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_INT_ADDRESS,        "IPv4 interface address" },
1380f74e101Schristos 	{ 0,		        NULL }
1390f74e101Schristos };
1400f74e101Schristos 
141870189d2Schristos static const struct tok lsa_opaque_grace_tlv_reason_values[] = {
1420f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN,     "Unknown" },
1430f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART,  "Software Restart" },
1440f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE,  "Software Reload/Upgrade" },
1450f74e101Schristos 	{ LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH,   "Control Processor Switch" },
1460f74e101Schristos 	{ 0,		        NULL }
1470f74e101Schristos };
1480f74e101Schristos 
149870189d2Schristos static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
1500f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
1510f74e101Schristos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA,  "Multi-Access" },
1520f74e101Schristos 	{ 0,			NULL }
1530f74e101Schristos };
1540f74e101Schristos 
155870189d2Schristos static const struct tok lsa_opaque_ri_tlv_values[] = {
1560f74e101Schristos 	{ LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
1570f74e101Schristos 	{ 0,		        NULL }
1580f74e101Schristos };
1590f74e101Schristos 
160870189d2Schristos static const struct tok lsa_opaque_ri_tlv_cap_values[] = {
1610f74e101Schristos 	{ 1, "Reserved" },
1620f74e101Schristos 	{ 2, "Reserved" },
1630f74e101Schristos 	{ 4, "Reserved" },
1640f74e101Schristos 	{ 8, "Reserved" },
1650f74e101Schristos 	{ 16, "graceful restart capable" },
1660f74e101Schristos 	{ 32, "graceful restart helper" },
1670f74e101Schristos 	{ 64, "Stub router support" },
1680f74e101Schristos 	{ 128, "Traffic engineering" },
1690f74e101Schristos 	{ 256, "p2p over LAN" },
1700f74e101Schristos 	{ 512, "path computation server" },
1710f74e101Schristos 	{ 0,		        NULL }
1720f74e101Schristos };
1730f74e101Schristos 
174870189d2Schristos static const struct tok ospf_lls_tlv_values[] = {
1750f74e101Schristos 	{ OSPF_LLS_EO,	"Extended Options" },
1760f74e101Schristos 	{ OSPF_LLS_MD5,	"MD5 Authentication" },
1770f74e101Schristos 	{ 0,	NULL }
1780f74e101Schristos };
1790f74e101Schristos 
180870189d2Schristos static const struct tok ospf_lls_eo_options[] = {
1810f74e101Schristos 	{ OSPF_LLS_EO_LR,	"LSDB resync" },
1820f74e101Schristos 	{ OSPF_LLS_EO_RS,	"Restart" },
1830f74e101Schristos 	{ 0,	NULL }
1840f74e101Schristos };
1850f74e101Schristos 
1860f74e101Schristos int
187c74ad251Schristos ospf_grace_lsa_print(netdissect_options *ndo,
188c74ad251Schristos                      const u_char *tptr, u_int ls_length)
189ba2ff121Schristos {
1900f74e101Schristos     u_int tlv_type, tlv_length;
1910f74e101Schristos 
1920f74e101Schristos 
1930f74e101Schristos     while (ls_length > 0) {
194c74ad251Schristos         ND_TCHECK_4(tptr);
1950f74e101Schristos         if (ls_length < 4) {
196c74ad251Schristos             ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length);
1970f74e101Schristos             return -1;
1980f74e101Schristos         }
199c74ad251Schristos         tlv_type = GET_BE_U_2(tptr);
200c74ad251Schristos         tlv_length = GET_BE_U_2(tptr + 2);
2010f74e101Schristos         tptr+=4;
2020f74e101Schristos         ls_length-=4;
2030f74e101Schristos 
204c74ad251Schristos         ND_PRINT("\n\t    %s TLV (%u), length %u, value: ",
2050f74e101Schristos                tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
2060f74e101Schristos                tlv_type,
207c74ad251Schristos                tlv_length);
2080f74e101Schristos 
2090f74e101Schristos         if (tlv_length > ls_length) {
210c74ad251Schristos             ND_PRINT("\n\t    Bogus length %u > %u", tlv_length,
211c74ad251Schristos                    ls_length);
2120f74e101Schristos             return -1;
2130f74e101Schristos         }
2140f74e101Schristos 
2150f74e101Schristos         /* Infinite loop protection. */
2160f74e101Schristos         if (tlv_type == 0 || tlv_length ==0) {
2170f74e101Schristos             return -1;
2180f74e101Schristos         }
2190f74e101Schristos 
220c74ad251Schristos         ND_TCHECK_LEN(tptr, tlv_length);
2210f74e101Schristos         switch(tlv_type) {
2220f74e101Schristos 
2230f74e101Schristos         case LS_OPAQUE_GRACE_TLV_PERIOD:
2240f74e101Schristos             if (tlv_length != 4) {
225c74ad251Schristos                 ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
2260f74e101Schristos                 return -1;
2270f74e101Schristos             }
228c74ad251Schristos             ND_PRINT("%us", GET_BE_U_4(tptr));
2290f74e101Schristos             break;
2300f74e101Schristos 
2310f74e101Schristos         case LS_OPAQUE_GRACE_TLV_REASON:
2320f74e101Schristos             if (tlv_length != 1) {
233c74ad251Schristos                 ND_PRINT("\n\t    Bogus length %u != 1", tlv_length);
2340f74e101Schristos                 return -1;
2350f74e101Schristos             }
236c74ad251Schristos             ND_PRINT("%s (%u)",
237c74ad251Schristos                    tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", GET_U_1(tptr)),
238c74ad251Schristos                    GET_U_1(tptr));
2390f74e101Schristos             break;
2400f74e101Schristos 
2410f74e101Schristos         case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
2420f74e101Schristos             if (tlv_length != 4) {
243c74ad251Schristos                 ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
2440f74e101Schristos                 return -1;
2450f74e101Schristos             }
246c74ad251Schristos             ND_PRINT("%s", GET_IPADDR_STRING(tptr));
2470f74e101Schristos             break;
2480f74e101Schristos 
2490f74e101Schristos         default:
250b3a00663Schristos             if (ndo->ndo_vflag <= 1) {
251b3a00663Schristos                 if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
2520f74e101Schristos                     return -1;
2530f74e101Schristos             }
2540f74e101Schristos             break;
2550f74e101Schristos 
2560f74e101Schristos         }
2570f74e101Schristos         /* in OSPF everything has to be 32-bit aligned, including TLVs */
2580f74e101Schristos         if (tlv_length%4 != 0)
2590f74e101Schristos             tlv_length+=4-(tlv_length%4);
2600f74e101Schristos         ls_length-=tlv_length;
2610f74e101Schristos         tptr+=tlv_length;
2620f74e101Schristos     }
2630f74e101Schristos 
2640f74e101Schristos     return 0;
2650f74e101Schristos trunc:
2660f74e101Schristos     return -1;
2670f74e101Schristos }
2680f74e101Schristos 
2690f74e101Schristos int
270c74ad251Schristos ospf_te_lsa_print(netdissect_options *ndo,
271c74ad251Schristos                   const u_char *tptr, u_int ls_length)
272ba2ff121Schristos {
2730f74e101Schristos     u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
2740f74e101Schristos     u_int priority_level, te_class, count_srlg;
2750f74e101Schristos     union { /* int to float conversion buffer for several subTLVs */
2760f74e101Schristos         float f;
277b3a00663Schristos         uint32_t i;
2780f74e101Schristos     } bw;
2790f74e101Schristos 
2800f74e101Schristos     while (ls_length != 0) {
281c74ad251Schristos         ND_TCHECK_4(tptr);
2820f74e101Schristos         if (ls_length < 4) {
283c74ad251Schristos             ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length);
2840f74e101Schristos             return -1;
2850f74e101Schristos         }
286c74ad251Schristos         tlv_type = GET_BE_U_2(tptr);
287c74ad251Schristos         tlv_length = GET_BE_U_2(tptr + 2);
2880f74e101Schristos         tptr+=4;
2890f74e101Schristos         ls_length-=4;
2900f74e101Schristos 
291c74ad251Schristos         ND_PRINT("\n\t    %s TLV (%u), length: %u",
2920f74e101Schristos                tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
2930f74e101Schristos                tlv_type,
294c74ad251Schristos                tlv_length);
2950f74e101Schristos 
2960f74e101Schristos         if (tlv_length > ls_length) {
297c74ad251Schristos             ND_PRINT("\n\t    Bogus length %u > %u", tlv_length,
298c74ad251Schristos                    ls_length);
2990f74e101Schristos             return -1;
3000f74e101Schristos         }
3010f74e101Schristos 
3020f74e101Schristos         /* Infinite loop protection. */
3030f74e101Schristos         if (tlv_type == 0 || tlv_length ==0) {
3040f74e101Schristos             return -1;
3050f74e101Schristos         }
3060f74e101Schristos 
3070f74e101Schristos         switch(tlv_type) {
3080f74e101Schristos         case LS_OPAQUE_TE_TLV_LINK:
309c74ad251Schristos             while (tlv_length != 0) {
3100f74e101Schristos                 if (tlv_length < 4) {
311c74ad251Schristos                     ND_PRINT("\n\t    Remaining TLV length %u < 4",
312c74ad251Schristos                            tlv_length);
3130f74e101Schristos                     return -1;
3140f74e101Schristos                 }
315c74ad251Schristos                 subtlv_type = GET_BE_U_2(tptr);
316c74ad251Schristos                 subtlv_length = GET_BE_U_2(tptr + 2);
3170f74e101Schristos                 tptr+=4;
3180f74e101Schristos                 tlv_length-=4;
3190f74e101Schristos 
320fdccd7e4Schristos 		/* Infinite loop protection */
321fdccd7e4Schristos 		if (subtlv_type == 0 || subtlv_length == 0)
322fdccd7e4Schristos 		    goto invalid;
323fdccd7e4Schristos 
324c74ad251Schristos                 ND_PRINT("\n\t      %s subTLV (%u), length: %u",
3250f74e101Schristos                        tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
3260f74e101Schristos                        subtlv_type,
327c74ad251Schristos                        subtlv_length);
3280f74e101Schristos 
329c74ad251Schristos                 if (tlv_length < subtlv_length) {
330c74ad251Schristos                     ND_PRINT("\n\t    Remaining TLV length %u < %u",
331c74ad251Schristos                            tlv_length + 4, subtlv_length + 4);
332c74ad251Schristos                     return -1;
333c74ad251Schristos                 }
334c74ad251Schristos                 ND_TCHECK_LEN(tptr, subtlv_length);
3350f74e101Schristos                 switch(subtlv_type) {
3360f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
337fdccd7e4Schristos 		    if (subtlv_length != 4) {
338c74ad251Schristos 			ND_PRINT(" != 4");
339fdccd7e4Schristos 			goto invalid;
340fdccd7e4Schristos 		    }
341c74ad251Schristos                     ND_PRINT(", 0x%08x", GET_BE_U_4(tptr));
3420f74e101Schristos                     break;
3430f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
3440f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
345fdccd7e4Schristos 		    if (subtlv_length != 4 && subtlv_length != 8) {
346c74ad251Schristos 			ND_PRINT(" != 4 && != 8");
347fdccd7e4Schristos 			goto invalid;
348fdccd7e4Schristos 		    }
349c74ad251Schristos                     ND_PRINT(", %s (0x%08x)",
350c74ad251Schristos                            GET_IPADDR_STRING(tptr),
351c74ad251Schristos                            GET_BE_U_4(tptr));
3520f74e101Schristos                     if (subtlv_length == 8) /* rfc4203 */
353c74ad251Schristos                         ND_PRINT(", %s (0x%08x)",
354c74ad251Schristos                                GET_IPADDR_STRING(tptr+4),
355c74ad251Schristos                                GET_BE_U_4(tptr + 4));
3560f74e101Schristos                     break;
3570f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
3580f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
359fdccd7e4Schristos 		    if (subtlv_length != 4) {
360c74ad251Schristos 			ND_PRINT(" != 4");
361fdccd7e4Schristos 			goto invalid;
362fdccd7e4Schristos 		    }
363c74ad251Schristos                     ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
3640f74e101Schristos                     break;
3650f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
3660f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
367fdccd7e4Schristos 		    if (subtlv_length != 4) {
368c74ad251Schristos 			ND_PRINT(" != 4");
369fdccd7e4Schristos 			goto invalid;
370fdccd7e4Schristos 		    }
371c74ad251Schristos                     bw.i = GET_BE_U_4(tptr);
372c74ad251Schristos                     ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000);
3730f74e101Schristos                     break;
3740f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
375fdccd7e4Schristos 		    if (subtlv_length != 32) {
376c74ad251Schristos 			ND_PRINT(" != 32");
377fdccd7e4Schristos 			goto invalid;
378fdccd7e4Schristos 		    }
3790f74e101Schristos                     for (te_class = 0; te_class < 8; te_class++) {
380c74ad251Schristos                         bw.i = GET_BE_U_4(tptr + te_class * 4);
381c74ad251Schristos                         ND_PRINT("\n\t\tTE-Class %u: %.3f Mbps",
3820f74e101Schristos                                te_class,
383c74ad251Schristos                                bw.f * 8 / 1000000);
3840f74e101Schristos                     }
3850f74e101Schristos                     break;
3860f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
387fdccd7e4Schristos 		    if (subtlv_length < 4) {
388c74ad251Schristos 			ND_PRINT(" < 4");
389fdccd7e4Schristos 			goto invalid;
390fdccd7e4Schristos 		    }
391fdccd7e4Schristos 		    /* BC Model Id (1 octet) + Reserved (3 octets) */
392c74ad251Schristos                     ND_PRINT("\n\t\tBandwidth Constraints Model ID: %s (%u)",
393c74ad251Schristos                            tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)),
394c74ad251Schristos                            GET_U_1(tptr));
395fdccd7e4Schristos 		    if (subtlv_length % 4 != 0) {
396c74ad251Schristos 			ND_PRINT("\n\t\tlength %u != N x 4", subtlv_length);
397fdccd7e4Schristos 			goto invalid;
398fdccd7e4Schristos 		    }
399fdccd7e4Schristos 		    if (subtlv_length > 36) {
400c74ad251Schristos 			ND_PRINT("\n\t\tlength %u > 36", subtlv_length);
401fdccd7e4Schristos 			goto invalid;
402fdccd7e4Schristos 		    }
4030f74e101Schristos                     /* decode BCs until the subTLV ends */
4040f74e101Schristos                     for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
405c74ad251Schristos                         bw.i = GET_BE_U_4(tptr + 4 + te_class * 4);
406c74ad251Schristos                         ND_PRINT("\n\t\t  Bandwidth constraint CT%u: %.3f Mbps",
4070f74e101Schristos                                te_class,
408c74ad251Schristos                                bw.f * 8 / 1000000);
4090f74e101Schristos                     }
4100f74e101Schristos                     break;
4110f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
412fdccd7e4Schristos 		    if (subtlv_length != 4) {
413c74ad251Schristos 			ND_PRINT(" != 4");
414fdccd7e4Schristos 			goto invalid;
415fdccd7e4Schristos 		    }
416c74ad251Schristos                     ND_PRINT(", Metric %u", GET_BE_U_4(tptr));
4170f74e101Schristos                     break;
4180f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
419fdccd7e4Schristos 		    /* Protection Cap (1 octet) + Reserved ((3 octets) */
420fdccd7e4Schristos 		    if (subtlv_length != 4) {
421c74ad251Schristos 			ND_PRINT(" != 4");
422fdccd7e4Schristos 			goto invalid;
423fdccd7e4Schristos 		    }
424c74ad251Schristos                     ND_PRINT(", %s",
425c74ad251Schristos                              bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr)));
4260f74e101Schristos                     break;
4270f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
428fdccd7e4Schristos 		    if (subtlv_length < 36) {
429c74ad251Schristos 			ND_PRINT(" < 36");
430fdccd7e4Schristos 			goto invalid;
431fdccd7e4Schristos 		    }
432fdccd7e4Schristos 		    /* Switching Cap (1 octet) + Encoding (1) +  Reserved (2) */
433c74ad251Schristos                     ND_PRINT("\n\t\tInterface Switching Capability: %s",
434c74ad251Schristos                            tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1((tptr))));
435c74ad251Schristos                     ND_PRINT("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
436c74ad251Schristos                            tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1))));
4370f74e101Schristos                     for (priority_level = 0; priority_level < 8; priority_level++) {
438c74ad251Schristos                         bw.i = GET_BE_U_4(tptr + 4 + (priority_level * 4));
439c74ad251Schristos                         ND_PRINT("\n\t\t  priority level %u: %.3f Mbps",
4400f74e101Schristos                                priority_level,
441c74ad251Schristos                                bw.f * 8 / 1000000);
4420f74e101Schristos                     }
4430f74e101Schristos                     break;
4440f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
445fdccd7e4Schristos 		    if (subtlv_length != 1) {
446c74ad251Schristos 			ND_PRINT(" != 1");
447fdccd7e4Schristos 			goto invalid;
448fdccd7e4Schristos 		    }
449c74ad251Schristos                     ND_PRINT(", %s (%u)",
450c74ad251Schristos                            tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",GET_U_1(tptr)),
451c74ad251Schristos                            GET_U_1(tptr));
4520f74e101Schristos                     break;
4530f74e101Schristos 
4540f74e101Schristos                 case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
455fdccd7e4Schristos 		    if (subtlv_length % 4 != 0) {
456c74ad251Schristos 			ND_PRINT(" != N x 4");
457fdccd7e4Schristos 			goto invalid;
458fdccd7e4Schristos 		    }
4590f74e101Schristos                     count_srlg = subtlv_length / 4;
4600f74e101Schristos                     if (count_srlg != 0)
461c74ad251Schristos                         ND_PRINT("\n\t\t  Shared risk group: ");
4620f74e101Schristos                     while (count_srlg > 0) {
463c74ad251Schristos                         bw.i = GET_BE_U_4(tptr);
464c74ad251Schristos                         ND_PRINT("%u", bw.i);
4650f74e101Schristos                         tptr+=4;
4660f74e101Schristos                         count_srlg--;
4670f74e101Schristos                         if (count_srlg > 0)
468c74ad251Schristos                             ND_PRINT(", ");
4690f74e101Schristos                     }
4700f74e101Schristos                     break;
4710f74e101Schristos 
4720f74e101Schristos                 default:
473b3a00663Schristos                     if (ndo->ndo_vflag <= 1) {
474b3a00663Schristos                         if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
4750f74e101Schristos                             return -1;
4760f74e101Schristos                     }
4770f74e101Schristos                     break;
4780f74e101Schristos                 }
4790f74e101Schristos                 /* in OSPF everything has to be 32-bit aligned, including subTLVs */
4800f74e101Schristos                 if (subtlv_length%4 != 0)
4810f74e101Schristos                     subtlv_length+=4-(subtlv_length%4);
4820f74e101Schristos 
483c74ad251Schristos                 if (tlv_length < subtlv_length) {
484c74ad251Schristos                     ND_PRINT("\n\t    Remaining TLV length %u < %u",
485c74ad251Schristos                            tlv_length + 4, subtlv_length + 4);
486c74ad251Schristos                     return -1;
487c74ad251Schristos                 }
4880f74e101Schristos                 tlv_length-=subtlv_length;
4890f74e101Schristos                 tptr+=subtlv_length;
4900f74e101Schristos 
4910f74e101Schristos             }
4920f74e101Schristos             break;
4930f74e101Schristos 
4940f74e101Schristos         case LS_OPAQUE_TE_TLV_ROUTER:
4950f74e101Schristos             if (tlv_length < 4) {
496c74ad251Schristos                 ND_PRINT("\n\t    TLV length %u < 4", tlv_length);
4970f74e101Schristos                 return -1;
4980f74e101Schristos             }
499c74ad251Schristos             ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
5000f74e101Schristos             break;
5010f74e101Schristos 
5020f74e101Schristos         default:
503b3a00663Schristos             if (ndo->ndo_vflag <= 1) {
504b3a00663Schristos                 if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
5050f74e101Schristos                     return -1;
5060f74e101Schristos             }
5070f74e101Schristos             break;
5080f74e101Schristos         }
5090f74e101Schristos         /* in OSPF everything has to be 32-bit aligned, including TLVs */
5100f74e101Schristos         if (tlv_length%4 != 0)
5110f74e101Schristos             tlv_length+=4-(tlv_length%4);
512c74ad251Schristos         if (tlv_length > ls_length) {
513c74ad251Schristos             ND_PRINT("\n\t    Bogus padded length %u > %u", tlv_length,
514c74ad251Schristos                    ls_length);
515c74ad251Schristos             return -1;
516c74ad251Schristos         }
5170f74e101Schristos         ls_length-=tlv_length;
5180f74e101Schristos         tptr+=tlv_length;
5190f74e101Schristos     }
5200f74e101Schristos     return 0;
5210f74e101Schristos trunc:
5220f74e101Schristos     return -1;
523fdccd7e4Schristos invalid:
524c74ad251Schristos     nd_print_invalid(ndo);
525fdccd7e4Schristos     return -1;
5260f74e101Schristos }
5270f74e101Schristos 
5280f74e101Schristos static int
529b3a00663Schristos ospf_print_lshdr(netdissect_options *ndo,
530c74ad251Schristos                  const struct lsa_hdr *lshp)
5310f74e101Schristos {
532c74ad251Schristos         u_int ls_type;
5330f74e101Schristos         u_int ls_length;
5340f74e101Schristos 
535c74ad251Schristos         ls_length = GET_BE_U_2(lshp->ls_length);
5360f74e101Schristos         if (ls_length < sizeof(struct lsa_hdr)) {
537c74ad251Schristos                 ND_PRINT("\n\t    Bogus length %u < header (%zu)", ls_length,
538c74ad251Schristos                     sizeof(struct lsa_hdr));
5390f74e101Schristos                 return(-1);
5400f74e101Schristos         }
541c74ad251Schristos         ND_PRINT("\n\t  Advertising Router %s, seq 0x%08x, age %us, length %zu",
542c74ad251Schristos                   GET_IPADDR_STRING(lshp->ls_router),
543c74ad251Schristos                   GET_BE_U_4(lshp->ls_seq),
544c74ad251Schristos                   GET_BE_U_2(lshp->ls_age),
545c74ad251Schristos                   ls_length - sizeof(struct lsa_hdr));
546c74ad251Schristos         ls_type = GET_U_1(lshp->ls_type);
547c74ad251Schristos         switch (ls_type) {
5480f74e101Schristos         /* the LSA header for opaque LSAs was slightly changed */
5490f74e101Schristos         case LS_TYPE_OPAQUE_LL:
5500f74e101Schristos         case LS_TYPE_OPAQUE_AL:
5510f74e101Schristos         case LS_TYPE_OPAQUE_DW:
552c74ad251Schristos             ND_PRINT("\n\t    %s LSA (%u), Opaque-Type %s LSA (%u), Opaque-ID %u",
553c74ad251Schristos                    tok2str(lsa_values,"unknown",ls_type),
554c74ad251Schristos                    ls_type,
5550f74e101Schristos 
5560f74e101Schristos 		   tok2str(lsa_opaque_values,
5570f74e101Schristos 			   "unknown",
558c74ad251Schristos 			   GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type)),
559c74ad251Schristos 		   GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type),
560c74ad251Schristos 		   GET_BE_U_3(lshp->un_lsa_id.opaque_field.opaque_id)
5610f74e101Schristos 
562c74ad251Schristos                    );
5630f74e101Schristos             break;
5640f74e101Schristos 
5650f74e101Schristos         /* all other LSA types use regular style LSA headers */
5660f74e101Schristos         default:
567c74ad251Schristos             ND_PRINT("\n\t    %s LSA (%u), LSA-ID: %s",
568c74ad251Schristos                    tok2str(lsa_values,"unknown",ls_type),
569c74ad251Schristos                    ls_type,
570c74ad251Schristos                    GET_IPADDR_STRING(lshp->un_lsa_id.lsa_id));
5710f74e101Schristos             break;
5720f74e101Schristos         }
573c74ad251Schristos         ND_PRINT("\n\t    Options: [%s]",
574c74ad251Schristos 		 bittok2str(ospf_option_values, "none", GET_U_1(lshp->ls_options)));
5750f74e101Schristos 
5760f74e101Schristos         return (ls_length);
5770f74e101Schristos }
5780f74e101Schristos 
5790f74e101Schristos /* draft-ietf-ospf-mt-09 */
580870189d2Schristos static const struct tok ospf_topology_values[] = {
5810f74e101Schristos     { 0, "default" },
5820f74e101Schristos     { 1, "multicast" },
5830f74e101Schristos     { 2, "management" },
5840f74e101Schristos     { 0, NULL }
5850f74e101Schristos };
5860f74e101Schristos 
5870f74e101Schristos /*
5880f74e101Schristos  * Print all the per-topology metrics.
5890f74e101Schristos  */
590c74ad251Schristos static void
591b3a00663Schristos ospf_print_tos_metrics(netdissect_options *ndo,
592b3a00663Schristos                        const union un_tos *tos)
5930f74e101Schristos {
594c74ad251Schristos     u_int metric_count;
595c74ad251Schristos     u_int toscount;
596c74ad251Schristos     u_int tos_type;
5970f74e101Schristos 
598c74ad251Schristos     toscount = GET_U_1(tos->link.link_tos_count)+1;
5990f74e101Schristos     metric_count = 0;
6000f74e101Schristos 
6010f74e101Schristos     /*
6020f74e101Schristos      * All but the first metric contain a valid topology id.
6030f74e101Schristos      */
604c74ad251Schristos     while (toscount != 0) {
605c74ad251Schristos         tos_type = GET_U_1(tos->metrics.tos_type);
606c74ad251Schristos         ND_PRINT("\n\t\ttopology %s (%u), metric %u",
607fdccd7e4Schristos                tok2str(ospf_topology_values, "Unknown",
608c74ad251Schristos                        metric_count ? tos_type : 0),
609c74ad251Schristos                metric_count ? tos_type : 0,
610c74ad251Schristos                GET_BE_U_2(tos->metrics.tos_metric));
6110f74e101Schristos         metric_count++;
6120f74e101Schristos         tos++;
6130f74e101Schristos         toscount--;
6140f74e101Schristos     }
6150f74e101Schristos }
6160f74e101Schristos 
6170f74e101Schristos /*
6180f74e101Schristos  * Print a single link state advertisement.  If truncated or if LSA length
6190f74e101Schristos  * field is less than the length of the LSA header, return NULl, else
6200f74e101Schristos  * return pointer to data past end of LSA.
6210f74e101Schristos  */
622b3a00663Schristos static const uint8_t *
623b3a00663Schristos ospf_print_lsa(netdissect_options *ndo,
624c74ad251Schristos                const struct lsa *lsap)
6250f74e101Schristos {
626c74ad251Schristos 	const uint8_t *ls_end;
627c74ad251Schristos 	const struct rlalink *rlp;
628c74ad251Schristos 	const nd_ipv4 *ap;
629c74ad251Schristos 	const struct aslametric *almp;
630c74ad251Schristos 	const struct mcla *mcp;
631c74ad251Schristos 	const uint8_t *lp;
632c74ad251Schristos 	u_int tlv_type, tlv_length, rla_count, topology;
633c74ad251Schristos 	int ospf_print_lshdr_ret;
634c74ad251Schristos 	u_int ls_length;
635b3a00663Schristos 	const uint8_t *tptr;
6360f74e101Schristos 
637fdccd7e4Schristos 	tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
638c74ad251Schristos 	ospf_print_lshdr_ret = ospf_print_lshdr(ndo, &lsap->ls_hdr);
639c74ad251Schristos 	if (ospf_print_lshdr_ret < 0)
6400f74e101Schristos 		return(NULL);
641c74ad251Schristos 	ls_length = (u_int)ospf_print_lshdr_ret;
642fdccd7e4Schristos 	ls_end = (const uint8_t *)lsap + ls_length;
643c74ad251Schristos 	/*
644c74ad251Schristos 	 * ospf_print_lshdr() returns -1 if the length is too short,
645c74ad251Schristos 	 * so we know ls_length is >= sizeof(struct lsa_hdr).
646c74ad251Schristos 	 */
6470f74e101Schristos 	ls_length -= sizeof(struct lsa_hdr);
6480f74e101Schristos 
649c74ad251Schristos 	switch (GET_U_1(lsap->ls_hdr.ls_type)) {
6500f74e101Schristos 
6510f74e101Schristos 	case LS_TYPE_ROUTER:
652c74ad251Schristos 		ND_PRINT("\n\t    Router LSA Options: [%s]",
653c74ad251Schristos 		          bittok2str(ospf_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
6540f74e101Schristos 
655c74ad251Schristos 		rla_count = GET_BE_U_2(lsap->lsa_un.un_rla.rla_count);
656c74ad251Schristos 		ND_TCHECK_SIZE(lsap->lsa_un.un_rla.rla_link);
6570f74e101Schristos 		rlp = lsap->lsa_un.un_rla.rla_link;
658c74ad251Schristos 		for (u_int i = rla_count; i != 0; i--) {
659c74ad251Schristos 			ND_TCHECK_SIZE(rlp);
660c74ad251Schristos 			switch (GET_U_1(rlp->un_tos.link.link_type)) {
6610f74e101Schristos 
6620f74e101Schristos 			case RLA_TYPE_VIRTUAL:
663c74ad251Schristos 				ND_PRINT("\n\t      Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
664c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_id),
665c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_data));
6660f74e101Schristos 				break;
6670f74e101Schristos 
6680f74e101Schristos 			case RLA_TYPE_ROUTER:
669c74ad251Schristos 				ND_PRINT("\n\t      Neighbor Router-ID: %s, Interface Address: %s",
670c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_id),
671c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_data));
6720f74e101Schristos 				break;
6730f74e101Schristos 
6740f74e101Schristos 			case RLA_TYPE_TRANSIT:
675c74ad251Schristos 				ND_PRINT("\n\t      Neighbor Network-ID: %s, Interface Address: %s",
676c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_id),
677c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_data));
6780f74e101Schristos 				break;
6790f74e101Schristos 
6800f74e101Schristos 			case RLA_TYPE_STUB:
681c74ad251Schristos 				ND_PRINT("\n\t      Stub Network: %s, Mask: %s",
682c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_id),
683c74ad251Schristos 				    GET_IPADDR_STRING(rlp->link_data));
6840f74e101Schristos 				break;
6850f74e101Schristos 
6860f74e101Schristos 			default:
687c74ad251Schristos 				ND_PRINT("\n\t      Unknown Router Link Type (%u)",
688c74ad251Schristos 				    GET_U_1(rlp->un_tos.link.link_type));
6890f74e101Schristos 				return (ls_end);
6900f74e101Schristos 			}
6910f74e101Schristos 
692c74ad251Schristos 			ospf_print_tos_metrics(ndo, &rlp->un_tos);
6930f74e101Schristos 
694fdccd7e4Schristos 			rlp = (const struct rlalink *)((const u_char *)(rlp + 1) +
695c74ad251Schristos 			    (GET_U_1(rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
6960f74e101Schristos 		}
6970f74e101Schristos 		break;
6980f74e101Schristos 
6990f74e101Schristos 	case LS_TYPE_NETWORK:
700c74ad251Schristos 		ND_PRINT("\n\t    Mask %s\n\t    Connected Routers:",
701c74ad251Schristos 		    GET_IPADDR_STRING(lsap->lsa_un.un_nla.nla_mask));
7020f74e101Schristos 		ap = lsap->lsa_un.un_nla.nla_router;
703fdccd7e4Schristos 		while ((const u_char *)ap < ls_end) {
704c74ad251Schristos 			ND_PRINT("\n\t      %s", GET_IPADDR_STRING(ap));
7050f74e101Schristos 			++ap;
7060f74e101Schristos 		}
7070f74e101Schristos 		break;
7080f74e101Schristos 
7090f74e101Schristos 	case LS_TYPE_SUM_IP:
710c74ad251Schristos 		ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
711c74ad251Schristos 		ND_PRINT("\n\t    Mask %s",
712c74ad251Schristos 		    GET_IPADDR_STRING(lsap->lsa_un.un_sla.sla_mask));
713c74ad251Schristos 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
714c74ad251Schristos 		lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
715c74ad251Schristos 		while (lp < ls_end) {
716c74ad251Schristos 			uint32_t ul;
7170f74e101Schristos 
718c74ad251Schristos 			ul = GET_BE_U_4(lp);
7190f74e101Schristos                         topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
720c74ad251Schristos 			ND_PRINT("\n\t\ttopology %s (%u) metric %u",
721fdccd7e4Schristos                                tok2str(ospf_topology_values, "Unknown", topology),
7220f74e101Schristos                                topology,
723c74ad251Schristos                                ul & SLA_MASK_METRIC);
724c74ad251Schristos 			lp += 4;
7250f74e101Schristos 		}
7260f74e101Schristos 		break;
7270f74e101Schristos 
7280f74e101Schristos 	case LS_TYPE_SUM_ABR:
729c74ad251Schristos 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
730c74ad251Schristos 		lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
731c74ad251Schristos 		while (lp < ls_end) {
732c74ad251Schristos 			uint32_t ul;
7330f74e101Schristos 
734c74ad251Schristos 			ul = GET_BE_U_4(lp);
7350f74e101Schristos                         topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
736c74ad251Schristos 			ND_PRINT("\n\t\ttopology %s (%u) metric %u",
737fdccd7e4Schristos                                tok2str(ospf_topology_values, "Unknown", topology),
7380f74e101Schristos                                topology,
739c74ad251Schristos                                ul & SLA_MASK_METRIC);
740c74ad251Schristos 			lp += 4;
7410f74e101Schristos 		}
7420f74e101Schristos 		break;
7430f74e101Schristos 
7440f74e101Schristos 	case LS_TYPE_ASE:
7450f74e101Schristos         case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */
746c74ad251Schristos 		ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
747c74ad251Schristos 		ND_PRINT("\n\t    Mask %s",
748c74ad251Schristos 		    GET_IPADDR_STRING(lsap->lsa_un.un_asla.asla_mask));
7490f74e101Schristos 
750c74ad251Schristos 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
7510f74e101Schristos 		almp = lsap->lsa_un.un_asla.asla_metric;
752fdccd7e4Schristos 		while ((const u_char *)almp < ls_end) {
753c74ad251Schristos 			uint32_t ul;
7540f74e101Schristos 
755c74ad251Schristos 			ul = GET_BE_U_4(almp->asla_tosmetric);
7560f74e101Schristos                         topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
757c74ad251Schristos 			ND_PRINT("\n\t\ttopology %s (%u), type %u, metric",
758fdccd7e4Schristos                                tok2str(ospf_topology_values, "Unknown", topology),
7590f74e101Schristos                                topology,
760c74ad251Schristos                                (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1);
7610f74e101Schristos 			if ((ul & ASLA_MASK_METRIC) == 0xffffff)
762c74ad251Schristos 				ND_PRINT(" infinite");
7630f74e101Schristos 			else
764c74ad251Schristos 				ND_PRINT(" %u", (ul & ASLA_MASK_METRIC));
7650f74e101Schristos 
766c74ad251Schristos 			if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_forward) != 0) {
767c74ad251Schristos 				ND_PRINT(", forward %s", GET_IPADDR_STRING(almp->asla_forward));
7680f74e101Schristos 			}
769c74ad251Schristos 			if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_tag) != 0) {
770c74ad251Schristos 				ND_PRINT(", tag %s", GET_IPADDR_STRING(almp->asla_tag));
7710f74e101Schristos 			}
7720f74e101Schristos 			++almp;
7730f74e101Schristos 		}
7740f74e101Schristos 		break;
7750f74e101Schristos 
7760f74e101Schristos 	case LS_TYPE_GROUP:
7770f74e101Schristos 		/* Multicast extensions as of 23 July 1991 */
7780f74e101Schristos 		mcp = lsap->lsa_un.un_mcla;
779fdccd7e4Schristos 		while ((const u_char *)mcp < ls_end) {
780c74ad251Schristos 			switch (GET_BE_U_4(mcp->mcla_vtype)) {
7810f74e101Schristos 
7820f74e101Schristos 			case MCLA_VERTEX_ROUTER:
783c74ad251Schristos 				ND_PRINT("\n\t    Router Router-ID %s",
784c74ad251Schristos 				    GET_IPADDR_STRING(mcp->mcla_vid));
7850f74e101Schristos 				break;
7860f74e101Schristos 
7870f74e101Schristos 			case MCLA_VERTEX_NETWORK:
788c74ad251Schristos 				ND_PRINT("\n\t    Network Designated Router %s",
789c74ad251Schristos 				    GET_IPADDR_STRING(mcp->mcla_vid));
7900f74e101Schristos 				break;
7910f74e101Schristos 
7920f74e101Schristos 			default:
793c74ad251Schristos 				ND_PRINT("\n\t    unknown VertexType (%u)",
794c74ad251Schristos 				    GET_BE_U_4(mcp->mcla_vtype));
7950f74e101Schristos 				break;
7960f74e101Schristos 			}
7970f74e101Schristos 		++mcp;
7980f74e101Schristos 		}
7990f74e101Schristos 		break;
8000f74e101Schristos 
8010f74e101Schristos 	case LS_TYPE_OPAQUE_LL: /* fall through */
8020f74e101Schristos 	case LS_TYPE_OPAQUE_AL:
8030f74e101Schristos 	case LS_TYPE_OPAQUE_DW:
8040f74e101Schristos 
805c74ad251Schristos 	    switch (GET_U_1(lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
8060f74e101Schristos             case LS_OPAQUE_TYPE_RI:
807c74ad251Schristos 		tptr = (const uint8_t *)(lsap->lsa_un.un_ri_tlv);
8080f74e101Schristos 
809c74ad251Schristos 		u_int ls_length_remaining = ls_length;
810c74ad251Schristos 		while (ls_length_remaining != 0) {
811c74ad251Schristos                     ND_TCHECK_4(tptr);
812c74ad251Schristos 		    if (ls_length_remaining < 4) {
813c74ad251Schristos                         ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length_remaining);
8140f74e101Schristos                         return(ls_end);
8150f74e101Schristos                     }
816c74ad251Schristos                     tlv_type = GET_BE_U_2(tptr);
817c74ad251Schristos                     tlv_length = GET_BE_U_2(tptr + 2);
8180f74e101Schristos                     tptr+=4;
819c74ad251Schristos                     ls_length_remaining-=4;
8200f74e101Schristos 
821c74ad251Schristos                     ND_PRINT("\n\t    %s TLV (%u), length: %u, value: ",
8220f74e101Schristos                            tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type),
8230f74e101Schristos                            tlv_type,
824c74ad251Schristos                            tlv_length);
8250f74e101Schristos 
826c74ad251Schristos                     if (tlv_length > ls_length_remaining) {
827c74ad251Schristos                         ND_PRINT("\n\t    Bogus length %u > remaining LS length %u", tlv_length,
828c74ad251Schristos                             ls_length_remaining);
8290f74e101Schristos                         return(ls_end);
8300f74e101Schristos                     }
831c74ad251Schristos                     ND_TCHECK_LEN(tptr, tlv_length);
8320f74e101Schristos                     switch(tlv_type) {
8330f74e101Schristos 
8340f74e101Schristos                     case LS_OPAQUE_RI_TLV_CAP:
8350f74e101Schristos                         if (tlv_length != 4) {
836c74ad251Schristos                             ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
8370f74e101Schristos                             return(ls_end);
8380f74e101Schristos                         }
839c74ad251Schristos                         ND_PRINT("Capabilities: %s",
840c74ad251Schristos                                bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr)));
8410f74e101Schristos                         break;
8420f74e101Schristos                     default:
843b3a00663Schristos                         if (ndo->ndo_vflag <= 1) {
844b3a00663Schristos                             if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
8450f74e101Schristos                                 return(ls_end);
8460f74e101Schristos                         }
8470f74e101Schristos                         break;
8480f74e101Schristos 
8490f74e101Schristos                     }
850*26ba0b50Schristos 
851*26ba0b50Schristos                     /* in OSPF everything has to be 32-bit aligned, including TLVs */
852*26ba0b50Schristos                     if (tlv_length % 4) {
853*26ba0b50Schristos                         tlv_length += (4 - (tlv_length % 4));
854*26ba0b50Schristos                     }
8550f74e101Schristos                     tptr+=tlv_length;
856c74ad251Schristos                     ls_length_remaining-=tlv_length;
8570f74e101Schristos                 }
8580f74e101Schristos                 break;
8590f74e101Schristos 
8600f74e101Schristos             case LS_OPAQUE_TYPE_GRACE:
861c74ad251Schristos                 if (ospf_grace_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_grace_tlv),
8620f74e101Schristos                                          ls_length) == -1) {
8630f74e101Schristos                     return(ls_end);
8640f74e101Schristos                 }
8650f74e101Schristos                 break;
8660f74e101Schristos 
8670f74e101Schristos 	    case LS_OPAQUE_TYPE_TE:
868c74ad251Schristos                 if (ospf_te_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_te_lsa_tlv),
8690f74e101Schristos                                       ls_length) == -1) {
8700f74e101Schristos                     return(ls_end);
8710f74e101Schristos                 }
8720f74e101Schristos                 break;
8730f74e101Schristos 
8740f74e101Schristos             default:
875b3a00663Schristos                 if (ndo->ndo_vflag <= 1) {
876fdccd7e4Schristos                     if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
8770f74e101Schristos                                            "\n\t    ", ls_length))
8780f74e101Schristos                         return(ls_end);
8790f74e101Schristos                 }
8800f74e101Schristos                 break;
8810f74e101Schristos             }
8820f74e101Schristos         }
8830f74e101Schristos 
8840f74e101Schristos         /* do we want to see an additionally hexdump ? */
885b3a00663Schristos         if (ndo->ndo_vflag> 1)
886fdccd7e4Schristos             if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
8870f74e101Schristos                                    "\n\t    ", ls_length)) {
8880f74e101Schristos                 return(ls_end);
8890f74e101Schristos             }
8900f74e101Schristos 
8910f74e101Schristos 	return (ls_end);
8920f74e101Schristos trunc:
8930f74e101Schristos 	return (NULL);
8940f74e101Schristos }
8950f74e101Schristos 
896c74ad251Schristos static void
897b3a00663Schristos ospf_decode_lls(netdissect_options *ndo,
898c74ad251Schristos                 const struct ospfhdr *op, u_int length)
8990f74e101Schristos {
900c74ad251Schristos     const u_char *dptr;
901c74ad251Schristos     const u_char *dataend;
902c74ad251Schristos     u_int length2;
903c74ad251Schristos     uint16_t lls_type, lls_len;
904c74ad251Schristos     uint32_t lls_flags;
9050f74e101Schristos 
906c74ad251Schristos     switch (GET_U_1(op->ospf_type)) {
9070f74e101Schristos 
9080f74e101Schristos     case OSPF_TYPE_HELLO:
909c74ad251Schristos         if (!(GET_U_1(op->ospf_hello.hello_options) & OSPF_OPTION_L))
910c74ad251Schristos             return;
9110f74e101Schristos         break;
9120f74e101Schristos 
9130f74e101Schristos     case OSPF_TYPE_DD:
914c74ad251Schristos         if (!(GET_U_1(op->ospf_db.db_options) & OSPF_OPTION_L))
915c74ad251Schristos             return;
9160f74e101Schristos         break;
9170f74e101Schristos 
9180f74e101Schristos     default:
919c74ad251Schristos         return;
9200f74e101Schristos     }
9210f74e101Schristos 
9220f74e101Schristos     /* dig deeper if LLS data is available; see RFC4813 */
923c74ad251Schristos     length2 = GET_BE_U_2(op->ospf_len);
924fdccd7e4Schristos     dptr = (const u_char *)op + length2;
925fdccd7e4Schristos     dataend = (const u_char *)op + length;
9260f74e101Schristos 
927c74ad251Schristos     if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
928c74ad251Schristos         dptr = dptr + GET_U_1(op->ospf_authdata + 3);
929c74ad251Schristos         length2 += GET_U_1(op->ospf_authdata + 3);
9300f74e101Schristos     }
9310f74e101Schristos     if (length2 >= length) {
932c74ad251Schristos         ND_PRINT("\n\t[LLS truncated]");
933c74ad251Schristos         return;
9340f74e101Schristos     }
935c74ad251Schristos     ND_PRINT("\n\t  LLS: checksum: 0x%04x", (u_int) GET_BE_U_2(dptr));
9360f74e101Schristos 
9370f74e101Schristos     dptr += 2;
938c74ad251Schristos     length2 = GET_BE_U_2(dptr);
939c74ad251Schristos     ND_PRINT(", length: %u", length2);
9400f74e101Schristos 
9410f74e101Schristos     dptr += 2;
9420f74e101Schristos     while (dptr < dataend) {
943c74ad251Schristos         lls_type = GET_BE_U_2(dptr);
944c74ad251Schristos         ND_PRINT("\n\t    %s (%u)",
9450f74e101Schristos                tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type),
946c74ad251Schristos                lls_type);
9470f74e101Schristos         dptr += 2;
948c74ad251Schristos         lls_len = GET_BE_U_2(dptr);
949c74ad251Schristos         ND_PRINT(", length: %u", lls_len);
9500f74e101Schristos         dptr += 2;
9510f74e101Schristos         switch (lls_type) {
9520f74e101Schristos 
9530f74e101Schristos         case OSPF_LLS_EO:
9540f74e101Schristos             if (lls_len != 4) {
955c74ad251Schristos                 ND_PRINT(" [should be 4]");
9560f74e101Schristos                 lls_len = 4;
9570f74e101Schristos             }
958c74ad251Schristos             lls_flags = GET_BE_U_4(dptr);
959c74ad251Schristos             ND_PRINT("\n\t      Options: 0x%08x [%s]", lls_flags,
960c74ad251Schristos                    bittok2str(ospf_lls_eo_options, "?", lls_flags));
9610f74e101Schristos 
9620f74e101Schristos             break;
9630f74e101Schristos 
9640f74e101Schristos         case OSPF_LLS_MD5:
9650f74e101Schristos             if (lls_len != 20) {
966c74ad251Schristos                 ND_PRINT(" [should be 20]");
9670f74e101Schristos                 lls_len = 20;
9680f74e101Schristos             }
969c74ad251Schristos             ND_PRINT("\n\t      Sequence number: 0x%08x", GET_BE_U_4(dptr));
9700f74e101Schristos             break;
9710f74e101Schristos         }
9720f74e101Schristos 
9730f74e101Schristos         dptr += lls_len;
9740f74e101Schristos     }
9750f74e101Schristos }
9760f74e101Schristos 
9770f74e101Schristos static int
978b3a00663Schristos ospf_decode_v2(netdissect_options *ndo,
979c74ad251Schristos                const struct ospfhdr *op, const u_char *dataend)
9800f74e101Schristos {
981c74ad251Schristos 	const nd_ipv4 *ap;
982c74ad251Schristos 	const struct lsr *lsrp;
983c74ad251Schristos 	const struct lsa_hdr *lshp;
984c74ad251Schristos 	const struct lsa *lsap;
985c74ad251Schristos 	uint32_t lsa_count,lsa_count_max;
9860f74e101Schristos 
987c74ad251Schristos 	switch (GET_U_1(op->ospf_type)) {
9880f74e101Schristos 
9890f74e101Schristos 	case OSPF_TYPE_HELLO:
990c74ad251Schristos 		ND_PRINT("\n\tOptions [%s]",
991c74ad251Schristos 		          bittok2str(ospf_option_values,"none",GET_U_1(op->ospf_hello.hello_options)));
9920f74e101Schristos 
993c74ad251Schristos 		ND_PRINT("\n\t  Hello Timer %us, Dead Timer %us, Mask %s, Priority %u",
994c74ad251Schristos 		          GET_BE_U_2(op->ospf_hello.hello_helloint),
995c74ad251Schristos 		          GET_BE_U_4(op->ospf_hello.hello_deadint),
996c74ad251Schristos 		          GET_IPADDR_STRING(op->ospf_hello.hello_mask),
997c74ad251Schristos 		          GET_U_1(op->ospf_hello.hello_priority));
9980f74e101Schristos 
999c74ad251Schristos 		if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_dr) != 0)
1000c74ad251Schristos 			ND_PRINT("\n\t  Designated Router %s",
1001c74ad251Schristos 			    GET_IPADDR_STRING(op->ospf_hello.hello_dr));
10020f74e101Schristos 
1003c74ad251Schristos 		if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_bdr) != 0)
1004c74ad251Schristos 			ND_PRINT(", Backup Designated Router %s",
1005c74ad251Schristos 			          GET_IPADDR_STRING(op->ospf_hello.hello_bdr));
10060f74e101Schristos 
10070f74e101Schristos 		ap = op->ospf_hello.hello_neighbor;
1008fdccd7e4Schristos 		if ((const u_char *)ap < dataend)
1009c74ad251Schristos 			ND_PRINT("\n\t  Neighbor List:");
1010fdccd7e4Schristos 		while ((const u_char *)ap < dataend) {
1011c74ad251Schristos 			ND_PRINT("\n\t    %s", GET_IPADDR_STRING(ap));
10120f74e101Schristos 			++ap;
10130f74e101Schristos 		}
10140f74e101Schristos 		break;	/* HELLO */
10150f74e101Schristos 
10160f74e101Schristos 	case OSPF_TYPE_DD:
1017c74ad251Schristos 		ND_PRINT("\n\tOptions [%s]",
1018c74ad251Schristos 		          bittok2str(ospf_option_values, "none", GET_U_1(op->ospf_db.db_options)));
1019c74ad251Schristos 		ND_PRINT(", DD Flags [%s]",
1020c74ad251Schristos 		          bittok2str(ospf_dd_flag_values, "none", GET_U_1(op->ospf_db.db_flags)));
1021c74ad251Schristos 		if (GET_BE_U_2(op->ospf_db.db_ifmtu)) {
1022c74ad251Schristos 			ND_PRINT(", MTU: %u",
1023c74ad251Schristos 				 GET_BE_U_2(op->ospf_db.db_ifmtu));
10240f74e101Schristos 		}
1025c74ad251Schristos 		ND_PRINT(", Sequence: 0x%08x", GET_BE_U_4(op->ospf_db.db_seq));
10260f74e101Schristos 
10270f74e101Schristos 		/* Print all the LS adv's */
10280f74e101Schristos 		lshp = op->ospf_db.db_lshdr;
1029fdccd7e4Schristos 		while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
10300f74e101Schristos 			++lshp;
10310f74e101Schristos 		}
10320f74e101Schristos 		break;
10330f74e101Schristos 
10340f74e101Schristos 	case OSPF_TYPE_LS_REQ:
10350f74e101Schristos                 lsrp = op->ospf_lsr;
1036fdccd7e4Schristos                 while ((const u_char *)lsrp < dataend) {
1037c74ad251Schristos                     ND_TCHECK_SIZE(lsrp);
10380f74e101Schristos 
1039c74ad251Schristos                     ND_PRINT("\n\t  Advertising Router: %s, %s LSA (%u)",
1040c74ad251Schristos                            GET_IPADDR_STRING(lsrp->ls_router),
1041c74ad251Schristos                            tok2str(lsa_values,"unknown",GET_BE_U_4(lsrp->ls_type)),
1042c74ad251Schristos                            GET_BE_U_4(lsrp->ls_type));
10430f74e101Schristos 
1044c74ad251Schristos                     switch (GET_BE_U_4(lsrp->ls_type)) {
10450f74e101Schristos                         /* the LSA header for opaque LSAs was slightly changed */
10460f74e101Schristos                     case LS_TYPE_OPAQUE_LL:
10470f74e101Schristos                     case LS_TYPE_OPAQUE_AL:
10480f74e101Schristos                     case LS_TYPE_OPAQUE_DW:
1049c74ad251Schristos                         ND_PRINT(", Opaque-Type: %s LSA (%u), Opaque-ID: %u",
1050c74ad251Schristos                                tok2str(lsa_opaque_values, "unknown",GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type)),
1051c74ad251Schristos                                GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type),
1052c74ad251Schristos                                GET_BE_U_3(lsrp->un_ls_stateid.opaque_field.opaque_id));
10530f74e101Schristos                         break;
10540f74e101Schristos                     default:
1055c74ad251Schristos                         ND_PRINT(", LSA-ID: %s",
1056c74ad251Schristos                                GET_IPADDR_STRING(lsrp->un_ls_stateid.ls_stateid));
10570f74e101Schristos                         break;
10580f74e101Schristos                     }
10590f74e101Schristos 
10600f74e101Schristos                     ++lsrp;
10610f74e101Schristos                 }
10620f74e101Schristos 		break;
10630f74e101Schristos 
10640f74e101Schristos 	case OSPF_TYPE_LS_UPDATE:
10650f74e101Schristos                 lsap = op->ospf_lsu.lsu_lsa;
1066c74ad251Schristos                 lsa_count_max = GET_BE_U_4(op->ospf_lsu.lsu_count);
1067c74ad251Schristos                 ND_PRINT(", %u LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max));
10680f74e101Schristos                 for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
1069c74ad251Schristos                     ND_PRINT("\n\t  LSA #%u", lsa_count);
1070b3a00663Schristos                         lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap);
10710f74e101Schristos                         if (lsap == NULL)
10720f74e101Schristos                                 goto trunc;
10730f74e101Schristos                 }
10740f74e101Schristos 		break;
10750f74e101Schristos 
10760f74e101Schristos 	case OSPF_TYPE_LS_ACK:
10770f74e101Schristos                 lshp = op->ospf_lsa.lsa_lshdr;
1078*26ba0b50Schristos                 while ((const u_char *)lshp < dataend) {
1079*26ba0b50Schristos                     ospf_print_lshdr(ndo, lshp);
10800f74e101Schristos                     ++lshp;
10810f74e101Schristos                 }
10820f74e101Schristos                 break;
10830f74e101Schristos 
10840f74e101Schristos 	default:
10850f74e101Schristos 		break;
10860f74e101Schristos 	}
10870f74e101Schristos 	return (0);
10880f74e101Schristos trunc:
10890f74e101Schristos 	return (1);
10900f74e101Schristos }
10910f74e101Schristos 
10920f74e101Schristos void
1093b3a00663Schristos ospf_print(netdissect_options *ndo,
1094c74ad251Schristos            const u_char *bp, u_int length,
10950f74e101Schristos            const u_char *bp2 _U_)
10960f74e101Schristos {
1097c74ad251Schristos 	const struct ospfhdr *op;
1098c74ad251Schristos 	const u_char *dataend;
1099c74ad251Schristos 	const char *cp;
11000f74e101Schristos 
1101c74ad251Schristos 	ndo->ndo_protocol = "ospf2";
1102fdccd7e4Schristos 	op = (const struct ospfhdr *)bp;
11030f74e101Schristos 
11040f74e101Schristos 	/* XXX Before we do anything else, strip off the MD5 trailer */
1105c74ad251Schristos 	if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
11060f74e101Schristos 		length -= OSPF_AUTH_MD5_LEN;
1107b3a00663Schristos 		ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN;
11080f74e101Schristos 	}
11090f74e101Schristos 
11100f74e101Schristos 	/* If the type is valid translate it, or just print the type */
11110f74e101Schristos 	/* value.  If it's not valid, say so and return */
1112c74ad251Schristos 	cp = tok2str(type2str, "unknown LS-type %u", GET_U_1(op->ospf_type));
1113c74ad251Schristos 	ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf_version), cp,
1114c74ad251Schristos 		 length);
11150f74e101Schristos 	if (*cp == 'u')
11160f74e101Schristos 		return;
11170f74e101Schristos 
1118b3a00663Schristos 	if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
11190f74e101Schristos 		return;
11200f74e101Schristos 	}
11210f74e101Schristos 
1122c74ad251Schristos 	if (length != GET_BE_U_2(op->ospf_len)) {
1123c74ad251Schristos 		ND_PRINT(" [len %u]", GET_BE_U_2(op->ospf_len));
11240f74e101Schristos 	}
11250f74e101Schristos 
1126c74ad251Schristos 	if (length > GET_BE_U_2(op->ospf_len)) {
1127c74ad251Schristos 		dataend = bp + GET_BE_U_2(op->ospf_len);
11280f74e101Schristos 	} else {
11290f74e101Schristos 		dataend = bp + length;
11300f74e101Schristos 	}
11310f74e101Schristos 
1132c74ad251Schristos 	ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf_routerid));
11330f74e101Schristos 
1134c74ad251Schristos 	if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_areaid) != 0)
1135c74ad251Schristos 		ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf_areaid));
11360f74e101Schristos 	else
1137c74ad251Schristos 		ND_PRINT(", Backbone Area");
11380f74e101Schristos 
1139b3a00663Schristos 	if (ndo->ndo_vflag) {
11400f74e101Schristos 		/* Print authentication data (should we really do this?) */
1141c74ad251Schristos 		ND_TCHECK_LEN(op->ospf_authdata, sizeof(op->ospf_authdata));
11420f74e101Schristos 
1143c74ad251Schristos 		ND_PRINT(", Authentication Type: %s (%u)",
1144c74ad251Schristos 		          tok2str(ospf_authtype_values, "unknown", GET_BE_U_2(op->ospf_authtype)),
1145c74ad251Schristos 		          GET_BE_U_2(op->ospf_authtype));
11460f74e101Schristos 
1147c74ad251Schristos 		switch (GET_BE_U_2(op->ospf_authtype)) {
11480f74e101Schristos 
11490f74e101Schristos 		case OSPF_AUTH_NONE:
11500f74e101Schristos 			break;
11510f74e101Schristos 
11520f74e101Schristos 		case OSPF_AUTH_SIMPLE:
1153c74ad251Schristos 			ND_PRINT("\n\tSimple text password: ");
1154c74ad251Schristos 			nd_printjnp(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
11550f74e101Schristos 			break;
11560f74e101Schristos 
11570f74e101Schristos 		case OSPF_AUTH_MD5:
1158c74ad251Schristos 			ND_PRINT("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x",
1159c74ad251Schristos 			          GET_U_1(op->ospf_authdata + 2),
1160c74ad251Schristos 			          GET_U_1(op->ospf_authdata + 3),
1161c74ad251Schristos 			          GET_BE_U_4((op->ospf_authdata) + 4));
11620f74e101Schristos 			break;
11630f74e101Schristos 
11640f74e101Schristos 		default:
11650f74e101Schristos 			return;
11660f74e101Schristos 		}
11670f74e101Schristos 	}
11680f74e101Schristos 	/* Do rest according to version.	 */
1169c74ad251Schristos 	switch (GET_U_1(op->ospf_version)) {
11700f74e101Schristos 
11710f74e101Schristos 	case 2:
11720f74e101Schristos 		/* ospf version 2 */
1173b3a00663Schristos 		if (ospf_decode_v2(ndo, op, dataend))
11740f74e101Schristos 			goto trunc;
1175c74ad251Schristos 		if (length > GET_BE_U_2(op->ospf_len))
1176c74ad251Schristos 			ospf_decode_lls(ndo, op, length);
11770f74e101Schristos 		break;
11780f74e101Schristos 
11790f74e101Schristos 	default:
1180c74ad251Schristos 		ND_PRINT(" ospf [version %u]", GET_U_1(op->ospf_version));
11810f74e101Schristos 		break;
11820f74e101Schristos 	}			/* end switch on version */
11830f74e101Schristos 
11840f74e101Schristos 	return;
11850f74e101Schristos trunc:
1186c74ad251Schristos 	nd_trunc_longjmp(ndo);
11870f74e101Schristos }
1188