Use "fork_child" rather than "child_process" - on Win32, "child_process"
[obnox/wireshark/wip.git] / packet-rsvp.c
index 7b826caee4511225d55a608172e0ca1841a18aa1..53ad6e930246ff7561c36a14b6ae0e3231ee2af9 100644 (file)
@@ -3,7 +3,7 @@
  *
  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
  *
- * $Id: packet-rsvp.c,v 1.80 2003/01/28 23:56:40 guy Exp $
+ * $Id: packet-rsvp.c,v 1.86 2003/11/11 20:11:05 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -68,6 +68,7 @@
 #include "packet-rsvp.h"
 #include "packet-ip.h"
 #include "packet-frame.h"
+#include "packet-diffserv-mpls-common.h"
 
 static int proto_rsvp = -1;
 
@@ -120,7 +121,11 @@ enum {
     TT_RESTART_CAP,
     TT_PROTECTION_INFO,
     TT_FAST_REROUTE,
+    TT_FAST_REROUTE_FLAGS,
     TT_DETOUR,
+    TT_DIFFSERV,
+    TT_DIFFSERV_MAP,
+    TT_DIFFSERV_MAP_PHBID,
     TT_UNKNOWN_CLASS,
 
     TT_MAX
@@ -220,6 +225,10 @@ enum rsvp_classes {
     RSVP_CLASS_LABEL_SET,
     RSVP_CLASS_PROTECTION,
 
+    RSVP_CLASS_DETOUR = 63,
+
+    RSVP_CLASS_DIFFSERV = 65,
+
     RSVP_CLASS_SUGGESTED_LABEL = 129,
     RSVP_CLASS_ACCEPTABLE_LABEL_SET,
     RSVP_CLASS_RESTART_CAP,
@@ -227,13 +236,12 @@ enum rsvp_classes {
     RSVP_CLASS_NOTIFY_REQUEST = 195,
     RSVP_CLASS_ADMIN_STATUS,
 
+    RSVP_CLASS_FAST_REROUTE = 205,
     RSVP_CLASS_SESSION_ATTRIBUTE = 207,
     RSVP_CLASS_GENERALIZED_UNI,
     RSVP_CLASS_DCLASS = 225,
-    RSVP_CLASS_LSP_TUNNEL_IF_ID = 227,
+    RSVP_CLASS_LSP_TUNNEL_IF_ID = 227
 
-    RSVP_CLASS_FAST_REROUTE = 228, /* TBD */
-    RSVP_CLASS_DETOUR = 229 /* TBD */
 };
 
 static value_string rsvp_class_vals[] = {
@@ -265,6 +273,7 @@ static value_string rsvp_class_vals[] = {
     {RSVP_CLASS_UPSTREAM_LABEL, "UPSTREAM-LABEL object"},
     {RSVP_CLASS_LABEL_SET, "LABEL-SET object"},
     {RSVP_CLASS_PROTECTION, "PROTECTION object"},
+    {RSVP_CLASS_DIFFSERV, "DIFFSERV object"},
     {RSVP_CLASS_SUGGESTED_LABEL, "SUGGESTED-LABEL object"},
     {RSVP_CLASS_ACCEPTABLE_LABEL_SET, "ACCEPTABLE-LABEL-SET object"},
     {RSVP_CLASS_RESTART_CAP, "RESTART-CAPABILITY object"},
@@ -273,6 +282,8 @@ static value_string rsvp_class_vals[] = {
     {RSVP_CLASS_NOTIFY_REQUEST, "NOTIFY-REQUEST object"},
     {RSVP_CLASS_ADMIN_STATUS, "ADMIN-STATUS object"},
     {RSVP_CLASS_GENERALIZED_UNI, "GENERALIZED-UNI object"},
+    {RSVP_CLASS_DETOUR, "DETOUR object"},
+    {RSVP_CLASS_FAST_REROUTE, "FAST-REROUTE object"},
     {0, NULL}
 };
 
@@ -296,10 +307,52 @@ enum rsvp_error_types {
     RSVP_ERROR_TRAFFIC_SYSTEM,
     RSVP_ERROR_SYSTEM,
     RSVP_ERROR_ROUTING,
-    RSVP_ERROR_NOTIFY
+    RSVP_ERROR_NOTIFY,
+    RSVP_ERROR_DIFFSERV = 27
+};
+
+enum {
+    RSVP_AC_ERROR_DELAY_BOUND_ERROR = 1,
+    RSVP_AC_ERROR_BANDWITH_UNAVAILABLE,
+    RSVP_AC_ERROR_LARGE_MTU
+};
+
+enum {
+    RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT = 1,
+    RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED,
+    RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC,
+    RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC,
+    RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC
+};
+
+enum {
+    RSVP_ROUTING_ERROR_BAD_ERO = 1,
+    RSVP_ROUTING_ERROR_BAD_STRICT,
+    RSVP_ROUTING_ERROR_BAD_LOOSE,
+    RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ,
+    RSVP_ROUTING_ERROR_NO_ROUTE,
+    RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL,
+    RSVP_ROUTING_ERROR_RRO_LOOP,
+    RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER,
+    RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL,
+    RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID
+};
+
+enum {
+    RSVP_NOTIFY_ERROR_RRO_TOO_LARGE = 1,
+    RSVP_NOTIFY_ERROR_RRO_NOTIFICATION,
+    RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED
+};
+
+enum {
+    RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ = 1,
+    RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB,
+    RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING,
+    RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC,
+    RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL
 };
 
-static value_string rsvp_error_vals[] = {
+static value_string rsvp_error_codes[] = {
     {RSVP_ERROR_CONFIRM, "Confirmation"},
     {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
     {RSVP_ERROR_POLICY, "Policy Control Failure"},
@@ -317,6 +370,53 @@ static value_string rsvp_error_vals[] = {
     {RSVP_ERROR_SYSTEM, "RSVP System Error"},
     {RSVP_ERROR_ROUTING, "Routing Error"},
     {RSVP_ERROR_NOTIFY, "RSVP Notify Error"},
+    {RSVP_ERROR_DIFFSERV, "RSVP Diff-Serv Error"},
+    {0, NULL}
+};
+
+static value_string rsvp_admission_control_error_vals[] = {
+    {RSVP_AC_ERROR_DELAY_BOUND_ERROR, "Delay bound cannot be met"},
+    {RSVP_AC_ERROR_BANDWITH_UNAVAILABLE, "Requested bandwidth unavailable"},
+    {RSVP_AC_ERROR_LARGE_MTU, "MTU in flowspec larger than interface MTU"},
+    {0, NULL}
+};
+
+static value_string rsvp_traffic_control_error_vals[] = { 
+    {RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT, "Service conflict"},
+    {RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED, "Service unsupported"},
+    {RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC, "Bad Flowspec value"},
+    {RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC, "Bad Tspec value"},
+    {RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC, "Bad Adspec value"},
+    {0, NULL}
+};
+
+static value_string rsvp_routing_error_vals[] = {
+    {RSVP_ROUTING_ERROR_BAD_ERO, "Bad EXPLICIT_ROUTE object"},
+    {RSVP_ROUTING_ERROR_BAD_STRICT, "Bad strict node"},
+    {RSVP_ROUTING_ERROR_BAD_LOOSE, "Bad loose node"},
+    {RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ, "Bad initial subobject"},
+    {RSVP_ROUTING_ERROR_NO_ROUTE, "No route available toward destination"},
+    {RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL, "Unacceptable label value"},
+    {RSVP_ROUTING_ERROR_RRO_LOOP, "RRO indicated routing loops"},
+    {RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER, "non-RSVP-capable router stands in the path"},
+    {RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL, "MPLS label allocation failure"},
+    {RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID, "Unsupported L3PID"},
+    {0, NULL}
+};
+
+static value_string rsvp_notify_error_vals[] = {
+    {RSVP_NOTIFY_ERROR_RRO_TOO_LARGE, "RRO too large for MTU"},
+    {RSVP_NOTIFY_ERROR_RRO_NOTIFICATION, "RRO Notification"},
+    {RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED, "Tunnel locally repaired"},
+    {0, NULL}
+};
+
+static value_string rsvp_diffserv_error_vals[] = {
+    {RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ, "Unexpected DIFFSERV object"},
+    {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB, "Unsupported PHB"},
+    {RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING, "Invalid `EXP<->PHB mapping'"},
+    {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC, "Unsupported PSC"},
+    {RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL, "Per-LSP context allocation failure"},
     {0, NULL}
 };
 
@@ -596,6 +696,7 @@ enum rsvp_filter_keys {
     RSVPF_UPSTREAM_LABEL,
     RSVPF_LABEL_SET,
     RSVPF_PROTECTION,
+    RSVPF_DIFFSERV,
 
     RSVPF_SUGGESTED_LABEL,
     RSVPF_ACCEPTABLE_LABEL_SET,
@@ -621,6 +722,16 @@ enum rsvp_filter_keys {
     RSVPF_SENDER_PORT,
     RSVPF_SENDER_LSP_ID,
 
+    /* Diffserv object */
+    RSVPF_DIFFSERV_MAPNB,
+    RSVPF_DIFFSERV_MAP,
+    RSVPF_DIFFSERV_MAP_EXP,
+    RSVPF_DIFFSERV_PHBID,
+    RSVPF_DIFFSERV_PHBID_DSCP,
+    RSVPF_DIFFSERV_PHBID_CODE,
+    RSVPF_DIFFSERV_PHBID_BIT14,
+    RSVPF_DIFFSERV_PHBID_BIT15,
+
     /* Sentinel */
     RSVPF_MAX
 };
@@ -777,6 +888,10 @@ static hf_register_info rsvpf_info[] = {
      { "PROTECTION", "rsvp.protection", FT_NONE, BASE_NONE, NULL, 0x0,
        "", HFILL }},
 
+    {&rsvp_filter[RSVPF_DIFFSERV],
+     { "DIFFSERV", "rsvp.diffserv", FT_NONE, BASE_NONE, NULL, 0x0,
+        "", HFILL }},
+
     {&rsvp_filter[RSVPF_RESTART_CAP],
      { "RESTART CAPABILITY", "rsvp.restart", FT_NONE, BASE_NONE, NULL, 0x0,
        "", HFILL }},
@@ -809,10 +924,6 @@ static hf_register_info rsvpf_info[] = {
      { "MESSAGE-ID LIST", "rsvp.msgid_list", FT_NONE, BASE_NONE, NULL, 0x0,
        "", HFILL }},
 
-    {&rsvp_filter[RSVPF_HELLO_OBJ],
-     { "HELLO", "rsvp.hello", FT_NONE, BASE_NONE, NULL, 0x0,
-       "", HFILL }},
-
     {&rsvp_filter[RSVPF_DCLASS],
      { "DCLASS", "rsvp.dclass", FT_NONE, BASE_NONE, NULL, 0x0,
        "", HFILL }},
@@ -869,7 +980,41 @@ static hf_register_info rsvpf_info[] = {
 
     {&rsvp_filter[RSVPF_SENDER_LSP_ID],
      { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_DEC, NULL, 0x0,
-       "", HFILL }}
+       "", HFILL }},
+
+    /* Diffserv object fields */
+    {&rsvp_filter[RSVPF_DIFFSERV_MAPNB],
+     { "MAPnb", "rsvp.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL, 0x0,
+       MAPNB_DESCRIPTION, HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_MAP],
+     { "MAP", "rsvp.diffserv.map", FT_NONE, BASE_NONE, NULL, 0x0,
+       MAP_DESCRIPTION, HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
+     { "EXP", "rsvp.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
+       EXP_DESCRIPTION, HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_PHBID],
+     { "PHBID", "rsvp.diffserv.phbid", FT_NONE, BASE_NONE, NULL, 0x0,
+       PHBID_DESCRIPTION, HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
+     { PHBID_DSCP_DESCRIPTION, "rsvp.diffserv.phbid.dscp", FT_UINT16,
+       BASE_DEC, NULL, PHBID_DSCP_MASK, "DSCP", HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
+     { PHBID_CODE_DESCRIPTION, "rsvp.diffserv.phbid.code", FT_UINT16,
+       BASE_DEC, NULL, PHBID_CODE_MASK, "PHB id code", HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
+     { PHBID_BIT14_DESCRIPTION, "rsvp.diffserv.phbid.bit14", FT_UINT16,
+       BASE_DEC, VALS(phbid_bit14_vals), PHBID_BIT14_MASK, "Bit 14", HFILL }},
+
+    {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15],
+     { PHBID_BIT15_DESCRIPTION, "rsvp.diffserv.phbid.bit15", FT_UINT16,
+       BASE_DEC, VALS(phbid_bit15_vals), PHBID_BIT15_MASK, "Bit 15", HFILL }}
+
 };
 
 static inline int rsvp_class_to_filter_num(int classnum)
@@ -911,6 +1056,9 @@ static inline int rsvp_class_to_filter_num(int classnum)
     case RSVP_CLASS_RESTART_CAP :
        return RSVPF_SUGGESTED_LABEL + (classnum - RSVP_CLASS_SUGGESTED_LABEL);
 
+    case RSVP_CLASS_DIFFSERV :
+       return RSVPF_DIFFSERV;
+
     case RSVP_CLASS_NOTIFY_REQUEST :
        return RSVPF_NOTIFY_REQUEST;
     case RSVP_CLASS_ADMIN_STATUS :
@@ -1318,6 +1466,52 @@ dissect_rsvp_time_values (proto_tree *ti, tvbuff_t *tvb,
     }
 }
 
+/*------------------------------------------------------------------------------
+ * Error value field in ERROR object
+ *------------------------------------------------------------------------------*/
+static guint16
+dissect_rsvp_error_value (proto_tree *ti, tvbuff_t *tvb,
+                          int offset, guint8 error_code)
+{
+    guint16 error_val;
+    value_string *rsvp_error_vals = NULL;
+
+    error_val = tvb_get_ntohs(tvb, offset);
+    switch (error_code) {
+    case RSVP_ERROR_ADMISSION:
+       rsvp_error_vals = rsvp_admission_control_error_vals;
+       break;
+    case RSVP_ERROR_TRAFFIC:
+       rsvp_error_vals = rsvp_traffic_control_error_vals;
+       break;
+    case RSVP_ERROR_ROUTING:
+       rsvp_error_vals = rsvp_routing_error_vals;
+       break;
+    case RSVP_ERROR_NOTIFY:
+       rsvp_error_vals = rsvp_notify_error_vals;
+       break;
+    case RSVP_ERROR_DIFFSERV:
+       rsvp_error_vals = rsvp_diffserv_error_vals;
+    }
+    switch (error_code) {
+    case RSVP_ERROR_ADMISSION:
+    case RSVP_ERROR_TRAFFIC:
+    case RSVP_ERROR_NOTIFY:
+    case RSVP_ERROR_ROUTING:
+    case RSVP_ERROR_DIFFSERV:
+       if ((error_val & 0xc0) == 0) {
+           proto_tree_add_text(ti, tvb, offset, 2,
+               "Error value: %u - %s", error_val,
+               val_to_str(error_val, rsvp_error_vals, "Unknown (%d)"));
+           break;
+       }
+    default:
+       proto_tree_add_text(ti, tvb, offset, 2,
+           "Error value: %u", error_val);
+    }
+    return error_val;
+}
+
 /*------------------------------------------------------------------------------
  * ERROR
  *------------------------------------------------------------------------------*/
@@ -1339,6 +1533,7 @@ dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb,
     switch(type) {
     case 1: {
        guint8 error_code;
+       guint16 error_val;
 
        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
                            "C-type: 1 - IPv4");
@@ -1351,19 +1546,17 @@ dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb,
        error_code = tvb_get_guint8(tvb, offset2+5);
        proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
                            "Error code: %u - %s", error_code,
-                           val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"));
-       proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
-                           "Error value: %u",
-                           tvb_get_ntohs(tvb, offset2+6));
+                           val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"));
+       error_val = dissect_rsvp_error_value(rsvp_object_tree, tvb, offset2+6, error_code);
        proto_item_set_text(ti, "ERROR: IPv4, Error code: %s, Value: %d, Error Node: %s",
-                           val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"),
-                           tvb_get_ntohs(tvb, offset2+6),
-                           ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+                           val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
+                           error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
        break;
     }
 
     case 2: {
        guint8 error_code;
+       guint16 error_val;
 
        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
                            "C-type: 2 - IPv6");
@@ -1375,17 +1568,16 @@ dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb,
                            tvb_get_guint8(tvb, offset2+16));
        error_code = tvb_get_guint8(tvb, offset2+17);
        proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
-                           "Error code: %u - %s", error_code,
-                           val_to_str(error_code, rsvp_error_vals, "Unknown"));
-       proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
-                           "Error value: %u",
-                           tvb_get_ntohs(tvb, offset2+18));
+                           "Error code: %u - %s",
+                           error_code,
+                           val_to_str(error_code, rsvp_error_codes, "Unknown"));
+       error_val = dissect_rsvp_error_value(ti, tvb, offset2+18, error_code);
        break;
     }
 
-    case 3:
-{
+    case 3: {
        guint8 error_code;
+       guint16 error_val;
 
        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
                            "C-type: 3 - IPv4 IF-ID");
@@ -1398,19 +1590,13 @@ dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb,
        error_code = tvb_get_guint8(tvb, offset2+5);
        proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
                            "Error code: %u - %s", error_code,
-                           val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"));
-       proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
-                           "Error value: %u",
-                           tvb_get_ntohs(tvb, offset2+6));
-
+                           val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"));
+       error_val = dissect_rsvp_error_value(ti, tvb, offset2+6, error_code);
        proto_item_set_text(ti, "ERROR: IPv4 IF-ID, Error code: %s, Value: %d, Control Node: %s. ",
-                           val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"),
-                           tvb_get_ntohs(tvb, offset2+6),
-                           ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
-
+                           val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
+                           error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
        dissect_rsvp_ifid_tlv(ti, rsvp_object_tree, tvb, offset+12, obj_length, 
                              TREE(TT_ERROR_SUBOBJ));
-                             
        break;
     }
 
@@ -2648,10 +2834,23 @@ dissect_rsvp_session_attribute (proto_tree *ti, tvbuff_t *tvb,
                        "Class number: %u - %s",
                        class, type_str);
     switch(type) {
+    case 1:
     case 7:
 
        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
-                           "C-type: 7 - IPv4 LSP");
+                           "C-type: %u - IPv4 LSP (%sResource Affinities)",
+                            type, (type == 1) ? "" : "No ");
+        
+        if (type == 1) {
+            proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
+                           "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset2));
+            proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4, 
+                           "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset2+4));
+            proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
+                           "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset2+8));
+            offset2 = offset2+12;
+        }
+
        proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
                            "Setup priority: %u",
                            tvb_get_guint8(tvb, offset2));
@@ -2721,7 +2920,7 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
                                 tvbuff_t *tvb,
                                 int offset, int obj_length, int class)
 {
-    int i, j, k, l;
+    int i, j, k, l, flags;
     proto_tree *ti2, *rsvp_ro_subtree, *rsvp_rro_flags_subtree;
     int tree_type;
 
@@ -2744,10 +2943,10 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
            k = tvb_get_guint8(tvb, offset+l) & 0x80;
            ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
                                      offset+l, 8,
-                                     "IPv4 Subobject - %s%s",
+                                     "IPv4 Subobject - %s%s",
                                      ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
                                      class == RSVP_CLASS_EXPLICIT_ROUTE ? 
-                                     (k ? "Loose" : "Strict") : "");
+                                     (k ? ", Loose" : ", Strict") : "");
            rsvp_ro_subtree =
                proto_item_add_subtree(ti2, tree_type);
            if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
@@ -2764,36 +2963,45 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
            proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+6, 1,
                                "Prefix length: %u",
                                tvb_get_guint8(tvb, offset+l+6));
+           if (i < 4) {
+               proto_item_append_text(ti, "IPv4 %s%s",
+                                      ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
+                                      k ? " [L]" : "");
+           }
            if (class == RSVP_CLASS_RECORD_ROUTE) {
-               if (k&0x01) proto_item_append_text(ti2, ", Local Protection Available");
-               if (k&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
-               if (k&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
-               if (k&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+               flags = tvb_get_guint8(tvb, offset+l+7);
+               if (flags&0x10) {
+                   proto_item_append_text(ti,  " (Node-id)");
+                   proto_item_append_text(ti2, " (Node-id)");
+               }
+               if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+               if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+               if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+               if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
                ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+7, 1,
-                                         "Flags: 0x%08x", k);
+                                         "Flags: 0x%02x", flags);
                rsvp_rro_flags_subtree = 
                    proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
-                                   decode_boolean_bitfield(k, 0x01, 8, 
+                                   decode_boolean_bitfield(flags, 0x01, 8, 
                                                            "Local Protection Available",
                                                            "Local Protection Not Available"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
-                                   decode_boolean_bitfield(k, 0x02, 8, 
+                                   decode_boolean_bitfield(flags, 0x02, 8, 
                                                            "Local Protection In Use",
                                                            "Local Protection Not In Use"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
-                                   decode_boolean_bitfield(k, 0x04, 8, 
+                                   decode_boolean_bitfield(flags, 0x04, 8, 
                                                            "Bandwidth Protection Available",
                                                            "Bandwidth Protection Not Available"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
-                                   decode_boolean_bitfield(k, 0x08, 8, 
+                                   decode_boolean_bitfield(flags, 0x08, 8, 
                                                            "Node Protection Available",
                                                            "Node Protection Not Available"));
-           }
-           if (i < 4) {
-               proto_item_append_text(ti, "IPv4 %s%s",
-                                      ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
-                                      k ? " [L]":"");
+               proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+                                   decode_boolean_bitfield(flags, 0x10, 8,
+                                                           "Address Specifies a Node-id Address",
+                                                           "Address Doesn't Specify a Node-id Address"));
            }
 
            break;
@@ -2819,34 +3027,43 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
            proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+18, 1,
                                "Prefix length: %u",
                                tvb_get_guint8(tvb, offset+l+18));
+           if (i < 4) {
+               proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
+           }
            if (class == RSVP_CLASS_RECORD_ROUTE) {
-               if (k&0x01) proto_item_append_text(ti2, ", Local Protection Available");
-               if (k&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
-               if (k&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
-               if (k&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+               flags = tvb_get_guint8(tvb, offset+l+19);
+               if (flags&0x10) {
+                   proto_item_append_text(ti,  " (Node-id)");
+                   proto_item_append_text(ti2, " (Node-id)");
+               }
+               if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+               if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+               if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+               if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
                ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+19, 1,
-                                         "Flags: 0x%08x", k);
+                                         "Flags: 0x%02x", flags);
                rsvp_rro_flags_subtree = 
                    proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
-                                   decode_boolean_bitfield(k, 0x01, 8, 
+                                   decode_boolean_bitfield(flags, 0x01, 8, 
                                                            "Local Protection Available",
                                                            "Local Protection Not Available"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
-                                   decode_boolean_bitfield(k, 0x02, 8, 
+                                   decode_boolean_bitfield(flags, 0x02, 8, 
                                                            "Local Protection In Use",
                                                            "Local Protection Not In Use"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
-                                   decode_boolean_bitfield(k, 0x04, 8, 
+                                   decode_boolean_bitfield(flags, 0x04, 8, 
                                                            "Backup Tunnel Has Bandwidth",
                                                            "Backup Tunnel Does Not Have Bandwidth"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
-                                   decode_boolean_bitfield(k, 0x08, 8, 
+                                   decode_boolean_bitfield(flags, 0x08, 8, 
                                                            "Backup Tunnel Goes To Next-Next-Hop",
                                                            "Backup Tunnel Goes To Next-Hop"));
-           }
-           if (i < 4) {
-               proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
+               proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+                                   decode_boolean_bitfield(flags, 0x10, 8,
+                                                           "Address Specifies a Node-id Address",
+                                                           "Address Doesn't Specify a Node-id Address"));
            }
 
            break;
@@ -2870,28 +3087,29 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
                                "Length: %u",
                                tvb_get_guint8(tvb, offset+l+1));
            if (class == RSVP_CLASS_RECORD_ROUTE) {
-               if (k&0x01) proto_item_append_text(ti2, ", Local Protection Available");
-               if (k&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
-               if (k&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
-               if (k&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+               flags = tvb_get_guint8(tvb, offset+l+2);
+               if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+               if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+               if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+               if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
                ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
-                                         "Flags: 0x%08x", k);
+                                         "Flags: 0x%02x", flags);
                rsvp_rro_flags_subtree = 
                    proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x01, 8, 
+                                   decode_boolean_bitfield(flags, 0x01, 8, 
                                                            "Local Protection Available",
                                                            "Local Protection Not Available"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x02, 8, 
+                                   decode_boolean_bitfield(flags, 0x02, 8, 
                                                            "Local Protection In Use",
                                                            "Local Protection Not In Use"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x04, 8, 
+                                   decode_boolean_bitfield(flags, 0x04, 8, 
                                                            "Backup Tunnel Has Bandwidth",
                                                            "Backup Tunnel Does Not Have Bandwidth"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x08, 8, 
+                                   decode_boolean_bitfield(flags, 0x08, 8, 
                                                            "Backup Tunnel Goes To Next-Next-Hop",
                                                            "Backup Tunnel Goes To Next-Hop"));
            }
@@ -2928,28 +3146,29 @@ dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
                                "Length: %u",
                                tvb_get_guint8(tvb, offset+l+1));
            if (class == RSVP_CLASS_RECORD_ROUTE) {
-               if (k&0x01) proto_item_append_text(ti2, ", Local Protection Available");
-               if (k&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
-               if (k&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
-               if (k&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+               flags = tvb_get_guint8(tvb, offset+l+2);
+               if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+               if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+               if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+               if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
                ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
-                                         "Flags: 0x%08x", k);
+                                         "Flags: 0x%02x", flags);
                rsvp_rro_flags_subtree = 
                    proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x01, 8, 
+                                   decode_boolean_bitfield(flags, 0x01, 8, 
                                                            "Local Protection Available",
                                                            "Local Protection Not Available"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x02, 8, 
+                                   decode_boolean_bitfield(flags, 0x02, 8, 
                                                            "Local Protection In Use",
                                                            "Local Protection Not In Use"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x04, 8, 
+                                   decode_boolean_bitfield(flags, 0x04, 8, 
                                                            "Backup Tunnel Has Bandwidth",
                                                            "Backup Tunnel Does Not Have Bandwidth"));
                proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
-                                   decode_boolean_bitfield(k, 0x08, 8, 
+                                   decode_boolean_bitfield(flags, 0x08, 8, 
                                                            "Backup Tunnel Goes To Next-Next-Hop",
                                                            "Backup Tunnel Goes To Next-Hop"));
            }
@@ -3810,6 +4029,8 @@ dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
                           char *type_str)
 {
     proto_tree *rsvp_object_tree;
+    guint8 flags;
+    proto_tree *ti2, *rsvp_frr_flags_tree;
 
     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FAST_REROUTE));
     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
@@ -3828,15 +4049,27 @@ dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
            break;
        }
        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
-                           "C-type: 1");
+                           "C-type: %u", type);
        proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1, 
                            "Setup Priority: %d", tvb_get_guint8(tvb, offset+4));
        proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 1, 
                            "Hold Priority: %d", tvb_get_guint8(tvb, offset+5));
        proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 1, 
                            "Hop Limit: %d", tvb_get_guint8(tvb, offset+6));
-       proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, 
-                           "Flags: %d", tvb_get_guint8(tvb, offset+7));
+
+        flags = tvb_get_guint8(tvb, offset+7);
+       ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, 
+                                  "Flags: 0x%02x", flags);
+        rsvp_frr_flags_tree = proto_item_add_subtree(ti2,
+                                                     TREE(TT_FAST_REROUTE_FLAGS));
+       proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
+                           decode_boolean_bitfield(flags, 0x01, 8,
+                                                   "One-to-One Backup desired",
+                                                   "One-to-One Backup not desired"));
+       proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
+                           decode_boolean_bitfield(flags, 0x02, 8,
+                                                   "Facility Backup desired",
+                                                   "Facility Backup not desired"));
        proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4, 
                            "Bandwidth: %.10g", tvb_get_ntohieee_float(tvb, offset+8));
        proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4, 
@@ -3847,6 +4080,10 @@ dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
            proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4, 
                                "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset+20));
        }
+
+        proto_item_append_text(ti, "%s%s",
+                               flags &0x01 ? "One-to-One Backup, " : "",
+                               flags &0x02 ? "Facility Backup" : "");
        break;
 
     default:
@@ -3870,6 +4107,7 @@ dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
 {
     proto_tree *rsvp_object_tree;
     int remaining_length, count;
+    int iter;
 
     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DETOUR));
     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
@@ -3877,9 +4115,12 @@ dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
                        "Class number: %u - %s",
                        class, type_str);
-    proto_item_set_text(ti, "FAST_REROUTE: ");
+    proto_item_set_text(ti, "DETOUR: ");
     switch(type) {
     case 7:
+        iter = 0;
+        proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+                           "C-type: %u", type);
        for (remaining_length = obj_length - 4, count = 1;
             remaining_length > 0; remaining_length -= 8, count++) {
            if (remaining_length < 8) {
@@ -3889,12 +4130,14 @@ dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
                proto_item_append_text(ti, "Invalid length");
                break;
            }
-           proto_tree_add_text(rsvp_object_tree, tvb, offset+4+remaining_length, 4,
+           iter++;
+           proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
                                "PLR ID %d: %s", count, 
-                               ip_to_str(tvb_get_ptr(tvb, offset+4+remaining_length, 4)));
-           proto_tree_add_text(rsvp_object_tree, tvb, offset+4+remaining_length, 4,
+                               ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
+           iter++;
+           proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
                                "Avoid Node ID %d: %s", count, 
-                               ip_to_str(tvb_get_ptr(tvb, offset+4+remaining_length, 4)));
+                               ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
        }
        break;
 
@@ -3908,6 +4151,72 @@ dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
     }
 }
 
+/*------------------------------------------------------------------------------
+ * DIFFSERV
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_diffserv (proto_tree *ti, tvbuff_t *tvb,
+                      int offset, int obj_length,
+                      int class, int type,
+                      char *type_str
+                      )
+{
+    proto_tree *rsvp_object_tree;
+    int mapnb, count;
+    int *hfindexes[] = {
+       &rsvp_filter[RSVPF_DIFFSERV_MAP],
+       &rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
+       &rsvp_filter[RSVPF_DIFFSERV_PHBID],
+       &rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
+       &rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
+       &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
+       &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15]
+    };
+    gint *etts[] = {
+       &TREE(TT_DIFFSERV_MAP),
+       &TREE(TT_DIFFSERV_MAP_PHBID)
+    };
+
+    rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DIFFSERV));
+    proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+                       "Length: %u", obj_length);
+    proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+                       "Class number: %u - %s",
+                       class, type_str);
+    proto_item_set_text(ti, "DIFFSERV: ");
+    offset += 3;
+    switch (type) {
+    case 1:
+       proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+                           "C-type: 1 - E-LSP");
+       proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_DIFFSERV_MAPNB],
+                           tvb, offset + 4, 1,
+                           mapnb = tvb_get_guint8(tvb, offset + 4) & 15);
+       proto_item_append_text(ti, "E-LSP, %u MAP%s", mapnb,
+                              (mapnb == 0) ? "" : "s");
+       offset += 5;
+
+       for (count = 0; count < mapnb; count++) {
+           dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
+                                        offset, hfindexes, etts);
+           offset += 4;
+       }
+       break;
+    case 2:
+       proto_item_append_text(ti, "L-LSP");
+       proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+                           "C-type: 2 - L-LSP");
+       dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
+                                    offset + 3, hfindexes, etts);
+       break;
+    default:
+       proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+                           "C-type: Unknown (%u)", type);
+       proto_tree_add_text(rsvp_object_tree, tvb, offset + 1, obj_length - 4,
+                           "Data (%d bytes)", obj_length - 4);
+    }
+}
+
 /*------------------------------------------------------------------------------
  * Dissect a single RSVP message in a tree
  *------------------------------------------------------------------------------*/
@@ -4174,6 +4483,10 @@ dissect_rsvp_msg_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
            dissect_rsvp_detour(ti, tvb, offset, obj_length, class, type, type_str);
            break;
 
+       case RSVP_CLASS_DIFFSERV:
+           dissect_rsvp_diffserv(ti, tvb, offset, obj_length, class, type, type_str);
+           break;
+
        case RSVP_CLASS_NULL:
        default:
            rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_UNKNOWN_CLASS));