2 * Routines for OSPF packet disassembly
3 * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
5 * $Id: packet-ospf.c,v 1.33 2001/01/03 06:55:30 guy Exp $
7 * At this time, this module is able to analyze OSPF
8 * packets as specified in RFC2328. MOSPF (RFC1584) and other
9 * OSPF Extensions which introduce new Packet types
10 * (e.g the External Atributes LSA) are not supported.
12 * TOS - support is not fully implemented
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@zing.org>
16 * Copyright 1998 Gerald Combs
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
51 #include "packet-ip.h"
53 #include "ieee-float.h"
55 #define OSPF_HEADER_LENGTH 24
58 #define OSPF_DB_DESC 2
63 static const value_string pt_vals[] = {
64 {OSPF_HELLO, "Hello Packet" },
65 {OSPF_DB_DESC, "DB Descr." },
66 {OSPF_LS_REQ, "LS Request" },
67 {OSPF_LS_UPD, "LS Update" },
68 {OSPF_LS_ACK, "LS Acknowledge" },
72 #define OSPF_AUTH_NONE 0
73 #define OSPF_AUTH_SIMPLE 1
74 #define OSPF_AUTH_CRYPT 2
76 static const value_string auth_vals[] = {
77 {OSPF_AUTH_NONE, "Null" },
78 {OSPF_AUTH_SIMPLE, "Simple password" },
79 {OSPF_AUTH_CRYPT, "Cryptographic" },
83 #define OSPF_OPTIONS_E 0x02
84 #define OSPF_OPTIONS_MC 0x04
85 #define OSPF_OPTIONS_NP 0x08
86 #define OSPF_OPTIONS_EA 0x10
87 #define OSPF_OPTIONS_DC 0x20
89 #define OSPF_DBD_FLAG_MS 1
90 #define OSPF_DBD_FLAG_M 2
91 #define OSPF_DBD_FLAG_I 4
93 #define OSPF_LS_REQ_LENGTH 12
95 #define OSPF_LSTYPE_ROUTER 1
96 #define OSPF_LSTYPE_NETWORK 2
97 #define OSPF_LSTYPE_SUMMERY 3
98 #define OSPF_LSTYPE_ASBR 4
99 #define OSPF_LSTYPE_ASEXT 5
100 #define OSPF_LSTYPE_ASEXT7 7
102 /* Opaque LSA types */
103 #define OSPF_LSTYPE_OP_LINKLOCAL 9
104 #define OSPF_LSTYPE_OP_AREALOCAL 10
105 #define OSPF_LSTYPE_OP_ASWIDE 11
107 #define OSPF_LINK_PTP 1
108 #define OSPF_LINK_TRANSIT 2
109 #define OSPF_LINK_STUB 3
110 #define OSPF_LINK_VIRTUAL 4
112 #define OSPF_LSA_HEADER_LENGTH 20
114 /* Known opaque LSAs */
115 #define OSPF_LSA_MPLS_TE 1
117 static const value_string ls_type_vals[] = {
118 {OSPF_LSTYPE_ROUTER, "Router-LSA" },
119 {OSPF_LSTYPE_NETWORK, "Network-LSA" },
120 {OSPF_LSTYPE_SUMMERY, "Summary-LSA (IP network)" },
121 {OSPF_LSTYPE_ASBR, "Summary-LSA (ASBR)" },
122 {OSPF_LSTYPE_ASEXT, "AS-External-LSA (ASBR)" },
126 static int proto_ospf = -1;
128 static gint ett_ospf = -1;
129 static gint ett_ospf_hdr = -1;
130 static gint ett_ospf_hello = -1;
131 static gint ett_ospf_desc = -1;
132 static gint ett_ospf_lsr = -1;
133 static gint ett_ospf_lsa = -1;
134 static gint ett_ospf_lsa_upd = -1;
136 /* Trees for opaque LSAs */
137 static gint ett_ospf_lsa_mpls = -1;
138 static gint ett_ospf_lsa_mpls_router = -1;
139 static gint ett_ospf_lsa_mpls_link = -1;
140 static gint ett_ospf_lsa_mpls_link_stlv = -1;
142 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*);
143 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*);
144 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*);
145 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*);
146 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*);
148 /* dissect_ospf_lsa returns the offset of the next LSA
149 * if disassemble_body is set to FALSE (e.g. in LSA ACK
150 * packets), the offset is set to the offset of the next
153 static int dissect_ospf_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
155 static void dissect_ospf_options(tvbuff_t *, int, proto_tree *);
158 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
160 proto_tree *ospf_tree = NULL;
162 proto_tree *ospf_header_tree;
168 guint16 cksum, computed_cksum;
169 guint length, reported_length;
174 CHECK_DISPLAY_AS_DATA(proto_ospf, tvb, pinfo, tree);
176 pinfo->current_proto = "OSPF";
178 version = tvb_get_guint8(tvb, 0);
179 packet_type = tvb_get_guint8(tvb, 1);
180 if (check_col(pinfo->fd, COL_PROTOCOL))
181 col_set_str(pinfo->fd, COL_PROTOCOL, "OSPF");
182 if (check_col(pinfo->fd, COL_INFO)) {
183 col_add_str(pinfo->fd, COL_INFO,
184 val_to_str(packet_type, pt_vals, "Unknown (%u)"));
188 ospflen = tvb_get_ntohs(tvb, 2);
190 ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE);
191 ospf_tree = proto_item_add_subtree(ti, ett_ospf);
193 ti = proto_tree_add_text(ospf_tree, tvb, 0, OSPF_HEADER_LENGTH,
195 ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
197 proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
199 proto_tree_add_text(ospf_header_tree, tvb, 1, 1, "OSPF Packet Type: %u (%s)",
201 val_to_str(packet_type, pt_vals, "Unknown"));
202 proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
204 proto_tree_add_text(ospf_header_tree, tvb, 4, 4, "Source OSPF Router ID: %s",
205 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
206 if (tvb_get_ntohl(tvb, 8) == 0) {
207 proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: Backbone");
209 proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s",
210 ip_to_str(tvb_get_ptr(tvb, 8, 4)));
212 cksum = tvb_get_ntohs(tvb, 12);
213 length = tvb_length(tvb);
214 /* XXX - include only the length from the OSPF header? */
215 reported_length = tvb_reported_length(tvb);
216 if (!pi.fragmented && length >= reported_length
217 && length >= OSPF_HEADER_LENGTH) {
218 /* The packet isn't part of a fragmented datagram and isn't
219 truncated, so we can checksum it. */
221 /* Header, not including the authentication data (the OSPF
222 checksum excludes the 64-bit authentication field). */
223 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
224 cksum_vec[0].len = 16;
225 if (length > OSPF_HEADER_LENGTH) {
226 /* Rest of the packet, again not including the
227 authentication data. */
228 reported_length -= OSPF_HEADER_LENGTH;
229 cksum_vec[1].ptr = tvb_get_ptr(tvb, OSPF_HEADER_LENGTH, reported_length);
230 cksum_vec[1].len = reported_length;
233 /* There's nothing but a header. */
236 computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
237 if (computed_cksum == 0) {
238 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
239 "Packet Checksum: 0x%04x (correct)", cksum);
241 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
242 "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)",
243 cksum, in_cksum_shouldbe(cksum, computed_cksum));
246 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
247 "Packet Checksum: 0x%04x", cksum);
249 auth_type = tvb_get_ntohs(tvb, 14);
250 proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
251 val_to_str(auth_type, auth_vals, "Unknown (%u)"));
255 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
258 case OSPF_AUTH_SIMPLE:
259 tvb_get_nstringz0(tvb, 16, 8, auth_data);
260 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
263 case OSPF_AUTH_CRYPT:
264 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
265 tvb_get_guint8(tvb, 18));
266 crypto_len = tvb_get_guint8(tvb, 19);
267 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
269 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
270 tvb_get_ntohl(tvb, 20));
272 /* Show the message digest that was appended to the end of the
273 OSPF message - but only if it's present (we don't want
274 to get an exception before we've tried dissecting OSPF
276 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
277 proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
279 tvb_bytes_to_str(tvb, ospflen, crypto_len));
284 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
288 /* Adjust the length of the tvbuff to match the size of the OSPF
289 * packet (since the dissect routines use it to work out where the
290 * end of the OSPF packet is).
292 tvb_set_reported_length(tvb, ospflen);
294 switch (packet_type){
297 dissect_ospf_hello(tvb, OSPF_HEADER_LENGTH, ospf_tree);
301 dissect_ospf_db_desc(tvb, OSPF_HEADER_LENGTH, ospf_tree);
305 dissect_ospf_ls_req(tvb, OSPF_HEADER_LENGTH, ospf_tree);
309 dissect_ospf_ls_upd(tvb, OSPF_HEADER_LENGTH, ospf_tree);
313 dissect_ospf_ls_ack(tvb, OSPF_HEADER_LENGTH, ospf_tree);
317 dissect_data(tvb, OSPF_HEADER_LENGTH, pinfo, tree);
324 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree)
326 proto_tree *ospf_hello_tree;
329 ti = proto_tree_add_text(tree, tvb, offset,
330 tvb_length_remaining(tvb, offset),
331 "OSPF Hello Packet");
332 ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
334 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
335 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
336 proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
337 "Hello Interval: %u seconds",
338 tvb_get_ntohs(tvb, offset + 4));
340 dissect_ospf_options(tvb, offset + 6, ospf_hello_tree);
341 proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
342 tvb_get_guint8(tvb, offset + 7));
343 proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
344 tvb_get_ntohl(tvb, offset + 8));
345 proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
346 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
347 proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
348 ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
351 while (tvb_reported_length_remaining(tvb, offset) != 0) {
352 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
353 "Active Neighbor: %s",
354 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
360 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree)
362 proto_tree *ospf_db_desc_tree=NULL;
365 char flags_string[20] = "";
368 ti = proto_tree_add_text(tree, tvb, offset,
369 tvb_length_remaining(tvb, offset),
370 "OSPF DB Description");
371 ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
373 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
374 tvb_get_ntohs(tvb, offset));
376 dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree);
378 flags = tvb_get_guint8(tvb, offset + 3);
379 if (flags & OSPF_DBD_FLAG_MS)
380 strcat(flags_string, "MS");
381 if (flags & OSPF_DBD_FLAG_M) {
382 if (flags_string[0] != '\0')
383 strcat(flags_string, "/");
384 strcat(flags_string, "M");
386 if (flags & OSPF_DBD_FLAG_I) {
387 if (flags_string[0] != '\0')
388 strcat(flags_string, "/");
389 strcat(flags_string, "I");
391 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)",
392 flags, flags_string);
393 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
394 tvb_get_ntohl(tvb, offset + 4));
397 /* LS Headers will be processed here */
398 /* skip to the end of DB-Desc header */
400 while (tvb_reported_length_remaining(tvb, offset) != 0)
401 offset = dissect_ospf_lsa(tvb, offset, tree, FALSE);
405 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree)
407 proto_tree *ospf_lsr_tree;
411 /* zero or more LS requests may be within a LS Request */
412 /* we place every request for a LSA in a single subtree */
413 while (tvb_reported_length_remaining(tvb, offset) != 0) {
414 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
415 "Link State Request");
416 ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
418 ls_type = tvb_get_ntohl(tvb, offset);
419 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 4, "LS Type: %s (%u)",
420 val_to_str(ls_type, ls_type_vals, "Unknown"),
423 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
424 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
425 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 8, 4, "Advertising Router: %s",
426 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
433 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree)
435 proto_tree *ospf_lsa_upd_tree=NULL;
440 ti = proto_tree_add_text(tree, tvb, offset,
441 tvb_length_remaining(tvb, offset),
443 ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
445 lsa_nr = tvb_get_ntohl(tvb, offset);
446 proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
448 /* skip to the beginning of the first LSA */
449 offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
452 while (lsa_counter < lsa_nr) {
453 offset = dissect_ospf_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
459 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree)
461 /* the body of a LS Ack packet simply contains zero or more LSA Headers */
462 while (tvb_reported_length_remaining(tvb, offset) != 0)
463 offset = dissect_ospf_lsa(tvb, offset, tree, FALSE);
467 * Returns if an LSA is opaque, i.e. requires special treatment
470 is_opaque(int lsa_type)
472 return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
473 lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
476 /* MPLS/TE TLV types */
477 #define MPLS_TLV_ROUTER 1
478 #define MPLS_TLV_LINK 2
480 /* MPLS/TE Link STLV types */
488 MPLS_LINK_MAX_RES_BW,
493 static const value_string mpls_link_stlv_str[] = {
494 {MPLS_LINK_TYPE, "Link Type"},
495 {MPLS_LINK_ID, "Link ID"},
496 {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
497 {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
498 {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
499 {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
500 {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
501 {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
502 {MPLS_LINK_COLOR, "Resource Class/Color"},
506 * Dissect MPLS/TE opaque LSA
509 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
513 proto_tree *mpls_tree;
514 proto_tree *tlv_tree;
515 proto_tree *stlv_tree;
521 int stlv_type, stlv_len, stlv_offset;
525 ti = proto_tree_add_text(tree, tvb, offset, length,
526 "MPLS Traffic Engineering LSA");
527 mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
529 while (length != 0) {
530 tlv_type = tvb_get_ntohs(tvb, offset);
531 tlv_length = tvb_get_ntohs(tvb, offset + 2);
532 tlv_end_offset = offset + tlv_length + 4;
536 case MPLS_TLV_ROUTER:
537 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
538 "Router Address: %s",
539 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
540 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
541 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
542 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
544 proto_tree_add_text(tlv_tree, tvb, offset+4, 4, "Router Address: %s",
545 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
549 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
551 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
552 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
553 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
555 stlv_offset = offset + 4;
557 /* Walk down the sub-TLVs for link information */
558 while (stlv_offset < tlv_end_offset) {
559 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
560 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
561 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
565 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
567 tvb_get_guint8(tvb, stlv_offset + 4));
568 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
569 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
570 "TLV Type: %u: %s", stlv_type, stlv_name);
571 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
573 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "%s: %u", stlv_name,
574 tvb_get_guint8(tvb, stlv_offset + 4));
578 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
579 "%s: %s (%x)", stlv_name,
580 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
581 tvb_get_ntohl(tvb, stlv_offset + 4));
582 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
583 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
584 "TLV Type: %u: %s", stlv_type, stlv_name);
585 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
587 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s (%x)", stlv_name,
588 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
589 tvb_get_ntohl(tvb, stlv_offset + 4));
592 case MPLS_LINK_LOCAL_IF:
593 case MPLS_LINK_REMOTE_IF:
594 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
596 ip_to_str(tvb_get_ptr(tvb, stlv_offset+4, 4)));
597 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
598 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
599 "TLV Type: %u: %s", stlv_type, stlv_name);
600 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
602 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s", stlv_name,
603 ip_to_str(tvb_get_ptr(tvb, stlv_offset+4, 4)));
606 case MPLS_LINK_TE_METRIC:
607 case MPLS_LINK_COLOR:
608 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
610 tvb_get_ntohl(tvb, stlv_offset + 4));
611 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
612 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
613 "TLV Type: %u: %s", stlv_type, stlv_name);
614 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
616 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
617 tvb_get_ntohl(tvb, stlv_offset + 4));
620 case MPLS_LINK_MAX_BW:
621 case MPLS_LINK_MAX_RES_BW:
622 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
623 "%s: %ld", stlv_name,
624 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
625 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
626 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
627 "TLV Type: %u: %s", stlv_type, stlv_name);
628 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
630 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %ld", stlv_name,
631 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
634 case MPLS_LINK_UNRES_BW:
635 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
637 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
638 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
639 "TLV Type: %u: %s", stlv_type, stlv_name);
640 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
642 for (i = 0; i < 8; i++) {
643 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
645 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4 + i*4, 4)));
650 proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
651 "Unknown Link sub-TLV: %u", stlv_type);
654 stlv_offset += ((stlv_len+4+3)/4)*4;
659 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
660 "Unknown LSA: %u", tlv_type);
661 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
662 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
664 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
666 proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
670 offset += tlv_length + 4;
671 length -= tlv_length + 4;
676 * Dissect opaque LSAs
679 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
680 guint8 ls_id_type, guint32 length)
682 switch (ls_id_type) {
684 case OSPF_LSA_MPLS_TE:
685 dissect_ospf_lsa_mpls(tvb, offset, tree, length);
689 proto_tree_add_text(tree, tvb, offset, length,
690 "Unknown LSA Type %u", ls_id_type);
692 } /* switch on opaque LSA id */
696 dissect_ospf_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
697 gboolean disassemble_body)
699 proto_tree *ospf_lsa_tree;
711 guint16 link_counter;
716 /* AS-external LSA */
722 ls_type = tvb_get_guint8(tvb, offset + 3);
723 ls_length = tvb_get_ntohs(tvb, offset + 18);
724 end_offset = offset + ls_length;
727 case OSPF_LSTYPE_ROUTER:
728 lsa_type="Router LSA";
731 case OSPF_LSTYPE_NETWORK:
732 lsa_type="Network LSA";
735 case OSPF_LSTYPE_SUMMERY:
736 lsa_type="Summary LSA";
739 case OSPF_LSTYPE_ASBR:
743 case OSPF_LSTYPE_ASEXT:
744 lsa_type="AS-external-LSA";
747 case OSPF_LSTYPE_ASEXT7:
748 lsa_type="AS-external-LSA Type 7/NSSA";
751 case OSPF_LSTYPE_OP_LINKLOCAL:
752 lsa_type="Opaque LSA, Link-local scope";
755 case OSPF_LSTYPE_OP_AREALOCAL:
756 lsa_type="Opaque LSA, Area-local scope";
759 case OSPF_LSTYPE_OP_ASWIDE:
760 lsa_type="Opaque LSA, AS-wide scope";
768 if (disassemble_body) {
769 ti = proto_tree_add_text(tree, tvb, offset, ls_length,
770 "%s (Type: %u)", lsa_type, ls_type);
772 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
775 ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
777 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
778 tvb_get_ntohs(tvb, offset));
779 dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree);
780 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 3, 1, "LSA Type: %u (%s)",
783 if (is_opaque(ls_type)) {
784 ls_id_type = tvb_get_guint8(tvb, offset + 4);
785 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 1, "Link State ID Opaque Type: %u",
787 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
788 tvb_get_ntoh24(tvb, offset + 5));
791 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
792 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
795 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Advertising Router: %s",
796 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
797 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%04x",
798 tvb_get_ntohl(tvb, offset + 12));
799 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
800 tvb_get_ntohs(tvb, offset + 16));
802 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
805 /* skip past the LSA header to the body */
806 offset += OSPF_LSA_HEADER_LENGTH;
807 ls_length -= OSPF_LSA_HEADER_LENGTH;
809 if (!disassemble_body)
814 case OSPF_LSTYPE_ROUTER:
815 /* again: flags should be secified in detail */
816 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x",
817 tvb_get_guint8(tvb, offset));
818 nr_links = tvb_get_ntohs(tvb, offset + 2);
819 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
822 /* nr_links links follow
823 * maybe we should put each of the links into its own subtree ???
825 for (link_counter = 1; link_counter <= nr_links; link_counter++) {
826 /* check the Link Type and ID */
827 link_type = tvb_get_guint8(tvb, offset + 8);
831 link_type_str="Point-to-point connection to another router";
832 link_id="Neighboring router's Router ID";
835 case OSPF_LINK_TRANSIT:
836 link_type_str="Connection to a transit network";
837 link_id="IP address of Designated Router";
841 link_type_str="Connection to a stub network";
842 link_id="IP network/subnet number";
845 case OSPF_LINK_VIRTUAL:
846 link_type_str="Virtual link";
847 link_id="Neighboring router's Router ID";
851 link_type_str="Unknown link type";
852 link_id="Unknown link ID";
856 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "%s: %s", link_id,
857 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
859 /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
860 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link Data: %s",
861 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
863 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
864 link_type, link_type_str);
865 nr_tos = tvb_get_guint8(tvb, offset + 9);
866 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
868 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
869 tvb_get_ntohs(tvb, offset + 10));
873 /* nr_tos metrics may follow each link
874 * ATTENTION: TOS metrics are not tested (I don't have TOS
876 * please send me a mail if it is/isn't working
878 for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
879 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
880 tvb_get_guint8(tvb, offset),
881 tvb_get_ntohs(tvb, offset + 2));
887 case OSPF_LSTYPE_NETWORK:
888 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
889 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
892 while (offset < end_offset) {
893 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
894 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
899 case OSPF_LSTYPE_SUMMERY:
900 /* Type 3 and 4 LSAs have the same format */
901 case OSPF_LSTYPE_ASBR:
902 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
903 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
906 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
907 tvb_get_ntoh24(tvb, offset + 1));
910 /* TOS-specific information, if any */
911 while (offset < end_offset) {
912 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
913 tvb_get_guint8(tvb, offset),
914 tvb_get_ntoh24(tvb, offset + 1));
919 case OSPF_LSTYPE_ASEXT:
920 case OSPF_LSTYPE_ASEXT7:
921 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
922 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
925 options = tvb_get_guint8(tvb, offset);
926 if (options & 0x80) { /* check wether or not E bit is set */
927 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
928 "External Type: Type 2 (metric is larger than any other link state path)");
930 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
931 "External Type: Type 1 (metric is specified in the same units as interface cost)");
933 /* the metric field of a AS-external LAS is specified in 3 bytes */
934 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
935 tvb_get_ntoh24(tvb, offset + 1));
938 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
939 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
942 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
943 tvb_get_ntohl(tvb, offset));
946 /* TOS-specific information, if any */
947 while (offset < end_offset) {
948 options = tvb_get_guint8(tvb, offset);
949 if (options & 0x80) { /* check wether or not E bit is set */
950 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
951 "External Type: Type 2 (metric is larger than any other link state path)");
953 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
954 "External Type: Type 1 (metric is specified in the same units as interface cost)");
956 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
958 tvb_get_ntoh24(tvb, offset + 1));
961 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
962 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
965 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
966 tvb_get_ntohl(tvb, offset));
971 case OSPF_LSTYPE_OP_LINKLOCAL:
972 case OSPF_LSTYPE_OP_AREALOCAL:
973 case OSPF_LSTYPE_OP_ASWIDE:
974 dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
980 /* unknown LSA type */
981 proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
986 /* return the offset of the next LSA */
991 dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree)
994 char options_string[20] = "";
996 /* ATTENTION !!! no check for length of options string */
997 options = tvb_get_guint8(tvb, offset);
998 if (options & OSPF_OPTIONS_E)
999 strcat(options_string, "E");
1000 if (options & OSPF_OPTIONS_MC) {
1001 if (options_string[0] != '\0')
1002 strcat(options_string, "/");
1003 strcat(options_string, "MC");
1005 if (options & OSPF_OPTIONS_NP) {
1006 if (options_string[0] != '\0')
1007 strcat(options_string, "/");
1008 strcat(options_string, "NP");
1010 if (options & OSPF_OPTIONS_EA) {
1011 if (options_string[0] != '\0')
1012 strcat(options_string, "/");
1013 strcat(options_string, "EA");
1015 if (options & OSPF_OPTIONS_DC) {
1016 if (options_string[0] != '\0')
1017 strcat(options_string, "/");
1018 strcat(options_string, "DC");
1021 proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)",
1022 options, options_string);
1026 proto_register_ospf(void)
1028 /* static hf_register_info hf[] = {
1030 { "Name", "ospf.abbreviation", TYPE, VALS_POINTER }},
1032 static gint *ett[] = {
1041 &ett_ospf_lsa_mpls_router,
1042 &ett_ospf_lsa_mpls_link,
1043 &ett_ospf_lsa_mpls_link_stlv
1046 proto_ospf = proto_register_protocol("Open Shortest Path First",
1048 /* proto_register_field_array(proto_ospf, hf, array_length(hf));*/
1049 proto_register_subtree_array(ett, array_length(ett));
1053 proto_reg_handoff_ospf(void)
1055 dissector_add("ip.proto", IP_PROTO_OSPF, dissect_ospf);