#include <string.h> and/or #include <stdio.h> not needed.
[obnox/wireshark/wip.git] / epan / dissectors / packet-mpls.c
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  * $Id$
15  *
16  * Wireshark - Network traffic analyzer
17  * By Gerald Combs <gerald@wireshark.org>
18  * Copyright 1998 Gerald Combs
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  */
34
35 /*
36  * NOTES
37  *
38  * This module defines routines to handle Ethernet-encapsulated MPLS IP packets.
39  * It should implement all the functionality in <draft-ietf-mpls-label-encaps-07.txt>
40  * Multicast MPLS support is not tested yet
41  */
42
43 /* FF NOTES
44  *
45  * The OAM patch should dissect OAM pdus as described in ITU-T Y.1711
46  */
47
48 #ifdef HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <glib.h>
53 #include <epan/packet.h>
54 #include <epan/ppptypes.h>
55 #include <epan/etypes.h>
56 #include <epan/prefs.h>
57 #include <epan/ipproto.h>
58 #include <epan/addr_resolv.h>
59 #include "packet-ppp.h"
60 #include "packet-mpls.h"
61 #include "packet-pw-common.h"
62
63 static gint proto_mpls = -1;
64 static gint proto_pw_ach = -1;
65 static gint proto_pw_mcw = -1;
66
67 static gint ett_mpls = -1;
68 static gint ett_mpls_pw_ach = -1;
69 static gint ett_mpls_pw_mcw = -1;
70 static gint ett_mpls_oam = -1;
71
72 void proto_reg_handoff_mpls(void);
73
74 const value_string special_labels[] = {
75     {LABEL_IP4_EXPLICIT_NULL,   "IPv4 Explicit-Null"},
76     {LABEL_ROUTER_ALERT,        "Router Alert"},
77     {LABEL_IP6_EXPLICIT_NULL,   "IPv6 Explicit-Null"},
78     {LABEL_IMPLICIT_NULL,       "Implicit-Null"},
79     {LABEL_OAM_ALERT,           "OAM Alert"},
80     {0, NULL }
81 };
82
83 /* MPLS filter values */
84 enum mpls_filter_keys {
85     /* MPLS encap properties */
86     MPLSF_LABEL,
87     MPLSF_EXP,
88     MPLSF_BOTTOM_OF_STACK,
89     MPLSF_TTL,
90     MPLSF_MAX
91 };
92
93 static dissector_handle_t dissector_data;
94 static dissector_handle_t dissector_ipv6;
95 static dissector_handle_t dissector_ip;
96 static dissector_handle_t dissector_bfd;
97 static dissector_handle_t dissector_pw_eth_heuristic;
98 static dissector_handle_t dissector_pw_fr;
99 static dissector_handle_t dissector_pw_hdlc_nocw_fr;
100 static dissector_handle_t dissector_pw_hdlc_nocw_hdlc_ppp;
101 static dissector_handle_t dissector_pw_eth_cw;
102 static dissector_handle_t dissector_pw_eth_nocw;
103 static dissector_handle_t dissector_pw_satop;
104 static dissector_handle_t dissector_itdm;
105 static dissector_handle_t dissector_mpls_pw_atm_n1_cw;
106 static dissector_handle_t dissector_mpls_pw_atm_n1_nocw;
107 static dissector_handle_t dissector_mpls_pw_atm_11_aal5pdu;
108 static dissector_handle_t dissector_mpls_pw_atm_aal5_sdu;
109 static dissector_handle_t dissector_pw_cesopsn;
110
111 enum mpls_default_dissector_t {
112     MDD_PW_ETH_HEUR = 0
113     ,MDD_PW_SATOP
114     ,MDD_PW_CESOPSN
115     ,MDD_MPLS_PW_FR_DLCI
116     ,MDD_MPLS_PW_HDLC_NOCW_FRPORT
117     ,MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP
118     ,MDD_MPLS_PW_ETH_CW
119     ,MDD_MPLS_PW_ETH_NOCW
120     ,MDD_MPLS_PW_GENERIC
121     ,MDD_ITDM
122     ,MDD_MPLS_PW_ATM_N1_CW
123     ,MDD_MPLS_PW_ATM_N1_NOCW
124     ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
125     ,MDD_MPLS_PW_ATM_AAL5_SDU
126 };
127
128 /* TODO the content of mpls_default_payload menu
129  * should be automatically built like mpls "decode as..." menu;
130  * this way, mpls_default_payload will be automatically filled up when
131  * new mpls-specific dissector added.
132  */
133 static enum_val_t mpls_default_payload_defs[] = {
134     {
135         "pw satop"
136         ,pwc_longname_pw_satop
137         ,MDD_PW_SATOP
138     },
139     {
140         "pw cesopsn"
141         ,pwc_longname_pw_cesopsn
142         ,MDD_PW_CESOPSN
143     },
144     {
145         "mpls pw ethernet heuristic"
146         ,"Ethernet MPLS PW (CW is heuristically detected)"
147         ,MDD_PW_ETH_HEUR
148     },
149     {
150         "mpls pw fr dlci"
151         ,"Frame relay DLCI MPLS PW"
152         ,MDD_MPLS_PW_FR_DLCI
153     },
154     {
155         "mpls pw hdlc no_cw fr_port"
156         ,"HDLC MPLS PW (no CW), FR Port mode"
157         ,MDD_MPLS_PW_HDLC_NOCW_FRPORT
158     },
159     {
160         "mpls pw hdlc no_cw hdlc payload_ppp"
161         ,"HDLC MPLS PW (no CW), HDLC mode, PPP payload"
162         ,MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP
163     },
164     {
165         "mpls pw ethernet cw"
166         ,"Ethernet MPLS PW (with CW)"
167         ,MDD_MPLS_PW_ETH_CW
168     },
169     {
170         "mpls pw ethernet no_cw"
171         ,"Ethernet MPLS PW (no CW, early implementations)"
172         ,MDD_MPLS_PW_ETH_NOCW
173     },
174     {
175         "mpls pw generic cw"
176         ,"Generic MPLS PW (with Generic/Preferred MPLS CW)"
177         ,MDD_MPLS_PW_GENERIC
178     },
179     {
180         "itdm"
181         ,"Internal TDM"
182         ,MDD_ITDM
183     },
184     {
185         "mpls pw atm n_to_one cw"
186         ,pwc_longname_pw_atm_n1_cw
187         ,MDD_MPLS_PW_ATM_N1_CW
188     },
189     {
190         "mpls pw atm n_to_one no_cw"
191         ,pwc_longname_pw_atm_n1_nocw
192         ,MDD_MPLS_PW_ATM_N1_NOCW
193     },
194     {
195         "mpls pw atm one_to_one or aal5_pdu"
196         ,pwc_longname_pw_atm_11_or_aal5_pdu
197         ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
198     },
199     {
200         "mpls pw atm aal5_sdu"
201         ,pwc_longname_pw_atm_aal5_sdu
202         ,MDD_MPLS_PW_ATM_AAL5_SDU
203     },
204     {
205         NULL
206         ,NULL
207         ,-1
208     }
209 };
210
211 static int mpls_filter[MPLSF_MAX];
212
213 static gint mpls_default_payload = 0;
214 static gboolean mpls_pref_pwac_all_as_bfd_xipv4 = FALSE;
215 static gboolean mpls_pref_pwac_0x0_as_bfd = FALSE;
216 static gboolean mpls_pref_pwac_try_ppp = TRUE;
217
218 static int hf_mpls_1st_nibble = -1;
219
220 static int hf_mpls_pw_ach_ver = -1;
221 static int hf_mpls_pw_ach_res = -1;
222 static int hf_mpls_pw_ach_channel_type = -1;
223
224 static int hf_mpls_pw_mcw_flags = -1;
225 static int hf_mpls_pw_mcw_length = -1;
226 static int hf_mpls_pw_mcw_sequence_number = -1;
227
228 static int hf_mpls_oam_function_type = -1;
229 static int hf_mpls_oam_ttsi = -1;
230 static int hf_mpls_oam_frequency = -1;
231 static int hf_mpls_oam_defect_type = -1;
232 static int hf_mpls_oam_defect_location = -1;
233 static int hf_mpls_oam_bip16 = -1;
234
235 static const value_string oam_function_type_vals[] = {
236     {0x00,      "Reserved"},
237     {0x01,      "CV (Connectivity Verification)"},
238     {0x02,      "FDI (Forward Defect Indicator)"},
239     {0x03,      "BDI (Backward Defect Indicator)"},
240     {0x04,      "Reserved for Performance packets"},
241     {0x05,      "Reserved for LB-Req (Loopback Request)"},
242     {0x06,      "Reserved for LB-Rsp (Loopback Response)"},
243     {0x07,      "FDD (Fast Failure Detection)"},
244     {0, NULL }
245 };
246
247 static const value_string oam_frequency_vals[] = {
248     {0x00,      "Reserved"},
249     {0x01,      "10 ms"},
250     {0x02,      "20 ms"},
251     {0x03,      "50 ms (default value)"},
252     {0x04,      "100 ms"},
253     {0x05,      "200 ms"},
254     {0x06,      "500 ms"},
255     /* 7-255 Reserved */
256     {0, NULL }
257 };
258
259 static const value_string oam_defect_type_vals[] = {
260     {0x0000,    "Reserved"},
261     {0x0101,    "dServer"},
262     {0x0102,    "dPeerME"},
263     {0x0201,    "dLOCV"},
264     {0x0202,    "dTTSI_Mismatch"},
265     {0x0203,    "dTTSI_Mismerge"},
266     {0x0204,    "dExcess"},
267     {0x02FF,    "dUnknown"},
268     {0xFFFF,    "Reserved"},
269     {0, NULL }
270 };
271
272 #if 0 /*not used yet*/
273 /*
274  * MPLS PW types
275  * http://www.iana.org/assignments/pwe3-parameters
276  */
277 static const value_string mpls_pw_types[] = {
278         { 0x0001, "Frame Relay DLCI ( Martini Mode )"              },
279         { 0x0002, "ATM AAL5 SDU VCC transport"                     },
280         { 0x0003, "ATM transparent cell transport"                 },
281         { 0x0004, "Ethernet Tagged Mode"                           },
282         { 0x0005, "Ethernet"                                       },
283         { 0x0006, "HDLC"                                           },
284         { 0x0007, "PPP"                                            },
285         { 0x0008, "SONET/SDH Circuit Emulation Service Over MPLS"  },
286         { 0x0009, "ATM n-to-one VCC cell transport"                },
287         { 0x000A, "ATM n-to-one VPC cell transport"                },
288         { 0x000B, "IP Layer2 Transport"                            },
289         { 0x000C, "ATM one-to-one VCC Cell Mode"                   },
290         { 0x000D, "ATM one-to-one VPC Cell Mode"                   },
291         { 0x000E, "ATM AAL5 PDU VCC transport"                     },
292         { 0x000F, "Frame-Relay Port mode"                          },
293         { 0x0010, "SONET/SDH Circuit Emulation over Packet"        },
294         { 0x0011, "Structure-agnostic E1 over Packet"              },
295         { 0x0012, "Structure-agnostic T1 (DS1) over Packet"        },
296         { 0x0013, "Structure-agnostic E3 over Packet"              },
297         { 0x0014, "Structure-agnostic T3 (DS3) over Packet"        },
298         { 0x0015, "CESoPSN basic mode"                             },
299         { 0x0016, "TDMoIP AAL1 Mode"                               },
300         { 0x0017, "CESoPSN TDM with CAS"                           },
301         { 0x0018, "TDMoIP AAL2 Mode"                               },
302         { 0x0019, "Frame Relay DLCI"                               },
303         { 0x001A, "ROHC Transport Header-compressed Packets"       },/*[RFC4995][RFC4901]*/
304         { 0x001B, "ECRTP Transport Header-compressed Packets"      },/*[RFC3545][RFC4901]*/
305         { 0x001C, "IPHC Transport Header-compressed Packets"       },/*[RFC2507][RFC4901]*/
306         { 0x001D, "cRTP Transport Header-compressed Packets"       },/*[RFC2508][RFC4901]*/
307         { 0x001E, "ATM VP Virtual Trunk"                           },/*[MFA9]*/
308         { 0x001F, "Reserved"                                       },/*[Bryant]  2008-04-17*/
309         { 0, NULL }
310 };
311 #endif
312
313 /*
314  * MPLS PW Associated Channel Types
315  * as per http://www.iana.org/assignments/pwe3-parameters
316  * and http://tools.ietf.org/html/draft-ietf-pwe3-vccv-bfd-05 clause 3.2
317  */
318 static const value_string mpls_pwac_types[] = {
319         { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
320         { 0x0021, "IPv4 packet" },
321         { 0x0057, "IPv6 packet" },
322         { 0, NULL }
323 };
324
325
326 static dissector_table_t ppp_subdissector_table;
327 static dissector_table_t mpls_subdissector_table;
328
329 /*
330  * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
331  * decode it.
332  * Return the label in "label", EXP bits in "exp",
333  * bottom_of_stack in "bos", and TTL in "ttl"
334  */
335 void decode_mpls_label(tvbuff_t *tvb, int offset,
336                        guint32 *label, guint8 *exp,
337                        guint8 *bos, guint8 *ttl)
338 {
339     guint8 octet0 = tvb_get_guint8(tvb, offset+0);
340     guint8 octet1 = tvb_get_guint8(tvb, offset+1);
341     guint8 octet2 = tvb_get_guint8(tvb, offset+2);
342
343     *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
344     *exp = (octet2 >> 1) & 0x7;
345     *bos = (octet2 & 0x1);
346     *ttl = tvb_get_guint8(tvb, offset+3);
347 }
348
349 /*
350  * FF: PW Associated Channel Header dissection as per RFC 4385.
351  */
352 static void
353 dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
354 {
355     proto_tree  *mpls_pw_ach_tree = NULL;
356     proto_item  *ti = NULL;
357     tvbuff_t    *next_tvb = NULL;
358     guint8      ver = 0;
359     guint16     res = 0;
360     guint16     channel_type = 0;
361
362     if (tvb_reported_length_remaining(tvb, 0) < 4) {
363         if (tree)
364             proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
365         return;
366     }
367     ver = (tvb_get_guint8(tvb, 0) & 0x0F);
368     res = tvb_get_guint8(tvb, 1);
369     channel_type = tvb_get_ntohs(tvb, 2);
370     if (tree) {
371         ti = proto_tree_add_item(tree, proto_pw_ach, tvb, 0, 4, FALSE);
372         mpls_pw_ach_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach);
373         if (mpls_pw_ach_tree == NULL)
374             return;
375         proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_ver,
376                                    tvb, 0, 1, ver, "Version: %d", ver);
377         ti = proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
378                                         tvb, 1, 1, res, "Reserved: 0x%02x", res);
379         if (res != 0)
380             proto_tree_add_text(mpls_pw_ach_tree, tvb, 1, 1,
381                 "Error: this byte is reserved and must be 0");
382         else
383             PROTO_ITEM_SET_HIDDEN(ti);
384         proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
385                                    tvb, 2, 2, channel_type,
386                                    "Channel Type: %s (0x%04x)",
387                                    val_to_str(channel_type, mpls_pwac_types, "Unknown"),
388                                               channel_type);
389     }
390     next_tvb = tvb_new_subset_remaining(tvb, 4);
391
392     if (0x21 == channel_type /*IPv4, RFC4385 clause 6.*/)
393     {
394         call_dissector(dissector_ip, next_tvb, pinfo, tree);
395     }
396     else if (0x7 == channel_type /*PWACH-encapsulated BFD, draft-ietf-pwe3-vccv-bfd-05 3.2*/
397             || mpls_pref_pwac_all_as_bfd_xipv4)
398     {
399         call_dissector(dissector_bfd, next_tvb, pinfo, tree);
400     }
401     else if (0x57 == channel_type /*IPv6, RFC4385 clause 6.*/)
402     {
403         call_dissector(dissector_ipv6, next_tvb, pinfo, tree);
404     }
405     else if (0x0 == channel_type && mpls_pref_pwac_0x0_as_bfd)
406     {
407         call_dissector(dissector_bfd, next_tvb, pinfo, tree);
408     }
409     else if (mpls_pref_pwac_try_ppp)
410     {
411         /* XXX perhaps this code should be reconsidered */
412         /* non-standard extension, therefore controlled by option*/
413         /* appeared in revision 10862 from Carlos M. Pignataro */
414         if (!dissector_try_port(ppp_subdissector_table, channel_type,
415                             next_tvb, pinfo, tree)) {
416             call_dissector(dissector_data, next_tvb, pinfo, tree);
417         }
418     }
419     else
420     {
421         call_dissector(dissector_data, next_tvb, pinfo, tree);
422     }
423 }
424
425 gboolean dissect_try_cw_first_nibble( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
426 {
427         guint8 nibble;
428         nibble = (tvb_get_guint8(tvb, 0 ) >> 4) & 0x0F;
429         switch ( nibble )
430         {
431         case 6:
432                 call_dissector( dissector_ipv6, tvb, pinfo, tree);
433                 return TRUE;
434         case 4:
435                 call_dissector( dissector_ip, tvb, pinfo, tree);
436                 return TRUE;
437         case 1:
438                 dissect_pw_ach( tvb, pinfo, tree );
439                 return TRUE;
440         default:
441                 break;
442         }
443         return FALSE;
444 }
445
446 /*
447  * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
448  */
449 static void
450 dissect_pw_mcw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
451 {
452     proto_tree  *mpls_pw_mcw_tree = NULL;
453     proto_item  *ti = NULL;
454     tvbuff_t    *next_tvb = NULL;
455     guint8      flags = 0;
456     guint8      frg = 0;
457     guint8      length = 0;
458     guint16     sequence_number = 0;
459
460     if (tvb_reported_length_remaining(tvb, 0) < 4) {
461         if (tree)
462             proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
463         return;
464     }
465
466     if ( dissect_try_cw_first_nibble( tvb, pinfo, tree ))
467        return;
468
469     /* bits 4 to 7 and FRG bits are displayed together */
470     flags = (tvb_get_guint8(tvb, 0) & 0x0F) << 2;
471     frg = (tvb_get_guint8(tvb, 1) & 0xC0) >> 6;
472     flags |= frg;
473     length = tvb_get_guint8(tvb, 1) & 0x3F;
474     sequence_number = tvb_get_ntohs(tvb, 2);
475     if (tree) {
476         ti = proto_tree_add_item(tree, proto_pw_mcw, tvb, 0, 4, FALSE);
477         mpls_pw_mcw_tree = proto_item_add_subtree(ti, ett_mpls_pw_mcw);
478         if (mpls_pw_mcw_tree == NULL)
479             return;
480         proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_flags,
481                                    tvb, 0, 1, flags, "Flags: 0x%02x", flags);
482         ti = proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_length,
483                                         tvb, 1, 1, length, "Length: %u", length);
484         proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_sequence_number,
485                                    tvb, 2, 2, sequence_number,
486                                    "Sequence Number: %d", sequence_number);
487     }
488     next_tvb = tvb_new_subset_remaining(tvb, 4);
489     call_dissector( dissector_data, next_tvb, pinfo, tree );
490 }
491
492 static void
493 dissect_mpls_oam_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *mpls_tree,
494                      int offset, guint8 exp, guint8 bos, guint8 ttl)
495 {
496     proto_tree  *mpls_oam_tree = NULL;
497     proto_item  *ti = NULL;
498     int functype = -1;
499     const guint8 allone[] = { 0xff, 0xff };
500     const guint8 allzero[] = { 0x00, 0x00, 0x00, 0x00, 0x00,
501                                0x00, 0x00, 0x00, 0x00, 0x00,
502                                0x00, 0x00, 0x00, 0x00, 0x00,
503                                0x00, 0x00, 0x00, 0x00, 0x00 };
504
505     /* if called with main tree == null just set col info with func type string and return */
506     if (!tree) {
507         if (check_col(pinfo->cinfo, COL_INFO)) {
508             if (tvb_bytes_exist(tvb, offset, 1)) {
509                 functype = tvb_get_guint8(tvb, offset);
510                 col_append_fstr(pinfo->cinfo, COL_INFO, " (OAM: %s)",
511                                 (functype == 0x01) ? "CV"  :
512                                 (functype == 0x02) ? "FDI" :
513                                 (functype == 0x03) ? "BDI" :
514                                 (functype == 0x07) ? "FDD" : "reserved/unknown");
515             }
516         }
517         return;
518     }
519
520     /* sanity checks */
521     if (!mpls_tree)
522         return;
523
524     if (!tvb_bytes_exist(tvb, offset, 44)) {
525         /* ITU-T Y.1711, 5.3: OAM pdus must have a minimum payload length of 44 bytes */
526         proto_tree_add_text(mpls_tree, tvb, offset, -1, "Error: must have a minimum payload length of 44 bytes");
527         return;
528     }
529
530     ti = proto_tree_add_text(mpls_tree, tvb, offset, 44, "MPLS Operation & Maintenance");
531     mpls_oam_tree = proto_item_add_subtree(ti, ett_mpls_oam);
532
533     if (!mpls_oam_tree)
534         return;
535
536     /* checks for exp, bos and ttl encoding */
537
538     if (exp!=0)
539         proto_tree_add_text(mpls_oam_tree, tvb, offset - 2, 1, "Warning: Exp bits should be 0 for OAM");
540
541     if (bos!=1)
542         proto_tree_add_text(mpls_oam_tree, tvb, offset - 2, 1, "Warning: S bit should be 1 for OAM");
543
544     if (ttl!=1)
545         proto_tree_add_text(mpls_oam_tree, tvb, offset - 1, 1, "Warning: TTL should be 1 for OAM");
546
547     /* starting dissection */
548
549     functype = tvb_get_guint8(tvb, offset);
550     proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_function_type, tvb, offset, 1, TRUE);
551     offset++;
552
553     switch(functype) {
554     case 0x01: /* CV */
555         {
556             guint32 lsrid_ipv4addr;
557
558             /* 3 octets reserved (all 0x00) */
559             if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
560                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
561                                     "Error: these bytes are reserved and must be 0x00");
562             }
563             offset+=3;
564
565             /* ttsi (ipv4 flavor as in RFC 2373) */
566             if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
567                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
568                                     "Error: these bytes are padding and must be 0x00");
569             }
570             offset+=10;
571
572             if (tvb_memeql(tvb, offset, allone, 2) == -1) {
573                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
574                                     "Error: these bytes are padding and must be 0xFF");
575             }
576             offset+=2;
577
578             lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
579             proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
580             offset+=4;
581
582             proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
583             offset+=4;
584
585             /* 18 octets of padding (all 0x00) */
586             if (tvb_memeql(tvb, offset, allzero, 18) == -1) {
587                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 18,
588                                     "Error: these bytes are padding and must be 0x00");
589             }
590             offset+=18;
591         }
592         break;
593
594     case 0x02: /* FDI */
595     case 0x03: /* BDI */
596         {
597             guint32 lsrid_ipv4addr;
598
599             /* 1 octets reserved (all 0x00) */
600             if (tvb_memeql(tvb, offset, allzero, 1) == -1) {
601                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
602                                     "Error: this byte is reserved and must be 0x00");
603             }
604             offset++;
605
606             proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_defect_type, tvb, offset, 2, TRUE);
607             offset+=2;
608
609             /* ttsi (ipv4 flavor as in RFC 2373) is optional if not used must be set to all 0x00 */
610             if (tvb_memeql(tvb, offset, allzero, 20) == 0) {
611                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 20, "TTSI not preset (optional for FDI/BDI)");
612                 offset+=20;
613             } else {
614                 if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
615                     proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
616                                         "Error: these bytes are padding and must be 0x00");
617                 }
618                 offset+=10;
619
620                 if (tvb_memeql(tvb, offset, allone, 2) == -1) {
621                     proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
622                                         "Error: these bytes are padding and must be 0xFF");
623                 }
624                 offset+=2;
625
626                 lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
627                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
628                 offset+=4;
629
630                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
631                 offset+=4;
632             }
633
634             /* defect location */
635             proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_defect_location, tvb, offset, 4, TRUE);
636             offset+=4;
637
638             /* 14 octets of padding (all 0x00) */
639             if (tvb_memeql(tvb, offset, allzero, 14) == -1) {
640                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 14,
641                                     "Error: these bytes are padding and must be 0x00");
642             }
643             offset+=14;
644         }
645         break;
646
647     case 0x07: /* FDD */
648         {
649             guint32 lsrid_ipv4addr;
650
651             /* 3 octets reserved (all 0x00) */
652             if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
653                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
654                                     "Error: these bytes are reserved and must be 0x00");
655             }
656             offset+=3;
657
658             /* ttsi (ipv4 flavor as in RFC 2373) */
659             if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
660                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
661                                     "Error: these bytes are padding and must be 0x00");
662             }
663             offset+=10;
664
665             if (tvb_memeql(tvb, offset, allone, 2) == -1) {
666                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
667                                     "Error: these bytes are padding and must be 0xFF");
668             }
669             offset+=2;
670
671             lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
672             proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
673             offset+=4;
674
675             proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
676             offset+=4;
677
678             proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_frequency, tvb, offset, 1, TRUE);
679             offset++;
680
681             /* 17 octets of padding (all 0x00) */
682             if (tvb_memeql(tvb, offset, allzero, 17) == -1) {
683                 proto_tree_add_text(mpls_oam_tree, tvb, offset, 17,
684                                     "Error: these bytes are padding and must be 0x00");
685             }
686             offset+=17;
687         }
688         break;
689
690     default:
691         proto_tree_add_text(mpls_oam_tree, tvb, offset - 1, -1, "Unknown MPLS OAM pdu");
692         return;
693     }
694
695     /* BIP16 */
696     proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_bip16, tvb, offset, 2, TRUE);
697     offset+=2;
698 }
699
700 static void
701 dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
702 {
703     int offset = 0;
704     guint32 label = LABEL_INVALID;
705     guint8 exp;
706     guint8 bos;
707     guint8 ttl;
708     proto_tree  *mpls_tree = NULL;
709     proto_item  *ti;
710     tvbuff_t *next_tvb;
711
712     col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS");
713
714     col_set_str(pinfo->cinfo, COL_INFO, "MPLS Label Switched Packet");
715
716     /* Start Decoding Here. */
717     while (tvb_reported_length_remaining(tvb, offset) > 0) {
718
719         decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
720         pinfo->mpls_label = label;
721
722         if (tree) {
723
724             ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, FALSE);
725             mpls_tree = proto_item_add_subtree(ti, ett_mpls);
726
727             proto_item_append_text(ti, ", Label: %u", label);
728             if (label <= LABEL_MAX_RESERVED){
729                 proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
730                                     offset, 3, label, "MPLS Label: %u (%s)",
731                                     label, val_to_str(label, special_labels,
732                                                       "Reserved - Unknown"));
733                 proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels,
734                                         "Reserved - Unknown"));
735             } else {
736                 proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
737                                     offset, 3, label, "MPLS Label: %u", label);
738             }
739
740             proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], tvb,
741                                 offset+2,1, exp);
742             proto_item_append_text(ti, ", Exp: %u", exp);
743
744             proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], tvb,
745                                 offset+2,1, bos);
746             proto_item_append_text(ti, ", S: %u", bos);
747
748             proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], tvb,
749                                 offset+3,1, ttl);
750             proto_item_append_text(ti, ", TTL: %u", ttl);
751         }
752
753         if (label == LABEL_OAM_ALERT) {
754             /* OAM pdus are injected in normal data plane flow in order to test a LSP,
755              * they carry no user data.
756              */
757             dissect_mpls_oam_pdu(tvb, pinfo, tree, mpls_tree, offset + 4, exp, bos, ttl);
758             return;
759         }
760
761         offset += 4;
762         if (bos) break;
763     }
764
765     next_tvb = tvb_new_subset_remaining(tvb, offset);
766
767     if ( !dissector_try_port(mpls_subdissector_table, label, next_tvb, pinfo, tree))
768     {
769         switch ( mpls_default_payload )
770         {
771         case MDD_PW_SATOP:
772                call_dissector(dissector_pw_satop, next_tvb, pinfo, tree);
773                break;
774         case MDD_PW_CESOPSN:
775                call_dissector(dissector_pw_cesopsn, next_tvb, pinfo, tree);
776                break;
777         case MDD_PW_ETH_HEUR:
778                call_dissector(dissector_pw_eth_heuristic, next_tvb, pinfo, tree);
779                break;
780         case MDD_MPLS_PW_FR_DLCI:
781                call_dissector(dissector_pw_fr, next_tvb, pinfo, tree);
782                break;
783         case MDD_MPLS_PW_HDLC_NOCW_FRPORT:
784                call_dissector(dissector_pw_hdlc_nocw_fr, next_tvb, pinfo, tree);
785                break;
786         case MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP:
787                call_dissector(dissector_pw_hdlc_nocw_hdlc_ppp, next_tvb, pinfo, tree);
788                break;
789         case MDD_MPLS_PW_ETH_CW:
790                call_dissector(dissector_pw_eth_cw, next_tvb, pinfo, tree);
791                break;
792         case MDD_MPLS_PW_ETH_NOCW:
793                call_dissector(dissector_pw_eth_nocw, next_tvb, pinfo, tree);
794                break;
795         case MDD_ITDM:
796                call_dissector(dissector_itdm, next_tvb, pinfo, tree);
797                break;
798         case MDD_MPLS_PW_ATM_N1_CW:
799                call_dissector(dissector_mpls_pw_atm_n1_cw, next_tvb, pinfo, tree);
800                break;
801         case MDD_MPLS_PW_ATM_N1_NOCW:
802                call_dissector(dissector_mpls_pw_atm_n1_nocw, next_tvb, pinfo, tree);
803                break;
804         case MDD_MPLS_PW_ATM_11_OR_AAL5_PDU:
805                call_dissector(dissector_mpls_pw_atm_11_aal5pdu, next_tvb, pinfo, tree);
806                break;
807         case MDD_MPLS_PW_ATM_AAL5_SDU:
808                call_dissector(dissector_mpls_pw_atm_aal5_sdu, next_tvb, pinfo, tree);
809                break;
810         default: /*fallthrough*/
811         case MDD_MPLS_PW_GENERIC:
812                dissect_pw_mcw(next_tvb, pinfo, tree);
813                break;
814         }
815     }
816 }
817
818 void
819 proto_register_mpls(void)
820 {
821         static hf_register_info mplsf_info[] = {
822
823                 /* MPLS header fields */
824                 {&mpls_filter[MPLSF_LABEL],
825                  {"MPLS Label", "mpls.label", FT_UINT32, BASE_DEC, VALS(special_labels), 0x0,
826                   NULL, HFILL }},
827
828                 {&mpls_filter[MPLSF_EXP],
829                  {"MPLS Experimental Bits", "mpls.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
830                   NULL, HFILL }},
831
832                 {&mpls_filter[MPLSF_BOTTOM_OF_STACK],
833                  {"MPLS Bottom Of Label Stack", "mpls.bottom", FT_UINT8, BASE_DEC, NULL, 0x0,
834                   NULL, HFILL }},
835
836                 {&mpls_filter[MPLSF_TTL],
837                  {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
838                   NULL, HFILL }},
839
840                 /* 1st nibble */
841                  {&hf_mpls_1st_nibble,
842                  {"MPLS 1st nibble", "mpls.1st_nibble", FT_UINT8,
843                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
844
845                 /* PW Associated Channel Header fields */
846                 {&hf_mpls_pw_ach_ver,
847                  {"PW Associated Channel Version", "pwach.ver", FT_UINT8, BASE_DEC,
848                   NULL, 0x0, NULL, HFILL }},
849
850                 {&hf_mpls_pw_ach_res,
851                  {"Reserved", "pwach.res", FT_UINT8, BASE_DEC,
852                   NULL, 0x0, NULL, HFILL }},
853
854                 {&hf_mpls_pw_ach_channel_type,
855                  {"PW Associated Channel Type", "pwach.channel_type", FT_UINT16, BASE_HEX,
856                   NULL, 0x0, NULL, HFILL }},
857
858                 /* Generic/Preferred PW MPLS Control Word fields */
859                 {&hf_mpls_pw_mcw_flags,
860                  {"Generic/Preferred PW MPLS Control Word Flags", "pwmcw.flags", FT_UINT8,
861                   BASE_HEX, NULL, 0x0, NULL,
862                   HFILL }},
863
864                 {&hf_mpls_pw_mcw_length,
865                  {"Generic/Preferred PW MPLS Control Word Length", "pwmcw.length", FT_UINT8,
866                   BASE_DEC, NULL, 0x0, NULL,
867                   HFILL }},
868
869                 {&hf_mpls_pw_mcw_sequence_number,
870                  {"Generic/Preferred PW MPLS Control Word Sequence Number",
871                   "pwmcw.sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0,
872                   NULL, HFILL }},
873
874                 /* OAM header fields */
875                 {&hf_mpls_oam_function_type,
876                  {"Function Type", "mpls.oam.function_type", FT_UINT8,
877                   BASE_HEX, VALS(oam_function_type_vals), 0x0, "Function Type codepoint", HFILL }},
878
879                 {&hf_mpls_oam_ttsi,
880                  {"Trail Termination Source Identifier", "mpls.oam.ttsi", FT_UINT32,
881                   BASE_HEX, NULL, 0x0, NULL, HFILL }},
882
883                 {&hf_mpls_oam_frequency,
884                  {"Frequency", "mpls.oam.frequency", FT_UINT8,
885                   BASE_HEX, VALS(oam_frequency_vals), 0x0, "Frequency of probe injection", HFILL }},
886
887                 {&hf_mpls_oam_defect_type,
888                  {"Defect Type", "mpls.oam.defect_type", FT_UINT16,
889                   BASE_HEX, VALS(oam_defect_type_vals), 0x0, NULL, HFILL }},
890
891                 {&hf_mpls_oam_defect_location,
892                  {"Defect Location (AS)", "mpls.oam.defect_location", FT_UINT32,
893                   BASE_DEC, NULL, 0x0, "Defect Location", HFILL }},
894
895                 {&hf_mpls_oam_bip16,
896                  {"BIP16", "mpls.oam.bip16", FT_UINT16,
897                   BASE_HEX, NULL, 0x0, NULL, HFILL }},
898         };
899
900         static gint *ett[] = {
901                 &ett_mpls,
902                 &ett_mpls_pw_ach,
903                 &ett_mpls_pw_mcw,
904                 &ett_mpls_oam,
905         };
906         module_t * module_mpls;
907
908         /* FF: mpls subdissector table is indexed by label */
909         mpls_subdissector_table = register_dissector_table("mpls.label",
910                                                            "MPLS protocol",
911                                                            FT_UINT32, BASE_DEC);
912         proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header",
913                                              "MPLS", "mpls");
914         proto_pw_ach = proto_register_protocol("PW Associated Channel Header",
915                                                "PW Associated Channel", "pwach");
916         proto_pw_mcw = proto_register_protocol("PW MPLS Control Word (generic/preferred)",
917                                                "Generic PW (with CW)", "pwmcw");
918
919         proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
920         proto_register_subtree_array(ett, array_length(ett));
921         register_dissector("mpls", dissect_mpls, proto_mpls);
922         register_dissector("mplspwcw", dissect_pw_mcw, proto_pw_mcw );
923
924         module_mpls = prefs_register_protocol( proto_mpls, proto_reg_handoff_mpls );
925
926         prefs_register_enum_preference( module_mpls,
927                                         "mplspref.payload",
928                                         "Default decoder for MPLS payload",
929                                         "Default decoder for MPLS payload",
930                                         &mpls_default_payload,
931                                         mpls_default_payload_defs,
932                                         FALSE );
933         prefs_register_bool_preference(module_mpls
934                 ,"mplspref.pwac_0x0_as_bfd"
935                 ,"Assume PWAC Channel Type 0x0 is raw BFD"
936                 ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
937                 " when VCCV carries PW-ACH-encapsulated BFD (i.e., BFD without IP/UDP Headers, or \"raw\" BFD)"
938                 "\n\n"
939                 "Legacy or buggy devices may not comply to this and use Channel Type 0x0 for BFD."
940                 " Enable this preference to decode such BFD traffic."
941                 " Disable for standard behavior of PWAC dissector (default)."
942                 ,&mpls_pref_pwac_0x0_as_bfd);
943         prefs_register_bool_preference(module_mpls
944                 ,"mplspref.pwac_all_as_bfd_xip"
945                 ,"Assume that all PWAC Channel Types (except 0x21) are raw BFD"
946                 ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
947                 " when VCCV carries PW-ACH-encapsulated BFD (i.e., \"raw\" BFD)"
948                 "\n\n"
949                 "Legacy or buggy devices may not comply to this and use voluntary Channel Type for BFD."
950                 " Enable this preference to decode all PWAC Channel Types as raw BFD,"
951                 " except Channel Type 0x21 (IPv4)."
952                 " Disable for standard behavior of PWAC dissector (default)."
953                 ,&mpls_pref_pwac_all_as_bfd_xipv4);
954         prefs_register_bool_preference(module_mpls
955                 ,"mplspref.pwac_try_ppp"
956                 ,"As a last resort, try to decode PWAC payloads as PPP traffic"
957                 ,"Legacy devices may use MPLS PW Associated Channel for PPP traffic."
958                 "\n\n"
959                 "Enable this preference to allow PWAC dissector to try PPP,"
960                 " if no other suitable dissector found (default)."
961                 ,&mpls_pref_pwac_try_ppp);
962 }
963
964 void
965 proto_reg_handoff_mpls(void)
966 {
967         static gboolean initialized=FALSE;
968
969         if ( !initialized )
970         {
971                 dissector_handle_t mpls_handle;
972
973                 ppp_subdissector_table = find_dissector_table("ppp.protocol");
974
975                 mpls_handle = find_dissector("mpls");
976                 dissector_add("ethertype", ETHERTYPE_MPLS, mpls_handle);
977                 dissector_add("ethertype", ETHERTYPE_MPLS_MULTI, mpls_handle);
978                 dissector_add("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
979                 dissector_add("ppp.protocol", PPP_MPLS_MULTI, mpls_handle);
980                 dissector_add("chdlctype", ETHERTYPE_MPLS, mpls_handle);
981                 dissector_add("chdlctype", ETHERTYPE_MPLS_MULTI, mpls_handle);
982                 dissector_add("gre.proto", ETHERTYPE_MPLS, mpls_handle);
983                 dissector_add("gre.proto", ETHERTYPE_MPLS_MULTI, mpls_handle);
984                 dissector_add("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
985
986                 mpls_handle = find_dissector("mplspwcw");
987                 dissector_add( "mpls.label", LABEL_INVALID, mpls_handle );
988
989                 dissector_data                  = find_dissector("data");
990                 dissector_ipv6                  = find_dissector("ipv6");
991                 dissector_ip                    = find_dissector("ip");
992                 dissector_bfd                   = find_dissector("bfd");
993                 dissector_pw_eth_heuristic      = find_dissector("pw_eth_heuristic");
994                 dissector_pw_fr                 = find_dissector("pw_fr");
995                 dissector_pw_hdlc_nocw_fr       = find_dissector("pw_hdlc_nocw_fr");
996                 dissector_pw_hdlc_nocw_hdlc_ppp = find_dissector("pw_hdlc_nocw_hdlc_ppp");
997                 dissector_pw_eth_cw             = find_dissector("pw_eth_cw");
998                 dissector_pw_eth_nocw           = find_dissector("pw_eth_nocw");
999                 dissector_pw_satop              = find_dissector("pw_satop_mpls");
1000                 dissector_itdm                  = find_dissector("itdm");
1001                 dissector_mpls_pw_atm_n1_cw     = find_dissector("mpls_pw_atm_n1_cw");
1002                 dissector_mpls_pw_atm_n1_nocw   = find_dissector("mpls_pw_atm_n1_nocw");
1003                 dissector_mpls_pw_atm_11_aal5pdu= find_dissector("mpls_pw_atm_11_or_aal5_pdu");
1004                 dissector_mpls_pw_atm_aal5_sdu  = find_dissector("mpls_pw_atm_aal5_sdu");
1005                 dissector_pw_cesopsn            = find_dissector("pw_cesopsn_mpls");
1006
1007                 initialized = TRUE;
1008         }
1009 }