Provide data to inner dissector for PER open type
[metze/wireshark/wip.git] / epan / dissectors / packet-lwm2mtlv.c
index b37c66039ef805e3b22d87e85e6fb6bb2138a493..325155fbe3af16f0c789d87e03bb8b9284d8fd8b 100644 (file)
@@ -1,11 +1,12 @@
 /* packet-lwm2mtlv.c
  * Routines for LWM2M TLV dissection
  * References:
- *     OMA LWM2M Specification: OMA-TS-LightweightM2M-V1_0-20151214-C.pdf
+ *     OMA LWM2M Specification: OMA-TS-LightweightM2M_Core-V1_1-20180710-A.pdf
  *     available from
- *     http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0
+ *     http://openmobilealliance.org/release/LightweightM2M/V1_1-20180710-A/
  *
  * Copyright 2016, Christoph Burger-Scheidlin
+ * Copyright 2018, Stig Bjorlykke <stig@bjorlykke.org>
  *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
@@ -31,6 +32,7 @@ static void parseArrayOfElements(tvbuff_t *tvb, proto_tree *tlv_tree, const char
 static int proto_lwm2mtlv = -1;
 
 static int hf_lwm2mtlv_object_name               = -1;
+static int hf_lwm2mtlv_resource_name             = -1;
 static int hf_lwm2mtlv_header                    = -1;
 static int hf_lwm2mtlv_type_type                 = -1;
 static int hf_lwm2mtlv_type_length_of_identifier = -1;
@@ -43,6 +45,7 @@ static int hf_lwm2mtlv_length                    = -1;
 static int hf_lwm2mtlv_value                     = -1;
 static int hf_lwm2mtlv_value_string              = -1;
 static int hf_lwm2mtlv_value_integer             = -1;
+static int hf_lwm2mtlv_value_unsigned_integer    = -1;
 static int hf_lwm2mtlv_value_float               = -1;
 static int hf_lwm2mtlv_value_double              = -1;
 static int hf_lwm2mtlv_value_boolean             = -1;
@@ -108,147 +111,189 @@ typedef struct _lwm2m_resource_t {
        char   *name;
        guint   data_type;
        gint   *hf_id;
+       gint   *ett_id;
        char   *field_name;
 } lwm2m_resource_t;
 
-#define DATA_TYPE_NONE    0
-#define DATA_TYPE_STRING  1
-#define DATA_TYPE_INTEGER 2
-#define DATA_TYPE_FLOAT   3
-#define DATA_TYPE_BOOLEAN 4
-#define DATA_TYPE_OPAQUE  5
-#define DATA_TYPE_TIME    6
-#define DATA_TYPE_OBJLNK  7
+/* RESOURCE_FILL initializes all the dynamic fields in a lwm2m_resource_t. */
+#define RESOURCE_FILL NULL, NULL, NULL
+
+#define DATA_TYPE_NONE             0
+#define DATA_TYPE_STRING           1
+#define DATA_TYPE_INTEGER          2
+#define DATA_TYPE_UNSIGNED_INTEGER 3
+#define DATA_TYPE_FLOAT            4
+#define DATA_TYPE_BOOLEAN          5
+#define DATA_TYPE_OPAQUE           6
+#define DATA_TYPE_TIME             7
+#define DATA_TYPE_OBJLNK           8
+#define DATA_TYPE_CORELNK          9
 
 static const value_string data_types[] = {
-       { DATA_TYPE_NONE,    "None"    },
-       { DATA_TYPE_STRING,  "String"  },
-       { DATA_TYPE_INTEGER, "Integer" },
-       { DATA_TYPE_FLOAT,   "Float"   },
-       { DATA_TYPE_BOOLEAN, "Boolean" },
-       { DATA_TYPE_OPAQUE,  "Opaque"  },
-       { DATA_TYPE_TIME,    "Time"    },
-       { DATA_TYPE_OBJLNK,  "Objlnk"  },
+       { DATA_TYPE_NONE,             "None"             },
+       { DATA_TYPE_STRING,           "String"           },
+       { DATA_TYPE_INTEGER,          "Integer"          },
+       { DATA_TYPE_UNSIGNED_INTEGER, "Unsigned Integer" },
+       { DATA_TYPE_FLOAT,            "Float"            },
+       { DATA_TYPE_BOOLEAN,          "Boolean"          },
+       { DATA_TYPE_OPAQUE,           "Opaque"           },
+       { DATA_TYPE_TIME,             "Time"             },
+       { DATA_TYPE_OBJLNK,           "Objlnk"           },
+       { DATA_TYPE_CORELNK,          "Corelnk"          },
        { 0, NULL }
 };
 
 /* LwM2M Objects defined by OMA (Normative) */
 static const value_string lwm2m_oma_objects[] = {
-       { 0, "LwM2M Security"          },
-       { 1, "LwM2M Server"            },
-       { 2, "Access Control"          },
-       { 3, "Device"                  },
-       { 4, "Connectivity Monitoring" },
-       { 5, "Firmware Update"         },
-       { 6, "Location"                },
-       { 7, "Connectivity Statistics" },
+       { 0,  "LwM2M Security"          },
+       { 1,  "LwM2M Server"            },
+       { 2,  "Access Control"          },
+       { 3,  "Device"                  },
+       { 4,  "Connectivity Monitoring" },
+       { 5,  "Firmware Update"         },
+       { 6,  "Location"                },
+       { 7,  "Connectivity Statistics" },
+       { 21, "OSCORE"                  },
        { 0, NULL }
 };
 
 static lwm2m_resource_t lwm2m_oma_resources[] =
 {
        /* LwM2M Security (0) */
-       { 0, 0,  "LwM2M Server URI", DATA_TYPE_STRING, NULL, NULL },
-       { 0, 1,  "Bootstrap-Server", DATA_TYPE_BOOLEAN, NULL, NULL },
-       { 0, 2,  "Security Mode", DATA_TYPE_INTEGER, NULL, NULL },
-       { 0, 3,  "Public Key or Identity", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 0, 4,  "Server Public Key", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 0, 5,  "Secret Key", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 0, 6,  "SMS Security Mode", DATA_TYPE_INTEGER, NULL, NULL },
-       { 0, 7,  "SMS Binding Key Parameters", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 0, 8,  "SMS Binding Secret Keys", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 0, 9,  "LwM2M Server SMS Number", DATA_TYPE_STRING, NULL, NULL },
-       { 0, 10, "Short Server ID", DATA_TYPE_INTEGER, NULL, NULL },
-       { 0, 11, "Client Hold Off Time", DATA_TYPE_INTEGER, NULL, NULL },
-       { 0, 12, "Bootstrap-Server Account Timeout", DATA_TYPE_INTEGER, NULL, NULL },
+       { 0, 0,  "LwM2M Server URI", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 0, 1,  "Bootstrap-Server", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
+       { 0, 2,  "Security Mode", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 0, 3,  "Public Key or Identity", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 0, 4,  "Server Public Key", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 0, 5,  "Secret Key", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 0, 6,  "SMS Security Mode", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 0, 7,  "SMS Binding Key Parameters", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 0, 8,  "SMS Binding Secret Keys", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 0, 9,  "LwM2M Server SMS Number", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 0, 10, "Short Server ID", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 0, 11, "Client Hold Off Time", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 0, 12, "Bootstrap-Server Account Timeout", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 0, 13, "Matching Type", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 0, 14, "SNI", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 0, 15, "Certificate Usage", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 0, 16, "TLS DTLS Ciphersuite", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 0, 17, "OSCORE Security Mode", DATA_TYPE_OBJLNK, RESOURCE_FILL },
 
        /* LwM2M Server (1) */
-       { 1, 0,  "Short Server ID", DATA_TYPE_INTEGER, NULL, NULL },
-       { 1, 1,  "Lifetime", DATA_TYPE_INTEGER, NULL, NULL },
-       { 1, 2,  "Default Minimum Period", DATA_TYPE_INTEGER, NULL, NULL },
-       { 1, 3,  "Default Maximum Period", DATA_TYPE_INTEGER, NULL, NULL },
-       { 1, 4,  "Disable", DATA_TYPE_NONE, NULL, NULL },
-       { 1, 5,  "Disable Timeout", DATA_TYPE_INTEGER, NULL, NULL },
-       { 1, 6,  "Notification Storing When Disabled or Offline", DATA_TYPE_BOOLEAN, NULL, NULL },
-       { 1, 7,  "Binding", DATA_TYPE_STRING, NULL, NULL },
+       { 1, 0,  "Short Server ID", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 1, 1,  "Lifetime", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 1, 2,  "Default Minimum Period", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 1, 3,  "Default Maximum Period", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 1, 4,  "Disable", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 1, 5,  "Disable Timeout", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 1, 6,  "Notification Storing When Disabled or Offline", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
+       { 1, 7,  "Binding", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 1, 8,  "Registration Update Trigger", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 1, 9,  "Bootstrap Request Trigger", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 1, 10, "APN Link", DATA_TYPE_OBJLNK, RESOURCE_FILL },
+       { 1, 11, "TLS DTLS Alert Code", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 12, "Last Bootstrapped", DATA_TYPE_TIME, RESOURCE_FILL },
+       { 1, 13, "Registration Priority Order", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 14, "Initial Registration Delay Timer", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 15, "Registration Failure Block", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
+       { 1, 16, "Bootstrap on Registration Failure", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
+       { 1, 17, "Communication Retry Count", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 18, "Communication Retry Timer", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 19, "Communication Sequence Delay Timer", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 20, "Communication Sequence Retry Count", DATA_TYPE_UNSIGNED_INTEGER, RESOURCE_FILL },
+       { 1, 21, "Trigger", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
+       { 1, 22, "Preferred Transport", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 1, 23, "Mute Send", DATA_TYPE_BOOLEAN, RESOURCE_FILL },
 
        /* Access Control (2) */
-       { 2, 0,  "Object ID", DATA_TYPE_INTEGER, NULL, NULL },
-       { 2, 1,  "Object Instance ID", DATA_TYPE_INTEGER, NULL, NULL },
-       { 2, 2,  "ACL", DATA_TYPE_INTEGER, NULL, NULL },
-       { 2, 3,  "Access Control Owner", DATA_TYPE_INTEGER, NULL, NULL },
+       { 2, 0,  "Object ID", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 2, 1,  "Object Instance ID", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 2, 2,  "ACL", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 2, 3,  "Access Control Owner", DATA_TYPE_INTEGER, RESOURCE_FILL },
 
        /* Device (3) */
-       { 3, 0,  "Manufacturer", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 1,  "Model Number", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 2,  "Serial Number", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 3,  "Firmware Version", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 4,  "Reboot", DATA_TYPE_NONE, NULL, NULL },
-       { 3, 5,  "Factory Reset", DATA_TYPE_NONE, NULL, NULL },
-       { 3, 6,  "Available Power Sources", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 7,  "Power Source Voltage", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 8,  "Power Source Current", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 9,  "Battery Level", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 10, "Memory Free", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 11, "Error Code", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 12, "Reset Error Code", DATA_TYPE_NONE, NULL, NULL },
-       { 3, 13, "Current Time", DATA_TYPE_TIME, NULL, NULL },
-       { 3, 14, "UTC Offset", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 15, "Timezone", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 16, "Supported Binding and Modes", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 17, "Device Type", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 18, "Hardware Version", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 19, "Software Version", DATA_TYPE_STRING, NULL, NULL },
-       { 3, 20, "Battery Status", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 21, "Memory Total", DATA_TYPE_INTEGER, NULL, NULL },
-       { 3, 22, "ExtDevInfo", DATA_TYPE_OBJLNK, NULL, NULL },
+       { 3, 0,  "Manufacturer", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 1,  "Model Number", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 2,  "Serial Number", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 3,  "Firmware Version", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 4,  "Reboot", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 3, 5,  "Factory Reset", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 3, 6,  "Available Power Sources", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 7,  "Power Source Voltage", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 8,  "Power Source Current", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 9,  "Battery Level", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 10, "Memory Free", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 11, "Error Code", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 12, "Reset Error Code", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 3, 13, "Current Time", DATA_TYPE_TIME, RESOURCE_FILL },
+       { 3, 14, "UTC Offset", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 15, "Timezone", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 16, "Supported Binding and Modes", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 17, "Device Type", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 18, "Hardware Version", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 19, "Software Version", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 3, 20, "Battery Status", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 21, "Memory Total", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 3, 22, "ExtDevInfo", DATA_TYPE_OBJLNK, RESOURCE_FILL },
 
        /* Connectivity Monitoring (4) */
-       { 4, 0,  "Network Bearer", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 1,  "Available Network Bearer", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 2,  "Radio Signal Strength", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 3,  "Link Quality", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 4,  "IP Addresses", DATA_TYPE_STRING, NULL, NULL },
-       { 4, 5,  "Router IP Addresses", DATA_TYPE_STRING, NULL, NULL },
-       { 4, 6,  "Link Utilization", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 7,  "APN", DATA_TYPE_STRING, NULL, NULL },
-       { 4, 8,  "Cell ID", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 9,  "SMNC", DATA_TYPE_INTEGER, NULL, NULL },
-       { 4, 10, "SMCC", DATA_TYPE_INTEGER, NULL, NULL },
+       { 4, 0,  "Network Bearer", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 1,  "Available Network Bearer", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 2,  "Radio Signal Strength", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 3,  "Link Quality", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 4,  "IP Addresses", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 4, 5,  "Router IP Addresses", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 4, 6,  "Link Utilization", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 7,  "APN", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 4, 8,  "Cell ID", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 9,  "SMNC", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 10, "SMCC", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 4, 11, "SignalSNR", DATA_TYPE_INTEGER, RESOURCE_FILL },
 
        /* Firmware Update (5) */
-       { 5, 0,  "Package", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 5, 1,  "Package URI", DATA_TYPE_STRING, NULL, NULL },
-       { 5, 2,  "Update", DATA_TYPE_NONE, NULL, NULL },
-       { 5, 3,  "State", DATA_TYPE_INTEGER, NULL, NULL },
-       /* { 5, 4,  "", DATA_TYPE_NONE, NULL, NULL }, */
-       { 5, 5,  "Update Result", DATA_TYPE_INTEGER, NULL, NULL },
-       { 5, 6,  "PkgName", DATA_TYPE_STRING, NULL, NULL },
-       { 5, 7,  "PkgVersion", DATA_TYPE_STRING, NULL, NULL },
-       { 5, 8,  "Firmware Update Protocol Support", DATA_TYPE_INTEGER, NULL, NULL },
-       { 5, 9,  "Firmware Update Delivery Method", DATA_TYPE_INTEGER, NULL, NULL },
+       { 5, 0,  "Package", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 5, 1,  "Package URI", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 5, 2,  "Update", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 5, 3,  "State", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       /* { 5, 4,  "", DATA_TYPE_NONE, RESOURCE_FILL }, */
+       { 5, 5,  "Update Result", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 5, 6,  "PkgName", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 5, 7,  "PkgVersion", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 5, 8,  "Firmware Update Protocol Support", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 5, 9,  "Firmware Update Delivery Method", DATA_TYPE_INTEGER, RESOURCE_FILL },
 
        /* Location (6) */
-       { 6, 0,  "Latitude", DATA_TYPE_FLOAT, NULL, NULL },
-       { 6, 1,  "Longitude", DATA_TYPE_FLOAT, NULL, NULL },
-       { 6, 2,  "Altitude", DATA_TYPE_FLOAT, NULL, NULL },
-       { 6, 3,  "Radius", DATA_TYPE_FLOAT, NULL, NULL },
-       { 6, 4,  "Velocity", DATA_TYPE_OPAQUE, NULL, NULL },
-       { 6, 5,  "Timestamp", DATA_TYPE_TIME, NULL, NULL },
-       { 6, 6,  "Speed", DATA_TYPE_FLOAT, NULL, NULL },
+       { 6, 0,  "Latitude", DATA_TYPE_FLOAT, RESOURCE_FILL },
+       { 6, 1,  "Longitude", DATA_TYPE_FLOAT, RESOURCE_FILL },
+       { 6, 2,  "Altitude", DATA_TYPE_FLOAT, RESOURCE_FILL },
+       { 6, 3,  "Radius", DATA_TYPE_FLOAT, RESOURCE_FILL },
+       { 6, 4,  "Velocity", DATA_TYPE_OPAQUE, RESOURCE_FILL },
+       { 6, 5,  "Timestamp", DATA_TYPE_TIME, RESOURCE_FILL },
+       { 6, 6,  "Speed", DATA_TYPE_FLOAT, RESOURCE_FILL },
 
        /* Connectivity Statistics (7) */
-       { 7, 0,  "SMS Tx Counter", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 1,  "SMS Rx Counter", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 2,  "Tx Data", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 3,  "Rx Data", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 4,  "Max Message Size", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 5,  "Average Message Size", DATA_TYPE_INTEGER, NULL, NULL },
-       { 7, 6,  "Start", DATA_TYPE_NONE, NULL, NULL },
-       { 7, 7,  "Stop", DATA_TYPE_NONE, NULL, NULL },
-       { 7, 8,  "Collection Period", DATA_TYPE_INTEGER, NULL, NULL },
+       { 7, 0,  "SMS Tx Counter", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 1,  "SMS Rx Counter", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 2,  "Tx Data", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 3,  "Rx Data", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 4,  "Max Message Size", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 5,  "Average Message Size", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 7, 6,  "Start", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 7, 7,  "Stop", DATA_TYPE_NONE, RESOURCE_FILL },
+       { 7, 8,  "Collection Period", DATA_TYPE_INTEGER, RESOURCE_FILL },
+
+       /* OSCORE (21) */
+       { 21, 0, "Master Secret", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 21, 1, "Sender ID", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 21, 2, "Recipient ID", DATA_TYPE_STRING, RESOURCE_FILL },
+       { 21, 3, "AEAD Algorithm", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 21, 4, "HMAC Algorithm", DATA_TYPE_INTEGER, RESOURCE_FILL },
+       { 21, 5, "Master Salt", DATA_TYPE_STRING, RESOURCE_FILL },
 };
 
+static hf_register_info *static_hf;
+static GArray *static_ett;
+
 /* LwM2M Objects defined by User */
 static lwm2m_object_name_t *lwm2m_uat_object_names;
 static guint num_lwm2m_uat_object_names;
@@ -257,7 +302,7 @@ static guint num_lwm2m_uat_resources;
 
 static hf_register_info *dynamic_hf;
 static guint dynamic_hf_size;
-static hf_register_info *static_hf;
+static GArray *dynamic_ett;
 
 static gboolean lwm2m_object_name_update_cb(void *record, char **error)
 {
@@ -359,11 +404,14 @@ static void lwm2m_resource_free_cb(void *record)
 static void lwm2m_add_resource(lwm2m_resource_t *resource, hf_register_info *hf)
 {
        gchar *resource_abbrev;
-       gint *hf_id;
+       gint *hf_id, *ett_id;
 
        hf_id = g_new(gint,1);
        *hf_id = -1;
 
+       ett_id = g_new(gint, 1);
+       *ett_id = -1;
+
        if (resource->field_name) {
                resource_abbrev = g_strdup(resource->field_name);
        } else {
@@ -376,6 +424,7 @@ static void lwm2m_add_resource(lwm2m_resource_t *resource, hf_register_info *hf)
        }
 
        resource->hf_id = hf_id;
+       resource->ett_id = ett_id;
 
        hf->p_id = hf_id;
        hf->hfinfo.name = g_strdup(resource->name);
@@ -384,6 +433,7 @@ static void lwm2m_add_resource(lwm2m_resource_t *resource, hf_register_info *hf)
 
        switch (resource->data_type) {
        case DATA_TYPE_STRING:
+       case DATA_TYPE_CORELNK:
                hf->hfinfo.display = BASE_NONE;
                hf->hfinfo.type = FT_STRING;
                break;
@@ -391,6 +441,10 @@ static void lwm2m_add_resource(lwm2m_resource_t *resource, hf_register_info *hf)
                hf->hfinfo.display = BASE_DEC;
                hf->hfinfo.type = FT_INT64;
                break;
+       case DATA_TYPE_UNSIGNED_INTEGER:
+               hf->hfinfo.display = BASE_DEC;
+               hf->hfinfo.type = FT_UINT64;
+               break;
        case DATA_TYPE_FLOAT:
                hf->hfinfo.display = BASE_NONE;
                hf->hfinfo.type = FT_FLOAT;
@@ -429,6 +483,11 @@ static void deregister_resource_fields(void)
                dynamic_hf = NULL;
                dynamic_hf_size = 0;
        }
+
+       if (dynamic_ett) {
+               proto_add_deregistered_data(g_array_free(dynamic_ett, TRUE));
+               dynamic_ett = NULL;
+       }
 }
 
 static void lwm2m_resource_post_update_cb(void)
@@ -437,12 +496,15 @@ static void lwm2m_resource_post_update_cb(void)
 
        if (num_lwm2m_uat_resources) {
                dynamic_hf = g_new0(hf_register_info, num_lwm2m_uat_resources);
+               dynamic_ett = g_array_new(TRUE, TRUE, sizeof(gint*));
 
                for (guint i = 0; i < num_lwm2m_uat_resources; i++) {
                        lwm2m_add_resource(&lwm2m_uat_resources[i], &dynamic_hf[dynamic_hf_size++]);
+                       g_array_append_val(dynamic_ett, lwm2m_uat_resources[i].ett_id);
                }
 
                proto_register_field_array(proto_lwm2mtlv, dynamic_hf, dynamic_hf_size);
+               proto_register_subtree_array((gint**)(void*)dynamic_ett->data, dynamic_ett->len);
        }
 }
 
@@ -518,6 +580,7 @@ static proto_tree*
 addElementTree(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *element, const lwm2m_resource_t *resource)
 {
        gchar *identifier = NULL;
+       gint ett_id;
 
        if (resource) {
                identifier = wmem_strdup_printf(wmem_packet_scope(), "[%02u] %s", element->identifier, resource->name);
@@ -536,11 +599,13 @@ addElementTree(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *element, con
                                                     "%02u", element->identifier);
 
        case RESOURCE_ARRAY:
-               return proto_tree_add_subtree_format(tlv_tree, tvb, 0, element->totalLength, ett_lwm2mtlv_resourceArray, NULL,
+               ett_id = resource ? *resource->ett_id : ett_lwm2mtlv_resourceArray;
+               return proto_tree_add_subtree_format(tlv_tree, tvb, 0, element->totalLength, ett_id, NULL,
                                                     "%s", identifier);
 
        case RESOURCE:
-               return proto_tree_add_subtree_format(tlv_tree, tvb, 0, element->totalLength, ett_lwm2mtlv_resource, NULL,
+               ett_id = resource ? *resource->ett_id : ett_lwm2mtlv_resource;
+               return proto_tree_add_subtree_format(tlv_tree, tvb, 0, element->totalLength, ett_id, NULL,
                                                     "%s", identifier);
        }
        return NULL;
@@ -557,6 +622,7 @@ addValueInterpretations(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *ele
        if (resource && resource->data_type != DATA_TYPE_NONE) {
                switch (resource->data_type) {
                case DATA_TYPE_STRING:
+               case DATA_TYPE_CORELNK:
                {
                        const guint8 *strval;
                        proto_tree_add_item_ret_string(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, ENC_UTF_8, wmem_packet_scope(), &strval);
@@ -567,6 +633,13 @@ addValueInterpretations(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *ele
                        proto_tree_add_item(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_item_append_text(tlv_tree, ": %" G_GINT64_FORMAT, decodeVariableInt(tvb, valueOffset, element->length_of_value));
                        break;
+               case DATA_TYPE_UNSIGNED_INTEGER:
+               {
+                       guint64 value;
+                       proto_tree_add_item_ret_uint64(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN, &value);
+                       proto_item_append_text(tlv_tree, ": %" G_GUINT64_FORMAT, value);
+                       break;
+               }
                case DATA_TYPE_FLOAT:
                        proto_tree_add_item(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_item_append_text(tlv_tree, ": %." G_STRINGIFY(FLT_DIG) "g", tvb_get_ieee_float(tvb, valueOffset, ENC_BIG_ENDIAN));
@@ -587,8 +660,15 @@ addValueInterpretations(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *ele
                        proto_item_append_text(tlv_tree, ": %s", abs_time_to_str(wmem_packet_scope(), &ts, ABSOLUTE_TIME_LOCAL, FALSE));
                        break;
                }
-               case DATA_TYPE_OPAQUE:
                case DATA_TYPE_OBJLNK:
+               {
+                       guint16 lnk1 = tvb_get_guint16(tvb, valueOffset, ENC_BIG_ENDIAN);
+                       guint16 lnk2 = tvb_get_guint16(tvb, valueOffset + 2, ENC_BIG_ENDIAN);
+                       proto_tree_add_bytes_format(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, NULL, "%u:%u", lnk1, lnk2);
+                       proto_item_append_text(tlv_tree, ": %u:%u", lnk1, lnk2);
+                       break;
+               }
+               case DATA_TYPE_OPAQUE:
                default:
                        proto_tree_add_item(tlv_tree, *resource->hf_id, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_item_append_text(tlv_tree, ": %s", tvb_bytes_to_str(wmem_packet_scope(), tvb, valueOffset, element->length_of_value));
@@ -606,20 +686,24 @@ addValueInterpretations(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *ele
                switch(element->length_of_value) {
                case 0x01:
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_unsigned_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        if (tvb_get_guint8(tvb, valueOffset) < 2) {
                                proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_boolean, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        }
                        break;
                case 0x02:
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_unsigned_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        break;
                case 0x04:
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_unsigned_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_float, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_timestamp, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        break;
                case 0x08:
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_unsigned_integer, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_double, tvb, valueOffset, element->length_of_value, ENC_BIG_ENDIAN);
                        /* apparently, wireshark does not deal well with 8 bytes. */
                        proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value_timestamp, tvb, valueOffset+4, element->length_of_value-4, ENC_BIG_ENDIAN);
@@ -633,6 +717,11 @@ addValueTree(tvbuff_t *tvb, proto_tree *tlv_tree, lwm2mElement_t *element, const
 {
        guint valueOffset = 1 + element->length_of_identifier + element->length_of_length;
 
+       if (resource && (element->type == RESOURCE || element->type == RESOURCE_ARRAY)) {
+               proto_item *ti = proto_tree_add_string(tlv_tree, hf_lwm2mtlv_resource_name, tvb, 0, 0, resource->name);
+               PROTO_ITEM_SET_GENERATED(ti);
+       }
+
        if ( element->type == RESOURCE || element->type == RESOURCE_INSTANCE ) {
                proto_tree_add_item(tlv_tree, hf_lwm2mtlv_value, tvb, valueOffset, element->length_of_value, ENC_NA);
                addValueInterpretations(tvb, tlv_tree, element, resource);
@@ -816,6 +905,9 @@ static void lwm2m_shutdown_routine(void)
 
        proto_add_deregistered_data(static_hf);
        static_hf = NULL;
+
+       proto_add_deregistered_data(g_array_free(static_ett, TRUE));
+       static_ett = NULL;
 }
 
 void proto_register_lwm2mtlv(void)
@@ -826,6 +918,11 @@ void proto_register_lwm2mtlv(void)
                                FT_STRING, BASE_NONE, NULL, 0,
                                NULL, HFILL }
                },
+               { &hf_lwm2mtlv_resource_name,
+                       { "Resource Name", "lwm2mtlv.resource_name",
+                               FT_STRING, BASE_NONE, NULL, 0,
+                               NULL, HFILL }
+               },
                { &hf_lwm2mtlv_header,
                        { "TLV header", "lwm2mtlv.header",
                                FT_NONE, BASE_NONE, NULL, 0x0,
@@ -881,6 +978,11 @@ void proto_register_lwm2mtlv(void)
                                FT_INT64, BASE_DEC, NULL, 0,
                                NULL, HFILL }
                },
+               { &hf_lwm2mtlv_value_unsigned_integer,
+                       { "As Unsigned Integer", "lwm2mtlv.value.unsigned_integer",
+                               FT_UINT64, BASE_DEC, NULL, 0,
+                               NULL, HFILL }
+               },
                { &hf_lwm2mtlv_value_float,
                        { "As Float", "lwm2mtlv.value.float",
                                FT_FLOAT, BASE_NONE, NULL, 0,
@@ -986,10 +1088,15 @@ void proto_register_lwm2mtlv(void)
                                      resource_uat);
 
        static_hf = g_new0(hf_register_info, array_length(lwm2m_oma_resources));
+       static_ett = g_array_new(TRUE, TRUE, sizeof(gint*));
+
        for (guint i = 0; i < array_length(lwm2m_oma_resources); i++) {
                lwm2m_add_resource(&lwm2m_oma_resources[i], &static_hf[i]);
+               g_array_append_val(static_ett, lwm2m_oma_resources[i].ett_id);
        }
+
        proto_register_field_array(proto_lwm2mtlv, static_hf, array_length(lwm2m_oma_resources));
+       proto_register_subtree_array((gint**)(void*)static_ett->data, static_ett->len);
 }
 
 void