xref: /dragonfly/contrib/tcpdump/print-ospf.c (revision ed775ee7)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos  * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos  * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos  * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos  * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos  * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos  * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos  * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos  * or promote products derived from this software without specific prior
1641c99275SPeter Avalos  * written permission.
1741c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos  *
2141c99275SPeter Avalos  * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
2241c99275SPeter Avalos  */
2341c99275SPeter Avalos 
24411677aeSAaron LI /* \summary: Open Shortest Path First (OSPF) printer */
2541c99275SPeter Avalos 
2641c99275SPeter Avalos #ifdef HAVE_CONFIG_H
27*ed775ee7SAntonio Huete Jimenez #include <config.h>
2841c99275SPeter Avalos #endif
2941c99275SPeter Avalos 
30*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3141c99275SPeter Avalos 
32411677aeSAaron LI #include "netdissect.h"
3341c99275SPeter Avalos #include "addrtoname.h"
3441c99275SPeter Avalos #include "extract.h"
3541c99275SPeter Avalos #include "gmpls.h"
3641c99275SPeter Avalos 
3741c99275SPeter Avalos #include "ospf.h"
3841c99275SPeter Avalos 
3941c99275SPeter Avalos 
40411677aeSAaron LI static const struct tok ospf_option_values[] = {
41*ed775ee7SAntonio Huete Jimenez 	{ OSPF_OPTION_MT,	"MultiTopology" }, /* draft-ietf-ospf-mt-09 */
4241c99275SPeter Avalos 	{ OSPF_OPTION_E,	"External" },
4341c99275SPeter Avalos 	{ OSPF_OPTION_MC,	"Multicast" },
4441c99275SPeter Avalos 	{ OSPF_OPTION_NP,	"NSSA" },
45ea7b4bf5SPeter Avalos 	{ OSPF_OPTION_L,	"LLS" },
4641c99275SPeter Avalos 	{ OSPF_OPTION_DC,	"Demand Circuit" },
4741c99275SPeter Avalos 	{ OSPF_OPTION_O,	"Opaque" },
4841c99275SPeter Avalos 	{ OSPF_OPTION_DN,	"Up/Down" },
4941c99275SPeter Avalos 	{ 0,			NULL }
5041c99275SPeter Avalos };
5141c99275SPeter Avalos 
52411677aeSAaron LI static const struct tok ospf_authtype_values[] = {
5341c99275SPeter Avalos 	{ OSPF_AUTH_NONE,	"none" },
5441c99275SPeter Avalos 	{ OSPF_AUTH_SIMPLE,	"simple" },
5541c99275SPeter Avalos 	{ OSPF_AUTH_MD5,	"MD5" },
5641c99275SPeter Avalos 	{ 0,			NULL }
5741c99275SPeter Avalos };
5841c99275SPeter Avalos 
59411677aeSAaron LI static const struct tok ospf_rla_flag_values[] = {
6041c99275SPeter Avalos 	{ RLA_FLAG_B,		"ABR" },
6141c99275SPeter Avalos 	{ RLA_FLAG_E,		"ASBR" },
6241c99275SPeter Avalos 	{ RLA_FLAG_W1,		"Virtual" },
6341c99275SPeter Avalos 	{ RLA_FLAG_W2,		"W2" },
6441c99275SPeter Avalos 	{ 0,			NULL }
6541c99275SPeter Avalos };
6641c99275SPeter Avalos 
67411677aeSAaron LI static const struct tok type2str[] = {
6841c99275SPeter Avalos 	{ OSPF_TYPE_HELLO,	"Hello" },
6941c99275SPeter Avalos 	{ OSPF_TYPE_DD,		"Database Description" },
7041c99275SPeter Avalos 	{ OSPF_TYPE_LS_REQ,	"LS-Request" },
7141c99275SPeter Avalos 	{ OSPF_TYPE_LS_UPDATE,	"LS-Update" },
7241c99275SPeter Avalos 	{ OSPF_TYPE_LS_ACK,	"LS-Ack" },
7341c99275SPeter Avalos 	{ 0,			NULL }
7441c99275SPeter Avalos };
7541c99275SPeter Avalos 
76411677aeSAaron LI static const struct tok lsa_values[] = {
7741c99275SPeter Avalos 	{ LS_TYPE_ROUTER,       "Router" },
7841c99275SPeter Avalos 	{ LS_TYPE_NETWORK,      "Network" },
7941c99275SPeter Avalos 	{ LS_TYPE_SUM_IP,       "Summary" },
8041c99275SPeter Avalos 	{ LS_TYPE_SUM_ABR,      "ASBR Summary" },
8141c99275SPeter Avalos 	{ LS_TYPE_ASE,          "External" },
8241c99275SPeter Avalos 	{ LS_TYPE_GROUP,        "Multicast Group" },
8341c99275SPeter Avalos 	{ LS_TYPE_NSSA,         "NSSA" },
8441c99275SPeter Avalos 	{ LS_TYPE_OPAQUE_LL,    "Link Local Opaque" },
8541c99275SPeter Avalos 	{ LS_TYPE_OPAQUE_AL,    "Area Local Opaque" },
8641c99275SPeter Avalos 	{ LS_TYPE_OPAQUE_DW,    "Domain Wide Opaque" },
8741c99275SPeter Avalos 	{ 0,			NULL }
8841c99275SPeter Avalos };
8941c99275SPeter Avalos 
90411677aeSAaron LI static const struct tok ospf_dd_flag_values[] = {
9141c99275SPeter Avalos 	{ OSPF_DB_INIT,	        "Init" },
9241c99275SPeter Avalos 	{ OSPF_DB_MORE,	        "More" },
9341c99275SPeter Avalos 	{ OSPF_DB_MASTER,	"Master" },
94ea7b4bf5SPeter Avalos     { OSPF_DB_RESYNC,	"OOBResync" },
9541c99275SPeter Avalos 	{ 0,			NULL }
9641c99275SPeter Avalos };
9741c99275SPeter Avalos 
98411677aeSAaron LI static const struct tok lsa_opaque_values[] = {
9941c99275SPeter Avalos 	{ LS_OPAQUE_TYPE_TE,    "Traffic Engineering" },
10041c99275SPeter Avalos 	{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
10141c99275SPeter Avalos 	{ LS_OPAQUE_TYPE_RI,    "Router Information" },
10241c99275SPeter Avalos 	{ 0,			NULL }
10341c99275SPeter Avalos };
10441c99275SPeter Avalos 
105411677aeSAaron LI static const struct tok lsa_opaque_te_tlv_values[] = {
10641c99275SPeter Avalos 	{ LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
10741c99275SPeter Avalos 	{ LS_OPAQUE_TE_TLV_LINK,   "Link" },
10841c99275SPeter Avalos 	{ 0,			NULL }
10941c99275SPeter Avalos };
11041c99275SPeter Avalos 
111411677aeSAaron LI static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
11241c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE,            "Link Type" },
11341c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID,              "Link ID" },
11441c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP,             "Local Interface IP address" },
11541c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP,            "Remote Interface IP address" },
11641c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC,            "Traffic Engineering Metric" },
11741c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW,               "Maximum Bandwidth" },
11841c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW,           "Maximum Reservable Bandwidth" },
11941c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW,             "Unreserved Bandwidth" },
12041c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP,          "Administrative Group" },
12141c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
12241c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
12341c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR,    "Interface Switching Capability" },
12441c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP,    "Shared Risk Link Group" },
12541c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS,       "Bandwidth Constraints" },
12641c99275SPeter Avalos 	{ 0,			NULL }
12741c99275SPeter Avalos };
12841c99275SPeter Avalos 
129411677aeSAaron LI static const struct tok lsa_opaque_grace_tlv_values[] = {
13041c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_PERIOD,             "Grace Period" },
13141c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_REASON,             "Graceful restart Reason" },
13241c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_INT_ADDRESS,        "IPv4 interface address" },
13341c99275SPeter Avalos 	{ 0,		        NULL }
13441c99275SPeter Avalos };
13541c99275SPeter Avalos 
136411677aeSAaron LI static const struct tok lsa_opaque_grace_tlv_reason_values[] = {
13741c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN,     "Unknown" },
13841c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART,  "Software Restart" },
13941c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE,  "Software Reload/Upgrade" },
14041c99275SPeter Avalos 	{ LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH,   "Control Processor Switch" },
14141c99275SPeter Avalos 	{ 0,		        NULL }
14241c99275SPeter Avalos };
14341c99275SPeter Avalos 
144411677aeSAaron LI static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
14541c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
14641c99275SPeter Avalos 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA,  "Multi-Access" },
14741c99275SPeter Avalos 	{ 0,			NULL }
14841c99275SPeter Avalos };
14941c99275SPeter Avalos 
150411677aeSAaron LI static const struct tok lsa_opaque_ri_tlv_values[] = {
15141c99275SPeter Avalos 	{ LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
15241c99275SPeter Avalos 	{ 0,		        NULL }
15341c99275SPeter Avalos };
15441c99275SPeter Avalos 
155411677aeSAaron LI static const struct tok lsa_opaque_ri_tlv_cap_values[] = {
15641c99275SPeter Avalos 	{ 1, "Reserved" },
15741c99275SPeter Avalos 	{ 2, "Reserved" },
15841c99275SPeter Avalos 	{ 4, "Reserved" },
15941c99275SPeter Avalos 	{ 8, "Reserved" },
16041c99275SPeter Avalos 	{ 16, "graceful restart capable" },
16141c99275SPeter Avalos 	{ 32, "graceful restart helper" },
16241c99275SPeter Avalos 	{ 64, "Stub router support" },
16341c99275SPeter Avalos 	{ 128, "Traffic engineering" },
16441c99275SPeter Avalos 	{ 256, "p2p over LAN" },
16541c99275SPeter Avalos 	{ 512, "path computation server" },
16641c99275SPeter Avalos 	{ 0,		        NULL }
16741c99275SPeter Avalos };
16841c99275SPeter Avalos 
169411677aeSAaron LI static const struct tok ospf_lls_tlv_values[] = {
170ea7b4bf5SPeter Avalos 	{ OSPF_LLS_EO,	"Extended Options" },
171ea7b4bf5SPeter Avalos 	{ OSPF_LLS_MD5,	"MD5 Authentication" },
172ea7b4bf5SPeter Avalos 	{ 0,	NULL }
173ea7b4bf5SPeter Avalos };
174ea7b4bf5SPeter Avalos 
175411677aeSAaron LI static const struct tok ospf_lls_eo_options[] = {
176ea7b4bf5SPeter Avalos 	{ OSPF_LLS_EO_LR,	"LSDB resync" },
177ea7b4bf5SPeter Avalos 	{ OSPF_LLS_EO_RS,	"Restart" },
178ea7b4bf5SPeter Avalos 	{ 0,	NULL }
179ea7b4bf5SPeter Avalos };
180ea7b4bf5SPeter Avalos 
181ea7b4bf5SPeter Avalos int
ospf_grace_lsa_print(netdissect_options * ndo,const u_char * tptr,u_int ls_length)182*ed775ee7SAntonio Huete Jimenez ospf_grace_lsa_print(netdissect_options *ndo,
183*ed775ee7SAntonio Huete Jimenez                      const u_char *tptr, u_int ls_length)
184411677aeSAaron LI {
185ea7b4bf5SPeter Avalos     u_int tlv_type, tlv_length;
18641c99275SPeter Avalos 
18741c99275SPeter Avalos 
188ea7b4bf5SPeter Avalos     while (ls_length > 0) {
189*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_4(tptr);
19041c99275SPeter Avalos         if (ls_length < 4) {
191*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length);
192ea7b4bf5SPeter Avalos             return -1;
19341c99275SPeter Avalos         }
194*ed775ee7SAntonio Huete Jimenez         tlv_type = GET_BE_U_2(tptr);
195*ed775ee7SAntonio Huete Jimenez         tlv_length = GET_BE_U_2(tptr + 2);
19641c99275SPeter Avalos         tptr+=4;
19741c99275SPeter Avalos         ls_length-=4;
19841c99275SPeter Avalos 
199*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t    %s TLV (%u), length %u, value: ",
20041c99275SPeter Avalos                tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
20141c99275SPeter Avalos                tlv_type,
202*ed775ee7SAntonio Huete Jimenez                tlv_length);
20341c99275SPeter Avalos 
20441c99275SPeter Avalos         if (tlv_length > ls_length) {
205*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    Bogus length %u > %u", tlv_length,
206*ed775ee7SAntonio Huete Jimenez                    ls_length);
207ea7b4bf5SPeter Avalos             return -1;
20841c99275SPeter Avalos         }
209ea7b4bf5SPeter Avalos 
210ea7b4bf5SPeter Avalos         /* Infinite loop protection. */
211ea7b4bf5SPeter Avalos         if (tlv_type == 0 || tlv_length ==0) {
212ea7b4bf5SPeter Avalos             return -1;
213ea7b4bf5SPeter Avalos         }
214ea7b4bf5SPeter Avalos 
215*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_LEN(tptr, tlv_length);
21641c99275SPeter Avalos         switch(tlv_type) {
21741c99275SPeter Avalos 
21841c99275SPeter Avalos         case LS_OPAQUE_GRACE_TLV_PERIOD:
21941c99275SPeter Avalos             if (tlv_length != 4) {
220*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
221ea7b4bf5SPeter Avalos                 return -1;
22241c99275SPeter Avalos             }
223*ed775ee7SAntonio Huete Jimenez             ND_PRINT("%us", GET_BE_U_4(tptr));
22441c99275SPeter Avalos             break;
225ea7b4bf5SPeter Avalos 
22641c99275SPeter Avalos         case LS_OPAQUE_GRACE_TLV_REASON:
22741c99275SPeter Avalos             if (tlv_length != 1) {
228*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t    Bogus length %u != 1", tlv_length);
229ea7b4bf5SPeter Avalos                 return -1;
23041c99275SPeter Avalos             }
231*ed775ee7SAntonio Huete Jimenez             ND_PRINT("%s (%u)",
232*ed775ee7SAntonio Huete Jimenez                    tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", GET_U_1(tptr)),
233*ed775ee7SAntonio Huete Jimenez                    GET_U_1(tptr));
23441c99275SPeter Avalos             break;
235ea7b4bf5SPeter Avalos 
23641c99275SPeter Avalos         case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
23741c99275SPeter Avalos             if (tlv_length != 4) {
238*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
239ea7b4bf5SPeter Avalos                 return -1;
24041c99275SPeter Avalos             }
241*ed775ee7SAntonio Huete Jimenez             ND_PRINT("%s", GET_IPADDR_STRING(tptr));
24241c99275SPeter Avalos             break;
243ea7b4bf5SPeter Avalos 
24441c99275SPeter Avalos         default:
245411677aeSAaron LI             if (ndo->ndo_vflag <= 1) {
246411677aeSAaron LI                 if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
247ea7b4bf5SPeter Avalos                     return -1;
24841c99275SPeter Avalos             }
24941c99275SPeter Avalos             break;
25041c99275SPeter Avalos 
25141c99275SPeter Avalos         }
252ea7b4bf5SPeter Avalos         /* in OSPF everything has to be 32-bit aligned, including TLVs */
253ea7b4bf5SPeter Avalos         if (tlv_length%4 != 0)
254ea7b4bf5SPeter Avalos             tlv_length+=4-(tlv_length%4);
255ea7b4bf5SPeter Avalos         ls_length-=tlv_length;
25641c99275SPeter Avalos         tptr+=tlv_length;
25741c99275SPeter Avalos     }
25841c99275SPeter Avalos 
259ea7b4bf5SPeter Avalos     return 0;
260ea7b4bf5SPeter Avalos trunc:
261ea7b4bf5SPeter Avalos     return -1;
262ea7b4bf5SPeter Avalos }
263ea7b4bf5SPeter Avalos 
264ea7b4bf5SPeter Avalos int
ospf_te_lsa_print(netdissect_options * ndo,const u_char * tptr,u_int ls_length)265*ed775ee7SAntonio Huete Jimenez ospf_te_lsa_print(netdissect_options *ndo,
266*ed775ee7SAntonio Huete Jimenez                   const u_char *tptr, u_int ls_length)
267411677aeSAaron LI {
268ea7b4bf5SPeter Avalos     u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
269ea7b4bf5SPeter Avalos     u_int priority_level, te_class, count_srlg;
270ea7b4bf5SPeter Avalos     union { /* int to float conversion buffer for several subTLVs */
271ea7b4bf5SPeter Avalos         float f;
272411677aeSAaron LI         uint32_t i;
273ea7b4bf5SPeter Avalos     } bw;
27441c99275SPeter Avalos 
27541c99275SPeter Avalos     while (ls_length != 0) {
276*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_4(tptr);
27741c99275SPeter Avalos         if (ls_length < 4) {
278*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length);
279ea7b4bf5SPeter Avalos             return -1;
28041c99275SPeter Avalos         }
281*ed775ee7SAntonio Huete Jimenez         tlv_type = GET_BE_U_2(tptr);
282*ed775ee7SAntonio Huete Jimenez         tlv_length = GET_BE_U_2(tptr + 2);
28341c99275SPeter Avalos         tptr+=4;
28441c99275SPeter Avalos         ls_length-=4;
28541c99275SPeter Avalos 
286*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t    %s TLV (%u), length: %u",
28741c99275SPeter Avalos                tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
28841c99275SPeter Avalos                tlv_type,
289*ed775ee7SAntonio Huete Jimenez                tlv_length);
29041c99275SPeter Avalos 
29141c99275SPeter Avalos         if (tlv_length > ls_length) {
292*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    Bogus length %u > %u", tlv_length,
293*ed775ee7SAntonio Huete Jimenez                    ls_length);
294ea7b4bf5SPeter Avalos             return -1;
29541c99275SPeter Avalos         }
296ea7b4bf5SPeter Avalos 
297ea7b4bf5SPeter Avalos         /* Infinite loop protection. */
298ea7b4bf5SPeter Avalos         if (tlv_type == 0 || tlv_length ==0) {
299ea7b4bf5SPeter Avalos             return -1;
300ea7b4bf5SPeter Avalos         }
301ea7b4bf5SPeter Avalos 
30241c99275SPeter Avalos         switch(tlv_type) {
30341c99275SPeter Avalos         case LS_OPAQUE_TE_TLV_LINK:
304*ed775ee7SAntonio Huete Jimenez             while (tlv_length != 0) {
30541c99275SPeter Avalos                 if (tlv_length < 4) {
306*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t    Remaining TLV length %u < 4",
307*ed775ee7SAntonio Huete Jimenez                            tlv_length);
308ea7b4bf5SPeter Avalos                     return -1;
30941c99275SPeter Avalos                 }
310*ed775ee7SAntonio Huete Jimenez                 subtlv_type = GET_BE_U_2(tptr);
311*ed775ee7SAntonio Huete Jimenez                 subtlv_length = GET_BE_U_2(tptr + 2);
31241c99275SPeter Avalos                 tptr+=4;
31341c99275SPeter Avalos                 tlv_length-=4;
31441c99275SPeter Avalos 
315411677aeSAaron LI 		/* Infinite loop protection */
316411677aeSAaron LI 		if (subtlv_type == 0 || subtlv_length == 0)
317411677aeSAaron LI 		    goto invalid;
318411677aeSAaron LI 
319*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t      %s subTLV (%u), length: %u",
32041c99275SPeter Avalos                        tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
32141c99275SPeter Avalos                        subtlv_type,
322*ed775ee7SAntonio Huete Jimenez                        subtlv_length);
32341c99275SPeter Avalos 
324*ed775ee7SAntonio Huete Jimenez                 if (tlv_length < subtlv_length) {
325*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t    Remaining TLV length %u < %u",
326*ed775ee7SAntonio Huete Jimenez                            tlv_length + 4, subtlv_length + 4);
327*ed775ee7SAntonio Huete Jimenez                     return -1;
328*ed775ee7SAntonio Huete Jimenez                 }
329*ed775ee7SAntonio Huete Jimenez                 ND_TCHECK_LEN(tptr, subtlv_length);
33041c99275SPeter Avalos                 switch(subtlv_type) {
33141c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
332411677aeSAaron LI 		    if (subtlv_length != 4) {
333*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4");
334411677aeSAaron LI 			goto invalid;
335411677aeSAaron LI 		    }
336*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", 0x%08x", GET_BE_U_4(tptr));
33741c99275SPeter Avalos                     break;
33841c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
33941c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
340411677aeSAaron LI 		    if (subtlv_length != 4 && subtlv_length != 8) {
341*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4 && != 8");
342411677aeSAaron LI 			goto invalid;
343411677aeSAaron LI 		    }
344*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %s (0x%08x)",
345*ed775ee7SAntonio Huete Jimenez                            GET_IPADDR_STRING(tptr),
346*ed775ee7SAntonio Huete Jimenez                            GET_BE_U_4(tptr));
347ea7b4bf5SPeter Avalos                     if (subtlv_length == 8) /* rfc4203 */
348*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", %s (0x%08x)",
349*ed775ee7SAntonio Huete Jimenez                                GET_IPADDR_STRING(tptr+4),
350*ed775ee7SAntonio Huete Jimenez                                GET_BE_U_4(tptr + 4));
35141c99275SPeter Avalos                     break;
35241c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
35341c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
354411677aeSAaron LI 		    if (subtlv_length != 4) {
355*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4");
356411677aeSAaron LI 			goto invalid;
357411677aeSAaron LI 		    }
358*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
35941c99275SPeter Avalos                     break;
36041c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
36141c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
362411677aeSAaron LI 		    if (subtlv_length != 4) {
363*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4");
364411677aeSAaron LI 			goto invalid;
365411677aeSAaron LI 		    }
366*ed775ee7SAntonio Huete Jimenez                     bw.i = GET_BE_U_4(tptr);
367*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000);
36841c99275SPeter Avalos                     break;
36941c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
370411677aeSAaron LI 		    if (subtlv_length != 32) {
371*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 32");
372411677aeSAaron LI 			goto invalid;
373411677aeSAaron LI 		    }
37441c99275SPeter Avalos                     for (te_class = 0; te_class < 8; te_class++) {
375*ed775ee7SAntonio Huete Jimenez                         bw.i = GET_BE_U_4(tptr + te_class * 4);
376*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t\tTE-Class %u: %.3f Mbps",
37741c99275SPeter Avalos                                te_class,
378*ed775ee7SAntonio Huete Jimenez                                bw.f * 8 / 1000000);
37941c99275SPeter Avalos                     }
38041c99275SPeter Avalos                     break;
38141c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
382411677aeSAaron LI 		    if (subtlv_length < 4) {
383*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" < 4");
384411677aeSAaron LI 			goto invalid;
385411677aeSAaron LI 		    }
386411677aeSAaron LI 		    /* BC Model Id (1 octet) + Reserved (3 octets) */
387*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t\tBandwidth Constraints Model ID: %s (%u)",
388*ed775ee7SAntonio Huete Jimenez                            tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)),
389*ed775ee7SAntonio Huete Jimenez                            GET_U_1(tptr));
390411677aeSAaron LI 		    if (subtlv_length % 4 != 0) {
391*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t\tlength %u != N x 4", subtlv_length);
392411677aeSAaron LI 			goto invalid;
393411677aeSAaron LI 		    }
394411677aeSAaron LI 		    if (subtlv_length > 36) {
395*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t\tlength %u > 36", subtlv_length);
396411677aeSAaron LI 			goto invalid;
397411677aeSAaron LI 		    }
39841c99275SPeter Avalos                     /* decode BCs until the subTLV ends */
39941c99275SPeter Avalos                     for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
400*ed775ee7SAntonio Huete Jimenez                         bw.i = GET_BE_U_4(tptr + 4 + te_class * 4);
401*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t\t  Bandwidth constraint CT%u: %.3f Mbps",
40241c99275SPeter Avalos                                te_class,
403*ed775ee7SAntonio Huete Jimenez                                bw.f * 8 / 1000000);
40441c99275SPeter Avalos                     }
40541c99275SPeter Avalos                     break;
40641c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
407411677aeSAaron LI 		    if (subtlv_length != 4) {
408*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4");
409411677aeSAaron LI 			goto invalid;
410411677aeSAaron LI 		    }
411*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", Metric %u", GET_BE_U_4(tptr));
41241c99275SPeter Avalos                     break;
41341c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
414411677aeSAaron LI 		    /* Protection Cap (1 octet) + Reserved ((3 octets) */
415411677aeSAaron LI 		    if (subtlv_length != 4) {
416*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 4");
417411677aeSAaron LI 			goto invalid;
418411677aeSAaron LI 		    }
419*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %s",
420*ed775ee7SAntonio Huete Jimenez                              bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr)));
42141c99275SPeter Avalos                     break;
42241c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
423411677aeSAaron LI 		    if (subtlv_length < 36) {
424*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" < 36");
425411677aeSAaron LI 			goto invalid;
426411677aeSAaron LI 		    }
427411677aeSAaron LI 		    /* Switching Cap (1 octet) + Encoding (1) +  Reserved (2) */
428*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t\tInterface Switching Capability: %s",
429*ed775ee7SAntonio Huete Jimenez                            tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1((tptr))));
430*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
431*ed775ee7SAntonio Huete Jimenez                            tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1))));
43241c99275SPeter Avalos                     for (priority_level = 0; priority_level < 8; priority_level++) {
433*ed775ee7SAntonio Huete Jimenez                         bw.i = GET_BE_U_4(tptr + 4 + (priority_level * 4));
434*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t\t  priority level %u: %.3f Mbps",
43541c99275SPeter Avalos                                priority_level,
436*ed775ee7SAntonio Huete Jimenez                                bw.f * 8 / 1000000);
43741c99275SPeter Avalos                     }
43841c99275SPeter Avalos                     break;
43941c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
440411677aeSAaron LI 		    if (subtlv_length != 1) {
441*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != 1");
442411677aeSAaron LI 			goto invalid;
443411677aeSAaron LI 		    }
444*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %s (%u)",
445*ed775ee7SAntonio Huete Jimenez                            tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",GET_U_1(tptr)),
446*ed775ee7SAntonio Huete Jimenez                            GET_U_1(tptr));
44741c99275SPeter Avalos                     break;
44841c99275SPeter Avalos 
44941c99275SPeter Avalos                 case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
450411677aeSAaron LI 		    if (subtlv_length % 4 != 0) {
451*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" != N x 4");
452411677aeSAaron LI 			goto invalid;
453411677aeSAaron LI 		    }
45441c99275SPeter Avalos                     count_srlg = subtlv_length / 4;
45541c99275SPeter Avalos                     if (count_srlg != 0)
456*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t\t  Shared risk group: ");
45741c99275SPeter Avalos                     while (count_srlg > 0) {
458*ed775ee7SAntonio Huete Jimenez                         bw.i = GET_BE_U_4(tptr);
459*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("%u", bw.i);
46041c99275SPeter Avalos                         tptr+=4;
46141c99275SPeter Avalos                         count_srlg--;
46241c99275SPeter Avalos                         if (count_srlg > 0)
463*ed775ee7SAntonio Huete Jimenez                             ND_PRINT(", ");
46441c99275SPeter Avalos                     }
46541c99275SPeter Avalos                     break;
46641c99275SPeter Avalos 
46741c99275SPeter Avalos                 default:
468411677aeSAaron LI                     if (ndo->ndo_vflag <= 1) {
469411677aeSAaron LI                         if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
470ea7b4bf5SPeter Avalos                             return -1;
47141c99275SPeter Avalos                     }
47241c99275SPeter Avalos                     break;
47341c99275SPeter Avalos                 }
474ea7b4bf5SPeter Avalos                 /* in OSPF everything has to be 32-bit aligned, including subTLVs */
47541c99275SPeter Avalos                 if (subtlv_length%4 != 0)
47641c99275SPeter Avalos                     subtlv_length+=4-(subtlv_length%4);
47741c99275SPeter Avalos 
478*ed775ee7SAntonio Huete Jimenez                 if (tlv_length < subtlv_length) {
479*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t    Remaining TLV length %u < %u",
480*ed775ee7SAntonio Huete Jimenez                            tlv_length + 4, subtlv_length + 4);
481*ed775ee7SAntonio Huete Jimenez                     return -1;
482*ed775ee7SAntonio Huete Jimenez                 }
48341c99275SPeter Avalos                 tlv_length-=subtlv_length;
48441c99275SPeter Avalos                 tptr+=subtlv_length;
48541c99275SPeter Avalos 
48641c99275SPeter Avalos             }
48741c99275SPeter Avalos             break;
48841c99275SPeter Avalos 
48941c99275SPeter Avalos         case LS_OPAQUE_TE_TLV_ROUTER:
49041c99275SPeter Avalos             if (tlv_length < 4) {
491*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t    TLV length %u < 4", tlv_length);
492ea7b4bf5SPeter Avalos                 return -1;
49341c99275SPeter Avalos             }
494*ed775ee7SAntonio Huete Jimenez             ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
49541c99275SPeter Avalos             break;
49641c99275SPeter Avalos 
49741c99275SPeter Avalos         default:
498411677aeSAaron LI             if (ndo->ndo_vflag <= 1) {
499411677aeSAaron LI                 if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
500ea7b4bf5SPeter Avalos                     return -1;
501ea7b4bf5SPeter Avalos             }
502ea7b4bf5SPeter Avalos             break;
503ea7b4bf5SPeter Avalos         }
504ea7b4bf5SPeter Avalos         /* in OSPF everything has to be 32-bit aligned, including TLVs */
505ea7b4bf5SPeter Avalos         if (tlv_length%4 != 0)
506ea7b4bf5SPeter Avalos             tlv_length+=4-(tlv_length%4);
507*ed775ee7SAntonio Huete Jimenez         if (tlv_length > ls_length) {
508*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    Bogus padded length %u > %u", tlv_length,
509*ed775ee7SAntonio Huete Jimenez                    ls_length);
510*ed775ee7SAntonio Huete Jimenez             return -1;
511*ed775ee7SAntonio Huete Jimenez         }
512ea7b4bf5SPeter Avalos         ls_length-=tlv_length;
513ea7b4bf5SPeter Avalos         tptr+=tlv_length;
514ea7b4bf5SPeter Avalos     }
515ea7b4bf5SPeter Avalos     return 0;
516ea7b4bf5SPeter Avalos trunc:
517ea7b4bf5SPeter Avalos     return -1;
518411677aeSAaron LI invalid:
519*ed775ee7SAntonio Huete Jimenez     nd_print_invalid(ndo);
520411677aeSAaron LI     return -1;
521ea7b4bf5SPeter Avalos }
522ea7b4bf5SPeter Avalos 
523ea7b4bf5SPeter Avalos static int
ospf_print_lshdr(netdissect_options * ndo,const struct lsa_hdr * lshp)524411677aeSAaron LI ospf_print_lshdr(netdissect_options *ndo,
525*ed775ee7SAntonio Huete Jimenez                  const struct lsa_hdr *lshp)
526ea7b4bf5SPeter Avalos {
527*ed775ee7SAntonio Huete Jimenez         u_int ls_type;
528ea7b4bf5SPeter Avalos         u_int ls_length;
529ea7b4bf5SPeter Avalos 
530*ed775ee7SAntonio Huete Jimenez         ls_length = GET_BE_U_2(lshp->ls_length);
531ea7b4bf5SPeter Avalos         if (ls_length < sizeof(struct lsa_hdr)) {
532*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t    Bogus length %u < header (%zu)", ls_length,
533*ed775ee7SAntonio Huete Jimenez                     sizeof(struct lsa_hdr));
534ea7b4bf5SPeter Avalos                 return(-1);
535ea7b4bf5SPeter Avalos         }
536*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t  Advertising Router %s, seq 0x%08x, age %us, length %zu",
537*ed775ee7SAntonio Huete Jimenez                   GET_IPADDR_STRING(lshp->ls_router),
538*ed775ee7SAntonio Huete Jimenez                   GET_BE_U_4(lshp->ls_seq),
539*ed775ee7SAntonio Huete Jimenez                   GET_BE_U_2(lshp->ls_age),
540*ed775ee7SAntonio Huete Jimenez                   ls_length - sizeof(struct lsa_hdr));
541*ed775ee7SAntonio Huete Jimenez         ls_type = GET_U_1(lshp->ls_type);
542*ed775ee7SAntonio Huete Jimenez         switch (ls_type) {
543ea7b4bf5SPeter Avalos         /* the LSA header for opaque LSAs was slightly changed */
544ea7b4bf5SPeter Avalos         case LS_TYPE_OPAQUE_LL:
545ea7b4bf5SPeter Avalos         case LS_TYPE_OPAQUE_AL:
546ea7b4bf5SPeter Avalos         case LS_TYPE_OPAQUE_DW:
547*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    %s LSA (%u), Opaque-Type %s LSA (%u), Opaque-ID %u",
548*ed775ee7SAntonio Huete Jimenez                    tok2str(lsa_values,"unknown",ls_type),
549*ed775ee7SAntonio Huete Jimenez                    ls_type,
550ea7b4bf5SPeter Avalos 
551ea7b4bf5SPeter Avalos 		   tok2str(lsa_opaque_values,
552ea7b4bf5SPeter Avalos 			   "unknown",
553*ed775ee7SAntonio Huete Jimenez 			   GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type)),
554*ed775ee7SAntonio Huete Jimenez 		   GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type),
555*ed775ee7SAntonio Huete Jimenez 		   GET_BE_U_3(lshp->un_lsa_id.opaque_field.opaque_id)
556ea7b4bf5SPeter Avalos 
557*ed775ee7SAntonio Huete Jimenez                    );
558ea7b4bf5SPeter Avalos             break;
559ea7b4bf5SPeter Avalos 
560ea7b4bf5SPeter Avalos         /* all other LSA types use regular style LSA headers */
561ea7b4bf5SPeter Avalos         default:
562*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t    %s LSA (%u), LSA-ID: %s",
563*ed775ee7SAntonio Huete Jimenez                    tok2str(lsa_values,"unknown",ls_type),
564*ed775ee7SAntonio Huete Jimenez                    ls_type,
565*ed775ee7SAntonio Huete Jimenez                    GET_IPADDR_STRING(lshp->un_lsa_id.lsa_id));
566ea7b4bf5SPeter Avalos             break;
567ea7b4bf5SPeter Avalos         }
568*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t    Options: [%s]",
569*ed775ee7SAntonio Huete Jimenez 		 bittok2str(ospf_option_values, "none", GET_U_1(lshp->ls_options)));
570ea7b4bf5SPeter Avalos 
571ea7b4bf5SPeter Avalos         return (ls_length);
572ea7b4bf5SPeter Avalos }
573ea7b4bf5SPeter Avalos 
574ea7b4bf5SPeter Avalos /* draft-ietf-ospf-mt-09 */
575411677aeSAaron LI static const struct tok ospf_topology_values[] = {
576ea7b4bf5SPeter Avalos     { 0, "default" },
577ea7b4bf5SPeter Avalos     { 1, "multicast" },
578ea7b4bf5SPeter Avalos     { 2, "management" },
579ea7b4bf5SPeter Avalos     { 0, NULL }
580ea7b4bf5SPeter Avalos };
581ea7b4bf5SPeter Avalos 
582ea7b4bf5SPeter Avalos /*
583ea7b4bf5SPeter Avalos  * Print all the per-topology metrics.
584ea7b4bf5SPeter Avalos  */
585*ed775ee7SAntonio Huete Jimenez static void
ospf_print_tos_metrics(netdissect_options * ndo,const union un_tos * tos)586411677aeSAaron LI ospf_print_tos_metrics(netdissect_options *ndo,
587411677aeSAaron LI                        const union un_tos *tos)
588ea7b4bf5SPeter Avalos {
589*ed775ee7SAntonio Huete Jimenez     u_int metric_count;
590*ed775ee7SAntonio Huete Jimenez     u_int toscount;
591*ed775ee7SAntonio Huete Jimenez     u_int tos_type;
592ea7b4bf5SPeter Avalos 
593*ed775ee7SAntonio Huete Jimenez     toscount = GET_U_1(tos->link.link_tos_count)+1;
594ea7b4bf5SPeter Avalos     metric_count = 0;
595ea7b4bf5SPeter Avalos 
596ea7b4bf5SPeter Avalos     /*
597ea7b4bf5SPeter Avalos      * All but the first metric contain a valid topology id.
598ea7b4bf5SPeter Avalos      */
599*ed775ee7SAntonio Huete Jimenez     while (toscount != 0) {
600*ed775ee7SAntonio Huete Jimenez         tos_type = GET_U_1(tos->metrics.tos_type);
601*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t\ttopology %s (%u), metric %u",
602411677aeSAaron LI                tok2str(ospf_topology_values, "Unknown",
603*ed775ee7SAntonio Huete Jimenez                        metric_count ? tos_type : 0),
604*ed775ee7SAntonio Huete Jimenez                metric_count ? tos_type : 0,
605*ed775ee7SAntonio Huete Jimenez                GET_BE_U_2(tos->metrics.tos_metric));
606ea7b4bf5SPeter Avalos         metric_count++;
607ea7b4bf5SPeter Avalos         tos++;
608ea7b4bf5SPeter Avalos         toscount--;
609ea7b4bf5SPeter Avalos     }
610ea7b4bf5SPeter Avalos }
611ea7b4bf5SPeter Avalos 
612ea7b4bf5SPeter Avalos /*
613ea7b4bf5SPeter Avalos  * Print a single link state advertisement.  If truncated or if LSA length
614ea7b4bf5SPeter Avalos  * field is less than the length of the LSA header, return NULl, else
615ea7b4bf5SPeter Avalos  * return pointer to data past end of LSA.
616ea7b4bf5SPeter Avalos  */
617411677aeSAaron LI static const uint8_t *
ospf_print_lsa(netdissect_options * ndo,const struct lsa * lsap)618411677aeSAaron LI ospf_print_lsa(netdissect_options *ndo,
619*ed775ee7SAntonio Huete Jimenez                const struct lsa *lsap)
620ea7b4bf5SPeter Avalos {
621*ed775ee7SAntonio Huete Jimenez 	const uint8_t *ls_end;
622*ed775ee7SAntonio Huete Jimenez 	const struct rlalink *rlp;
623*ed775ee7SAntonio Huete Jimenez 	const nd_ipv4 *ap;
624*ed775ee7SAntonio Huete Jimenez 	const struct aslametric *almp;
625*ed775ee7SAntonio Huete Jimenez 	const struct mcla *mcp;
626*ed775ee7SAntonio Huete Jimenez 	const uint8_t *lp;
627*ed775ee7SAntonio Huete Jimenez 	u_int tlv_type, tlv_length, rla_count, topology;
628*ed775ee7SAntonio Huete Jimenez 	int ospf_print_lshdr_ret;
629*ed775ee7SAntonio Huete Jimenez 	u_int ls_length;
630411677aeSAaron LI 	const uint8_t *tptr;
631ea7b4bf5SPeter Avalos 
632411677aeSAaron LI 	tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
633*ed775ee7SAntonio Huete Jimenez 	ospf_print_lshdr_ret = ospf_print_lshdr(ndo, &lsap->ls_hdr);
634*ed775ee7SAntonio Huete Jimenez 	if (ospf_print_lshdr_ret < 0)
635ea7b4bf5SPeter Avalos 		return(NULL);
636*ed775ee7SAntonio Huete Jimenez 	ls_length = (u_int)ospf_print_lshdr_ret;
637411677aeSAaron LI 	ls_end = (const uint8_t *)lsap + ls_length;
638*ed775ee7SAntonio Huete Jimenez 	/*
639*ed775ee7SAntonio Huete Jimenez 	 * ospf_print_lshdr() returns -1 if the length is too short,
640*ed775ee7SAntonio Huete Jimenez 	 * so we know ls_length is >= sizeof(struct lsa_hdr).
641*ed775ee7SAntonio Huete Jimenez 	 */
642ea7b4bf5SPeter Avalos 	ls_length -= sizeof(struct lsa_hdr);
643ea7b4bf5SPeter Avalos 
644*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(lsap->ls_hdr.ls_type)) {
645ea7b4bf5SPeter Avalos 
646ea7b4bf5SPeter Avalos 	case LS_TYPE_ROUTER:
647*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t    Router LSA Options: [%s]",
648*ed775ee7SAntonio Huete Jimenez 		          bittok2str(ospf_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
649ea7b4bf5SPeter Avalos 
650*ed775ee7SAntonio Huete Jimenez 		rla_count = GET_BE_U_2(lsap->lsa_un.un_rla.rla_count);
651*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_SIZE(lsap->lsa_un.un_rla.rla_link);
652ea7b4bf5SPeter Avalos 		rlp = lsap->lsa_un.un_rla.rla_link;
653*ed775ee7SAntonio Huete Jimenez 		for (u_int i = rla_count; i != 0; i--) {
654*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_SIZE(rlp);
655*ed775ee7SAntonio Huete Jimenez 			switch (GET_U_1(rlp->un_tos.link.link_type)) {
656ea7b4bf5SPeter Avalos 
657ea7b4bf5SPeter Avalos 			case RLA_TYPE_VIRTUAL:
658*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t      Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
659*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_id),
660*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_data));
661ea7b4bf5SPeter Avalos 				break;
662ea7b4bf5SPeter Avalos 
663ea7b4bf5SPeter Avalos 			case RLA_TYPE_ROUTER:
664*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t      Neighbor Router-ID: %s, Interface Address: %s",
665*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_id),
666*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_data));
667ea7b4bf5SPeter Avalos 				break;
668ea7b4bf5SPeter Avalos 
669ea7b4bf5SPeter Avalos 			case RLA_TYPE_TRANSIT:
670*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t      Neighbor Network-ID: %s, Interface Address: %s",
671*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_id),
672*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_data));
673ea7b4bf5SPeter Avalos 				break;
674ea7b4bf5SPeter Avalos 
675ea7b4bf5SPeter Avalos 			case RLA_TYPE_STUB:
676*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t      Stub Network: %s, Mask: %s",
677*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_id),
678*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(rlp->link_data));
679ea7b4bf5SPeter Avalos 				break;
680ea7b4bf5SPeter Avalos 
681ea7b4bf5SPeter Avalos 			default:
682*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t      Unknown Router Link Type (%u)",
683*ed775ee7SAntonio Huete Jimenez 				    GET_U_1(rlp->un_tos.link.link_type));
684ea7b4bf5SPeter Avalos 				return (ls_end);
685ea7b4bf5SPeter Avalos 			}
686ea7b4bf5SPeter Avalos 
687*ed775ee7SAntonio Huete Jimenez 			ospf_print_tos_metrics(ndo, &rlp->un_tos);
688ea7b4bf5SPeter Avalos 
689411677aeSAaron LI 			rlp = (const struct rlalink *)((const u_char *)(rlp + 1) +
690*ed775ee7SAntonio Huete Jimenez 			    (GET_U_1(rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
691ea7b4bf5SPeter Avalos 		}
692ea7b4bf5SPeter Avalos 		break;
693ea7b4bf5SPeter Avalos 
694ea7b4bf5SPeter Avalos 	case LS_TYPE_NETWORK:
695*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t    Mask %s\n\t    Connected Routers:",
696*ed775ee7SAntonio Huete Jimenez 		    GET_IPADDR_STRING(lsap->lsa_un.un_nla.nla_mask));
697ea7b4bf5SPeter Avalos 		ap = lsap->lsa_un.un_nla.nla_router;
698411677aeSAaron LI 		while ((const u_char *)ap < ls_end) {
699*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_SIZE(ap);
700*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t      %s", GET_IPADDR_STRING(*ap));
701ea7b4bf5SPeter Avalos 			++ap;
702ea7b4bf5SPeter Avalos 		}
703ea7b4bf5SPeter Avalos 		break;
704ea7b4bf5SPeter Avalos 
705ea7b4bf5SPeter Avalos 	case LS_TYPE_SUM_IP:
706*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
707*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t    Mask %s",
708*ed775ee7SAntonio Huete Jimenez 		    GET_IPADDR_STRING(lsap->lsa_un.un_sla.sla_mask));
709*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
710*ed775ee7SAntonio Huete Jimenez 		lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
711*ed775ee7SAntonio Huete Jimenez 		while (lp < ls_end) {
712*ed775ee7SAntonio Huete Jimenez 			uint32_t ul;
713ea7b4bf5SPeter Avalos 
714*ed775ee7SAntonio Huete Jimenez 			ul = GET_BE_U_4(lp);
715ea7b4bf5SPeter Avalos                         topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
716*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t\ttopology %s (%u) metric %u",
717411677aeSAaron LI                                tok2str(ospf_topology_values, "Unknown", topology),
718ea7b4bf5SPeter Avalos                                topology,
719*ed775ee7SAntonio Huete Jimenez                                ul & SLA_MASK_METRIC);
720*ed775ee7SAntonio Huete Jimenez 			lp += 4;
721ea7b4bf5SPeter Avalos 		}
722ea7b4bf5SPeter Avalos 		break;
723ea7b4bf5SPeter Avalos 
724ea7b4bf5SPeter Avalos 	case LS_TYPE_SUM_ABR:
725*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
726*ed775ee7SAntonio Huete Jimenez 		lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
727*ed775ee7SAntonio Huete Jimenez 		while (lp < ls_end) {
728*ed775ee7SAntonio Huete Jimenez 			uint32_t ul;
729ea7b4bf5SPeter Avalos 
730*ed775ee7SAntonio Huete Jimenez 			ul = GET_BE_U_4(lp);
731ea7b4bf5SPeter Avalos                         topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
732*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t\ttopology %s (%u) metric %u",
733411677aeSAaron LI                                tok2str(ospf_topology_values, "Unknown", topology),
734ea7b4bf5SPeter Avalos                                topology,
735*ed775ee7SAntonio Huete Jimenez                                ul & SLA_MASK_METRIC);
736*ed775ee7SAntonio Huete Jimenez 			lp += 4;
737ea7b4bf5SPeter Avalos 		}
738ea7b4bf5SPeter Avalos 		break;
739ea7b4bf5SPeter Avalos 
740ea7b4bf5SPeter Avalos 	case LS_TYPE_ASE:
741ea7b4bf5SPeter Avalos         case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */
742*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
743*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t    Mask %s",
744*ed775ee7SAntonio Huete Jimenez 		    GET_IPADDR_STRING(lsap->lsa_un.un_asla.asla_mask));
745ea7b4bf5SPeter Avalos 
746*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
747ea7b4bf5SPeter Avalos 		almp = lsap->lsa_un.un_asla.asla_metric;
748411677aeSAaron LI 		while ((const u_char *)almp < ls_end) {
749*ed775ee7SAntonio Huete Jimenez 			uint32_t ul;
750ea7b4bf5SPeter Avalos 
751*ed775ee7SAntonio Huete Jimenez 			ul = GET_BE_U_4(almp->asla_tosmetric);
752ea7b4bf5SPeter Avalos                         topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
753*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t\ttopology %s (%u), type %u, metric",
754411677aeSAaron LI                                tok2str(ospf_topology_values, "Unknown", topology),
755ea7b4bf5SPeter Avalos                                topology,
756*ed775ee7SAntonio Huete Jimenez                                (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1);
757ea7b4bf5SPeter Avalos 			if ((ul & ASLA_MASK_METRIC) == 0xffffff)
758*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" infinite");
759ea7b4bf5SPeter Avalos 			else
760*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %u", (ul & ASLA_MASK_METRIC));
761ea7b4bf5SPeter Avalos 
762*ed775ee7SAntonio Huete Jimenez 			if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_forward) != 0) {
763*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", forward %s", GET_IPADDR_STRING(almp->asla_forward));
764ea7b4bf5SPeter Avalos 			}
765*ed775ee7SAntonio Huete Jimenez 			if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_tag) != 0) {
766*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", tag %s", GET_IPADDR_STRING(almp->asla_tag));
767ea7b4bf5SPeter Avalos 			}
768ea7b4bf5SPeter Avalos 			++almp;
769ea7b4bf5SPeter Avalos 		}
770ea7b4bf5SPeter Avalos 		break;
771ea7b4bf5SPeter Avalos 
772ea7b4bf5SPeter Avalos 	case LS_TYPE_GROUP:
773ea7b4bf5SPeter Avalos 		/* Multicast extensions as of 23 July 1991 */
774ea7b4bf5SPeter Avalos 		mcp = lsap->lsa_un.un_mcla;
775411677aeSAaron LI 		while ((const u_char *)mcp < ls_end) {
776*ed775ee7SAntonio Huete Jimenez 			switch (GET_BE_U_4(mcp->mcla_vtype)) {
777ea7b4bf5SPeter Avalos 
778ea7b4bf5SPeter Avalos 			case MCLA_VERTEX_ROUTER:
779*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t    Router Router-ID %s",
780*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(mcp->mcla_vid));
781ea7b4bf5SPeter Avalos 				break;
782ea7b4bf5SPeter Avalos 
783ea7b4bf5SPeter Avalos 			case MCLA_VERTEX_NETWORK:
784*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t    Network Designated Router %s",
785*ed775ee7SAntonio Huete Jimenez 				    GET_IPADDR_STRING(mcp->mcla_vid));
786ea7b4bf5SPeter Avalos 				break;
787ea7b4bf5SPeter Avalos 
788ea7b4bf5SPeter Avalos 			default:
789*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t    unknown VertexType (%u)",
790*ed775ee7SAntonio Huete Jimenez 				    GET_BE_U_4(mcp->mcla_vtype));
791ea7b4bf5SPeter Avalos 				break;
792ea7b4bf5SPeter Avalos 			}
793ea7b4bf5SPeter Avalos 		++mcp;
794ea7b4bf5SPeter Avalos 		}
795ea7b4bf5SPeter Avalos 		break;
796ea7b4bf5SPeter Avalos 
797ea7b4bf5SPeter Avalos 	case LS_TYPE_OPAQUE_LL: /* fall through */
798ea7b4bf5SPeter Avalos 	case LS_TYPE_OPAQUE_AL:
799ea7b4bf5SPeter Avalos 	case LS_TYPE_OPAQUE_DW:
800ea7b4bf5SPeter Avalos 
801*ed775ee7SAntonio Huete Jimenez 	    switch (GET_U_1(lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
802ea7b4bf5SPeter Avalos             case LS_OPAQUE_TYPE_RI:
803*ed775ee7SAntonio Huete Jimenez 		tptr = (const uint8_t *)(lsap->lsa_un.un_ri_tlv);
804ea7b4bf5SPeter Avalos 
805*ed775ee7SAntonio Huete Jimenez 		u_int ls_length_remaining = ls_length;
806*ed775ee7SAntonio Huete Jimenez 		while (ls_length_remaining != 0) {
807*ed775ee7SAntonio Huete Jimenez                     ND_TCHECK_4(tptr);
808*ed775ee7SAntonio Huete Jimenez 		    if (ls_length_remaining < 4) {
809*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t    Remaining LS length %u < 4", ls_length_remaining);
810ea7b4bf5SPeter Avalos                         return(ls_end);
811ea7b4bf5SPeter Avalos                     }
812*ed775ee7SAntonio Huete Jimenez                     tlv_type = GET_BE_U_2(tptr);
813*ed775ee7SAntonio Huete Jimenez                     tlv_length = GET_BE_U_2(tptr + 2);
814ea7b4bf5SPeter Avalos                     tptr+=4;
815*ed775ee7SAntonio Huete Jimenez                     ls_length_remaining-=4;
816ea7b4bf5SPeter Avalos 
817*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t    %s TLV (%u), length: %u, value: ",
818ea7b4bf5SPeter Avalos                            tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type),
819ea7b4bf5SPeter Avalos                            tlv_type,
820*ed775ee7SAntonio Huete Jimenez                            tlv_length);
821ea7b4bf5SPeter Avalos 
822*ed775ee7SAntonio Huete Jimenez                     if (tlv_length > ls_length_remaining) {
823*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("\n\t    Bogus length %u > remaining LS length %u", tlv_length,
824*ed775ee7SAntonio Huete Jimenez                             ls_length_remaining);
825ea7b4bf5SPeter Avalos                         return(ls_end);
826ea7b4bf5SPeter Avalos                     }
827*ed775ee7SAntonio Huete Jimenez                     ND_TCHECK_LEN(tptr, tlv_length);
828ea7b4bf5SPeter Avalos                     switch(tlv_type) {
829ea7b4bf5SPeter Avalos 
830ea7b4bf5SPeter Avalos                     case LS_OPAQUE_RI_TLV_CAP:
831ea7b4bf5SPeter Avalos                         if (tlv_length != 4) {
832*ed775ee7SAntonio Huete Jimenez                             ND_PRINT("\n\t    Bogus length %u != 4", tlv_length);
833ea7b4bf5SPeter Avalos                             return(ls_end);
834ea7b4bf5SPeter Avalos                         }
835*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("Capabilities: %s",
836*ed775ee7SAntonio Huete Jimenez                                bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr)));
837ea7b4bf5SPeter Avalos                         break;
838ea7b4bf5SPeter Avalos                     default:
839411677aeSAaron LI                         if (ndo->ndo_vflag <= 1) {
840411677aeSAaron LI                             if (!print_unknown_data(ndo, tptr, "\n\t      ", tlv_length))
84141c99275SPeter Avalos                                 return(ls_end);
84241c99275SPeter Avalos                         }
84341c99275SPeter Avalos                         break;
844ea7b4bf5SPeter Avalos 
84541c99275SPeter Avalos                     }
84641c99275SPeter Avalos                     tptr+=tlv_length;
847*ed775ee7SAntonio Huete Jimenez                     ls_length_remaining-=tlv_length;
84841c99275SPeter Avalos                 }
84941c99275SPeter Avalos                 break;
850ea7b4bf5SPeter Avalos 
851ea7b4bf5SPeter Avalos             case LS_OPAQUE_TYPE_GRACE:
852*ed775ee7SAntonio Huete Jimenez                 if (ospf_grace_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_grace_tlv),
853ea7b4bf5SPeter Avalos                                          ls_length) == -1) {
854ea7b4bf5SPeter Avalos                     return(ls_end);
85541c99275SPeter Avalos                 }
85641c99275SPeter Avalos                 break;
857ea7b4bf5SPeter Avalos 
858ea7b4bf5SPeter Avalos 	    case LS_OPAQUE_TYPE_TE:
859*ed775ee7SAntonio Huete Jimenez                 if (ospf_te_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_te_lsa_tlv),
860ea7b4bf5SPeter Avalos                                       ls_length) == -1) {
861ea7b4bf5SPeter Avalos                     return(ls_end);
862ea7b4bf5SPeter Avalos                 }
863ea7b4bf5SPeter Avalos                 break;
864ea7b4bf5SPeter Avalos 
86541c99275SPeter Avalos             default:
866411677aeSAaron LI                 if (ndo->ndo_vflag <= 1) {
867411677aeSAaron LI                     if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
86841c99275SPeter Avalos                                            "\n\t    ", ls_length))
86941c99275SPeter Avalos                         return(ls_end);
87041c99275SPeter Avalos                 }
87141c99275SPeter Avalos                 break;
87241c99275SPeter Avalos             }
873ea7b4bf5SPeter Avalos         }
87441c99275SPeter Avalos 
87541c99275SPeter Avalos         /* do we want to see an additionally hexdump ? */
876411677aeSAaron LI         if (ndo->ndo_vflag> 1)
877411677aeSAaron LI             if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
87841c99275SPeter Avalos                                    "\n\t    ", ls_length)) {
87941c99275SPeter Avalos                 return(ls_end);
88041c99275SPeter Avalos             }
88141c99275SPeter Avalos 
88241c99275SPeter Avalos 	return (ls_end);
88341c99275SPeter Avalos trunc:
88441c99275SPeter Avalos 	return (NULL);
88541c99275SPeter Avalos }
88641c99275SPeter Avalos 
887*ed775ee7SAntonio Huete Jimenez static void
ospf_decode_lls(netdissect_options * ndo,const struct ospfhdr * op,u_int length)888411677aeSAaron LI ospf_decode_lls(netdissect_options *ndo,
889*ed775ee7SAntonio Huete Jimenez                 const struct ospfhdr *op, u_int length)
890ea7b4bf5SPeter Avalos {
891*ed775ee7SAntonio Huete Jimenez     const u_char *dptr;
892*ed775ee7SAntonio Huete Jimenez     const u_char *dataend;
893*ed775ee7SAntonio Huete Jimenez     u_int length2;
894*ed775ee7SAntonio Huete Jimenez     uint16_t lls_type, lls_len;
895*ed775ee7SAntonio Huete Jimenez     uint32_t lls_flags;
896ea7b4bf5SPeter Avalos 
897*ed775ee7SAntonio Huete Jimenez     switch (GET_U_1(op->ospf_type)) {
898ea7b4bf5SPeter Avalos 
899ea7b4bf5SPeter Avalos     case OSPF_TYPE_HELLO:
900*ed775ee7SAntonio Huete Jimenez         if (!(GET_U_1(op->ospf_hello.hello_options) & OSPF_OPTION_L))
901*ed775ee7SAntonio Huete Jimenez             return;
902ea7b4bf5SPeter Avalos         break;
903ea7b4bf5SPeter Avalos 
904ea7b4bf5SPeter Avalos     case OSPF_TYPE_DD:
905*ed775ee7SAntonio Huete Jimenez         if (!(GET_U_1(op->ospf_db.db_options) & OSPF_OPTION_L))
906*ed775ee7SAntonio Huete Jimenez             return;
907ea7b4bf5SPeter Avalos         break;
908ea7b4bf5SPeter Avalos 
909ea7b4bf5SPeter Avalos     default:
910*ed775ee7SAntonio Huete Jimenez         return;
911ea7b4bf5SPeter Avalos     }
912ea7b4bf5SPeter Avalos 
913ea7b4bf5SPeter Avalos     /* dig deeper if LLS data is available; see RFC4813 */
914*ed775ee7SAntonio Huete Jimenez     length2 = GET_BE_U_2(op->ospf_len);
915411677aeSAaron LI     dptr = (const u_char *)op + length2;
916411677aeSAaron LI     dataend = (const u_char *)op + length;
917ea7b4bf5SPeter Avalos 
918*ed775ee7SAntonio Huete Jimenez     if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
919*ed775ee7SAntonio Huete Jimenez         dptr = dptr + GET_U_1(op->ospf_authdata + 3);
920*ed775ee7SAntonio Huete Jimenez         length2 += GET_U_1(op->ospf_authdata + 3);
921ea7b4bf5SPeter Avalos     }
922ea7b4bf5SPeter Avalos     if (length2 >= length) {
923*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t[LLS truncated]");
924*ed775ee7SAntonio Huete Jimenez         return;
925ea7b4bf5SPeter Avalos     }
926*ed775ee7SAntonio Huete Jimenez     ND_PRINT("\n\t  LLS: checksum: 0x%04x", (u_int) GET_BE_U_2(dptr));
927ea7b4bf5SPeter Avalos 
928ea7b4bf5SPeter Avalos     dptr += 2;
929*ed775ee7SAntonio Huete Jimenez     length2 = GET_BE_U_2(dptr);
930*ed775ee7SAntonio Huete Jimenez     ND_PRINT(", length: %u", length2);
931ea7b4bf5SPeter Avalos 
932ea7b4bf5SPeter Avalos     dptr += 2;
933ea7b4bf5SPeter Avalos     while (dptr < dataend) {
934*ed775ee7SAntonio Huete Jimenez         lls_type = GET_BE_U_2(dptr);
935*ed775ee7SAntonio Huete Jimenez         ND_PRINT("\n\t    %s (%u)",
936ea7b4bf5SPeter Avalos                tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type),
937*ed775ee7SAntonio Huete Jimenez                lls_type);
938ea7b4bf5SPeter Avalos         dptr += 2;
939*ed775ee7SAntonio Huete Jimenez         lls_len = GET_BE_U_2(dptr);
940*ed775ee7SAntonio Huete Jimenez         ND_PRINT(", length: %u", lls_len);
941ea7b4bf5SPeter Avalos         dptr += 2;
942ea7b4bf5SPeter Avalos         switch (lls_type) {
943ea7b4bf5SPeter Avalos 
944ea7b4bf5SPeter Avalos         case OSPF_LLS_EO:
945ea7b4bf5SPeter Avalos             if (lls_len != 4) {
946*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" [should be 4]");
947ea7b4bf5SPeter Avalos                 lls_len = 4;
948ea7b4bf5SPeter Avalos             }
949*ed775ee7SAntonio Huete Jimenez             lls_flags = GET_BE_U_4(dptr);
950*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t      Options: 0x%08x [%s]", lls_flags,
951*ed775ee7SAntonio Huete Jimenez                    bittok2str(ospf_lls_eo_options, "?", lls_flags));
952ea7b4bf5SPeter Avalos 
953ea7b4bf5SPeter Avalos             break;
954ea7b4bf5SPeter Avalos 
955ea7b4bf5SPeter Avalos         case OSPF_LLS_MD5:
956ea7b4bf5SPeter Avalos             if (lls_len != 20) {
957*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" [should be 20]");
958ea7b4bf5SPeter Avalos                 lls_len = 20;
959ea7b4bf5SPeter Avalos             }
960*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\t      Sequence number: 0x%08x", GET_BE_U_4(dptr));
961ea7b4bf5SPeter Avalos             break;
962ea7b4bf5SPeter Avalos         }
963ea7b4bf5SPeter Avalos 
964ea7b4bf5SPeter Avalos         dptr += lls_len;
965ea7b4bf5SPeter Avalos     }
966ea7b4bf5SPeter Avalos }
967ea7b4bf5SPeter Avalos 
968ea7b4bf5SPeter Avalos static int
ospf_decode_v2(netdissect_options * ndo,const struct ospfhdr * op,const u_char * dataend)969411677aeSAaron LI ospf_decode_v2(netdissect_options *ndo,
970*ed775ee7SAntonio Huete Jimenez                const struct ospfhdr *op, const u_char *dataend)
97141c99275SPeter Avalos {
972*ed775ee7SAntonio Huete Jimenez 	const nd_ipv4 *ap;
973*ed775ee7SAntonio Huete Jimenez 	const struct lsr *lsrp;
974*ed775ee7SAntonio Huete Jimenez 	const struct lsa_hdr *lshp;
975*ed775ee7SAntonio Huete Jimenez 	const struct lsa *lsap;
976*ed775ee7SAntonio Huete Jimenez 	uint32_t lsa_count,lsa_count_max;
97741c99275SPeter Avalos 
978*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(op->ospf_type)) {
97941c99275SPeter Avalos 
98041c99275SPeter Avalos 	case OSPF_TYPE_HELLO:
981*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tOptions [%s]",
982*ed775ee7SAntonio Huete Jimenez 		          bittok2str(ospf_option_values,"none",GET_U_1(op->ospf_hello.hello_options)));
98341c99275SPeter Avalos 
984*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  Hello Timer %us, Dead Timer %us, Mask %s, Priority %u",
985*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_2(op->ospf_hello.hello_helloint),
986*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_4(op->ospf_hello.hello_deadint),
987*ed775ee7SAntonio Huete Jimenez 		          GET_IPADDR_STRING(op->ospf_hello.hello_mask),
988*ed775ee7SAntonio Huete Jimenez 		          GET_U_1(op->ospf_hello.hello_priority));
98941c99275SPeter Avalos 
990*ed775ee7SAntonio Huete Jimenez 		if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_dr) != 0)
991*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t  Designated Router %s",
992*ed775ee7SAntonio Huete Jimenez 			    GET_IPADDR_STRING(op->ospf_hello.hello_dr));
99341c99275SPeter Avalos 
994*ed775ee7SAntonio Huete Jimenez 		if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_bdr) != 0)
995*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", Backup Designated Router %s",
996*ed775ee7SAntonio Huete Jimenez 			          GET_IPADDR_STRING(op->ospf_hello.hello_bdr));
99741c99275SPeter Avalos 
99841c99275SPeter Avalos 		ap = op->ospf_hello.hello_neighbor;
999411677aeSAaron LI 		if ((const u_char *)ap < dataend)
1000*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t  Neighbor List:");
1001411677aeSAaron LI 		while ((const u_char *)ap < dataend) {
1002*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_SIZE(ap);
1003*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t    %s", GET_IPADDR_STRING(*ap));
100441c99275SPeter Avalos 			++ap;
100541c99275SPeter Avalos 		}
100641c99275SPeter Avalos 		break;	/* HELLO */
100741c99275SPeter Avalos 
100841c99275SPeter Avalos 	case OSPF_TYPE_DD:
1009*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tOptions [%s]",
1010*ed775ee7SAntonio Huete Jimenez 		          bittok2str(ospf_option_values, "none", GET_U_1(op->ospf_db.db_options)));
1011*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", DD Flags [%s]",
1012*ed775ee7SAntonio Huete Jimenez 		          bittok2str(ospf_dd_flag_values, "none", GET_U_1(op->ospf_db.db_flags)));
1013*ed775ee7SAntonio Huete Jimenez 		if (GET_BE_U_2(op->ospf_db.db_ifmtu)) {
1014*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", MTU: %u",
1015*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_2(op->ospf_db.db_ifmtu));
1016ea7b4bf5SPeter Avalos 		}
1017*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", Sequence: 0x%08x", GET_BE_U_4(op->ospf_db.db_seq));
101841c99275SPeter Avalos 
101941c99275SPeter Avalos 		/* Print all the LS adv's */
102041c99275SPeter Avalos 		lshp = op->ospf_db.db_lshdr;
1021411677aeSAaron LI 		while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
102241c99275SPeter Avalos 			++lshp;
102341c99275SPeter Avalos 		}
102441c99275SPeter Avalos 		break;
102541c99275SPeter Avalos 
102641c99275SPeter Avalos 	case OSPF_TYPE_LS_REQ:
102741c99275SPeter Avalos                 lsrp = op->ospf_lsr;
1028411677aeSAaron LI                 while ((const u_char *)lsrp < dataend) {
1029*ed775ee7SAntonio Huete Jimenez                     ND_TCHECK_SIZE(lsrp);
103041c99275SPeter Avalos 
1031*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t  Advertising Router: %s, %s LSA (%u)",
1032*ed775ee7SAntonio Huete Jimenez                            GET_IPADDR_STRING(lsrp->ls_router),
1033*ed775ee7SAntonio Huete Jimenez                            tok2str(lsa_values,"unknown",GET_BE_U_4(lsrp->ls_type)),
1034*ed775ee7SAntonio Huete Jimenez                            GET_BE_U_4(lsrp->ls_type));
103541c99275SPeter Avalos 
1036*ed775ee7SAntonio Huete Jimenez                     switch (GET_BE_U_4(lsrp->ls_type)) {
103741c99275SPeter Avalos                         /* the LSA header for opaque LSAs was slightly changed */
103841c99275SPeter Avalos                     case LS_TYPE_OPAQUE_LL:
103941c99275SPeter Avalos                     case LS_TYPE_OPAQUE_AL:
104041c99275SPeter Avalos                     case LS_TYPE_OPAQUE_DW:
1041*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", Opaque-Type: %s LSA (%u), Opaque-ID: %u",
1042*ed775ee7SAntonio Huete Jimenez                                tok2str(lsa_opaque_values, "unknown",GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type)),
1043*ed775ee7SAntonio Huete Jimenez                                GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type),
1044*ed775ee7SAntonio Huete Jimenez                                GET_BE_U_3(lsrp->un_ls_stateid.opaque_field.opaque_id));
104541c99275SPeter Avalos                         break;
104641c99275SPeter Avalos                     default:
1047*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", LSA-ID: %s",
1048*ed775ee7SAntonio Huete Jimenez                                GET_IPADDR_STRING(lsrp->un_ls_stateid.ls_stateid));
104941c99275SPeter Avalos                         break;
105041c99275SPeter Avalos                     }
105141c99275SPeter Avalos 
105241c99275SPeter Avalos                     ++lsrp;
105341c99275SPeter Avalos                 }
105441c99275SPeter Avalos 		break;
105541c99275SPeter Avalos 
105641c99275SPeter Avalos 	case OSPF_TYPE_LS_UPDATE:
105741c99275SPeter Avalos                 lsap = op->ospf_lsu.lsu_lsa;
1058*ed775ee7SAntonio Huete Jimenez                 lsa_count_max = GET_BE_U_4(op->ospf_lsu.lsu_count);
1059*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", %u LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max));
106041c99275SPeter Avalos                 for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
1061*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("\n\t  LSA #%u", lsa_count);
1062411677aeSAaron LI                         lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap);
106341c99275SPeter Avalos                         if (lsap == NULL)
106441c99275SPeter Avalos                                 goto trunc;
106541c99275SPeter Avalos                 }
106641c99275SPeter Avalos 		break;
106741c99275SPeter Avalos 
106841c99275SPeter Avalos 	case OSPF_TYPE_LS_ACK:
106941c99275SPeter Avalos                 lshp = op->ospf_lsa.lsa_lshdr;
1070411677aeSAaron LI                 while (ospf_print_lshdr(ndo, lshp) != -1) {
107141c99275SPeter Avalos                     ++lshp;
107241c99275SPeter Avalos                 }
107341c99275SPeter Avalos                 break;
107441c99275SPeter Avalos 
107541c99275SPeter Avalos 	default:
107641c99275SPeter Avalos 		break;
107741c99275SPeter Avalos 	}
107841c99275SPeter Avalos 	return (0);
107941c99275SPeter Avalos trunc:
108041c99275SPeter Avalos 	return (1);
108141c99275SPeter Avalos }
108241c99275SPeter Avalos 
108341c99275SPeter Avalos void
ospf_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2 _U_)1084411677aeSAaron LI ospf_print(netdissect_options *ndo,
1085*ed775ee7SAntonio Huete Jimenez            const u_char *bp, u_int length,
108641c99275SPeter Avalos            const u_char *bp2 _U_)
108741c99275SPeter Avalos {
1088*ed775ee7SAntonio Huete Jimenez 	const struct ospfhdr *op;
1089*ed775ee7SAntonio Huete Jimenez 	const u_char *dataend;
1090*ed775ee7SAntonio Huete Jimenez 	const char *cp;
109141c99275SPeter Avalos 
1092*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "ospf2";
1093411677aeSAaron LI 	op = (const struct ospfhdr *)bp;
109441c99275SPeter Avalos 
109541c99275SPeter Avalos 	/* XXX Before we do anything else, strip off the MD5 trailer */
1096*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
109741c99275SPeter Avalos 		length -= OSPF_AUTH_MD5_LEN;
1098411677aeSAaron LI 		ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN;
109941c99275SPeter Avalos 	}
110041c99275SPeter Avalos 
110141c99275SPeter Avalos 	/* If the type is valid translate it, or just print the type */
110241c99275SPeter Avalos 	/* value.  If it's not valid, say so and return */
1103*ed775ee7SAntonio Huete Jimenez 	cp = tok2str(type2str, "unknown LS-type %u", GET_U_1(op->ospf_type));
1104*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf_version), cp,
1105*ed775ee7SAntonio Huete Jimenez 		 length);
110641c99275SPeter Avalos 	if (*cp == 'u')
110741c99275SPeter Avalos 		return;
110841c99275SPeter Avalos 
1109411677aeSAaron LI 	if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
111041c99275SPeter Avalos 		return;
1111ea7b4bf5SPeter Avalos 	}
111241c99275SPeter Avalos 
1113*ed775ee7SAntonio Huete Jimenez 	if (length != GET_BE_U_2(op->ospf_len)) {
1114*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" [len %u]", GET_BE_U_2(op->ospf_len));
111541c99275SPeter Avalos 	}
1116ea7b4bf5SPeter Avalos 
1117*ed775ee7SAntonio Huete Jimenez 	if (length > GET_BE_U_2(op->ospf_len)) {
1118*ed775ee7SAntonio Huete Jimenez 		dataend = bp + GET_BE_U_2(op->ospf_len);
1119ea7b4bf5SPeter Avalos 	} else {
112041c99275SPeter Avalos 		dataend = bp + length;
1121ea7b4bf5SPeter Avalos 	}
112241c99275SPeter Avalos 
1123*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf_routerid));
112441c99275SPeter Avalos 
1125*ed775ee7SAntonio Huete Jimenez 	if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_areaid) != 0)
1126*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf_areaid));
112741c99275SPeter Avalos 	else
1128*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", Backbone Area");
112941c99275SPeter Avalos 
1130411677aeSAaron LI 	if (ndo->ndo_vflag) {
113141c99275SPeter Avalos 		/* Print authentication data (should we really do this?) */
1132*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(op->ospf_authdata, sizeof(op->ospf_authdata));
113341c99275SPeter Avalos 
1134*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", Authentication Type: %s (%u)",
1135*ed775ee7SAntonio Huete Jimenez 		          tok2str(ospf_authtype_values, "unknown", GET_BE_U_2(op->ospf_authtype)),
1136*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_2(op->ospf_authtype));
113741c99275SPeter Avalos 
1138*ed775ee7SAntonio Huete Jimenez 		switch (GET_BE_U_2(op->ospf_authtype)) {
113941c99275SPeter Avalos 
114041c99275SPeter Avalos 		case OSPF_AUTH_NONE:
114141c99275SPeter Avalos 			break;
114241c99275SPeter Avalos 
114341c99275SPeter Avalos 		case OSPF_AUTH_SIMPLE:
1144*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\tSimple text password: ");
1145*ed775ee7SAntonio Huete Jimenez 			nd_printjnp(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
114641c99275SPeter Avalos 			break;
114741c99275SPeter Avalos 
114841c99275SPeter Avalos 		case OSPF_AUTH_MD5:
1149*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x",
1150*ed775ee7SAntonio Huete Jimenez 			          GET_U_1(op->ospf_authdata + 2),
1151*ed775ee7SAntonio Huete Jimenez 			          GET_U_1(op->ospf_authdata + 3),
1152*ed775ee7SAntonio Huete Jimenez 			          GET_BE_U_4((op->ospf_authdata) + 4));
115341c99275SPeter Avalos 			break;
115441c99275SPeter Avalos 
115541c99275SPeter Avalos 		default:
115641c99275SPeter Avalos 			return;
115741c99275SPeter Avalos 		}
115841c99275SPeter Avalos 	}
115941c99275SPeter Avalos 	/* Do rest according to version.	 */
1160*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(op->ospf_version)) {
116141c99275SPeter Avalos 
116241c99275SPeter Avalos 	case 2:
116341c99275SPeter Avalos 		/* ospf version 2 */
1164411677aeSAaron LI 		if (ospf_decode_v2(ndo, op, dataend))
116541c99275SPeter Avalos 			goto trunc;
1166*ed775ee7SAntonio Huete Jimenez 		if (length > GET_BE_U_2(op->ospf_len))
1167*ed775ee7SAntonio Huete Jimenez 			ospf_decode_lls(ndo, op, length);
116841c99275SPeter Avalos 		break;
116941c99275SPeter Avalos 
117041c99275SPeter Avalos 	default:
1171*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ospf [version %u]", GET_U_1(op->ospf_version));
117241c99275SPeter Avalos 		break;
117341c99275SPeter Avalos 	}			/* end switch on version */
117441c99275SPeter Avalos 
117541c99275SPeter Avalos 	return;
117641c99275SPeter Avalos trunc:
1177*ed775ee7SAntonio Huete Jimenez 	nd_trunc_longjmp(ndo);
117841c99275SPeter Avalos }
1179