1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3*b636d99dSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
4*b636d99dSDavid van Moolenbroek *
5*b636d99dSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek * modification, are permitted provided that: (1) source code distributions
7*b636d99dSDavid van Moolenbroek * retain the above copyright notice and this paragraph in its entirety, (2)
8*b636d99dSDavid van Moolenbroek * distributions including binary code include the above copyright notice and
9*b636d99dSDavid van Moolenbroek * this paragraph in its entirety in the documentation or other materials
10*b636d99dSDavid van Moolenbroek * provided with the distribution, and (3) all advertising materials mentioning
11*b636d99dSDavid van Moolenbroek * features or use of this software display the following acknowledgement:
12*b636d99dSDavid van Moolenbroek * ``This product includes software developed by the University of California,
13*b636d99dSDavid van Moolenbroek * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*b636d99dSDavid van Moolenbroek * the University nor the names of its contributors may be used to endorse
15*b636d99dSDavid van Moolenbroek * or promote products derived from this software without specific prior
16*b636d99dSDavid van Moolenbroek * written permission.
17*b636d99dSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*b636d99dSDavid van Moolenbroek * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*b636d99dSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*b636d99dSDavid van Moolenbroek *
21*b636d99dSDavid van Moolenbroek * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
22*b636d99dSDavid van Moolenbroek */
23*b636d99dSDavid van Moolenbroek
24*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
25*b636d99dSDavid van Moolenbroek #ifndef lint
26*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-ospf.c,v 1.6 2015/03/31 21:59:35 christos Exp $");
27*b636d99dSDavid van Moolenbroek #endif
28*b636d99dSDavid van Moolenbroek
29*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
30*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
31*b636d99dSDavid van Moolenbroek #include "config.h"
32*b636d99dSDavid van Moolenbroek #endif
33*b636d99dSDavid van Moolenbroek
34*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
35*b636d99dSDavid van Moolenbroek
36*b636d99dSDavid van Moolenbroek #include "interface.h"
37*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
38*b636d99dSDavid van Moolenbroek #include "extract.h"
39*b636d99dSDavid van Moolenbroek #include "gmpls.h"
40*b636d99dSDavid van Moolenbroek
41*b636d99dSDavid van Moolenbroek #include "ospf.h"
42*b636d99dSDavid van Moolenbroek
43*b636d99dSDavid van Moolenbroek static const char tstr[] = " [|ospf2]";
44*b636d99dSDavid van Moolenbroek
45*b636d99dSDavid van Moolenbroek static const struct tok ospf_option_values[] = {
46*b636d99dSDavid van Moolenbroek { OSPF_OPTION_T, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */
47*b636d99dSDavid van Moolenbroek { OSPF_OPTION_E, "External" },
48*b636d99dSDavid van Moolenbroek { OSPF_OPTION_MC, "Multicast" },
49*b636d99dSDavid van Moolenbroek { OSPF_OPTION_NP, "NSSA" },
50*b636d99dSDavid van Moolenbroek { OSPF_OPTION_L, "LLS" },
51*b636d99dSDavid van Moolenbroek { OSPF_OPTION_DC, "Demand Circuit" },
52*b636d99dSDavid van Moolenbroek { OSPF_OPTION_O, "Opaque" },
53*b636d99dSDavid van Moolenbroek { OSPF_OPTION_DN, "Up/Down" },
54*b636d99dSDavid van Moolenbroek { 0, NULL }
55*b636d99dSDavid van Moolenbroek };
56*b636d99dSDavid van Moolenbroek
57*b636d99dSDavid van Moolenbroek static const struct tok ospf_authtype_values[] = {
58*b636d99dSDavid van Moolenbroek { OSPF_AUTH_NONE, "none" },
59*b636d99dSDavid van Moolenbroek { OSPF_AUTH_SIMPLE, "simple" },
60*b636d99dSDavid van Moolenbroek { OSPF_AUTH_MD5, "MD5" },
61*b636d99dSDavid van Moolenbroek { 0, NULL }
62*b636d99dSDavid van Moolenbroek };
63*b636d99dSDavid van Moolenbroek
64*b636d99dSDavid van Moolenbroek static const struct tok ospf_rla_flag_values[] = {
65*b636d99dSDavid van Moolenbroek { RLA_FLAG_B, "ABR" },
66*b636d99dSDavid van Moolenbroek { RLA_FLAG_E, "ASBR" },
67*b636d99dSDavid van Moolenbroek { RLA_FLAG_W1, "Virtual" },
68*b636d99dSDavid van Moolenbroek { RLA_FLAG_W2, "W2" },
69*b636d99dSDavid van Moolenbroek { 0, NULL }
70*b636d99dSDavid van Moolenbroek };
71*b636d99dSDavid van Moolenbroek
72*b636d99dSDavid van Moolenbroek static const struct tok type2str[] = {
73*b636d99dSDavid van Moolenbroek { OSPF_TYPE_UMD, "UMD" },
74*b636d99dSDavid van Moolenbroek { OSPF_TYPE_HELLO, "Hello" },
75*b636d99dSDavid van Moolenbroek { OSPF_TYPE_DD, "Database Description" },
76*b636d99dSDavid van Moolenbroek { OSPF_TYPE_LS_REQ, "LS-Request" },
77*b636d99dSDavid van Moolenbroek { OSPF_TYPE_LS_UPDATE, "LS-Update" },
78*b636d99dSDavid van Moolenbroek { OSPF_TYPE_LS_ACK, "LS-Ack" },
79*b636d99dSDavid van Moolenbroek { 0, NULL }
80*b636d99dSDavid van Moolenbroek };
81*b636d99dSDavid van Moolenbroek
82*b636d99dSDavid van Moolenbroek static const struct tok lsa_values[] = {
83*b636d99dSDavid van Moolenbroek { LS_TYPE_ROUTER, "Router" },
84*b636d99dSDavid van Moolenbroek { LS_TYPE_NETWORK, "Network" },
85*b636d99dSDavid van Moolenbroek { LS_TYPE_SUM_IP, "Summary" },
86*b636d99dSDavid van Moolenbroek { LS_TYPE_SUM_ABR, "ASBR Summary" },
87*b636d99dSDavid van Moolenbroek { LS_TYPE_ASE, "External" },
88*b636d99dSDavid van Moolenbroek { LS_TYPE_GROUP, "Multicast Group" },
89*b636d99dSDavid van Moolenbroek { LS_TYPE_NSSA, "NSSA" },
90*b636d99dSDavid van Moolenbroek { LS_TYPE_OPAQUE_LL, "Link Local Opaque" },
91*b636d99dSDavid van Moolenbroek { LS_TYPE_OPAQUE_AL, "Area Local Opaque" },
92*b636d99dSDavid van Moolenbroek { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" },
93*b636d99dSDavid van Moolenbroek { 0, NULL }
94*b636d99dSDavid van Moolenbroek };
95*b636d99dSDavid van Moolenbroek
96*b636d99dSDavid van Moolenbroek static const struct tok ospf_dd_flag_values[] = {
97*b636d99dSDavid van Moolenbroek { OSPF_DB_INIT, "Init" },
98*b636d99dSDavid van Moolenbroek { OSPF_DB_MORE, "More" },
99*b636d99dSDavid van Moolenbroek { OSPF_DB_MASTER, "Master" },
100*b636d99dSDavid van Moolenbroek { OSPF_DB_RESYNC, "OOBResync" },
101*b636d99dSDavid van Moolenbroek { 0, NULL }
102*b636d99dSDavid van Moolenbroek };
103*b636d99dSDavid van Moolenbroek
104*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_values[] = {
105*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TYPE_TE, "Traffic Engineering" },
106*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
107*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TYPE_RI, "Router Information" },
108*b636d99dSDavid van Moolenbroek { 0, NULL }
109*b636d99dSDavid van Moolenbroek };
110*b636d99dSDavid van Moolenbroek
111*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_te_tlv_values[] = {
112*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
113*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_TLV_LINK, "Link" },
114*b636d99dSDavid van Moolenbroek { 0, NULL }
115*b636d99dSDavid van Moolenbroek };
116*b636d99dSDavid van Moolenbroek
117*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
118*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" },
119*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" },
120*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" },
121*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" },
122*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" },
123*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" },
124*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" },
125*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" },
126*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" },
127*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
128*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
129*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
130*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" },
131*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" },
132*b636d99dSDavid van Moolenbroek { 0, NULL }
133*b636d99dSDavid van Moolenbroek };
134*b636d99dSDavid van Moolenbroek
135*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_grace_tlv_values[] = {
136*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" },
137*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" },
138*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" },
139*b636d99dSDavid van Moolenbroek { 0, NULL }
140*b636d99dSDavid van Moolenbroek };
141*b636d99dSDavid van Moolenbroek
142*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_grace_tlv_reason_values[] = {
143*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" },
144*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" },
145*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" },
146*b636d99dSDavid van Moolenbroek { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" },
147*b636d99dSDavid van Moolenbroek { 0, NULL }
148*b636d99dSDavid van Moolenbroek };
149*b636d99dSDavid van Moolenbroek
150*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
151*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
152*b636d99dSDavid van Moolenbroek { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" },
153*b636d99dSDavid van Moolenbroek { 0, NULL }
154*b636d99dSDavid van Moolenbroek };
155*b636d99dSDavid van Moolenbroek
156*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_ri_tlv_values[] = {
157*b636d99dSDavid van Moolenbroek { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
158*b636d99dSDavid van Moolenbroek { 0, NULL }
159*b636d99dSDavid van Moolenbroek };
160*b636d99dSDavid van Moolenbroek
161*b636d99dSDavid van Moolenbroek static const struct tok lsa_opaque_ri_tlv_cap_values[] = {
162*b636d99dSDavid van Moolenbroek { 1, "Reserved" },
163*b636d99dSDavid van Moolenbroek { 2, "Reserved" },
164*b636d99dSDavid van Moolenbroek { 4, "Reserved" },
165*b636d99dSDavid van Moolenbroek { 8, "Reserved" },
166*b636d99dSDavid van Moolenbroek { 16, "graceful restart capable" },
167*b636d99dSDavid van Moolenbroek { 32, "graceful restart helper" },
168*b636d99dSDavid van Moolenbroek { 64, "Stub router support" },
169*b636d99dSDavid van Moolenbroek { 128, "Traffic engineering" },
170*b636d99dSDavid van Moolenbroek { 256, "p2p over LAN" },
171*b636d99dSDavid van Moolenbroek { 512, "path computation server" },
172*b636d99dSDavid van Moolenbroek { 0, NULL }
173*b636d99dSDavid van Moolenbroek };
174*b636d99dSDavid van Moolenbroek
175*b636d99dSDavid van Moolenbroek static const struct tok ospf_lls_tlv_values[] = {
176*b636d99dSDavid van Moolenbroek { OSPF_LLS_EO, "Extended Options" },
177*b636d99dSDavid van Moolenbroek { OSPF_LLS_MD5, "MD5 Authentication" },
178*b636d99dSDavid van Moolenbroek { 0, NULL }
179*b636d99dSDavid van Moolenbroek };
180*b636d99dSDavid van Moolenbroek
181*b636d99dSDavid van Moolenbroek static const struct tok ospf_lls_eo_options[] = {
182*b636d99dSDavid van Moolenbroek { OSPF_LLS_EO_LR, "LSDB resync" },
183*b636d99dSDavid van Moolenbroek { OSPF_LLS_EO_RS, "Restart" },
184*b636d99dSDavid van Moolenbroek { 0, NULL }
185*b636d99dSDavid van Moolenbroek };
186*b636d99dSDavid van Moolenbroek
187*b636d99dSDavid van Moolenbroek int
ospf_print_grace_lsa(netdissect_options * ndo,const uint8_t * tptr,u_int ls_length)188*b636d99dSDavid van Moolenbroek ospf_print_grace_lsa(netdissect_options *ndo,
189*b636d99dSDavid van Moolenbroek const uint8_t *tptr, u_int ls_length)
190*b636d99dSDavid van Moolenbroek {
191*b636d99dSDavid van Moolenbroek u_int tlv_type, tlv_length;
192*b636d99dSDavid van Moolenbroek
193*b636d99dSDavid van Moolenbroek
194*b636d99dSDavid van Moolenbroek while (ls_length > 0) {
195*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, 4);
196*b636d99dSDavid van Moolenbroek if (ls_length < 4) {
197*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length));
198*b636d99dSDavid van Moolenbroek return -1;
199*b636d99dSDavid van Moolenbroek }
200*b636d99dSDavid van Moolenbroek tlv_type = EXTRACT_16BITS(tptr);
201*b636d99dSDavid van Moolenbroek tlv_length = EXTRACT_16BITS(tptr+2);
202*b636d99dSDavid van Moolenbroek tptr+=4;
203*b636d99dSDavid van Moolenbroek ls_length-=4;
204*b636d99dSDavid van Moolenbroek
205*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s TLV (%u), length %u, value: ",
206*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
207*b636d99dSDavid van Moolenbroek tlv_type,
208*b636d99dSDavid van Moolenbroek tlv_length));
209*b636d99dSDavid van Moolenbroek
210*b636d99dSDavid van Moolenbroek if (tlv_length > ls_length) {
211*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length,
212*b636d99dSDavid van Moolenbroek ls_length));
213*b636d99dSDavid van Moolenbroek return -1;
214*b636d99dSDavid van Moolenbroek }
215*b636d99dSDavid van Moolenbroek
216*b636d99dSDavid van Moolenbroek /* Infinite loop protection. */
217*b636d99dSDavid van Moolenbroek if (tlv_type == 0 || tlv_length ==0) {
218*b636d99dSDavid van Moolenbroek return -1;
219*b636d99dSDavid van Moolenbroek }
220*b636d99dSDavid van Moolenbroek
221*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, tlv_length);
222*b636d99dSDavid van Moolenbroek switch(tlv_type) {
223*b636d99dSDavid van Moolenbroek
224*b636d99dSDavid van Moolenbroek case LS_OPAQUE_GRACE_TLV_PERIOD:
225*b636d99dSDavid van Moolenbroek if (tlv_length != 4) {
226*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length));
227*b636d99dSDavid van Moolenbroek return -1;
228*b636d99dSDavid van Moolenbroek }
229*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%us", EXTRACT_32BITS(tptr)));
230*b636d99dSDavid van Moolenbroek break;
231*b636d99dSDavid van Moolenbroek
232*b636d99dSDavid van Moolenbroek case LS_OPAQUE_GRACE_TLV_REASON:
233*b636d99dSDavid van Moolenbroek if (tlv_length != 1) {
234*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u != 1", tlv_length));
235*b636d99dSDavid van Moolenbroek return -1;
236*b636d99dSDavid van Moolenbroek }
237*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s (%u)",
238*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr),
239*b636d99dSDavid van Moolenbroek *tptr));
240*b636d99dSDavid van Moolenbroek break;
241*b636d99dSDavid van Moolenbroek
242*b636d99dSDavid van Moolenbroek case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
243*b636d99dSDavid van Moolenbroek if (tlv_length != 4) {
244*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length));
245*b636d99dSDavid van Moolenbroek return -1;
246*b636d99dSDavid van Moolenbroek }
247*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
248*b636d99dSDavid van Moolenbroek break;
249*b636d99dSDavid van Moolenbroek
250*b636d99dSDavid van Moolenbroek default:
251*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1) {
252*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
253*b636d99dSDavid van Moolenbroek return -1;
254*b636d99dSDavid van Moolenbroek }
255*b636d99dSDavid van Moolenbroek break;
256*b636d99dSDavid van Moolenbroek
257*b636d99dSDavid van Moolenbroek }
258*b636d99dSDavid van Moolenbroek /* in OSPF everything has to be 32-bit aligned, including TLVs */
259*b636d99dSDavid van Moolenbroek if (tlv_length%4 != 0)
260*b636d99dSDavid van Moolenbroek tlv_length+=4-(tlv_length%4);
261*b636d99dSDavid van Moolenbroek ls_length-=tlv_length;
262*b636d99dSDavid van Moolenbroek tptr+=tlv_length;
263*b636d99dSDavid van Moolenbroek }
264*b636d99dSDavid van Moolenbroek
265*b636d99dSDavid van Moolenbroek return 0;
266*b636d99dSDavid van Moolenbroek trunc:
267*b636d99dSDavid van Moolenbroek return -1;
268*b636d99dSDavid van Moolenbroek }
269*b636d99dSDavid van Moolenbroek
270*b636d99dSDavid van Moolenbroek int
ospf_print_te_lsa(netdissect_options * ndo,const uint8_t * tptr,u_int ls_length)271*b636d99dSDavid van Moolenbroek ospf_print_te_lsa(netdissect_options *ndo,
272*b636d99dSDavid van Moolenbroek const uint8_t *tptr, u_int ls_length)
273*b636d99dSDavid van Moolenbroek {
274*b636d99dSDavid van Moolenbroek u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
275*b636d99dSDavid van Moolenbroek u_int priority_level, te_class, count_srlg;
276*b636d99dSDavid van Moolenbroek union { /* int to float conversion buffer for several subTLVs */
277*b636d99dSDavid van Moolenbroek float f;
278*b636d99dSDavid van Moolenbroek uint32_t i;
279*b636d99dSDavid van Moolenbroek } bw;
280*b636d99dSDavid van Moolenbroek
281*b636d99dSDavid van Moolenbroek while (ls_length != 0) {
282*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, 4);
283*b636d99dSDavid van Moolenbroek if (ls_length < 4) {
284*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length));
285*b636d99dSDavid van Moolenbroek return -1;
286*b636d99dSDavid van Moolenbroek }
287*b636d99dSDavid van Moolenbroek tlv_type = EXTRACT_16BITS(tptr);
288*b636d99dSDavid van Moolenbroek tlv_length = EXTRACT_16BITS(tptr+2);
289*b636d99dSDavid van Moolenbroek tptr+=4;
290*b636d99dSDavid van Moolenbroek ls_length-=4;
291*b636d99dSDavid van Moolenbroek
292*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u",
293*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
294*b636d99dSDavid van Moolenbroek tlv_type,
295*b636d99dSDavid van Moolenbroek tlv_length));
296*b636d99dSDavid van Moolenbroek
297*b636d99dSDavid van Moolenbroek if (tlv_length > ls_length) {
298*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length,
299*b636d99dSDavid van Moolenbroek ls_length));
300*b636d99dSDavid van Moolenbroek return -1;
301*b636d99dSDavid van Moolenbroek }
302*b636d99dSDavid van Moolenbroek
303*b636d99dSDavid van Moolenbroek /* Infinite loop protection. */
304*b636d99dSDavid van Moolenbroek if (tlv_type == 0 || tlv_length ==0) {
305*b636d99dSDavid van Moolenbroek return -1;
306*b636d99dSDavid van Moolenbroek }
307*b636d99dSDavid van Moolenbroek
308*b636d99dSDavid van Moolenbroek switch(tlv_type) {
309*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_TLV_LINK:
310*b636d99dSDavid van Moolenbroek while (tlv_length >= sizeof(subtlv_type) + sizeof(subtlv_length)) {
311*b636d99dSDavid van Moolenbroek if (tlv_length < 4) {
312*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Remaining TLV length %u < 4",
313*b636d99dSDavid van Moolenbroek tlv_length));
314*b636d99dSDavid van Moolenbroek return -1;
315*b636d99dSDavid van Moolenbroek }
316*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, 4);
317*b636d99dSDavid van Moolenbroek subtlv_type = EXTRACT_16BITS(tptr);
318*b636d99dSDavid van Moolenbroek subtlv_length = EXTRACT_16BITS(tptr+2);
319*b636d99dSDavid van Moolenbroek tptr+=4;
320*b636d99dSDavid van Moolenbroek tlv_length-=4;
321*b636d99dSDavid van Moolenbroek
322*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s subTLV (%u), length: %u",
323*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
324*b636d99dSDavid van Moolenbroek subtlv_type,
325*b636d99dSDavid van Moolenbroek subtlv_length));
326*b636d99dSDavid van Moolenbroek
327*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, subtlv_length);
328*b636d99dSDavid van Moolenbroek switch(subtlv_type) {
329*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
330*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr)));
331*b636d99dSDavid van Moolenbroek break;
332*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
333*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
334*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s (0x%08x)",
335*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, tptr),
336*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(tptr)));
337*b636d99dSDavid van Moolenbroek if (subtlv_length == 8) /* rfc4203 */
338*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s (0x%08x)",
339*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, tptr+4),
340*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(tptr + 4)));
341*b636d99dSDavid van Moolenbroek break;
342*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
343*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
344*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr)));
345*b636d99dSDavid van Moolenbroek break;
346*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
347*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
348*b636d99dSDavid van Moolenbroek bw.i = EXTRACT_32BITS(tptr);
349*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000));
350*b636d99dSDavid van Moolenbroek break;
351*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
352*b636d99dSDavid van Moolenbroek for (te_class = 0; te_class < 8; te_class++) {
353*b636d99dSDavid van Moolenbroek bw.i = EXTRACT_32BITS(tptr+te_class*4);
354*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\tTE-Class %u: %.3f Mbps",
355*b636d99dSDavid van Moolenbroek te_class,
356*b636d99dSDavid van Moolenbroek bw.f * 8 / 1000000));
357*b636d99dSDavid van Moolenbroek }
358*b636d99dSDavid van Moolenbroek break;
359*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
360*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\tBandwidth Constraints Model ID: %s (%u)",
361*b636d99dSDavid van Moolenbroek tok2str(diffserv_te_bc_values, "unknown", *tptr),
362*b636d99dSDavid van Moolenbroek *tptr));
363*b636d99dSDavid van Moolenbroek /* decode BCs until the subTLV ends */
364*b636d99dSDavid van Moolenbroek for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
365*b636d99dSDavid van Moolenbroek bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
366*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\t Bandwidth constraint CT%u: %.3f Mbps",
367*b636d99dSDavid van Moolenbroek te_class,
368*b636d99dSDavid van Moolenbroek bw.f * 8 / 1000000));
369*b636d99dSDavid van Moolenbroek }
370*b636d99dSDavid van Moolenbroek break;
371*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
372*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Metric %u", EXTRACT_32BITS(tptr)));
373*b636d99dSDavid van Moolenbroek break;
374*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
375*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s, Priority %u",
376*b636d99dSDavid van Moolenbroek bittok2str(gmpls_link_prot_values, "none", *tptr),
377*b636d99dSDavid van Moolenbroek *(tptr + 1)));
378*b636d99dSDavid van Moolenbroek break;
379*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
380*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\tInterface Switching Capability: %s",
381*b636d99dSDavid van Moolenbroek tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))));
382*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
383*b636d99dSDavid van Moolenbroek tok2str(gmpls_encoding_values, "Unknown", *(tptr + 1))));
384*b636d99dSDavid van Moolenbroek for (priority_level = 0; priority_level < 8; priority_level++) {
385*b636d99dSDavid van Moolenbroek bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4));
386*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\t priority level %d: %.3f Mbps",
387*b636d99dSDavid van Moolenbroek priority_level,
388*b636d99dSDavid van Moolenbroek bw.f * 8 / 1000000));
389*b636d99dSDavid van Moolenbroek }
390*b636d99dSDavid van Moolenbroek break;
391*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
392*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s (%u)",
393*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
394*b636d99dSDavid van Moolenbroek *tptr));
395*b636d99dSDavid van Moolenbroek break;
396*b636d99dSDavid van Moolenbroek
397*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
398*b636d99dSDavid van Moolenbroek count_srlg = subtlv_length / 4;
399*b636d99dSDavid van Moolenbroek if (count_srlg != 0)
400*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\t Shared risk group: "));
401*b636d99dSDavid van Moolenbroek while (count_srlg > 0) {
402*b636d99dSDavid van Moolenbroek bw.i = EXTRACT_32BITS(tptr);
403*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%d", bw.i));
404*b636d99dSDavid van Moolenbroek tptr+=4;
405*b636d99dSDavid van Moolenbroek count_srlg--;
406*b636d99dSDavid van Moolenbroek if (count_srlg > 0)
407*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", "));
408*b636d99dSDavid van Moolenbroek }
409*b636d99dSDavid van Moolenbroek break;
410*b636d99dSDavid van Moolenbroek
411*b636d99dSDavid van Moolenbroek default:
412*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1) {
413*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
414*b636d99dSDavid van Moolenbroek return -1;
415*b636d99dSDavid van Moolenbroek }
416*b636d99dSDavid van Moolenbroek break;
417*b636d99dSDavid van Moolenbroek }
418*b636d99dSDavid van Moolenbroek /* in OSPF everything has to be 32-bit aligned, including subTLVs */
419*b636d99dSDavid van Moolenbroek if (subtlv_length%4 != 0)
420*b636d99dSDavid van Moolenbroek subtlv_length+=4-(subtlv_length%4);
421*b636d99dSDavid van Moolenbroek
422*b636d99dSDavid van Moolenbroek tlv_length-=subtlv_length;
423*b636d99dSDavid van Moolenbroek tptr+=subtlv_length;
424*b636d99dSDavid van Moolenbroek
425*b636d99dSDavid van Moolenbroek }
426*b636d99dSDavid van Moolenbroek break;
427*b636d99dSDavid van Moolenbroek
428*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TE_TLV_ROUTER:
429*b636d99dSDavid van Moolenbroek if (tlv_length < 4) {
430*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t TLV length %u < 4", tlv_length));
431*b636d99dSDavid van Moolenbroek return -1;
432*b636d99dSDavid van Moolenbroek }
433*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, 4);
434*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr)));
435*b636d99dSDavid van Moolenbroek break;
436*b636d99dSDavid van Moolenbroek
437*b636d99dSDavid van Moolenbroek default:
438*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1) {
439*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
440*b636d99dSDavid van Moolenbroek return -1;
441*b636d99dSDavid van Moolenbroek }
442*b636d99dSDavid van Moolenbroek break;
443*b636d99dSDavid van Moolenbroek }
444*b636d99dSDavid van Moolenbroek /* in OSPF everything has to be 32-bit aligned, including TLVs */
445*b636d99dSDavid van Moolenbroek if (tlv_length%4 != 0)
446*b636d99dSDavid van Moolenbroek tlv_length+=4-(tlv_length%4);
447*b636d99dSDavid van Moolenbroek ls_length-=tlv_length;
448*b636d99dSDavid van Moolenbroek tptr+=tlv_length;
449*b636d99dSDavid van Moolenbroek }
450*b636d99dSDavid van Moolenbroek return 0;
451*b636d99dSDavid van Moolenbroek trunc:
452*b636d99dSDavid van Moolenbroek return -1;
453*b636d99dSDavid van Moolenbroek }
454*b636d99dSDavid van Moolenbroek
455*b636d99dSDavid van Moolenbroek static int
ospf_print_lshdr(netdissect_options * ndo,register const struct lsa_hdr * lshp)456*b636d99dSDavid van Moolenbroek ospf_print_lshdr(netdissect_options *ndo,
457*b636d99dSDavid van Moolenbroek register const struct lsa_hdr *lshp)
458*b636d99dSDavid van Moolenbroek {
459*b636d99dSDavid van Moolenbroek u_int ls_length;
460*b636d99dSDavid van Moolenbroek
461*b636d99dSDavid van Moolenbroek ND_TCHECK(lshp->ls_length);
462*b636d99dSDavid van Moolenbroek ls_length = EXTRACT_16BITS(&lshp->ls_length);
463*b636d99dSDavid van Moolenbroek if (ls_length < sizeof(struct lsa_hdr)) {
464*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u < header (%lu)", ls_length,
465*b636d99dSDavid van Moolenbroek (unsigned long)sizeof(struct lsa_hdr)));
466*b636d99dSDavid van Moolenbroek return(-1);
467*b636d99dSDavid van Moolenbroek }
468*b636d99dSDavid van Moolenbroek
469*b636d99dSDavid van Moolenbroek ND_TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */
470*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u",
471*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lshp->ls_router),
472*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(&lshp->ls_seq),
473*b636d99dSDavid van Moolenbroek EXTRACT_16BITS(&lshp->ls_age),
474*b636d99dSDavid van Moolenbroek ls_length - (u_int)sizeof(struct lsa_hdr)));
475*b636d99dSDavid van Moolenbroek
476*b636d99dSDavid van Moolenbroek ND_TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */
477*b636d99dSDavid van Moolenbroek switch (lshp->ls_type) {
478*b636d99dSDavid van Moolenbroek /* the LSA header for opaque LSAs was slightly changed */
479*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_LL:
480*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_AL:
481*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_DW:
482*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s LSA (%d), Opaque-Type %s LSA (%u), Opaque-ID %u",
483*b636d99dSDavid van Moolenbroek tok2str(lsa_values,"unknown",lshp->ls_type),
484*b636d99dSDavid van Moolenbroek lshp->ls_type,
485*b636d99dSDavid van Moolenbroek
486*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_values,
487*b636d99dSDavid van Moolenbroek "unknown",
488*b636d99dSDavid van Moolenbroek *(&lshp->un_lsa_id.opaque_field.opaque_type)),
489*b636d99dSDavid van Moolenbroek *(&lshp->un_lsa_id.opaque_field.opaque_type),
490*b636d99dSDavid van Moolenbroek EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id)
491*b636d99dSDavid van Moolenbroek
492*b636d99dSDavid van Moolenbroek ));
493*b636d99dSDavid van Moolenbroek break;
494*b636d99dSDavid van Moolenbroek
495*b636d99dSDavid van Moolenbroek /* all other LSA types use regular style LSA headers */
496*b636d99dSDavid van Moolenbroek default:
497*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s LSA (%d), LSA-ID: %s",
498*b636d99dSDavid van Moolenbroek tok2str(lsa_values,"unknown",lshp->ls_type),
499*b636d99dSDavid van Moolenbroek lshp->ls_type,
500*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lshp->un_lsa_id.lsa_id)));
501*b636d99dSDavid van Moolenbroek break;
502*b636d99dSDavid van Moolenbroek }
503*b636d99dSDavid van Moolenbroek
504*b636d99dSDavid van Moolenbroek ND_TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */
505*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Options: [%s]", bittok2str(ospf_option_values, "none", lshp->ls_options)));
506*b636d99dSDavid van Moolenbroek
507*b636d99dSDavid van Moolenbroek return (ls_length);
508*b636d99dSDavid van Moolenbroek trunc:
509*b636d99dSDavid van Moolenbroek return (-1);
510*b636d99dSDavid van Moolenbroek }
511*b636d99dSDavid van Moolenbroek
512*b636d99dSDavid van Moolenbroek /* draft-ietf-ospf-mt-09 */
513*b636d99dSDavid van Moolenbroek static const struct tok ospf_topology_values[] = {
514*b636d99dSDavid van Moolenbroek { 0, "default " },
515*b636d99dSDavid van Moolenbroek { 1, "multicast " },
516*b636d99dSDavid van Moolenbroek { 2, "management " },
517*b636d99dSDavid van Moolenbroek { 0, NULL }
518*b636d99dSDavid van Moolenbroek };
519*b636d99dSDavid van Moolenbroek
520*b636d99dSDavid van Moolenbroek /*
521*b636d99dSDavid van Moolenbroek * Print all the per-topology metrics.
522*b636d99dSDavid van Moolenbroek */
523*b636d99dSDavid van Moolenbroek static void
ospf_print_tos_metrics(netdissect_options * ndo,const union un_tos * tos)524*b636d99dSDavid van Moolenbroek ospf_print_tos_metrics(netdissect_options *ndo,
525*b636d99dSDavid van Moolenbroek const union un_tos *tos)
526*b636d99dSDavid van Moolenbroek {
527*b636d99dSDavid van Moolenbroek int metric_count;
528*b636d99dSDavid van Moolenbroek int toscount;
529*b636d99dSDavid van Moolenbroek
530*b636d99dSDavid van Moolenbroek toscount = tos->link.link_tos_count+1;
531*b636d99dSDavid van Moolenbroek metric_count = 0;
532*b636d99dSDavid van Moolenbroek
533*b636d99dSDavid van Moolenbroek /*
534*b636d99dSDavid van Moolenbroek * All but the first metric contain a valid topology id.
535*b636d99dSDavid van Moolenbroek */
536*b636d99dSDavid van Moolenbroek while (toscount) {
537*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\ttopology %s(%u), metric %u",
538*b636d99dSDavid van Moolenbroek tok2str(ospf_topology_values, "",
539*b636d99dSDavid van Moolenbroek metric_count ? tos->metrics.tos_type : 0),
540*b636d99dSDavid van Moolenbroek metric_count ? tos->metrics.tos_type : 0,
541*b636d99dSDavid van Moolenbroek EXTRACT_16BITS(&tos->metrics.tos_metric)));
542*b636d99dSDavid van Moolenbroek metric_count++;
543*b636d99dSDavid van Moolenbroek tos++;
544*b636d99dSDavid van Moolenbroek toscount--;
545*b636d99dSDavid van Moolenbroek }
546*b636d99dSDavid van Moolenbroek }
547*b636d99dSDavid van Moolenbroek
548*b636d99dSDavid van Moolenbroek /*
549*b636d99dSDavid van Moolenbroek * Print a single link state advertisement. If truncated or if LSA length
550*b636d99dSDavid van Moolenbroek * field is less than the length of the LSA header, return NULl, else
551*b636d99dSDavid van Moolenbroek * return pointer to data past end of LSA.
552*b636d99dSDavid van Moolenbroek */
553*b636d99dSDavid van Moolenbroek static const uint8_t *
ospf_print_lsa(netdissect_options * ndo,register const struct lsa * lsap)554*b636d99dSDavid van Moolenbroek ospf_print_lsa(netdissect_options *ndo,
555*b636d99dSDavid van Moolenbroek register const struct lsa *lsap)
556*b636d99dSDavid van Moolenbroek {
557*b636d99dSDavid van Moolenbroek register const uint8_t *ls_end;
558*b636d99dSDavid van Moolenbroek register const struct rlalink *rlp;
559*b636d99dSDavid van Moolenbroek register const struct in_addr *ap;
560*b636d99dSDavid van Moolenbroek register const struct aslametric *almp;
561*b636d99dSDavid van Moolenbroek register const struct mcla *mcp;
562*b636d99dSDavid van Moolenbroek register const uint32_t *lp;
563*b636d99dSDavid van Moolenbroek register int j, tlv_type, tlv_length, topology;
564*b636d99dSDavid van Moolenbroek register int ls_length;
565*b636d99dSDavid van Moolenbroek const uint8_t *tptr;
566*b636d99dSDavid van Moolenbroek
567*b636d99dSDavid van Moolenbroek tptr = (uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
568*b636d99dSDavid van Moolenbroek ls_length = ospf_print_lshdr(ndo, &lsap->ls_hdr);
569*b636d99dSDavid van Moolenbroek if (ls_length == -1)
570*b636d99dSDavid van Moolenbroek return(NULL);
571*b636d99dSDavid van Moolenbroek ls_end = (uint8_t *)lsap + ls_length;
572*b636d99dSDavid van Moolenbroek ls_length -= sizeof(struct lsa_hdr);
573*b636d99dSDavid van Moolenbroek
574*b636d99dSDavid van Moolenbroek switch (lsap->ls_hdr.ls_type) {
575*b636d99dSDavid van Moolenbroek
576*b636d99dSDavid van Moolenbroek case LS_TYPE_ROUTER:
577*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_rla.rla_flags);
578*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Router LSA Options: [%s]",
579*b636d99dSDavid van Moolenbroek bittok2str(ospf_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags)));
580*b636d99dSDavid van Moolenbroek
581*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_rla.rla_count);
582*b636d99dSDavid van Moolenbroek j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count);
583*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_rla.rla_link);
584*b636d99dSDavid van Moolenbroek rlp = lsap->lsa_un.un_rla.rla_link;
585*b636d99dSDavid van Moolenbroek while (j--) {
586*b636d99dSDavid van Moolenbroek ND_TCHECK(*rlp);
587*b636d99dSDavid van Moolenbroek switch (rlp->un_tos.link.link_type) {
588*b636d99dSDavid van Moolenbroek
589*b636d99dSDavid van Moolenbroek case RLA_TYPE_VIRTUAL:
590*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
591*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_id),
592*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_data)));
593*b636d99dSDavid van Moolenbroek break;
594*b636d99dSDavid van Moolenbroek
595*b636d99dSDavid van Moolenbroek case RLA_TYPE_ROUTER:
596*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Neighbor Router-ID: %s, Interface Address: %s",
597*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_id),
598*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_data)));
599*b636d99dSDavid van Moolenbroek break;
600*b636d99dSDavid van Moolenbroek
601*b636d99dSDavid van Moolenbroek case RLA_TYPE_TRANSIT:
602*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Neighbor Network-ID: %s, Interface Address: %s",
603*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_id),
604*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_data)));
605*b636d99dSDavid van Moolenbroek break;
606*b636d99dSDavid van Moolenbroek
607*b636d99dSDavid van Moolenbroek case RLA_TYPE_STUB:
608*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Stub Network: %s, Mask: %s",
609*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_id),
610*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &rlp->link_data)));
611*b636d99dSDavid van Moolenbroek break;
612*b636d99dSDavid van Moolenbroek
613*b636d99dSDavid van Moolenbroek default:
614*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Unknown Router Link Type (%u)",
615*b636d99dSDavid van Moolenbroek rlp->un_tos.link.link_type));
616*b636d99dSDavid van Moolenbroek return (ls_end);
617*b636d99dSDavid van Moolenbroek }
618*b636d99dSDavid van Moolenbroek
619*b636d99dSDavid van Moolenbroek ospf_print_tos_metrics(ndo, &rlp->un_tos);
620*b636d99dSDavid van Moolenbroek
621*b636d99dSDavid van Moolenbroek rlp = (struct rlalink *)((u_char *)(rlp + 1) +
622*b636d99dSDavid van Moolenbroek ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
623*b636d99dSDavid van Moolenbroek }
624*b636d99dSDavid van Moolenbroek break;
625*b636d99dSDavid van Moolenbroek
626*b636d99dSDavid van Moolenbroek case LS_TYPE_NETWORK:
627*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_nla.nla_mask);
628*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Mask %s\n\t Connected Routers:",
629*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lsap->lsa_un.un_nla.nla_mask)));
630*b636d99dSDavid van Moolenbroek ap = lsap->lsa_un.un_nla.nla_router;
631*b636d99dSDavid van Moolenbroek while ((u_char *)ap < ls_end) {
632*b636d99dSDavid van Moolenbroek ND_TCHECK(*ap);
633*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap)));
634*b636d99dSDavid van Moolenbroek ++ap;
635*b636d99dSDavid van Moolenbroek }
636*b636d99dSDavid van Moolenbroek break;
637*b636d99dSDavid van Moolenbroek
638*b636d99dSDavid van Moolenbroek case LS_TYPE_SUM_IP:
639*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_nla.nla_mask);
640*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Mask %s",
641*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lsap->lsa_un.un_sla.sla_mask)));
642*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
643*b636d99dSDavid van Moolenbroek lp = lsap->lsa_un.un_sla.sla_tosmetric;
644*b636d99dSDavid van Moolenbroek while ((u_char *)lp < ls_end) {
645*b636d99dSDavid van Moolenbroek register uint32_t ul;
646*b636d99dSDavid van Moolenbroek
647*b636d99dSDavid van Moolenbroek ND_TCHECK(*lp);
648*b636d99dSDavid van Moolenbroek ul = EXTRACT_32BITS(lp);
649*b636d99dSDavid van Moolenbroek topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
650*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d",
651*b636d99dSDavid van Moolenbroek tok2str(ospf_topology_values, "", topology),
652*b636d99dSDavid van Moolenbroek topology,
653*b636d99dSDavid van Moolenbroek ul & SLA_MASK_METRIC));
654*b636d99dSDavid van Moolenbroek ++lp;
655*b636d99dSDavid van Moolenbroek }
656*b636d99dSDavid van Moolenbroek break;
657*b636d99dSDavid van Moolenbroek
658*b636d99dSDavid van Moolenbroek case LS_TYPE_SUM_ABR:
659*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
660*b636d99dSDavid van Moolenbroek lp = lsap->lsa_un.un_sla.sla_tosmetric;
661*b636d99dSDavid van Moolenbroek while ((u_char *)lp < ls_end) {
662*b636d99dSDavid van Moolenbroek register uint32_t ul;
663*b636d99dSDavid van Moolenbroek
664*b636d99dSDavid van Moolenbroek ND_TCHECK(*lp);
665*b636d99dSDavid van Moolenbroek ul = EXTRACT_32BITS(lp);
666*b636d99dSDavid van Moolenbroek topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
667*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d",
668*b636d99dSDavid van Moolenbroek tok2str(ospf_topology_values, "", topology),
669*b636d99dSDavid van Moolenbroek topology,
670*b636d99dSDavid van Moolenbroek ul & SLA_MASK_METRIC));
671*b636d99dSDavid van Moolenbroek ++lp;
672*b636d99dSDavid van Moolenbroek }
673*b636d99dSDavid van Moolenbroek break;
674*b636d99dSDavid van Moolenbroek
675*b636d99dSDavid van Moolenbroek case LS_TYPE_ASE:
676*b636d99dSDavid van Moolenbroek case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */
677*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_nla.nla_mask);
678*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Mask %s",
679*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lsap->lsa_un.un_asla.asla_mask)));
680*b636d99dSDavid van Moolenbroek
681*b636d99dSDavid van Moolenbroek ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
682*b636d99dSDavid van Moolenbroek almp = lsap->lsa_un.un_asla.asla_metric;
683*b636d99dSDavid van Moolenbroek while ((u_char *)almp < ls_end) {
684*b636d99dSDavid van Moolenbroek register uint32_t ul;
685*b636d99dSDavid van Moolenbroek
686*b636d99dSDavid van Moolenbroek ND_TCHECK(almp->asla_tosmetric);
687*b636d99dSDavid van Moolenbroek ul = EXTRACT_32BITS(&almp->asla_tosmetric);
688*b636d99dSDavid van Moolenbroek topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
689*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t\ttopology %s(%u), type %d, metric",
690*b636d99dSDavid van Moolenbroek tok2str(ospf_topology_values, "", topology),
691*b636d99dSDavid van Moolenbroek topology,
692*b636d99dSDavid van Moolenbroek (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1));
693*b636d99dSDavid van Moolenbroek if ((ul & ASLA_MASK_METRIC) == 0xffffff)
694*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " infinite"));
695*b636d99dSDavid van Moolenbroek else
696*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " %d", (ul & ASLA_MASK_METRIC)));
697*b636d99dSDavid van Moolenbroek
698*b636d99dSDavid van Moolenbroek ND_TCHECK(almp->asla_forward);
699*b636d99dSDavid van Moolenbroek if (almp->asla_forward.s_addr) {
700*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", forward %s", ipaddr_string(ndo, &almp->asla_forward)));
701*b636d99dSDavid van Moolenbroek }
702*b636d99dSDavid van Moolenbroek ND_TCHECK(almp->asla_tag);
703*b636d99dSDavid van Moolenbroek if (almp->asla_tag.s_addr) {
704*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", tag %s", ipaddr_string(ndo, &almp->asla_tag)));
705*b636d99dSDavid van Moolenbroek }
706*b636d99dSDavid van Moolenbroek ++almp;
707*b636d99dSDavid van Moolenbroek }
708*b636d99dSDavid van Moolenbroek break;
709*b636d99dSDavid van Moolenbroek
710*b636d99dSDavid van Moolenbroek case LS_TYPE_GROUP:
711*b636d99dSDavid van Moolenbroek /* Multicast extensions as of 23 July 1991 */
712*b636d99dSDavid van Moolenbroek mcp = lsap->lsa_un.un_mcla;
713*b636d99dSDavid van Moolenbroek while ((u_char *)mcp < ls_end) {
714*b636d99dSDavid van Moolenbroek ND_TCHECK(mcp->mcla_vid);
715*b636d99dSDavid van Moolenbroek switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
716*b636d99dSDavid van Moolenbroek
717*b636d99dSDavid van Moolenbroek case MCLA_VERTEX_ROUTER:
718*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Router Router-ID %s",
719*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &mcp->mcla_vid)));
720*b636d99dSDavid van Moolenbroek break;
721*b636d99dSDavid van Moolenbroek
722*b636d99dSDavid van Moolenbroek case MCLA_VERTEX_NETWORK:
723*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Network Designated Router %s",
724*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &mcp->mcla_vid)));
725*b636d99dSDavid van Moolenbroek break;
726*b636d99dSDavid van Moolenbroek
727*b636d99dSDavid van Moolenbroek default:
728*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t unknown VertexType (%u)",
729*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(&mcp->mcla_vtype)));
730*b636d99dSDavid van Moolenbroek break;
731*b636d99dSDavid van Moolenbroek }
732*b636d99dSDavid van Moolenbroek ++mcp;
733*b636d99dSDavid van Moolenbroek }
734*b636d99dSDavid van Moolenbroek break;
735*b636d99dSDavid van Moolenbroek
736*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_LL: /* fall through */
737*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_AL:
738*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_DW:
739*b636d99dSDavid van Moolenbroek
740*b636d99dSDavid van Moolenbroek switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
741*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TYPE_RI:
742*b636d99dSDavid van Moolenbroek tptr = (uint8_t *)(&lsap->lsa_un.un_ri_tlv.type);
743*b636d99dSDavid van Moolenbroek
744*b636d99dSDavid van Moolenbroek while (ls_length != 0) {
745*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, 4);
746*b636d99dSDavid van Moolenbroek if (ls_length < 4) {
747*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length));
748*b636d99dSDavid van Moolenbroek return(ls_end);
749*b636d99dSDavid van Moolenbroek }
750*b636d99dSDavid van Moolenbroek tlv_type = EXTRACT_16BITS(tptr);
751*b636d99dSDavid van Moolenbroek tlv_length = EXTRACT_16BITS(tptr+2);
752*b636d99dSDavid van Moolenbroek tptr+=4;
753*b636d99dSDavid van Moolenbroek ls_length-=4;
754*b636d99dSDavid van Moolenbroek
755*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u, value: ",
756*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type),
757*b636d99dSDavid van Moolenbroek tlv_type,
758*b636d99dSDavid van Moolenbroek tlv_length));
759*b636d99dSDavid van Moolenbroek
760*b636d99dSDavid van Moolenbroek if (tlv_length > ls_length) {
761*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length,
762*b636d99dSDavid van Moolenbroek ls_length));
763*b636d99dSDavid van Moolenbroek return(ls_end);
764*b636d99dSDavid van Moolenbroek }
765*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, tlv_length);
766*b636d99dSDavid van Moolenbroek switch(tlv_type) {
767*b636d99dSDavid van Moolenbroek
768*b636d99dSDavid van Moolenbroek case LS_OPAQUE_RI_TLV_CAP:
769*b636d99dSDavid van Moolenbroek if (tlv_length != 4) {
770*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length));
771*b636d99dSDavid van Moolenbroek return(ls_end);
772*b636d99dSDavid van Moolenbroek }
773*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Capabilities: %s",
774*b636d99dSDavid van Moolenbroek bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr))));
775*b636d99dSDavid van Moolenbroek break;
776*b636d99dSDavid van Moolenbroek default:
777*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1) {
778*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
779*b636d99dSDavid van Moolenbroek return(ls_end);
780*b636d99dSDavid van Moolenbroek }
781*b636d99dSDavid van Moolenbroek break;
782*b636d99dSDavid van Moolenbroek
783*b636d99dSDavid van Moolenbroek }
784*b636d99dSDavid van Moolenbroek tptr+=tlv_length;
785*b636d99dSDavid van Moolenbroek ls_length-=tlv_length;
786*b636d99dSDavid van Moolenbroek }
787*b636d99dSDavid van Moolenbroek break;
788*b636d99dSDavid van Moolenbroek
789*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TYPE_GRACE:
790*b636d99dSDavid van Moolenbroek if (ospf_print_grace_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_grace_tlv.type),
791*b636d99dSDavid van Moolenbroek ls_length) == -1) {
792*b636d99dSDavid van Moolenbroek return(ls_end);
793*b636d99dSDavid van Moolenbroek }
794*b636d99dSDavid van Moolenbroek break;
795*b636d99dSDavid van Moolenbroek
796*b636d99dSDavid van Moolenbroek case LS_OPAQUE_TYPE_TE:
797*b636d99dSDavid van Moolenbroek if (ospf_print_te_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
798*b636d99dSDavid van Moolenbroek ls_length) == -1) {
799*b636d99dSDavid van Moolenbroek return(ls_end);
800*b636d99dSDavid van Moolenbroek }
801*b636d99dSDavid van Moolenbroek break;
802*b636d99dSDavid van Moolenbroek
803*b636d99dSDavid van Moolenbroek default:
804*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1) {
805*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown,
806*b636d99dSDavid van Moolenbroek "\n\t ", ls_length))
807*b636d99dSDavid van Moolenbroek return(ls_end);
808*b636d99dSDavid van Moolenbroek }
809*b636d99dSDavid van Moolenbroek break;
810*b636d99dSDavid van Moolenbroek }
811*b636d99dSDavid van Moolenbroek }
812*b636d99dSDavid van Moolenbroek
813*b636d99dSDavid van Moolenbroek /* do we want to see an additionally hexdump ? */
814*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag> 1)
815*b636d99dSDavid van Moolenbroek if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown,
816*b636d99dSDavid van Moolenbroek "\n\t ", ls_length)) {
817*b636d99dSDavid van Moolenbroek return(ls_end);
818*b636d99dSDavid van Moolenbroek }
819*b636d99dSDavid van Moolenbroek
820*b636d99dSDavid van Moolenbroek return (ls_end);
821*b636d99dSDavid van Moolenbroek trunc:
822*b636d99dSDavid van Moolenbroek return (NULL);
823*b636d99dSDavid van Moolenbroek }
824*b636d99dSDavid van Moolenbroek
825*b636d99dSDavid van Moolenbroek static int
ospf_decode_lls(netdissect_options * ndo,register const struct ospfhdr * op,register u_int length)826*b636d99dSDavid van Moolenbroek ospf_decode_lls(netdissect_options *ndo,
827*b636d99dSDavid van Moolenbroek register const struct ospfhdr *op, register u_int length)
828*b636d99dSDavid van Moolenbroek {
829*b636d99dSDavid van Moolenbroek register const u_char *dptr;
830*b636d99dSDavid van Moolenbroek register const u_char *dataend;
831*b636d99dSDavid van Moolenbroek register u_int length2;
832*b636d99dSDavid van Moolenbroek register uint16_t lls_type, lls_len;
833*b636d99dSDavid van Moolenbroek register uint32_t lls_flags;
834*b636d99dSDavid van Moolenbroek
835*b636d99dSDavid van Moolenbroek switch (op->ospf_type) {
836*b636d99dSDavid van Moolenbroek
837*b636d99dSDavid van Moolenbroek case OSPF_TYPE_HELLO:
838*b636d99dSDavid van Moolenbroek if (!(op->ospf_hello.hello_options & OSPF_OPTION_L))
839*b636d99dSDavid van Moolenbroek return (0);
840*b636d99dSDavid van Moolenbroek break;
841*b636d99dSDavid van Moolenbroek
842*b636d99dSDavid van Moolenbroek case OSPF_TYPE_DD:
843*b636d99dSDavid van Moolenbroek if (!(op->ospf_db.db_options & OSPF_OPTION_L))
844*b636d99dSDavid van Moolenbroek return (0);
845*b636d99dSDavid van Moolenbroek break;
846*b636d99dSDavid van Moolenbroek
847*b636d99dSDavid van Moolenbroek default:
848*b636d99dSDavid van Moolenbroek return (0);
849*b636d99dSDavid van Moolenbroek }
850*b636d99dSDavid van Moolenbroek
851*b636d99dSDavid van Moolenbroek /* dig deeper if LLS data is available; see RFC4813 */
852*b636d99dSDavid van Moolenbroek length2 = EXTRACT_16BITS(&op->ospf_len);
853*b636d99dSDavid van Moolenbroek dptr = (u_char *)op + length2;
854*b636d99dSDavid van Moolenbroek dataend = (u_char *)op + length;
855*b636d99dSDavid van Moolenbroek
856*b636d99dSDavid van Moolenbroek if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
857*b636d99dSDavid van Moolenbroek dptr = dptr + op->ospf_authdata[3];
858*b636d99dSDavid van Moolenbroek length2 += op->ospf_authdata[3];
859*b636d99dSDavid van Moolenbroek }
860*b636d99dSDavid van Moolenbroek if (length2 >= length) {
861*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t[LLS truncated]"));
862*b636d99dSDavid van Moolenbroek return (1);
863*b636d99dSDavid van Moolenbroek }
864*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 2);
865*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr)));
866*b636d99dSDavid van Moolenbroek
867*b636d99dSDavid van Moolenbroek dptr += 2;
868*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 2);
869*b636d99dSDavid van Moolenbroek length2 = EXTRACT_16BITS(dptr);
870*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", length: %u", length2));
871*b636d99dSDavid van Moolenbroek
872*b636d99dSDavid van Moolenbroek dptr += 2;
873*b636d99dSDavid van Moolenbroek ND_TCHECK(*dptr);
874*b636d99dSDavid van Moolenbroek while (dptr < dataend) {
875*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 2);
876*b636d99dSDavid van Moolenbroek lls_type = EXTRACT_16BITS(dptr);
877*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s (%u)",
878*b636d99dSDavid van Moolenbroek tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type),
879*b636d99dSDavid van Moolenbroek lls_type));
880*b636d99dSDavid van Moolenbroek dptr += 2;
881*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 2);
882*b636d99dSDavid van Moolenbroek lls_len = EXTRACT_16BITS(dptr);
883*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", length: %u", lls_len));
884*b636d99dSDavid van Moolenbroek dptr += 2;
885*b636d99dSDavid van Moolenbroek switch (lls_type) {
886*b636d99dSDavid van Moolenbroek
887*b636d99dSDavid van Moolenbroek case OSPF_LLS_EO:
888*b636d99dSDavid van Moolenbroek if (lls_len != 4) {
889*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " [should be 4]"));
890*b636d99dSDavid van Moolenbroek lls_len = 4;
891*b636d99dSDavid van Moolenbroek }
892*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 4);
893*b636d99dSDavid van Moolenbroek lls_flags = EXTRACT_32BITS(dptr);
894*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Options: 0x%08x [%s]", lls_flags,
895*b636d99dSDavid van Moolenbroek bittok2str(ospf_lls_eo_options, "?", lls_flags)));
896*b636d99dSDavid van Moolenbroek
897*b636d99dSDavid van Moolenbroek break;
898*b636d99dSDavid van Moolenbroek
899*b636d99dSDavid van Moolenbroek case OSPF_LLS_MD5:
900*b636d99dSDavid van Moolenbroek if (lls_len != 20) {
901*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " [should be 20]"));
902*b636d99dSDavid van Moolenbroek lls_len = 20;
903*b636d99dSDavid van Moolenbroek }
904*b636d99dSDavid van Moolenbroek ND_TCHECK2(*dptr, 4);
905*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr)));
906*b636d99dSDavid van Moolenbroek break;
907*b636d99dSDavid van Moolenbroek }
908*b636d99dSDavid van Moolenbroek
909*b636d99dSDavid van Moolenbroek dptr += lls_len;
910*b636d99dSDavid van Moolenbroek }
911*b636d99dSDavid van Moolenbroek
912*b636d99dSDavid van Moolenbroek return (0);
913*b636d99dSDavid van Moolenbroek trunc:
914*b636d99dSDavid van Moolenbroek return (1);
915*b636d99dSDavid van Moolenbroek }
916*b636d99dSDavid van Moolenbroek
917*b636d99dSDavid van Moolenbroek static int
ospf_decode_v2(netdissect_options * ndo,register const struct ospfhdr * op,register const u_char * dataend)918*b636d99dSDavid van Moolenbroek ospf_decode_v2(netdissect_options *ndo,
919*b636d99dSDavid van Moolenbroek register const struct ospfhdr *op, register const u_char *dataend)
920*b636d99dSDavid van Moolenbroek {
921*b636d99dSDavid van Moolenbroek register const struct in_addr *ap;
922*b636d99dSDavid van Moolenbroek register const struct lsr *lsrp;
923*b636d99dSDavid van Moolenbroek register const struct lsa_hdr *lshp;
924*b636d99dSDavid van Moolenbroek register const struct lsa *lsap;
925*b636d99dSDavid van Moolenbroek register uint32_t lsa_count,lsa_count_max;
926*b636d99dSDavid van Moolenbroek
927*b636d99dSDavid van Moolenbroek switch (op->ospf_type) {
928*b636d99dSDavid van Moolenbroek
929*b636d99dSDavid van Moolenbroek case OSPF_TYPE_UMD:
930*b636d99dSDavid van Moolenbroek /*
931*b636d99dSDavid van Moolenbroek * Rob Coltun's special monitoring packets;
932*b636d99dSDavid van Moolenbroek * do nothing
933*b636d99dSDavid van Moolenbroek */
934*b636d99dSDavid van Moolenbroek break;
935*b636d99dSDavid van Moolenbroek
936*b636d99dSDavid van Moolenbroek case OSPF_TYPE_HELLO:
937*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tOptions [%s]",
938*b636d99dSDavid van Moolenbroek bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)));
939*b636d99dSDavid van Moolenbroek
940*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_hello.hello_deadint);
941*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u",
942*b636d99dSDavid van Moolenbroek EXTRACT_16BITS(&op->ospf_hello.hello_helloint),
943*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(&op->ospf_hello.hello_deadint),
944*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &op->ospf_hello.hello_mask),
945*b636d99dSDavid van Moolenbroek op->ospf_hello.hello_priority));
946*b636d99dSDavid van Moolenbroek
947*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_hello.hello_dr);
948*b636d99dSDavid van Moolenbroek if (op->ospf_hello.hello_dr.s_addr != 0)
949*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Designated Router %s",
950*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &op->ospf_hello.hello_dr)));
951*b636d99dSDavid van Moolenbroek
952*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_hello.hello_bdr);
953*b636d99dSDavid van Moolenbroek if (op->ospf_hello.hello_bdr.s_addr != 0)
954*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Backup Designated Router %s",
955*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &op->ospf_hello.hello_bdr)));
956*b636d99dSDavid van Moolenbroek
957*b636d99dSDavid van Moolenbroek ap = op->ospf_hello.hello_neighbor;
958*b636d99dSDavid van Moolenbroek if ((u_char *)ap < dataend)
959*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Neighbor List:"));
960*b636d99dSDavid van Moolenbroek while ((u_char *)ap < dataend) {
961*b636d99dSDavid van Moolenbroek ND_TCHECK(*ap);
962*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap)));
963*b636d99dSDavid van Moolenbroek ++ap;
964*b636d99dSDavid van Moolenbroek }
965*b636d99dSDavid van Moolenbroek break; /* HELLO */
966*b636d99dSDavid van Moolenbroek
967*b636d99dSDavid van Moolenbroek case OSPF_TYPE_DD:
968*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_db.db_options);
969*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tOptions [%s]",
970*b636d99dSDavid van Moolenbroek bittok2str(ospf_option_values, "none", op->ospf_db.db_options)));
971*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_db.db_flags);
972*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", DD Flags [%s]",
973*b636d99dSDavid van Moolenbroek bittok2str(ospf_dd_flag_values, "none", op->ospf_db.db_flags)));
974*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_db.db_ifmtu);
975*b636d99dSDavid van Moolenbroek if (op->ospf_db.db_ifmtu) {
976*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", MTU: %u", EXTRACT_16BITS(&op->ospf_db.db_ifmtu)));
977*b636d99dSDavid van Moolenbroek }
978*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_db.db_seq);
979*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq)));
980*b636d99dSDavid van Moolenbroek
981*b636d99dSDavid van Moolenbroek /* Print all the LS adv's */
982*b636d99dSDavid van Moolenbroek lshp = op->ospf_db.db_lshdr;
983*b636d99dSDavid van Moolenbroek while (((u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
984*b636d99dSDavid van Moolenbroek ++lshp;
985*b636d99dSDavid van Moolenbroek }
986*b636d99dSDavid van Moolenbroek break;
987*b636d99dSDavid van Moolenbroek
988*b636d99dSDavid van Moolenbroek case OSPF_TYPE_LS_REQ:
989*b636d99dSDavid van Moolenbroek lsrp = op->ospf_lsr;
990*b636d99dSDavid van Moolenbroek while ((u_char *)lsrp < dataend) {
991*b636d99dSDavid van Moolenbroek ND_TCHECK(*lsrp);
992*b636d99dSDavid van Moolenbroek
993*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t Advertising Router: %s, %s LSA (%u)",
994*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lsrp->ls_router),
995*b636d99dSDavid van Moolenbroek tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)),
996*b636d99dSDavid van Moolenbroek EXTRACT_32BITS(&lsrp->ls_type)));
997*b636d99dSDavid van Moolenbroek
998*b636d99dSDavid van Moolenbroek switch (EXTRACT_32BITS(lsrp->ls_type)) {
999*b636d99dSDavid van Moolenbroek /* the LSA header for opaque LSAs was slightly changed */
1000*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_LL:
1001*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_AL:
1002*b636d99dSDavid van Moolenbroek case LS_TYPE_OPAQUE_DW:
1003*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Opaque-Type: %s LSA (%u), Opaque-ID: %u",
1004*b636d99dSDavid van Moolenbroek tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type),
1005*b636d99dSDavid van Moolenbroek lsrp->un_ls_stateid.opaque_field.opaque_type,
1006*b636d99dSDavid van Moolenbroek EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id)));
1007*b636d99dSDavid van Moolenbroek break;
1008*b636d99dSDavid van Moolenbroek default:
1009*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", LSA-ID: %s",
1010*b636d99dSDavid van Moolenbroek ipaddr_string(ndo, &lsrp->un_ls_stateid.ls_stateid)));
1011*b636d99dSDavid van Moolenbroek break;
1012*b636d99dSDavid van Moolenbroek }
1013*b636d99dSDavid van Moolenbroek
1014*b636d99dSDavid van Moolenbroek ++lsrp;
1015*b636d99dSDavid van Moolenbroek }
1016*b636d99dSDavid van Moolenbroek break;
1017*b636d99dSDavid van Moolenbroek
1018*b636d99dSDavid van Moolenbroek case OSPF_TYPE_LS_UPDATE:
1019*b636d99dSDavid van Moolenbroek lsap = op->ospf_lsu.lsu_lsa;
1020*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_lsu.lsu_count);
1021*b636d99dSDavid van Moolenbroek lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count);
1022*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %d LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max)));
1023*b636d99dSDavid van Moolenbroek for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
1024*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t LSA #%u", lsa_count));
1025*b636d99dSDavid van Moolenbroek lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap);
1026*b636d99dSDavid van Moolenbroek if (lsap == NULL)
1027*b636d99dSDavid van Moolenbroek goto trunc;
1028*b636d99dSDavid van Moolenbroek }
1029*b636d99dSDavid van Moolenbroek break;
1030*b636d99dSDavid van Moolenbroek
1031*b636d99dSDavid van Moolenbroek case OSPF_TYPE_LS_ACK:
1032*b636d99dSDavid van Moolenbroek lshp = op->ospf_lsa.lsa_lshdr;
1033*b636d99dSDavid van Moolenbroek while (ospf_print_lshdr(ndo, lshp) != -1) {
1034*b636d99dSDavid van Moolenbroek ++lshp;
1035*b636d99dSDavid van Moolenbroek }
1036*b636d99dSDavid van Moolenbroek break;
1037*b636d99dSDavid van Moolenbroek
1038*b636d99dSDavid van Moolenbroek default:
1039*b636d99dSDavid van Moolenbroek break;
1040*b636d99dSDavid van Moolenbroek }
1041*b636d99dSDavid van Moolenbroek return (0);
1042*b636d99dSDavid van Moolenbroek trunc:
1043*b636d99dSDavid van Moolenbroek return (1);
1044*b636d99dSDavid van Moolenbroek }
1045*b636d99dSDavid van Moolenbroek
1046*b636d99dSDavid van Moolenbroek void
ospf_print(netdissect_options * ndo,register const u_char * bp,register u_int length,const u_char * bp2 _U_)1047*b636d99dSDavid van Moolenbroek ospf_print(netdissect_options *ndo,
1048*b636d99dSDavid van Moolenbroek register const u_char *bp, register u_int length,
1049*b636d99dSDavid van Moolenbroek const u_char *bp2 _U_)
1050*b636d99dSDavid van Moolenbroek {
1051*b636d99dSDavid van Moolenbroek register const struct ospfhdr *op;
1052*b636d99dSDavid van Moolenbroek register const u_char *dataend;
1053*b636d99dSDavid van Moolenbroek register const char *cp;
1054*b636d99dSDavid van Moolenbroek
1055*b636d99dSDavid van Moolenbroek op = (struct ospfhdr *)bp;
1056*b636d99dSDavid van Moolenbroek
1057*b636d99dSDavid van Moolenbroek /* XXX Before we do anything else, strip off the MD5 trailer */
1058*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_authtype);
1059*b636d99dSDavid van Moolenbroek if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
1060*b636d99dSDavid van Moolenbroek length -= OSPF_AUTH_MD5_LEN;
1061*b636d99dSDavid van Moolenbroek ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN;
1062*b636d99dSDavid van Moolenbroek }
1063*b636d99dSDavid van Moolenbroek
1064*b636d99dSDavid van Moolenbroek /* If the type is valid translate it, or just print the type */
1065*b636d99dSDavid van Moolenbroek /* value. If it's not valid, say so and return */
1066*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_type);
1067*b636d99dSDavid van Moolenbroek cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
1068*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "OSPFv%u, %s, length %u", op->ospf_version, cp, length));
1069*b636d99dSDavid van Moolenbroek if (*cp == 'u')
1070*b636d99dSDavid van Moolenbroek return;
1071*b636d99dSDavid van Moolenbroek
1072*b636d99dSDavid van Moolenbroek if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
1073*b636d99dSDavid van Moolenbroek return;
1074*b636d99dSDavid van Moolenbroek }
1075*b636d99dSDavid van Moolenbroek
1076*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_len);
1077*b636d99dSDavid van Moolenbroek if (length != EXTRACT_16BITS(&op->ospf_len)) {
1078*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " [len %d]", EXTRACT_16BITS(&op->ospf_len)));
1079*b636d99dSDavid van Moolenbroek }
1080*b636d99dSDavid van Moolenbroek
1081*b636d99dSDavid van Moolenbroek if (length > EXTRACT_16BITS(&op->ospf_len)) {
1082*b636d99dSDavid van Moolenbroek dataend = bp + EXTRACT_16BITS(&op->ospf_len);
1083*b636d99dSDavid van Moolenbroek } else {
1084*b636d99dSDavid van Moolenbroek dataend = bp + length;
1085*b636d99dSDavid van Moolenbroek }
1086*b636d99dSDavid van Moolenbroek
1087*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_routerid);
1088*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf_routerid)));
1089*b636d99dSDavid van Moolenbroek
1090*b636d99dSDavid van Moolenbroek ND_TCHECK(op->ospf_areaid);
1091*b636d99dSDavid van Moolenbroek if (op->ospf_areaid.s_addr != 0)
1092*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf_areaid)));
1093*b636d99dSDavid van Moolenbroek else
1094*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Backbone Area"));
1095*b636d99dSDavid van Moolenbroek
1096*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) {
1097*b636d99dSDavid van Moolenbroek /* Print authentication data (should we really do this?) */
1098*b636d99dSDavid van Moolenbroek ND_TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata));
1099*b636d99dSDavid van Moolenbroek
1100*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Authentication Type: %s (%u)",
1101*b636d99dSDavid van Moolenbroek tok2str(ospf_authtype_values, "unknown", EXTRACT_16BITS(&op->ospf_authtype)),
1102*b636d99dSDavid van Moolenbroek EXTRACT_16BITS(&op->ospf_authtype)));
1103*b636d99dSDavid van Moolenbroek
1104*b636d99dSDavid van Moolenbroek switch (EXTRACT_16BITS(&op->ospf_authtype)) {
1105*b636d99dSDavid van Moolenbroek
1106*b636d99dSDavid van Moolenbroek case OSPF_AUTH_NONE:
1107*b636d99dSDavid van Moolenbroek break;
1108*b636d99dSDavid van Moolenbroek
1109*b636d99dSDavid van Moolenbroek case OSPF_AUTH_SIMPLE:
1110*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tSimple text password: "));
1111*b636d99dSDavid van Moolenbroek safeputs(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
1112*b636d99dSDavid van Moolenbroek break;
1113*b636d99dSDavid van Moolenbroek
1114*b636d99dSDavid van Moolenbroek case OSPF_AUTH_MD5:
1115*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x",
1116*b636d99dSDavid van Moolenbroek *((op->ospf_authdata) + 2),
1117*b636d99dSDavid van Moolenbroek *((op->ospf_authdata) + 3),
1118*b636d99dSDavid van Moolenbroek EXTRACT_32BITS((op->ospf_authdata) + 4)));
1119*b636d99dSDavid van Moolenbroek break;
1120*b636d99dSDavid van Moolenbroek
1121*b636d99dSDavid van Moolenbroek default:
1122*b636d99dSDavid van Moolenbroek return;
1123*b636d99dSDavid van Moolenbroek }
1124*b636d99dSDavid van Moolenbroek }
1125*b636d99dSDavid van Moolenbroek /* Do rest according to version. */
1126*b636d99dSDavid van Moolenbroek switch (op->ospf_version) {
1127*b636d99dSDavid van Moolenbroek
1128*b636d99dSDavid van Moolenbroek case 2:
1129*b636d99dSDavid van Moolenbroek /* ospf version 2 */
1130*b636d99dSDavid van Moolenbroek if (ospf_decode_v2(ndo, op, dataend))
1131*b636d99dSDavid van Moolenbroek goto trunc;
1132*b636d99dSDavid van Moolenbroek if (length > EXTRACT_16BITS(&op->ospf_len)) {
1133*b636d99dSDavid van Moolenbroek if (ospf_decode_lls(ndo, op, length))
1134*b636d99dSDavid van Moolenbroek goto trunc;
1135*b636d99dSDavid van Moolenbroek }
1136*b636d99dSDavid van Moolenbroek break;
1137*b636d99dSDavid van Moolenbroek
1138*b636d99dSDavid van Moolenbroek default:
1139*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " ospf [version %d]", op->ospf_version));
1140*b636d99dSDavid van Moolenbroek break;
1141*b636d99dSDavid van Moolenbroek } /* end switch on version */
1142*b636d99dSDavid van Moolenbroek
1143*b636d99dSDavid van Moolenbroek return;
1144*b636d99dSDavid van Moolenbroek trunc:
1145*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s", tstr));
1146*b636d99dSDavid van Moolenbroek }
1147