Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-mpls.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-mpls.c
2
 * Routines for MPLS data packet disassembly
3
 * RFC 3032
4
 *
5
 * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
6
 *
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
13
 *
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
20
 *
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
28
 *
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
31
 *
32
 * Wireshark - Network traffic analyzer
33
 * By Gerald Combs <gerald@wireshark.org>
34
 * Copyright 1998 Gerald Combs
35
 *
36
 * SPDX-License-Identifier: GPL-2.0-or-later
37
 */
38
39
#include "config.h"
40
41
#include <epan/packet.h>
42
#include <epan/expert.h>
43
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>
50
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"
60
61
void proto_register_mpls(void);
62
void proto_reg_handoff_mpls(void);
63
64
static int proto_mpls;
65
static int proto_pw_ach;
66
static int proto_pw_ach_mcc;
67
static int proto_pw_mcw;
68
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";
74
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 }
84
};
85
86
static dissector_table_t   pw_ach_subdissector_table;
87
static dissector_table_t   pw_ach_mcc_subdissector_table;
88
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;
96
97
/*
98
 * RFC 8469 deprecated Ethernet without CW, so default this to false.
99
 * https://datatracker.ietf.org/doc/html/rfc8469
100
 */
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;
104
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;
110
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;
114
115
static int hf_mpls_pw_ach_mcc_proto;
116
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;
120
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;
125
126
#if 0 /*not used yet*/
127
/*
128
 * MPLS PW types
129
 * http://www.iana.org/assignments/pwe3-parameters
130
 */
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, "FC Port Mode"                                   },/*[RFC6307]*/
163
    { 0, NULL }
164
};
165
static value_string_ext mpls_pw_types_ext = VALUE_STRING_EXT_INIT(mpls_pw_types);
166
#endif
167
168
/*
169
 * MPLS PW Associated Channel Types
170
 * as per https://www.iana.org/assignments/pwe3-parameters
171
 * now known as MPLS Generalized Associated Channel (G-ACh) Types (including Pseudowire
172
 * Associated Channel Types) as per https://www.iana.org/assignments/g-ach-parameters
173
 * and RFC 5885 clause 3.2
174
 */
175
static const value_string mpls_pwac_types[] = {
176
    { 0x0000, "Reserved"},
177
    { 0x0001, "Management Communication Channel (MCC)"},
178
    { 0x0002, "Signaling Communication Channel (SCC)"},
179
    { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
180
    { 0x0008, "S-BFD Control, PW-ACH/L2SS encapsulation (without IP/UDP Headers)"},
181
    { 0x0009, "MPLS-TP Dual-Homing Coordination message"},
182
    { 0x000A, "MPLS Direct Loss Measurement (DLM)"},
183
    { 0x000B, "MPLS Inferred Loss Measurement (ILM)"},
184
    { 0x000C, "MPLS Delay Measurement (DM)"},
185
    { 0x000D, "MPLS Direct Loss and Delay Measurement (DLM+DM)"},
186
    { 0x000E, "MPLS Inferred Loss and Delay Measurement (ILM+DM)"},
187
    { 0x000F, "Residence Time Measurement"},
188
    { 0x0010, "Time Bucket Jitter Measurement"},
189
    { 0x0011, "Multi-packet Delay Measurement"},
190
    { 0x0012, "Average Delay Measurement"},
191
    { 0x0021, "IPv4 packet" },
192
    { 0x0022, "MPLS-TP CC message"},
193
    { 0x0023, "MPLS-TP CV message"},
194
    { 0x0024, "Protection State Coordination Protocol (PSC)"},
195
    { 0x0025, "On-Demand CV"},
196
    { 0x0026, "LI"},
197
    { 0x0027, "Pseudo-Wire OAM"},
198
    { 0x0028, "MAC Withdraw OAM Msg"},
199
    { 0x0029, "PW Status Refresh Reduction"},
200
    { 0x002A, "Ring Protection Switching (RPS) Protocol"},
201
    { 0x0057, "IPv6 packet" },
202
    { 0x0058, "Fault OAM"},
203
    { 0x0059, "G-ACh Advertisement Protocol"},
204
    { 0x7FF8, "Reserved for Experimental Use"},
205
    { 0x7FF9, "Reserved for Experimental Use"},
206
    { 0x7FFA, "Reserved for Experimental Use"},
207
    { 0x7FFB, "Reserved for Experimental Use"},
208
    { 0x7FFC, "Reserved for Experimental Use"},
209
    { 0x7FFD, "Reserved for Experimental Use"},
210
    { 0x7FFE, "Reserved for Experimental Use"},
211
    { 0x7FFF, "Reserved for Experimental Use"},
212
    { 0x8902, "MPLS-TP OAM"},
213
    { 0, NULL }
214
};
215
static value_string_ext mpls_pwac_types_ext = VALUE_STRING_EXT_INIT(mpls_pwac_types);
216
217
static dissector_table_t mpls_subdissector_table;
218
/*
219
 * Post-stack First Nibble
220
 * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
221
 */
222
static dissector_table_t mpls_pfn_subdissector_table;
223
static heur_dissector_list_t mpls_heur_subdissector_list;
224
225
static void mpls_prompt(packet_info *pinfo, char* result)
226
0
{
227
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Data after label %u as",
228
0
        GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 0)));
229
0
}
230
231
static void *mpls_value(packet_info *pinfo)
232
0
{
233
0
    return p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 0);
234
0
}
235
236
static void mpls_pfn_prompt(packet_info *pinfo, char* result)
237
0
{
238
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Data after post-stack first nibble %u as",
239
0
        GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 1)));
240
0
}
241
242
static void *mpls_pfn_value(packet_info *pinfo)
243
0
{
244
0
    return p_get_proto_data(pinfo->pool, pinfo, proto_mpls, 1);
245
0
}
246
247
static void pw_ach_prompt(packet_info *pinfo, char* result)
248
0
{
249
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Channel type 0x%x as",
250
0
        GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0)));
251
0
}
252
253
static void *pw_ach_value(packet_info *pinfo)
254
0
{
255
0
    return p_get_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0);
256
0
}
257
258
/*
259
 * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
260
 * decode it.
261
 * Return the label in "label", EXP bits in "exp",
262
 * bottom_of_stack in "bos", and TTL in "ttl"
263
 */
264
void
265
decode_mpls_label(tvbuff_t *tvb, int offset,
266
                       uint32_t *label, uint8_t *exp,
267
                       uint8_t  *bos, uint8_t *ttl)
268
2.90k
{
269
2.90k
    uint8_t octet0 = tvb_get_uint8(tvb, offset+0);
270
2.90k
    uint8_t octet1 = tvb_get_uint8(tvb, offset+1);
271
2.90k
    uint8_t octet2 = tvb_get_uint8(tvb, offset+2);
272
273
2.90k
    *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
274
2.90k
    *exp = (octet2 >> 1) & 0x7;
275
2.90k
    *bos = (octet2 & 0x1);
276
2.90k
    *ttl = tvb_get_uint8(tvb, offset+3);
277
2.90k
}
278
279
/*
280
 * PW Associated Channel Header Management Communication
281
 * Network (MCN) dissection as per RFC 5718.
282
 */
283
static int
284
dissect_pw_ach_mcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
285
1
{
286
1
    tvbuff_t   *next_tvb;
287
1
    proto_tree *mpls_pw_ach_mcc_tree;
288
1
    proto_item *ti;
289
1
    uint32_t    pid;
290
291
1
    ti = proto_tree_add_item(tree, proto_pw_ach_mcc, tvb, 0,2, ENC_NA);
292
1
    mpls_pw_ach_mcc_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach_mcc);
293
1
    proto_tree_add_item_ret_uint(mpls_pw_ach_mcc_tree, hf_mpls_pw_ach_mcc_proto,tvb, 0, 2, ENC_BIG_ENDIAN, &pid);
294
295
1
    next_tvb = tvb_new_subset_remaining(tvb, 2);
296
297
1
    if (!dissector_try_uint(pw_ach_mcc_subdissector_table, pid, next_tvb, pinfo, tree))
298
1
    {
299
1
        call_data_dissector(next_tvb, pinfo, tree);
300
1
    }
301
302
1
    return tvb_captured_length(tvb);
303
1
}
304
305
/*
306
 * FF: PW Associated Channel Header dissection as per RFC 4385.
307
 */
308
static int
309
dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
310
14
{
311
14
    tvbuff_t   *next_tvb;
312
14
    unsigned    channel_type;
313
314
14
    if (tvb_reported_length_remaining(tvb, 0) < 4) {
315
2
        proto_tree_add_expert(tree, pinfo, &ei_mpls_pw_ach_error_processing_message, tvb, 0, -1);
316
2
        return tvb_captured_length(tvb);
317
2
    }
318
319
12
    channel_type = tvb_get_ntohs(tvb, 2);
320
12
    p_add_proto_data(pinfo->pool, pinfo, proto_pw_ach, 0, GUINT_TO_POINTER(channel_type));
321
322
12
    proto_tree *mpls_pw_ach_tree;
323
12
    proto_item *ti;
324
12
    uint16_t    res;
325
326
12
    ti = proto_tree_add_item(tree, proto_pw_ach, tvb, 0, 4, ENC_NA);
327
12
    mpls_pw_ach_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach);
328
329
12
    proto_tree_add_item(mpls_pw_ach_tree, hf_mpls_pw_ach_ver,
330
12
                        tvb, 0, 1, ENC_BIG_ENDIAN);
331
332
12
    res = tvb_get_uint8(tvb, 1);
333
12
    ti = proto_tree_add_uint(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
334
12
                                    tvb, 1, 1, res);
335
12
    if (res != 0)
336
6
        expert_add_info(pinfo, ti, &ei_mpls_pw_ach_res);
337
338
12
    proto_tree_add_item(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
339
12
                        tvb, 2, 2, ENC_BIG_ENDIAN);
340
341
12
    next_tvb = tvb_new_subset_remaining(tvb, 4);
342
343
12
    if (!dissector_try_uint(pw_ach_subdissector_table, channel_type, next_tvb, pinfo, tree))
344
11
    {
345
11
        call_data_dissector(next_tvb, pinfo, tree);
346
11
    }
347
348
12
    if (channel_type == PW_ACH_TYPE_BFD_CV)
349
0
    {
350
        /* The BFD dissector has already been called, this is called in addition
351
           XXX - Perhaps a new dissector function that combines both is preferred.*/
352
0
        dissect_bfd_mep(next_tvb, tree, 0);
353
0
    }
354
12
    return tvb_captured_length(tvb);
355
14
}
356
357
bool
358
dissect_try_cw_first_nibble( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
359
529
{
360
529
    uint8_t nibble;
361
362
529
    nibble = (tvb_get_uint8(tvb, 0 ) >> 4) & 0x0F;
363
529
    switch ( nibble )
364
529
    {
365
0
        case 6:
366
            /*
367
             * XXX - this could be from an pseudo-wire without a control
368
             * word, with the packet's first nibble being 6.
369
             */
370
0
            call_dissector(dissector_ipv6, tvb, pinfo, tree);
371
0
            return true;
372
0
        case 4:
373
            /*
374
             * XXX - this could be from an pseudo-wire without a control
375
             * word, with the packet's first nibble being 4.
376
             */
377
0
            call_dissector(dissector_ip, tvb, pinfo, tree);
378
0
            return true;
379
0
        case 1:
380
            /*
381
             * XXX - this could be from an pseudo-wire without a control
382
             * word, with the packet's first nibble being 1.
383
             */
384
0
            call_dissector(dissector_pw_ach, tvb, pinfo, tree );
385
0
            return true;
386
529
        default:
387
529
            break;
388
529
    }
389
529
    return false;
390
529
}
391
392
/*
393
 * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
394
 */
395
static int
396
dissect_pw_mcw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
397
0
{
398
0
    tvbuff_t *next_tvb;
399
400
0
    if (tvb_reported_length_remaining(tvb, 0) < 4) {
401
0
        proto_tree_add_expert(tree, pinfo, &ei_mpls_pw_mcw_error_processing_message, tvb, 0, -1);
402
0
        return tvb_captured_length(tvb);
403
0
    }
404
405
0
    if ( dissect_try_cw_first_nibble( tvb, pinfo, tree ))
406
0
        return tvb_captured_length(tvb);
407
408
0
    if (tree) {
409
0
        proto_tree  *mpls_pw_mcw_tree;
410
0
        proto_item  *ti;
411
412
0
        ti = proto_tree_add_item(tree, proto_pw_mcw, tvb, 0, 4, ENC_NA);
413
0
        mpls_pw_mcw_tree = proto_item_add_subtree(ti, ett_mpls_pw_mcw);
414
415
0
        proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_flags,
416
0
                            tvb, 0, 2, ENC_BIG_ENDIAN);
417
        /* bits 4 to 7 and FRG bits are displayed together */
418
0
        proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_length,
419
0
                            tvb, 1, 1, ENC_BIG_ENDIAN);
420
0
        proto_tree_add_item(mpls_pw_mcw_tree, hf_mpls_pw_mcw_sequence_number,
421
0
                            tvb, 2, 2, ENC_BIG_ENDIAN);
422
0
    }
423
0
    next_tvb = tvb_new_subset_remaining(tvb, 4);
424
0
    call_data_dissector(next_tvb, pinfo, tree);
425
0
    return tvb_captured_length(tvb);
426
0
}
427
428
static int
429
dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
430
1.38k
{
431
1.38k
    int       offset = 0;
432
1.38k
    uint32_t  label  = MPLS_LABEL_INVALID;
433
1.38k
    uint8_t   exp;
434
1.38k
    uint8_t   bos;
435
1.38k
    uint8_t   ttl;
436
1.38k
    tvbuff_t *next_tvb;
437
1.38k
    int       found;
438
1.38k
    uint8_t   first_nibble;
439
1.38k
    struct mplsinfo mplsinfo;
440
1.38k
    heur_dtbl_entry_t *hdtbl_entry;
441
1.38k
    dissector_handle_t payload_handle;
442
443
1.38k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS");
444
1.38k
    col_set_str(pinfo->cinfo, COL_INFO, "MPLS Label Switched Packet");
445
446
    /* Ensure structure is initialized */
447
1.38k
    memset(&mplsinfo, 0, sizeof(struct mplsinfo));
448
449
    /* Start Decoding Here. */
450
2.92k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
451
452
2.90k
        decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
453
454
        /*
455
         * FF: export (last shim in stack) info to subdissectors and
456
         * update pinfo
457
         */
458
2.90k
        mplsinfo.label = label;
459
2.90k
        p_add_proto_data(pinfo->pool, pinfo, proto_mpls, 0, GUINT_TO_POINTER(label));
460
2.90k
        mplsinfo.exp   = exp;
461
2.90k
        mplsinfo.bos   = bos;
462
2.90k
        mplsinfo.ttl   = ttl;
463
464
2.90k
        if (tree) {
465
2.90k
            proto_item *ti;
466
2.90k
            proto_tree *mpls_tree;
467
468
2.90k
            ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, ENC_NA);
469
2.90k
            mpls_tree = proto_item_add_subtree(ti, ett_mpls);
470
471
2.90k
            if (mpls_bos_flowlabel && bos) {
472
0
                proto_item_append_text(ti, ", Label: %u (Flow Label)", label);
473
2.90k
            } else {
474
2.90k
                proto_item_append_text(ti, ", Label: %u", label);
475
2.90k
            }
476
2.90k
            if (label <= MPLS_LABEL_MAX_RESERVED){
477
778
                proto_tree_add_item(mpls_tree, hf_mpls_label_special, tvb,
478
778
                                    offset, 4, ENC_BIG_ENDIAN);
479
778
                proto_item_append_text(ti, " (%s)",
480
778
                                       val_to_str_const(label, special_labels, "Reserved - Unknown"));
481
2.12k
            } else {
482
2.12k
                proto_tree_add_item(mpls_tree, hf_mpls_label, tvb, offset, 4,
483
2.12k
                                    ENC_BIG_ENDIAN);
484
2.12k
            }
485
486
2.90k
            proto_tree_add_item(mpls_tree, hf_mpls_exp, tvb, offset, 4,
487
2.90k
                                ENC_BIG_ENDIAN);
488
2.90k
            proto_item_append_text(ti, ", Exp: %u", exp);
489
490
2.90k
            proto_tree_add_item(mpls_tree, hf_mpls_bos , tvb, offset, 4,
491
2.90k
                                ENC_BIG_ENDIAN);
492
2.90k
            proto_item_append_text(ti, ", S: %u", bos);
493
494
2.90k
            proto_tree_add_item(mpls_tree, hf_mpls_ttl, tvb, offset, 4,
495
2.90k
                                ENC_BIG_ENDIAN);
496
2.90k
            proto_item_append_text(ti, ", TTL: %u", ttl);
497
2.90k
        }
498
499
2.90k
        offset += 4;
500
501
2.90k
        if ((label == MPLS_LABEL_GACH) && !bos) {
502
1
            proto_tree_add_expert(tree, pinfo, &ei_mpls_invalid_label, tvb, 0, -1);
503
1
        }
504
505
2.90k
        if ((label == MPLS_LABEL_GACH) && bos) {
506
4
            (void) g_strlcpy(PW_ACH, "Generic Associated Channel Header",50);
507
4
            next_tvb = tvb_new_subset_remaining(tvb, offset);
508
4
            call_dissector(dissector_pw_ach, next_tvb, pinfo, tree );
509
4
            return tvb_captured_length(tvb);
510
4
        }
511
2.90k
        else
512
2.90k
            (void) g_strlcpy(PW_ACH, "PW Associated Channel Header",50);
513
514
2.90k
        if (bos)
515
1.36k
            break;
516
2.90k
    }
517
518
1.38k
    first_nibble = (tvb_get_uint8(tvb, offset) >> 4) & 0x0F;
519
1.38k
    p_add_proto_data(pinfo->pool, pinfo, proto_mpls, 1, GUINT_TO_POINTER(first_nibble));
520
521
1.38k
    next_tvb = tvb_new_subset_remaining(tvb, offset);
522
523
    /*
524
     * Is there an explicit label-to-dissector binding?
525
     * If so, use it.
526
     */
527
1.38k
    found = dissector_try_uint_with_data(mpls_subdissector_table, label,
528
1.38k
                               next_tvb, pinfo, tree, false, &mplsinfo);
529
1.38k
    if (found) {
530
        /* Yes, there is. */
531
5
        return tvb_captured_length(tvb);
532
5
    }
533
534
    /*
535
     * Do we try heuristic dissectors first? This is necessary for, e.g.,
536
     * Ethernet without CW where the address begins with a 4 or 6 nibble.
537
     */
538
1.37k
    if (mpls_try_heuristic_first) {
539
0
        if (dissector_try_heuristic(mpls_heur_subdissector_list, next_tvb, pinfo,
540
0
                                    tree, &hdtbl_entry, NULL)) {
541
0
            return tvb_captured_length(tvb);
542
0
        }
543
0
    }
544
545
    /*
546
     * Use the 1st nibble logic (see BCP 128 (RFC 4928), RFC 4385 and 5586).
547
     * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
548
     */
549
1.37k
    if (dissector_try_uint_with_data(mpls_pfn_subdissector_table, first_nibble,
550
1.37k
        next_tvb, pinfo, tree, false, &mplsinfo)) {
551
552
1.17k
        payload_handle = dissector_get_uint_handle(mpls_pfn_subdissector_table, first_nibble);
553
1.17k
        if (payload_handle == dissector_ip || payload_handle == dissector_ipv6) {
554
            /* IPv4 and IPv6 dissectors may reduce the length of the tvb.
555
               We need to do the same, so that any Ethernet trailer is detected.
556
             */
557
532
            set_actual_length(tvb, offset+tvb_reported_length(next_tvb));
558
532
        }
559
1.17k
        return tvb_captured_length(tvb);
560
1.17k
    }
561
562
202
    if (!mpls_try_heuristic_first) {
563
149
        if (dissector_try_heuristic(mpls_heur_subdissector_list, next_tvb, pinfo,
564
149
                                    tree, &hdtbl_entry, NULL)) {
565
16
            return tvb_captured_length(tvb);
566
16
        }
567
149
    }
568
569
186
    call_data_dissector(next_tvb, pinfo, tree);
570
186
    return tvb_captured_length(tvb);
571
202
}
572
573
void
574
proto_register_mpls(void)
575
14
{
576
14
    static hf_register_info mplsf_info[] = {
577
578
        /* MPLS header fields */
579
14
        {&hf_mpls_label,
580
14
         {"MPLS Label", "mpls.label",
581
14
          FT_UINT32, BASE_DEC_HEX, NULL, 0xFFFFF000,
582
14
          NULL, HFILL }
583
14
        },
584
585
14
        {&hf_mpls_label_special,
586
14
         {"MPLS Label", "mpls.label",
587
14
          FT_UINT32, BASE_DEC_HEX, VALS(special_labels), 0xFFFFF000,
588
14
          NULL, HFILL }
589
14
        },
590
591
14
        {&hf_mpls_exp,
592
14
         {"MPLS Experimental Bits", "mpls.exp",
593
14
          FT_UINT32, BASE_DEC, NULL, 0x00000E00,
594
14
          NULL, HFILL }
595
14
        },
596
597
14
        {&hf_mpls_bos,
598
14
         {"MPLS Bottom Of Label Stack", "mpls.bottom",
599
14
          FT_UINT32, BASE_DEC, NULL, 0x00000100,
600
14
          NULL, HFILL }
601
14
        },
602
603
14
        {&hf_mpls_ttl,
604
14
         {"MPLS TTL", "mpls.ttl",
605
14
          FT_UINT32, BASE_DEC, NULL, 0x000000FF,
606
14
          NULL, HFILL }
607
14
        },
608
609
        /* PW Associated Channel Header fields */
610
14
        {&hf_mpls_pw_ach_ver,
611
14
         {"Channel Version", "pwach.ver",
612
14
          FT_UINT8, BASE_DEC, NULL, 0x0F,
613
14
          "PW Associated Channel Version", HFILL }
614
14
        },
615
616
14
        {&hf_mpls_pw_ach_res,
617
14
         {"Reserved", "pwach.res",
618
14
          FT_UINT8, BASE_HEX, NULL, 0x0,
619
14
          NULL, HFILL }
620
14
        },
621
622
14
        {&hf_mpls_pw_ach_channel_type,
623
14
         {"Channel Type", "pwach.channel_type",
624
14
          FT_UINT16, BASE_HEX|BASE_EXT_STRING, &mpls_pwac_types_ext, 0x0,
625
14
          "PW Associated Channel Type", HFILL }
626
14
        },
627
628
        /* Generic/Preferred PW MPLS MCC Control Word fields */
629
14
        {&hf_mpls_pw_ach_mcc_proto,
630
14
         {"Protocol Id", "mcc.proto",
631
14
          FT_UINT16, BASE_HEX|BASE_EXT_STRING, &mpls_pwac_types_ext, 0x0,
632
14
          "MCC Protocol", HFILL }
633
14
        },
634
635
        /* Generic/Preferred PW MPLS Control Word fields */
636
14
        {&hf_mpls_pw_mcw_flags,
637
14
         {"Flags", "pwmcw.flags",
638
14
          FT_UINT16, BASE_HEX, NULL, 0x0FC0,
639
14
          "Generic/Preferred PW MPLS Control Word Flags", HFILL }
640
14
        },
641
642
14
        {&hf_mpls_pw_mcw_length,
643
14
         {"Length", "pwmcw.length",
644
14
          FT_UINT8, BASE_DEC, NULL, 0x3F,
645
14
          "Generic/Preferred PW MPLS Control Word Length", HFILL }
646
14
        },
647
648
14
        {&hf_mpls_pw_mcw_sequence_number,
649
14
         {"Sequence Number", "pwmcw.sequence_number",
650
14
          FT_UINT16, BASE_DEC, NULL, 0x0,
651
14
          "Generic/Preferred PW MPLS Control Word Sequence Number", HFILL }
652
14
        },
653
14
    };
654
655
14
    static int *ett[] = {
656
14
        &ett_mpls,
657
14
        &ett_mpls_pw_ach,
658
14
        &ett_mpls_pw_ach_mcc,
659
14
        &ett_mpls_pw_mcw,
660
14
    };
661
662
14
    static ei_register_info ei[] = {
663
14
        { &ei_mpls_pw_ach_error_processing_message, { "pwach.error_processing_message", PI_MALFORMED, PI_ERROR, "Error processing Message", EXPFILL }},
664
14
        { &ei_mpls_pw_ach_res, { "pwach.res.not_zero", PI_PROTOCOL, PI_WARN, "Error: this byte is reserved and must be 0", EXPFILL }},
665
14
        { &ei_mpls_pw_mcw_error_processing_message, { "pwmcw.error_processing_message", PI_MALFORMED, PI_ERROR, "Error processing Message", EXPFILL }},
666
14
        { &ei_mpls_invalid_label, { "mpls.invalid_label", PI_PROTOCOL, PI_WARN, "Invalid Label", EXPFILL }},
667
14
    };
668
669
    /* Decode As handling */
670
14
    static build_valid_func mpls_da_build_value[1] = {mpls_value};
671
14
    static decode_as_value_t mpls_da_values = {mpls_prompt, 1, mpls_da_build_value};
672
14
    static decode_as_t mpls_da = {"mpls", "mpls.label", 1, 0, &mpls_da_values, NULL, NULL,
673
14
                                  decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
674
675
14
    static build_valid_func mpls_pfn_da_build_value[1] = {mpls_pfn_value};
676
14
    static decode_as_value_t mpls_pfn_da_values = {mpls_pfn_prompt, 1, mpls_pfn_da_build_value};
677
14
    static decode_as_t mpls_pfn_da = {"mpls", "mpls.pfn", 1, 0, &mpls_pfn_da_values, NULL, NULL,
678
14
                                  decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
679
680
14
    static build_valid_func pw_ach_da_build_value[1] = {pw_ach_value};
681
14
    static decode_as_value_t pw_ach_da_values = {pw_ach_prompt, 1, pw_ach_da_build_value};
682
14
    static decode_as_t pw_ach_da = {"pwach", "pwach.channel_type", 1, 0, &pw_ach_da_values, NULL, NULL,
683
14
                                  decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
684
685
14
    expert_module_t* expert_mpls;
686
14
    module_t * module_mpls;
687
688
14
    proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header", "MPLS", "mpls");
689
14
    proto_pw_ach = proto_register_protocol(PW_ACH, "PW Associated Channel", "pwach");
690
14
    proto_pw_mcw = proto_register_protocol("PW MPLS Control Word (generic/preferred)", "Generic PW (with CW)", "pwmcw");
691
14
    proto_pw_ach_mcc = proto_register_protocol("Management Communication Channel (MCC)", "PW Associated Management Communication Channel", "mcc");
692
693
14
    proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
694
14
    proto_register_subtree_array(ett, array_length(ett));
695
14
    expert_mpls = expert_register_protocol(proto_mpls);
696
14
    expert_register_field_array(expert_mpls, ei, array_length(ei));
697
698
14
    mpls_handle = register_dissector("mpls", dissect_mpls, proto_mpls);
699
14
    mpls_mcc_handle = register_dissector("mplsmcc", dissect_pw_ach_mcc, proto_pw_ach_mcc);
700
14
    mpls_pwcw_handle = register_dissector("mplspwcw", dissect_pw_mcw, proto_pw_mcw);
701
14
    dissector_pw_ach = register_dissector("mplspwach", dissect_pw_ach, proto_pw_ach );
702
703
    /* FF: mpls subdissector table is indexed by label */
704
14
    mpls_subdissector_table = register_dissector_table("mpls.label",
705
14
                                                       "MPLS label",
706
14
                                                       proto_mpls, FT_UINT32, BASE_DEC);
707
708
14
    mpls_pfn_subdissector_table = register_dissector_table("mpls.pfn",
709
14
                                                           "MPLS post-stack first nibble",
710
14
                                                           proto_mpls, FT_UINT8, BASE_HEX);
711
712
14
    mpls_heur_subdissector_list = register_heur_dissector_list_with_description("mpls", "MPLS payload", proto_mpls);
713
714
14
    pw_ach_subdissector_table  = register_dissector_table("pwach.channel_type", "PW Associated Channel Type", proto_pw_ach, FT_UINT16, BASE_HEX);
715
716
14
    pw_ach_mcc_subdissector_table  = register_dissector_table("mcc.proto", "PW Associated Management Communication Channel Protocol", proto_pw_ach_mcc, FT_UINT16, BASE_HEX);
717
718
14
    module_mpls = prefs_register_protocol( proto_mpls, NULL );
719
720
14
    prefs_register_obsolete_preference(module_mpls, "mplspref.payload");
721
722
14
    prefs_register_bool_preference(module_mpls, "try_heuristic_first",
723
14
                                "Try heuristic sub-dissectors first",
724
14
                                "Try to decode a packet heuristically, e.g. as "
725
14
                                "Ethernet without control word, before trying "
726
14
                                "sub-dissectors based upon the first nibble.",
727
14
                                &mpls_try_heuristic_first);
728
729
    /* RFC6391: Flow aware transport of pseudowire*/
730
14
    prefs_register_bool_preference(module_mpls,
731
14
                                    "flowlabel_in_mpls_header",
732
14
                                    "Assume bottom of stack label as Flow label",
733
14
                                    "Lowest label is used to segregate flows inside a pseudowire",
734
14
                                    &mpls_bos_flowlabel);
735
736
14
    register_decode_as(&mpls_da);
737
14
    register_decode_as(&mpls_pfn_da);
738
14
    register_decode_as(&pw_ach_da);
739
14
}
740
741
void
742
proto_reg_handoff_mpls(void)
743
14
{
744
14
    dissector_add_uint("ethertype", ETHERTYPE_MPLS, mpls_handle);
745
14
    dissector_add_uint("ethertype", ETHERTYPE_MPLS_MULTI, mpls_handle);
746
14
    dissector_add_uint("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
747
14
    dissector_add_uint("ppp.protocol", PPP_MPLS_MULTI, mpls_handle);
748
14
    dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS, mpls_handle);
749
14
    dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS_MULTI, mpls_handle);
750
14
    dissector_add_uint("gre.proto", ETHERTYPE_MPLS, mpls_handle);
751
14
    dissector_add_uint("gre.proto", ETHERTYPE_MPLS_MULTI, mpls_handle);
752
14
    dissector_add_uint("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
753
14
    dissector_add_uint("juniper.proto", JUNIPER_PROTO_MPLS, mpls_handle);
754
14
    dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP_MPLS, mpls_handle);
755
14
    dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP6_MPLS, mpls_handle);
756
14
    dissector_add_uint("juniper.proto", JUNIPER_PROTO_CLNP_MPLS, mpls_handle);
757
14
    dissector_add_for_decode_as("pwach.channel_type", mpls_handle);
758
14
    dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_MPLS, mpls_handle);
759
14
    dissector_add_for_decode_as("l2tp.pw_type", mpls_handle);
760
14
    dissector_add_uint_with_preference("udp.port", UDP_PORT_MPLS_OVER_UDP, mpls_handle);
761
14
    dissector_add_uint("vxlan.next_proto", VXLAN_MPLS, mpls_handle);
762
14
    dissector_add_uint("nsh.next_proto", NSH_MPLS, mpls_handle);
763
764
14
    dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, mpls_pwcw_handle);
765
766
14
    dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_MCC, mpls_mcc_handle);
767
768
14
    dissector_ipv6                  = find_dissector_add_dependency("ipv6", proto_pw_mcw );
769
14
    dissector_ip                    = find_dissector_add_dependency("ip", proto_pw_mcw );
770
14
    dissector_pw_eth_heuristic      = find_dissector_add_dependency("pw_eth_heuristic", proto_pw_mcw);
771
772
    /*
773
     * Our previous default behavior has been to try the Eth CW heuristic
774
     * on first nibble 0. Continue doing that. For other first nibbles
775
     * registered to dissectors, "try heuristic first" can be enabled.
776
     */
777
14
    dissector_add_for_decode_as("mpls.pfn", mpls_pwcw_handle);
778
14
    dissector_add_uint("mpls.pfn", 0, dissector_pw_eth_heuristic);
779
14
    dissector_add_uint("mpls.pfn", 1, dissector_pw_ach);
780
14
    dissector_add_uint("mpls.pfn", 4, dissector_ip);
781
14
    dissector_add_uint("mpls.pfn", 6, dissector_ipv6);
782
14
}
783
784
/*
785
 * Editor modelines
786
 *
787
 * Local Variables:
788
 * c-basic-offset: 4
789
 * tab-width: 8
790
 * indent-tabs-mode: nil
791
 * End:
792
 *
793
 * ex: set shiftwidth=4 tabstop=8 expandtab:
794
 * :indentSize=4:tabSize=8:noTabs=true:
795
 */