xref: /freebsd/contrib/tcpdump/print-ospf.c (revision c98323078dede7579020518ec84cdcb478e5c142)
1 /*
2  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
22  */
23 
24 #ifndef lint
25 static const char rcsid[] _U_ =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.45.2.4 2004/03/24 02:44:30 guy Exp $ (LBL)";
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <tcpdump-stdinc.h>
34 
35 #include <stdio.h>
36 
37 #include "interface.h"
38 #include "addrtoname.h"
39 #include "extract.h"
40 #include "gmpls.h"
41 
42 #include "ospf.h"
43 
44 #include "ip.h"
45 
46 static struct tok ospf_option_values[] = {
47 	{ OSPF_OPTION_T,	"TOS" },
48 	{ OSPF_OPTION_E,	"External" },
49 	{ OSPF_OPTION_MC,	"Multicast" },
50 	{ OSPF_OPTION_NP,	"NSSA" },
51 	{ OSPF_OPTION_EA,	"Advertise External" },
52 	{ OSPF_OPTION_DC,	"Demand Circuit" },
53 	{ OSPF_OPTION_O,	"Opaque" },
54 	{ 0,			NULL }
55 };
56 
57 static struct tok ospf_authtype_values[] = {
58 	{ OSPF_AUTH_NONE,	"none" },
59 	{ OSPF_AUTH_NONE,	"simple" },
60 	{ OSPF_AUTH_MD5,	"MD5" },
61 	{ 0,			NULL }
62 };
63 
64 static struct tok ospf_rla_flag_values[] = {
65 	{ RLA_FLAG_B,		"ABR" },
66 	{ RLA_FLAG_E,		"ASBR" },
67 	{ RLA_FLAG_W1,		"Virtual" },
68 	{ RLA_FLAG_W2,		"W2" },
69 	{ 0,			NULL }
70 };
71 
72 static struct tok type2str[] = {
73 	{ OSPF_TYPE_UMD,	"UMD" },
74 	{ OSPF_TYPE_HELLO,	"Hello" },
75 	{ OSPF_TYPE_DD,		"Database Description" },
76 	{ OSPF_TYPE_LS_REQ,	"LS-Request" },
77 	{ OSPF_TYPE_LS_UPDATE,	"LS-Update" },
78 	{ OSPF_TYPE_LS_ACK,	"LS-Ack" },
79 	{ 0,			NULL }
80 };
81 
82 static struct tok lsa_values[] = {
83 	{ LS_TYPE_ROUTER,       "Router" },
84 	{ LS_TYPE_NETWORK,      "Network" },
85 	{ LS_TYPE_SUM_IP,       "Summary" },
86 	{ LS_TYPE_SUM_ABR,      "ASBR Summary" },
87 	{ LS_TYPE_ASE,          "External" },
88 	{ LS_TYPE_GROUP,        "Multicast Group" },
89 	{ LS_TYPE_NSSA,         "NSSA" },
90 	{ LS_TYPE_OPAQUE_LL,    "Link Local Opaque" },
91 	{ LS_TYPE_OPAQUE_AL,    "Area Local Opaque" },
92 	{ LS_TYPE_OPAQUE_DW,    "Domain Wide Opaque" },
93 	{ 0,			NULL }
94 };
95 
96 static struct tok ospf_dd_flag_values[] = {
97 	{ OSPF_DB_INIT,	        "Init" },
98 	{ OSPF_DB_MORE,	        "More" },
99 	{ OSPF_DB_MASTER,	"Master" },
100 	{ 0,			NULL }
101 };
102 
103 static struct tok lsa_opaque_values[] = {
104 	{ LS_OPAQUE_TYPE_TE,    "Traffic Engineering" },
105 	{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
106 	{ 0,			NULL }
107 };
108 
109 static struct tok lsa_opaque_te_tlv_values[] = {
110 	{ LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
111 	{ LS_OPAQUE_TE_TLV_LINK,   "Link" },
112 	{ 0,			NULL }
113 };
114 
115 static struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
116 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE,            "Link Type" },
117 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID,              "Link ID" },
118 	{ LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP,             "Local Interface IP address" },
119 	{ LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP,            "Remote Interface IP address" },
120 	{ LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC,            "Traffic Engineering Metric" },
121 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW,               "Maximum Bandwidth" },
122 	{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW,           "Maximum Reservable Bandwidth" },
123 	{ LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW,             "Unreserved Bandwidth" },
124 	{ LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP,          "Administrative Group" },
125 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
126 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
127 	{ LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR,    "Interface Switching Capability" },
128 	{ LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP,    "Shared Risk Link Group" },
129 	{ 0,			NULL }
130 };
131 
132 #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP        1  /* rfc3630 */
133 #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA         2  /* rfc3630 */
134 
135 static struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
136 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
137 	{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA,  "Multi-Access" },
138 	{ 0,			NULL }
139 };
140 
141 static char tstr[] = " [|ospf]";
142 
143 #ifdef WIN32
144 #define inline __inline
145 #endif /* WIN32 */
146 
147 static int ospf_print_lshdr(const struct lsa_hdr *);
148 static const u_char *ospf_print_lsa(const struct lsa *);
149 static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
150 
151 static int
152 ospf_print_lshdr(register const struct lsa_hdr *lshp)
153 {
154         u_int ls_length;
155 
156         TCHECK(lshp->ls_length);
157         ls_length = EXTRACT_16BITS(&lshp->ls_length);
158         if (ls_length < sizeof(struct lsa_hdr)) {
159                 printf("\n\t    Bogus length %u < %lu", ls_length,
160                     (unsigned long)sizeof(struct lsa_hdr));
161                 return(-1);
162         }
163 
164         TCHECK(lshp->ls_seq);	/* XXX - ls_length check checked this */
165 	printf("\n\t  Advertising Router: %s, seq 0x%08x, age %us, length: %u",
166 	       ipaddr_string(&lshp->ls_router),
167 	       EXTRACT_32BITS(&lshp->ls_seq),
168 	       EXTRACT_16BITS(&lshp->ls_age),
169                ls_length-(u_int)sizeof(struct lsa_hdr));
170 
171 	TCHECK(lshp->ls_type);	/* XXX - ls_length check checked this */
172         switch (lshp->ls_type) {
173 	/* the LSA header for opaque LSAs was slightly changed */
174         case LS_TYPE_OPAQUE_LL:
175         case LS_TYPE_OPAQUE_AL:
176         case LS_TYPE_OPAQUE_DW:
177             printf("\n\t    %s LSA (%d), Opaque-Type: %s LSA (%u), Opaque-ID: %u",
178                    tok2str(lsa_values,"unknown",lshp->ls_type),
179                    lshp->ls_type,
180 
181 		   tok2str(lsa_opaque_values,
182 			   "unknown",
183 			   *(&lshp->un_lsa_id.opaque_field.opaque_type)),
184 		   *(&lshp->un_lsa_id.opaque_field.opaque_type),
185 		   EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id)
186 
187                    );
188             break;
189 
190 	/* all other LSA types use regular style LSA headers */
191 	default:
192             printf("\n\t    %s LSA (%d), LSA-ID: %s",
193                    tok2str(lsa_values,"unknown",lshp->ls_type),
194                    lshp->ls_type,
195                    ipaddr_string(&lshp->un_lsa_id.lsa_id));
196             break;
197         }
198 
199 	TCHECK(lshp->ls_options);	/* XXX - ls_length check checked this */
200         printf("\n\t    Options: [%s]", bittok2str(ospf_option_values,"none",lshp->ls_options));
201 
202         return (ls_length);
203 trunc:
204 	return (-1);
205 }
206 
207 /*
208  * Print a single link state advertisement.  If truncated or if LSA length
209  * field is less than the length of the LSA header, return NULl, else
210  * return pointer to data past end of LSA.
211  */
212 static const u_int8_t *
213 ospf_print_lsa(register const struct lsa *lsap)
214 {
215 	register const u_int8_t *ls_end;
216 	register const struct rlalink *rlp;
217 	register const struct tos_metric *tosp;
218 	register const struct in_addr *ap;
219 	register const struct aslametric *almp;
220 	register const struct mcla *mcp;
221 	register const u_int32_t *lp;
222 	register int j, k, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level;
223 	register int ls_length;
224 	const u_int8_t *tptr;
225 	int count_srlg;
226         union { /* int to float conversion buffer for several subTLVs */
227             float f;
228             u_int32_t i;
229         } bw;
230 
231 	tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
232         ls_length = ospf_print_lshdr(&lsap->ls_hdr);
233         if (ls_length == -1)
234                 return(NULL);
235 	ls_end = (u_int8_t *)lsap + ls_length;
236 	ls_length -= sizeof(struct lsa_hdr);
237 
238 	switch (lsap->ls_hdr.ls_type) {
239 
240 	case LS_TYPE_ROUTER:
241 		TCHECK(lsap->lsa_un.un_rla.rla_flags);
242                 printf("\n\t    Router LSA Options: [%s]", bittok2str(ospf_rla_flag_values,"none",lsap->lsa_un.un_rla.rla_flags));
243 
244 		TCHECK(lsap->lsa_un.un_rla.rla_count);
245 		j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count);
246 		TCHECK(lsap->lsa_un.un_rla.rla_link);
247 		rlp = lsap->lsa_un.un_rla.rla_link;
248 		while (j--) {
249 			TCHECK(*rlp);
250 			switch (rlp->link_type) {
251 
252 			case RLA_TYPE_VIRTUAL:
253 				printf("\n\t      Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
254 				    ipaddr_string(&rlp->link_id),
255 				    ipaddr_string(&rlp->link_data));
256                                 break;
257 
258 			case RLA_TYPE_ROUTER:
259 				printf("\n\t      Neighbor Router-ID: %s, Interface Address: %s",
260 				    ipaddr_string(&rlp->link_id),
261 				    ipaddr_string(&rlp->link_data));
262 				break;
263 
264 			case RLA_TYPE_TRANSIT:
265 				printf("\n\t      Neighbor Network-ID: %s, Interface Address: %s",
266 				    ipaddr_string(&rlp->link_id),
267 				    ipaddr_string(&rlp->link_data));
268 				break;
269 
270 			case RLA_TYPE_STUB:
271 				printf("\n\t      Stub Network: %s, Mask: %s",
272 				    ipaddr_string(&rlp->link_id),
273 				    ipaddr_string(&rlp->link_data));
274 				break;
275 
276 			default:
277 				printf("\n\t      Unknown Router Link Type (%u)",
278 				    rlp->link_type);
279 				return (ls_end);
280 			}
281 			printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric));
282 			tosp = (struct tos_metric *)
283 			    ((sizeof rlp->link_tos0metric) + (u_char *) rlp);
284 			for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) {
285 				TCHECK(*tosp);
286 				printf(", tos %d, metric: %d",
287 				    tosp->tos_type,
288 				    EXTRACT_16BITS(&tosp->tos_metric));
289 			}
290 			rlp = (struct rlalink *)((u_char *)(rlp + 1) +
291 			    ((rlp->link_toscount) * sizeof(*tosp)));
292 		}
293 		break;
294 
295 	case LS_TYPE_NETWORK:
296 		TCHECK(lsap->lsa_un.un_nla.nla_mask);
297 		printf("\n\t    Mask %s\n\t    Connected Routers:",
298 		    ipaddr_string(&lsap->lsa_un.un_nla.nla_mask));
299 		ap = lsap->lsa_un.un_nla.nla_router;
300 		while ((u_char *)ap < ls_end) {
301 			TCHECK(*ap);
302 			printf("\n\t      %s", ipaddr_string(ap));
303 			++ap;
304 		}
305 		break;
306 
307 	case LS_TYPE_SUM_IP:
308 		TCHECK(lsap->lsa_un.un_nla.nla_mask);
309 		printf("\n\t    Mask %s",
310 		    ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
311 		TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
312 		lp = lsap->lsa_un.un_sla.sla_tosmetric;
313                 /* suppress tos if its not supported */
314                 if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
315                     printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
316                     break;
317                 }
318 		while ((u_char *)lp < ls_end) {
319 			register u_int32_t ul;
320 
321 			TCHECK(*lp);
322 			ul = EXTRACT_32BITS(lp);
323 			printf(", tos %d metric %d",
324 			    (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
325 			    ul & SLA_MASK_METRIC);
326 			++lp;
327 		}
328 		break;
329 
330 	case LS_TYPE_SUM_ABR:
331 		TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
332 		lp = lsap->lsa_un.un_sla.sla_tosmetric;
333                 /* suppress tos if its not supported */
334                 if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
335                     printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
336                     break;
337                 }
338 		while ((u_char *)lp < ls_end) {
339 			register u_int32_t ul;
340 
341 			TCHECK(*lp);
342 			ul = EXTRACT_32BITS(lp);
343 			printf(", tos %d metric %d",
344 			    (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
345 			    ul & SLA_MASK_METRIC);
346 			++lp;
347 		}
348 		break;
349 
350 	case LS_TYPE_ASE:
351 		TCHECK(lsap->lsa_un.un_nla.nla_mask);
352 		printf("\n\t    Mask %s",
353 		    ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
354 
355 		TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
356 		almp = lsap->lsa_un.un_asla.asla_metric;
357 		while ((u_char *)almp < ls_end) {
358 			register u_int32_t ul;
359 
360 			TCHECK(almp->asla_tosmetric);
361 			ul = EXTRACT_32BITS(&almp->asla_tosmetric);
362 			printf(", type %d, tos %d metric:",
363 			    (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
364 			    (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
365                         if ((ul & ASLA_MASK_METRIC)==0xffffff)
366                             printf(" infinite");
367                         else
368                             printf(" %d", (ul & ASLA_MASK_METRIC));
369 
370 			TCHECK(almp->asla_forward);
371 			if (almp->asla_forward.s_addr) {
372 				printf(", forward %s",
373 				    ipaddr_string(&almp->asla_forward));
374 			}
375 			TCHECK(almp->asla_tag);
376 			if (almp->asla_tag.s_addr) {
377 				printf(", tag %s",
378 				    ipaddr_string(&almp->asla_tag));
379 			}
380 			++almp;
381 		}
382 		break;
383 
384 	case LS_TYPE_GROUP:
385 		/* Multicast extensions as of 23 July 1991 */
386 		mcp = lsap->lsa_un.un_mcla;
387 		while ((u_char *)mcp < ls_end) {
388 			TCHECK(mcp->mcla_vid);
389 			switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
390 
391 			case MCLA_VERTEX_ROUTER:
392 				printf("\n\t    Router Router-ID %s",
393 				    ipaddr_string(&mcp->mcla_vid));
394 				break;
395 
396 			case MCLA_VERTEX_NETWORK:
397 				printf("\n\t    Network Designated Router %s",
398 				    ipaddr_string(&mcp->mcla_vid));
399 				break;
400 
401 			default:
402 				printf("\n\t    unknown VertexType (%u)",
403 				    EXTRACT_32BITS(&mcp->mcla_vtype));
404 				break;
405 			}
406 		++mcp;
407 		}
408 		break;
409 
410 	case LS_TYPE_OPAQUE_LL: /* fall through */
411 	case LS_TYPE_OPAQUE_AL:
412 	case LS_TYPE_OPAQUE_DW:
413 
414 	    switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
415 	    case LS_OPAQUE_TYPE_TE:
416 		tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type);
417 
418 		while (ls_length != 0) {
419                     TCHECK2(*tptr, 4);
420 		    if (ls_length < 4) {
421                         printf("\n\t    Remaining LS length %u < 4", ls_length);
422                         return(ls_end);
423                     }
424                     tlv_type = EXTRACT_16BITS(tptr);
425                     tlv_length = EXTRACT_16BITS(tptr+2);
426                     tptr+=4;
427                     ls_length-=4;
428 
429                     printf("\n\t    %s TLV (%u), length: %u",
430                            tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
431                            tlv_type,
432                            tlv_length);
433 
434                     if (tlv_length > ls_length) {
435                         printf("\n\t    Bogus length %u > %u", tlv_length,
436                             ls_length);
437                         return(ls_end);
438                     }
439                     ls_length-=tlv_length;
440                     switch(tlv_type) {
441                     case LS_OPAQUE_TE_TLV_LINK:
442                         while (tlv_length != 0) {
443                             if (tlv_length < 4) {
444                                 printf("\n\t    Remaining TLV length %u < 4",
445                                     tlv_length);
446                                 return(ls_end);
447                             }
448                             TCHECK2(*tptr, 4);
449                             subtlv_type = EXTRACT_16BITS(tptr);
450                             subtlv_length = EXTRACT_16BITS(tptr+2);
451                             tptr+=4;
452                             tlv_length-=4;
453 
454                             printf("\n\t      %s subTLV (%u), length: %u",
455                                    tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
456                                    subtlv_type,
457                                    subtlv_length);
458 
459                             TCHECK2(*tptr, subtlv_length);
460                             switch(subtlv_type) {
461                             case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
462                                 printf(", 0x%08x", EXTRACT_32BITS(tptr));
463                                 break;
464                             case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
465                             case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
466                                 printf(", %s (0x%08x)",
467                                        ipaddr_string(tptr),
468                                        EXTRACT_32BITS(tptr));
469                                 if (subtlv_length == 8) /* draft-ietf-ccamp-ospf-gmpls-extensions */
470                                     printf(", %s (0x%08x)",
471                                            ipaddr_string(tptr+4),
472                                            EXTRACT_32BITS(tptr+4));
473                                 break;
474                             case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
475                             case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
476                                 printf(", %s", ipaddr_string(tptr));
477                                 break;
478                             case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
479                             case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
480                                 bw.i = EXTRACT_32BITS(tptr);
481                                 printf(", %.3f Mbps", bw.f*8/1000000 );
482                                 break;
483                             case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
484                                 for (priority_level = 0; priority_level < 8; priority_level++) {
485                                     bw.i = EXTRACT_32BITS(tptr+priority_level*4);
486                                     printf("\n\t\tpriority level %d: %.3f Mbps",
487                                            priority_level,
488                                            bw.f*8/1000000 );
489                                 }
490                                 break;
491                             case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
492                                 printf(", Metric %u", EXTRACT_32BITS(tptr));
493                                 break;
494                             case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
495                                 printf(", %s, Priority %u",
496                                        bittok2str(gmpls_link_prot_values, "none", *tptr),
497                                        *(tptr+1));
498                                 break;
499                             case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
500                                 printf("\n\t\tInterface Switching Capability: %s",
501                                        tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
502                                 printf("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
503                                        tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
504                                 for (priority_level = 0; priority_level < 8; priority_level++) {
505                                     bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4));
506                                     printf("\n\t\t  priority level %d: %.3f Mbps",
507                                            priority_level,
508                                            bw.f*8/1000000 );
509                                 }
510                                 break;
511                             case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
512                                 printf(", %s (%u)",
513                                        tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
514                                        *tptr);
515                                 break;
516 
517                             case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
518                                 count_srlg = subtlv_length / 4;
519                                 if (count_srlg != 0)
520                                      printf("\n\t\t  Shared risk group: ");
521                                 while (count_srlg > 0) {
522                                         bw.i = EXTRACT_32BITS(tptr);
523                                         printf("%d",bw.i);
524                                         tptr+=4;
525                                         count_srlg--;
526                                         if (count_srlg > 0)
527                                             printf(", ");
528                                 }
529                                 break;
530 
531                             default:
532                                 if (vflag <= 1) {
533                                     if(!print_unknown_data(tptr,"\n\t\t",subtlv_length))
534                                         return(ls_end);
535                                 }
536                                 break;
537                             }
538                             /* in OSPF everything has to be 32-bit aligned, including TLVs */
539                             if (subtlv_length%4 != 0)
540                                 subtlv_length+=4-(subtlv_length%4);
541 
542                             tlv_length-=subtlv_length;
543                             tptr+=subtlv_length;
544 
545                         }
546                         break;
547 
548                     case LS_OPAQUE_TE_TLV_ROUTER:
549                         if (tlv_length < 4) {
550                             printf("\n\t    TLV length %u < 4", tlv_length);
551                             return(ls_end);
552                         }
553                         TCHECK2(*tptr, 4);
554                         printf(", %s", ipaddr_string(tptr));
555                         break;
556 
557                     default:
558                         if (vflag <= 1) {
559                             if(!print_unknown_data(tptr,"\n\t      ",tlv_length))
560                                 return(ls_end);
561                         }
562                         break;
563                     }
564                     tptr+=tlv_length;
565 		}
566                 break;
567 	    }
568 	    break;
569         default:
570             if (vflag <= 1) {
571                 if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
572                                        "\n\t    ", ls_length))
573                     return(ls_end);
574             }
575             break;
576         }
577 
578         /* do we want to see an additionally hexdump ? */
579         if (vflag> 1)
580             if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
581                                    "\n\t    ", ls_length)) {
582                 return(ls_end);
583             }
584 
585 	return (ls_end);
586 trunc:
587 	return (NULL);
588 }
589 
590 static int
591 ospf_decode_v2(register const struct ospfhdr *op,
592     register const u_char *dataend)
593 {
594 	register const struct in_addr *ap;
595 	register const struct lsr *lsrp;
596 	register const struct lsa_hdr *lshp;
597 	register const struct lsa *lsap;
598 	register u_int32_t lsa_count,lsa_count_max;
599 
600 	switch (op->ospf_type) {
601 
602 	case OSPF_TYPE_UMD:
603 		/*
604 		 * Rob Coltun's special monitoring packets;
605 		 * do nothing
606 		 */
607 		break;
608 
609 	case OSPF_TYPE_HELLO:
610                 printf("\n\tOptions: [%s]",
611                        bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options));
612 
613                 TCHECK(op->ospf_hello.hello_deadint);
614                 printf("\n\t  Hello Timer: %us, Dead Timer %us, Mask: %s, Priority: %u",
615                        EXTRACT_16BITS(&op->ospf_hello.hello_helloint),
616                        EXTRACT_32BITS(&op->ospf_hello.hello_deadint),
617                        ipaddr_string(&op->ospf_hello.hello_mask),
618                        op->ospf_hello.hello_priority);
619 
620 		TCHECK(op->ospf_hello.hello_dr);
621 		if (op->ospf_hello.hello_dr.s_addr != 0)
622 			printf("\n\t  Designated Router %s",
623 			    ipaddr_string(&op->ospf_hello.hello_dr));
624 
625 		TCHECK(op->ospf_hello.hello_bdr);
626 		if (op->ospf_hello.hello_bdr.s_addr != 0)
627 			printf(", Backup Designated Router %s",
628 			    ipaddr_string(&op->ospf_hello.hello_bdr));
629 
630                 ap = op->ospf_hello.hello_neighbor;
631                 if ((u_char *)ap < dataend)
632                         printf("\n\t  Neighbor List:");
633                 while ((u_char *)ap < dataend) {
634                         TCHECK(*ap);
635                         printf("\n\t    %s", ipaddr_string(ap));
636                         ++ap;
637                 }
638 		break;	/* HELLO */
639 
640 	case OSPF_TYPE_DD:
641 		TCHECK(op->ospf_db.db_options);
642                 printf("\n\tOptions: [%s]",
643                        bittok2str(ospf_option_values,"none",op->ospf_db.db_options));
644 		TCHECK(op->ospf_db.db_flags);
645                 printf(", DD Flags: [%s]",
646                        bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags));
647 
648 		if (vflag) {
649 			/* Print all the LS adv's */
650 			lshp = op->ospf_db.db_lshdr;
651 			while (ospf_print_lshdr(lshp) != -1) {
652 				++lshp;
653 			}
654 		}
655 		break;
656 
657 	case OSPF_TYPE_LS_REQ:
658                 lsrp = op->ospf_lsr;
659                 while ((u_char *)lsrp < dataend) {
660                     TCHECK(*lsrp);
661 
662                     printf("\n\t  Advertising Router: %s, %s LSA (%u)",
663                            ipaddr_string(&lsrp->ls_router),
664                            tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)),
665                            EXTRACT_32BITS(&lsrp->ls_type));
666 
667                     switch (EXTRACT_32BITS(lsrp->ls_type)) {
668                         /* the LSA header for opaque LSAs was slightly changed */
669                     case LS_TYPE_OPAQUE_LL:
670                     case LS_TYPE_OPAQUE_AL:
671                     case LS_TYPE_OPAQUE_DW:
672                         printf(", Opaque-Type: %s LSA (%u), Opaque-ID: %u",
673                                tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type),
674                                lsrp->un_ls_stateid.opaque_field.opaque_type,
675                                EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id));
676                         break;
677                     default:
678                         printf(", LSA-ID: %s",
679                                ipaddr_string(&lsrp->un_ls_stateid.ls_stateid));
680                         break;
681                     }
682 
683                     ++lsrp;
684                 }
685 		break;
686 
687 	case OSPF_TYPE_LS_UPDATE:
688                 lsap = op->ospf_lsu.lsu_lsa;
689                 TCHECK(op->ospf_lsu.lsu_count);
690                 lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count);
691                 printf(", %d LSA%s",lsa_count_max, lsa_count_max > 1 ? "s" : "");
692                 for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
693                     printf("\n\t  LSA #%u",lsa_count);
694                         lsap = (const struct lsa *)ospf_print_lsa(lsap);
695                         if (lsap == NULL)
696                                 goto trunc;
697                 }
698 		break;
699 
700 	case OSPF_TYPE_LS_ACK:
701                 lshp = op->ospf_lsa.lsa_lshdr;
702                 while (ospf_print_lshdr(lshp) != -1) {
703                     ++lshp;
704                 }
705                 break;
706 
707 	default:
708 		printf("v2 type (%d)", op->ospf_type);
709 		break;
710 	}
711 	return (0);
712 trunc:
713 	return (1);
714 }
715 
716 void
717 ospf_print(register const u_char *bp, register u_int length,
718     register const u_char *bp2)
719 {
720 	register const struct ospfhdr *op;
721 	register const struct ip *ip;
722 	register const u_char *dataend;
723 	register const char *cp;
724 
725 	op = (struct ospfhdr *)bp;
726 	ip = (struct ip *)bp2;
727 
728         /* XXX Before we do anything else, strip off the MD5 trailer */
729         TCHECK(op->ospf_authtype);
730         if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
731                 length -= OSPF_AUTH_MD5_LEN;
732                 snapend -= OSPF_AUTH_MD5_LEN;
733         }
734 
735 	/* If the type is valid translate it, or just print the type */
736 	/* value.  If it's not valid, say so and return */
737 	TCHECK(op->ospf_type);
738 	cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
739 	printf("OSPFv%u, %s (%u), length: %u",
740 	       op->ospf_version,
741 	       cp,
742 	       op->ospf_type,
743 	       length);
744 	if (*cp == 'u')
745 		return;
746 
747         if(!vflag) /* non verbose - so lets bail out here */
748                 return;
749 
750 	TCHECK(op->ospf_len);
751 	if (length != EXTRACT_16BITS(&op->ospf_len)) {
752 		printf(" [len %d]", EXTRACT_16BITS(&op->ospf_len));
753 		return;
754 	}
755 	dataend = bp + length;
756 
757 	TCHECK(op->ospf_routerid);
758         printf("\n\tRouter-ID: %s", ipaddr_string(&op->ospf_routerid));
759 
760 	TCHECK(op->ospf_areaid);
761 	if (op->ospf_areaid.s_addr != 0)
762 		printf(", Area %s", ipaddr_string(&op->ospf_areaid));
763 	else
764 		printf(", Backbone Area");
765 
766 	if (vflag) {
767 		/* Print authentication data (should we really do this?) */
768 		TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata));
769 
770                 printf(", Authentication Type: %s (%u)",
771                        tok2str(ospf_authtype_values,"unknown",EXTRACT_16BITS(&op->ospf_authtype)),
772                        EXTRACT_16BITS(&op->ospf_authtype));
773 
774 		switch (EXTRACT_16BITS(&op->ospf_authtype)) {
775 
776 		case OSPF_AUTH_NONE:
777 			break;
778 
779 		case OSPF_AUTH_SIMPLE:
780 			(void)fn_printn(op->ospf_authdata,
781 			    sizeof(op->ospf_authdata), NULL);
782 			printf("\"");
783 			break;
784 
785 		case OSPF_AUTH_MD5:
786                         printf("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x",
787                                *((op->ospf_authdata)+2),
788                                *((op->ospf_authdata)+3),
789                                EXTRACT_32BITS((op->ospf_authdata)+4));
790 			break;
791 
792 		default:
793 			return;
794 		}
795 	}
796 	/* Do rest according to version.	 */
797 	switch (op->ospf_version) {
798 
799 	case 2:
800 		/* ospf version 2 */
801 		if (ospf_decode_v2(op, dataend))
802 			goto trunc;
803 		break;
804 
805 	default:
806 		printf(" ospf [version %d]", op->ospf_version);
807 		break;
808 	}			/* end switch on version */
809 
810 	return;
811 trunc:
812 	fputs(tstr, stdout);
813 }
814