Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mpls.c
blob23da6f24dae4c290bc3eb7d967677eca2cde1115
1 /* packet-mpls.c
2 * Routines for MPLS data packet disassembly
3 * RFC 3032
5 * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
7 * (c) Copyright 2006, _FF_ Francesco Fondelli <francesco.fondelli@gmail.com>
8 * - added MPLS OAM support, ITU-T Y.1711
9 * - PW Associated Channel Header dissection as per RFC 4385
10 * - PW MPLS Control Word dissection as per RFC 4385
11 * - mpls subdissector table indexed by label value
12 * - enhanced "what's past last mpls label?" heuristic
14 * (c) Copyright 2011, Shobhank Sharma <ssharma5@ncsu.edu>
15 * - Removed some mpls preferences which are no longer relevant/needed like
16 * decode PWAC payloads as PPP traffic and assume all channel types except
17 * 0x21 are raw BFD.
18 * - MPLS extension from PW-ACH to MPLS Generic Associated Channel as per RFC 5586
19 * - Updated Pseudowire Associated Channel Types as per http://www.iana.org/assignments/pwe3-parameters
21 * (c) Copyright 2011, Jaihari Kalijanakiraman <jaiharik@ipinfusion.com>
22 * Krishnamurthy Mayya <krishnamurthy.mayya@ipinfusion.com>
23 * Nikitha Malgi <malgi.nikitha@ipinfusion.com>
24 * - Identification of BFD CC, BFD CV and ON-Demand CV ACH types as per RFC 6428, RFC 6426
25 * respectively and the corresponding decoding of messages
26 * - Decoding support for MPLS-TP Lock Instruct as per RFC 6435
27 * - Decoding support for MPLS-TP Fault-Management as per RFC 6427
29 * (c) Copyright 2012, Aditya Ambadkar and Diana Chris <arambadk,dvchris@ncsu.edu>
30 * - Added preference to select BOS label as flowlabel as per RFC 6391
32 * Wireshark - Network traffic analyzer
33 * By Gerald Combs <gerald@wireshark.org>
34 * Copyright 1998 Gerald Combs
36 * SPDX-License-Identifier: GPL-2.0-or-later
39 #include "config.h"
41 #include <epan/packet.h>
42 #include <epan/expert.h>
44 #include <epan/ppptypes.h>
45 #include <epan/etypes.h>
46 #include <epan/prefs.h>
47 #include <epan/ipproto.h>
48 #include <epan/decode_as.h>
49 #include <epan/proto_data.h>
51 #include "packet-ppp.h"
52 #include "packet-mpls.h"
53 #include "packet-pw-common.h"
54 #include "packet-bfd.h"
55 #include "packet-juniper.h"
56 #include "packet-sflow.h"
57 #include "packet-l2tp.h"
58 #include "packet-vxlan.h"
59 #include "packet-nsh.h"
61 void proto_register_mpls(void);
62 void proto_reg_handoff_mpls(void);
64 static int proto_mpls;
65 static int proto_pw_ach;
66 static int proto_pw_ach_mcc;
67 static int proto_pw_mcw;
69 static int ett_mpls;
70 static int ett_mpls_pw_ach;
71 static int ett_mpls_pw_ach_mcc;
72 static int ett_mpls_pw_mcw;
73 static char PW_ACH[50] = "PW Associated Channel Header";
75 const value_string special_labels[] = {
76 {MPLS_LABEL_IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"},
77 {MPLS_LABEL_ROUTER_ALERT, "Router Alert"},
78 {MPLS_LABEL_IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"},
79 {MPLS_LABEL_IMPLICIT_NULL, "Implicit-Null"},
80 {MPLS_LABEL_OAM_ALERT, "OAM Alert"},
81 {MPLS_LABEL_GACH, "Generic Associated Channel Label (GAL)"},
82 {MPLS_LABEL_ELI, "Entropy Label Indicator (ELI)"},
83 {0, NULL }
86 static dissector_table_t pw_ach_subdissector_table;
87 static dissector_table_t pw_ach_mcc_subdissector_table;
89 static dissector_handle_t dissector_ipv6;
90 static dissector_handle_t dissector_ip;
91 static dissector_handle_t dissector_pw_ach;
92 static dissector_handle_t dissector_pw_eth_heuristic;
93 static dissector_handle_t mpls_handle;
94 static dissector_handle_t mpls_pwcw_handle;
95 static dissector_handle_t mpls_mcc_handle;
98 * RFC 8469 deprecated Ethernet without CW, so default this to false.
99 * https://datatracker.ietf.org/doc/html/rfc8469
101 static bool mpls_try_heuristic_first;
102 /* For RFC6391 - Flow aware transport of pseudowire over a mpls PSN*/
103 static bool mpls_bos_flowlabel;
105 static int hf_mpls_label;
106 static int hf_mpls_label_special;
107 static int hf_mpls_exp;
108 static int hf_mpls_bos;
109 static int hf_mpls_ttl;
111 static int hf_mpls_pw_ach_ver;
112 static int hf_mpls_pw_ach_res;
113 static int hf_mpls_pw_ach_channel_type;
115 static int hf_mpls_pw_ach_mcc_proto;
117 static int hf_mpls_pw_mcw_flags;
118 static int hf_mpls_pw_mcw_length;
119 static int hf_mpls_pw_mcw_sequence_number;
121 static expert_field ei_mpls_pw_ach_error_processing_message;
122 static expert_field ei_mpls_pw_ach_res;
123 static expert_field ei_mpls_pw_mcw_error_processing_message;
124 static expert_field ei_mpls_invalid_label;
126 #if 0 /*not used yet*/
128 * MPLS PW types
129 * http://www.iana.org/assignments/pwe3-parameters
131 static const value_string mpls_pw_types[] = {
132 { 0x0001, "Frame Relay DLCI ( Martini Mode )" },
133 { 0x0002, "ATM AAL5 SDU VCC transport" },
134 { 0x0003, "ATM transparent cell transport" },
135 { 0x0004, "Ethernet Tagged Mode" },
136 { 0x0005, "Ethernet" },
137 { 0x0006, "HDLC" },
138 { 0x0007, "PPP" },
139 { 0x0008, "SONET/SDH Circuit Emulation Service Over MPLS" },
140 { 0x0009, "ATM n-to-one VCC cell transport" },
141 { 0x000A, "ATM n-to-one VPC cell transport" },
142 { 0x000B, "IP Layer2 Transport" },
143 { 0x000C, "ATM one-to-one VCC Cell Mode" },
144 { 0x000D, "ATM one-to-one VPC Cell Mode" },
145 { 0x000E, "ATM AAL5 PDU VCC transport" },
146 { 0x000F, "Frame-Relay Port mode" },
147 { 0x0010, "SONET/SDH Circuit Emulation over Packet" },
148 { 0x0011, "Structure-agnostic E1 over Packet" },
149 { 0x0012, "Structure-agnostic T1 (DS1) over Packet" },
150 { 0x0013, "Structure-agnostic E3 over Packet" },
151 { 0x0014, "Structure-agnostic T3 (DS3) over Packet" },
152 { 0x0015, "CESoPSN basic mode" },
153 { 0x0016, "TDMoIP AAL1 Mode" },
154 { 0x0017, "CESoPSN TDM with CAS" },
155 { 0x0018, "TDMoIP AAL2 Mode" },
156 { 0x0019, "Frame Relay DLCI" },
157 { 0x001A, "ROHC Transport Header-compressed Packets" },/*[RFC4995][RFC4901]*/
158 { 0x001B, "ECRTP Transport Header-compressed Packets" },/*[RFC3545][RFC4901]*/
159 { 0x001C, "IPHC Transport Header-compressed Packets" },/*[RFC2507][RFC4901]*/
160 { 0x001D, "cRTP Transport Header-compressed Packets" },/*[RFC2508][RFC4901]*/
161 { 0x001E, "ATM VP Virtual Trunk" },/*[MFA9]*/
162 { 0x001F, "Reserved" },/*[Bryant] 2008-04-17*/
163 { 0, NULL }
165 static value_string_ext mpls_pw_types_ext = VALUE_STRING_EXT_INIT(mpls_pw_types);
166 #endif
169 * MPLS PW Associated Channel Types
170 * as per http://www.iana.org/assignments/pwe3-parameters
171 * and https://tools.ietf.org/html/draft-ietf-pwe3-vccv-bfd-05 clause 3.2
173 static const value_string mpls_pwac_types[] = {
174 { 0x0000, "Reserved"},
175 { 0x0001, "Management Communication Channel (MCC)"},
176 { 0x0002, "Signaling Communication Channel (SCC)"},
177 { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
178 { 0x000A, "MPLS Direct Loss Measurement (DLM)"},
179 { 0x000B, "MPLS Inferred Loss Measurement (ILM)"},
180 { 0x000C, "MPLS Delay Measurement (DM)"},
181 { 0x000D, "MPLS Direct Loss and Delay Measurement (DLM+DM)"},
182 { 0x000E, "MPLS Inferred Loss and Delay Measurement (ILM+DM)"},
183 { 0x0021, "IPv4 packet" },
184 { 0x0022, "MPLS-TP CC message"},
185 { 0x0023, "MPLS-TP CV message"},
186 { 0x0024, "Protection State Coordination Protocol (PSC)"},
187 { 0x0025, "On-Demand CV"},
188 { 0x0026, "LI"},
189 { 0x0027, "Pseudo-Wire OAM"},
190 { 0x0028, "MAC Withdraw OAM Msg"},
191 { 0x0057, "IPv6 packet" },
192 { 0x0058, "Fault OAM"},
193 { 0x7FF8, "Reserved for Experimental Use"},
194 { 0x7FF9, "Reserved for Experimental Use"},
195 { 0x7FFA, "Reserved for Experimental Use"},
196 { 0x7FFB, "Reserved for Experimental Use"},
197 { 0x7FFC, "Reserved for Experimental Use"},
198 { 0x7FFD, "Reserved for Experimental Use"},
199 { 0x7FFE, "Reserved for Experimental Use"},
200 { 0x7FFF, "Reserved for Experimental Use"},
201 { 0x8902, "MPLS-TP OAM"},
202 { 0, NULL }
204 static value_string_ext mpls_pwac_types_ext = VALUE_STRING_EXT_INIT(mpls_pwac_types);
206 static dissector_table_t mpls_subdissector_table;
208 * Post-stack First Nibble
209 * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
211 static dissector_table_t mpls_pfn_subdissector_table;
212 static heur_dissector_list_t mpls_heur_subdissector_list;
214 static void mpls_prompt(packet_info *pinfo, char* result)
216 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Data after label %u as",
217 GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 0)));
220 static void *mpls_value(packet_info *pinfo)
222 return p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 0);
225 static void mpls_pfn_prompt(packet_info *pinfo, char* result)
227 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Data after post-stack first nibble %u as",
228 GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 1)));
231 static void *mpls_pfn_value(packet_info *pinfo)
233 return p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 1);
236 static void pw_ach_prompt(packet_info *pinfo, char* result)
238 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Channel type 0x%x as",
239 GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0)));
242 static void *pw_ach_value(packet_info *pinfo)
244 return p_get_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0);
248 * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
249 * decode it.
250 * Return the label in "label", EXP bits in "exp",
251 * bottom_of_stack in "bos", and TTL in "ttl"
253 void
254 decode_mpls_label(tvbuff_t *tvb, int offset,
255 uint32_t *label, uint8_t *exp,
256 uint8_t *bos, uint8_t *ttl)
258 uint8_t octet0 = tvb_get_uint8(tvb, offset+0);
259 uint8_t octet1 = tvb_get_uint8(tvb, offset+1);
260 uint8_t octet2 = tvb_get_uint8(tvb, offset+2);
262 *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
263 *exp = (octet2 >> 1) & 0x7;
264 *bos = (octet2 & 0x1);
265 *ttl = tvb_get_uint8(tvb, offset+3);
269 * PW Associated Channel Header Management Communication
270 * Network (MCN) dissection as per RFC 5718.
272 static int
273 dissect_pw_ach_mcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
275 tvbuff_t *next_tvb;
276 proto_tree *mpls_pw_ach_mcc_tree;
277 proto_item *ti;
278 uint32_t pid;
280 ti = proto_tree_add_item(tree, proto_pw_ach_mcc, tvb, 0,2, ENC_NA);
281 mpls_pw_ach_mcc_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach_mcc);
282 proto_tree_add_item_ret_uint(mpls_pw_ach_mcc_tree, hf_mpls_pw_ach_mcc_proto,tvb, 0, 2, ENC_BIG_ENDIAN, &pid);
284 next_tvb = tvb_new_subset_remaining(tvb, 2);
286 if (!dissector_try_uint(pw_ach_mcc_subdissector_table, pid, next_tvb, pinfo, tree))
288 call_data_dissector(next_tvb, pinfo, tree);
291 return tvb_captured_length(tvb);
295 * FF: PW Associated Channel Header dissection as per RFC 4385.
297 static int
298 dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
300 tvbuff_t *next_tvb;
301 unsigned channel_type;
303 if (tvb_reported_length_remaining(tvb, 0) < 4) {
304 proto_tree_add_expert(tree, pinfo, &ei_mpls_pw_ach_error_processing_message, tvb, 0, -1);
305 return tvb_captured_length(tvb);
308 channel_type = tvb_get_ntohs(tvb, 2);
309 p_add_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0, GUINT_TO_POINTER(channel_type));
311 if (tree) {
312 proto_tree *mpls_pw_ach_tree;
313 proto_item *ti;
314 uint16_t res;
316 ti = proto_tree_add_item(tree, proto_pw_ach, tvb, 0, 4, ENC_NA);
317 mpls_pw_ach_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach);
319 proto_tree_add_item(mpls_pw_ach_tree, hf_mpls_pw_ach_ver,
320 tvb, 0, 1, ENC_BIG_ENDIAN);
322 res = tvb_get_uint8(tvb, 1);
323 ti = proto_tree_add_uint(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
324 tvb, 1, 1, res);
325 if (res != 0)
326 expert_add_info(pinfo, ti, &ei_mpls_pw_ach_res);
328 proto_tree_add_item(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
329 tvb, 2, 2, ENC_BIG_ENDIAN);
331 } /* if (tree) */
333 next_tvb = tvb_new_subset_remaining(tvb, 4);
335 if (!dissector_try_uint(pw_ach_subdissector_table, channel_type, next_tvb, pinfo, tree))
337 call_data_dissector(next_tvb, pinfo, tree);
340 if (channel_type == PW_ACH_TYPE_BFD_CV)
342 /* The BFD dissector has already been called, this is called in addition
343 XXX - Perhaps a new dissector function that combines both is preferred.*/
344 dissect_bfd_mep(next_tvb, tree, 0);
346 return tvb_captured_length(tvb);
349 bool
350 dissect_try_cw_first_nibble( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
352 uint8_t nibble;
354 nibble = (tvb_get_uint8(tvb, 0 ) >> 4) & 0x0F;
355 switch ( nibble )
357 case 6:
359 * XXX - this could be from an pseudo-wire without a control
360 * word, with the packet's first nibble being 6.
362 call_dissector(dissector_ipv6, tvb, pinfo, tree);
363 return true;
364 case 4:
366 * XXX - this could be from an pseudo-wire without a control
367 * word, with the packet's first nibble being 4.
369 call_dissector(dissector_ip, tvb, pinfo, tree);
370 return true;
371 case 1:
373 * XXX - this could be from an pseudo-wire without a control
374 * word, with the packet's first nibble being 1.
376 call_dissector(dissector_pw_ach, tvb, pinfo, tree );
377 return true;
378 default:
379 break;
381 return false;
385 * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
387 static int
388 dissect_pw_mcw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
390 tvbuff_t *next_tvb;
392 if (tvb_reported_length_remaining(tvb, 0) < 4) {
393 proto_tree_add_expert(tree, pinfo, &ei_mpls_pw_mcw_error_processing_message, tvb, 0, -1);
394 return tvb_captured_length(tvb);
397 if ( dissect_try_cw_first_nibble( tvb, pinfo, tree ))
398 return tvb_captured_length(tvb);
400 if (tree) {
401 proto_tree *mpls_pw_mcw_tree;
402 proto_item *ti;
404 ti = proto_tree_add_item(tree, proto_pw_mcw, tvb, 0, 4, ENC_NA);
405 mpls_pw_mcw_tree = proto_item_add_subtree(ti, ett_mpls_pw_mcw);
407 proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_flags,
408 tvb, 0, 2, ENC_BIG_ENDIAN);
409 /* bits 4 to 7 and FRG bits are displayed together */
410 proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_length,
411 tvb, 1, 1, ENC_BIG_ENDIAN);
412 proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_sequence_number,
413 tvb, 2, 2, ENC_BIG_ENDIAN);
415 next_tvb = tvb_new_subset_remaining(tvb, 4);
416 call_data_dissector(next_tvb, pinfo, tree);
417 return tvb_captured_length(tvb);
420 static int
421 dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
423 int offset = 0;
424 uint32_t label = MPLS_LABEL_INVALID;
425 uint8_t exp;
426 uint8_t bos;
427 uint8_t ttl;
428 tvbuff_t *next_tvb;
429 int found;
430 uint8_t first_nibble;
431 struct mplsinfo mplsinfo;
432 heur_dtbl_entry_t *hdtbl_entry;
433 dissector_handle_t payload_handle;
435 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS");
436 col_set_str(pinfo->cinfo, COL_INFO, "MPLS Label Switched Packet");
438 /* Ensure structure is initialized */
439 memset(&mplsinfo, 0, sizeof(struct mplsinfo));
441 /* Start Decoding Here. */
442 while (tvb_reported_length_remaining(tvb, offset) > 0) {
444 decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
447 * FF: export (last shim in stack) info to subdissectors and
448 * update pinfo
450 mplsinfo.label = label;
451 p_add_proto_data(pinfo->pool, pinfo, proto_mpls, 0, GUINT_TO_POINTER(label));
452 mplsinfo.exp = exp;
453 mplsinfo.bos = bos;
454 mplsinfo.ttl = ttl;
456 if (tree) {
457 proto_item *ti;
458 proto_tree *mpls_tree;
460 ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, ENC_NA);
461 mpls_tree = proto_item_add_subtree(ti, ett_mpls);
463 if (mpls_bos_flowlabel && bos) {
464 proto_item_append_text(ti, ", Label: %u (Flow Label)", label);
465 } else {
466 proto_item_append_text(ti, ", Label: %u", label);
468 if (label <= MPLS_LABEL_MAX_RESERVED){
469 proto_tree_add_item(mpls_tree, hf_mpls_label_special, tvb,
470 offset, 4, ENC_BIG_ENDIAN);
471 proto_item_append_text(ti, " (%s)",
472 val_to_str_const(label, special_labels, "Reserved - Unknown"));
473 } else {
474 proto_tree_add_item(mpls_tree, hf_mpls_label, tvb, offset, 4,
475 ENC_BIG_ENDIAN);
478 proto_tree_add_item(mpls_tree, hf_mpls_exp, tvb, offset, 4,
479 ENC_BIG_ENDIAN);
480 proto_item_append_text(ti, ", Exp: %u", exp);
482 proto_tree_add_item(mpls_tree, hf_mpls_bos , tvb, offset, 4,
483 ENC_BIG_ENDIAN);
484 proto_item_append_text(ti, ", S: %u", bos);
486 proto_tree_add_item(mpls_tree, hf_mpls_ttl, tvb, offset, 4,
487 ENC_BIG_ENDIAN);
488 proto_item_append_text(ti, ", TTL: %u", ttl);
491 offset += 4;
493 if ((label == MPLS_LABEL_GACH) && !bos) {
494 proto_tree_add_expert(tree, pinfo, &ei_mpls_invalid_label, tvb, 0, -1);
497 if ((label == MPLS_LABEL_GACH) && bos) {
498 (void) g_strlcpy(PW_ACH, "Generic Associated Channel Header",50);
499 next_tvb = tvb_new_subset_remaining(tvb, offset);
500 call_dissector(dissector_pw_ach, next_tvb, pinfo, tree );
501 return tvb_captured_length(tvb);
503 else
504 (void) g_strlcpy(PW_ACH, "PW Associated Channel Header",50);
506 if (bos)
507 break;
510 first_nibble = (tvb_get_uint8(tvb, offset) >> 4) & 0x0F;
511 p_add_proto_data(pinfo->pool, pinfo, proto_mpls, 1, GUINT_TO_POINTER(first_nibble));
513 next_tvb = tvb_new_subset_remaining(tvb, offset);
516 * Is there an explicit label-to-dissector binding?
517 * If so, use it.
519 found = dissector_try_uint_with_data(mpls_subdissector_table, label,
520 next_tvb, pinfo, tree, false, &mplsinfo);
521 if (found) {
522 /* Yes, there is. */
523 return tvb_captured_length(tvb);
527 * Do we try heuristic dissectors first? This is necessary for, e.g.,
528 * Ethernet without CW where the address begins with a 4 or 6 nibble.
530 if (mpls_try_heuristic_first) {
531 if (dissector_try_heuristic(mpls_heur_subdissector_list, next_tvb, pinfo,
532 tree, &hdtbl_entry, NULL)) {
533 return tvb_captured_length(tvb);
538 * Use the 1st nibble logic (see BCP 128 (RFC 4928), RFC 4385 and 5586).
539 * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
541 if (dissector_try_uint_with_data(mpls_pfn_subdissector_table, first_nibble,
542 next_tvb, pinfo, tree, false, &mplsinfo)) {
544 payload_handle = dissector_get_uint_handle(mpls_pfn_subdissector_table, first_nibble);
545 if (payload_handle == dissector_ip || payload_handle == dissector_ipv6) {
546 /* IPv4 and IPv6 dissectors may reduce the length of the tvb.
547 We need to do the same, so that any Ethernet trailer is detected.
549 set_actual_length(tvb, offset+tvb_reported_length(next_tvb));
551 return tvb_captured_length(tvb);
554 if (!mpls_try_heuristic_first) {
555 if (dissector_try_heuristic(mpls_heur_subdissector_list, next_tvb, pinfo,
556 tree, &hdtbl_entry, NULL)) {
557 return tvb_captured_length(tvb);
561 call_data_dissector(next_tvb, pinfo, tree);
562 return tvb_captured_length(tvb);
565 void
566 proto_register_mpls(void)
568 static hf_register_info mplsf_info[] = {
570 /* MPLS header fields */
571 {&hf_mpls_label,
572 {"MPLS Label", "mpls.label",
573 FT_UINT32, BASE_DEC_HEX, NULL, 0xFFFFF000,
574 NULL, HFILL }
577 {&hf_mpls_label_special,
578 {"MPLS Label", "mpls.label",
579 FT_UINT32, BASE_DEC_HEX, VALS(special_labels), 0xFFFFF000,
580 NULL, HFILL }
583 {&hf_mpls_exp,
584 {"MPLS Experimental Bits", "mpls.exp",
585 FT_UINT32, BASE_DEC, NULL, 0x00000E00,
586 NULL, HFILL }
589 {&hf_mpls_bos,
590 {"MPLS Bottom Of Label Stack", "mpls.bottom",
591 FT_UINT32, BASE_DEC, NULL, 0x00000100,
592 NULL, HFILL }
595 {&hf_mpls_ttl,
596 {"MPLS TTL", "mpls.ttl",
597 FT_UINT32, BASE_DEC, NULL, 0x000000FF,
598 NULL, HFILL }
601 /* PW Associated Channel Header fields */
602 {&hf_mpls_pw_ach_ver,
603 {"Channel Version", "pwach.ver",
604 FT_UINT8, BASE_DEC, NULL, 0x0F,
605 "PW Associated Channel Version", HFILL }
608 {&hf_mpls_pw_ach_res,
609 {"Reserved", "pwach.res",
610 FT_UINT8, BASE_HEX, NULL, 0x0,
611 NULL, HFILL }
614 {&hf_mpls_pw_ach_channel_type,
615 {"Channel Type", "pwach.channel_type",
616 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &mpls_pwac_types_ext, 0x0,
617 "PW Associated Channel Type", HFILL }
620 /* Generic/Preferred PW MPLS MCC Control Word fields */
621 {&hf_mpls_pw_ach_mcc_proto,
622 {"Protocol Id", "mcc.proto",
623 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &mpls_pwac_types_ext, 0x0,
624 "MCC Protocol", HFILL }
627 /* Generic/Preferred PW MPLS Control Word fields */
628 {&hf_mpls_pw_mcw_flags,
629 {"Flags", "pwmcw.flags",
630 FT_UINT16, BASE_HEX, NULL, 0x0FC0,
631 "Generic/Preferred PW MPLS Control Word Flags", HFILL }
634 {&hf_mpls_pw_mcw_length,
635 {"Length", "pwmcw.length",
636 FT_UINT8, BASE_DEC, NULL, 0x3F,
637 "Generic/Preferred PW MPLS Control Word Length", HFILL }
640 {&hf_mpls_pw_mcw_sequence_number,
641 {"Sequence Number", "pwmcw.sequence_number",
642 FT_UINT16, BASE_DEC, NULL, 0x0,
643 "Generic/Preferred PW MPLS Control Word Sequence Number", HFILL }
647 static int *ett[] = {
648 &ett_mpls,
649 &ett_mpls_pw_ach,
650 &ett_mpls_pw_ach_mcc,
651 &ett_mpls_pw_mcw,
654 static ei_register_info ei[] = {
655 { &ei_mpls_pw_ach_error_processing_message, { "pwach.error_processing_message", PI_MALFORMED, PI_ERROR, "Error processing Message", EXPFILL }},
656 { &ei_mpls_pw_ach_res, { "pwach.res.not_zero", PI_PROTOCOL, PI_WARN, "Error: this byte is reserved and must be 0", EXPFILL }},
657 { &ei_mpls_pw_mcw_error_processing_message, { "pwmcw.error_processing_message", PI_MALFORMED, PI_ERROR, "Error processing Message", EXPFILL }},
658 { &ei_mpls_invalid_label, { "mpls.invalid_label", PI_PROTOCOL, PI_WARN, "Invalid Label", EXPFILL }},
661 /* Decode As handling */
662 static build_valid_func mpls_da_build_value[1] = {mpls_value};
663 static decode_as_value_t mpls_da_values = {mpls_prompt, 1, mpls_da_build_value};
664 static decode_as_t mpls_da = {"mpls", "mpls.label", 1, 0, &mpls_da_values, NULL, NULL,
665 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
667 static build_valid_func mpls_pfn_da_build_value[1] = {mpls_pfn_value};
668 static decode_as_value_t mpls_pfn_da_values = {mpls_pfn_prompt, 1, mpls_pfn_da_build_value};
669 static decode_as_t mpls_pfn_da = {"mpls", "mpls.pfn", 1, 0, &mpls_pfn_da_values, NULL, NULL,
670 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
672 static build_valid_func pw_ach_da_build_value[1] = {pw_ach_value};
673 static decode_as_value_t pw_ach_da_values = {pw_ach_prompt, 1, pw_ach_da_build_value};
674 static decode_as_t pw_ach_da = {"pwach", "pwach.channel_type", 1, 0, &pw_ach_da_values, NULL, NULL,
675 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
677 expert_module_t* expert_mpls;
678 module_t * module_mpls;
680 proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header", "MPLS", "mpls");
681 proto_pw_ach = proto_register_protocol(PW_ACH, "PW Associated Channel", "pwach");
682 proto_pw_mcw = proto_register_protocol("PW MPLS Control Word (generic/preferred)", "Generic PW (with CW)", "pwmcw");
683 proto_pw_ach_mcc = proto_register_protocol("Management Communication Channel (MCC)", "PW Associated Management Communication Channel", "mcc");
685 proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
686 proto_register_subtree_array(ett, array_length(ett));
687 expert_mpls = expert_register_protocol(proto_mpls);
688 expert_register_field_array(expert_mpls, ei, array_length(ei));
690 mpls_handle = register_dissector("mpls", dissect_mpls, proto_mpls);
691 mpls_mcc_handle = register_dissector("mplsmcc", dissect_pw_ach_mcc, proto_pw_ach_mcc);
692 mpls_pwcw_handle = register_dissector("mplspwcw", dissect_pw_mcw, proto_pw_mcw);
693 dissector_pw_ach = register_dissector("mplspwach", dissect_pw_ach, proto_pw_ach );
695 /* FF: mpls subdissector table is indexed by label */
696 mpls_subdissector_table = register_dissector_table("mpls.label",
697 "MPLS label",
698 proto_mpls, FT_UINT32, BASE_DEC);
700 mpls_pfn_subdissector_table = register_dissector_table("mpls.pfn",
701 "MPLS post-stack first nibble",
702 proto_mpls, FT_UINT8, BASE_HEX);
704 mpls_heur_subdissector_list = register_heur_dissector_list_with_description("mpls", "MPLS payload", proto_mpls);
706 pw_ach_subdissector_table = register_dissector_table("pwach.channel_type", "PW Associated Channel Type", proto_pw_ach, FT_UINT16, BASE_HEX);
708 pw_ach_mcc_subdissector_table = register_dissector_table("mcc.proto", "PW Associated Management Communication Channel Protocol", proto_pw_ach_mcc, FT_UINT16, BASE_HEX);
710 module_mpls = prefs_register_protocol( proto_mpls, NULL );
712 prefs_register_obsolete_preference(module_mpls, "mplspref.payload");
714 prefs_register_bool_preference(module_mpls, "try_heuristic_first",
715 "Try heuristic sub-dissectors first",
716 "Try to decode a packet heuristically, e.g. as "
717 "Ethernet without control word, before trying "
718 "sub-dissectors based upon the first nibble.",
719 &mpls_try_heuristic_first);
721 /* RFC6391: Flow aware transport of pseudowire*/
722 prefs_register_bool_preference(module_mpls,
723 "flowlabel_in_mpls_header",
724 "Assume bottom of stack label as Flow label",
725 "Lowest label is used to segregate flows inside a pseudowire",
726 &mpls_bos_flowlabel);
728 register_decode_as(&mpls_da);
729 register_decode_as(&mpls_pfn_da);
730 register_decode_as(&pw_ach_da);
733 void
734 proto_reg_handoff_mpls(void)
736 dissector_add_uint("ethertype", ETHERTYPE_MPLS, mpls_handle);
737 dissector_add_uint("ethertype", ETHERTYPE_MPLS_MULTI, mpls_handle);
738 dissector_add_uint("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
739 dissector_add_uint("ppp.protocol", PPP_MPLS_MULTI, mpls_handle);
740 dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS, mpls_handle);
741 dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS_MULTI, mpls_handle);
742 dissector_add_uint("gre.proto", ETHERTYPE_MPLS, mpls_handle);
743 dissector_add_uint("gre.proto", ETHERTYPE_MPLS_MULTI, mpls_handle);
744 dissector_add_uint("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
745 dissector_add_uint("juniper.proto", JUNIPER_PROTO_MPLS, mpls_handle);
746 dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP_MPLS, mpls_handle);
747 dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP6_MPLS, mpls_handle);
748 dissector_add_uint("juniper.proto", JUNIPER_PROTO_CLNP_MPLS, mpls_handle);
749 dissector_add_for_decode_as("pwach.channel_type", mpls_handle);
750 dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_MPLS, mpls_handle);
751 dissector_add_for_decode_as("l2tp.pw_type", mpls_handle);
752 dissector_add_uint_with_preference("udp.port", UDP_PORT_MPLS_OVER_UDP, mpls_handle);
753 dissector_add_uint("vxlan.next_proto", VXLAN_MPLS, mpls_handle);
754 dissector_add_uint("nsh.next_proto", NSH_MPLS, mpls_handle);
756 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, mpls_pwcw_handle);
758 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_MCC, mpls_mcc_handle);
760 dissector_ipv6 = find_dissector_add_dependency("ipv6", proto_pw_mcw );
761 dissector_ip = find_dissector_add_dependency("ip", proto_pw_mcw );
762 dissector_pw_eth_heuristic = find_dissector_add_dependency("pw_eth_heuristic", proto_pw_mcw);
765 * Our previous default behavior has been to try the Eth CW heuristic
766 * on first nibble 0. Continue doing that. For other first nibbles
767 * registered to dissectors, "try heuristic first" can be enabled.
769 dissector_add_for_decode_as("mpls.pfn", mpls_pwcw_handle);
770 dissector_add_uint("mpls.pfn", 0, dissector_pw_eth_heuristic);
771 dissector_add_uint("mpls.pfn", 1, dissector_pw_ach);
772 dissector_add_uint("mpls.pfn", 4, dissector_ip);
773 dissector_add_uint("mpls.pfn", 6, dissector_ipv6);
777 * Editor modelines
779 * Local Variables:
780 * c-basic-offset: 4
781 * tab-width: 8
782 * indent-tabs-mode: nil
783 * End:
785 * ex: set shiftwidth=4 tabstop=8 expandtab:
786 * :indentSize=4:tabSize=8:noTabs=true: