static int dissect_PNMRRT_PDU(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *item) { guint16 version; guint8 type; guint8 length; gint i = 0; /* MRRT_Version */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrrt_version, &version); while (tvb_reported_length_remaining(tvb, offset) > 0) { /* MRRT_TLVHeader.Type */ offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrrt_type, &type); /* MRRT_TLVHeader.Length */ offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrrt_length, &length); if (i != 0) { col_append_str(pinfo->cinfo, COL_INFO, ", "); proto_item_append_text(item, ", "); } i++; switch(type) { case 0x00: /* no content */ col_append_str(pinfo->cinfo, COL_INFO, "End"); proto_item_append_text(item, "End"); return offset; break; case 0x01: offset = dissect_PNMRRT_Common(tvb, offset, pinfo, tree, item, length); break; case 0x02: offset = dissect_PNMRRT_Test(tvb, offset, pinfo, tree, item, length); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type); proto_item_append_text(item, "Unknown TLVType 0x%x", type); break; } } return offset; }
/* dissect the "DHCP" suboption */ static int dissect_PNDCP_Suboption_DHCP(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id _U_, gboolean is_response _U_) { guint8 suboption; guint16 block_length; guint16 block_info; guint16 block_qualifier; gboolean have_block_info = FALSE; gboolean have_block_qualifier = FALSE; offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp, &suboption); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); /* BlockInfo? */ if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); have_block_info=TRUE; block_length -= 2; } /* BlockQualifier? */ if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); have_block_qualifier=TRUE; block_length -= 2; } switch (suboption) { case PNDCP_SUBOPTION_DHCP_CLIENT_ID: pn_append_info(pinfo, dcp_item, ", DHCP client identifier"); proto_item_append_text(block_item, "DHCP/Client-ID"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_tree_add_item(tree, hf_pn_dcp_suboption_dhcp_device_id, tvb, offset, block_length, ENC_NA); offset += block_length; break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
/* dissect one DCP block */ static int dissect_PNDCP_Block(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *dcp_item, guint8 service_id, gboolean is_response) { guint8 option; proto_item *block_item; proto_tree *block_tree; int ori_offset = offset; /* subtree for block */ block_item = proto_tree_add_none_format(tree, hf_pn_dcp_block, tvb, offset, 0, "Block: "); block_tree = proto_item_add_subtree(block_item, ett_pn_dcp_block); offset = dissect_pn_uint8(tvb, offset, pinfo, block_tree, hf_pn_dcp_option, &option); switch (option) { case PNDCP_OPTION_IP: offset = dissect_PNDCP_Suboption_IP(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_DEVICE: offset = dissect_PNDCP_Suboption_Device(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_DHCP: offset = dissect_PNDCP_Suboption_DHCP(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_CONTROL: offset = dissect_PNDCP_Suboption_Control(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_DEVICEINITIATIVE: offset = dissect_PNDCP_Suboption_DeviceInitiative(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_ALLSELECTOR: offset = dissect_PNDCP_Suboption_All(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); break; case PNDCP_OPTION_MANUF_X80: case PNDCP_OPTION_MANUF_X81: default: offset = dissect_PNDCP_Suboption_Manuf(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); } proto_item_set_len(block_item, offset-ori_offset); if ((offset-ori_offset) & 1) { /* we have an odd number of bytes in this block, add a padding byte */ offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); } return offset; }
/* dissect the option field */ static int dissect_PNDCP_Option(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, int hfindex, gboolean append_col) { guint8 option; guint8 suboption; const value_string *val_str; offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hfindex, &option); switch (option) { case PNDCP_OPTION_IP: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip, &suboption); val_str = pn_dcp_suboption_ip; break; case PNDCP_OPTION_DEVICE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption); val_str = pn_dcp_suboption_device; break; case PNDCP_OPTION_DHCP: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp, &suboption); val_str = pn_dcp_suboption_dhcp; break; case PNDCP_OPTION_CONTROL: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control, &suboption); val_str = pn_dcp_suboption_control; break; case PNDCP_OPTION_DEVICEINITIATIVE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_deviceinitiative, &suboption); val_str = pn_dcp_suboption_deviceinitiative; break; case PNDCP_OPTION_ALLSELECTOR: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_all, &suboption); val_str = pn_dcp_suboption_all; break; default: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_manuf, &suboption); val_str = pn_dcp_suboption_manuf; } proto_item_append_text(block_item, ", Status from %s - %s", val_to_str(option, pn_dcp_option, "Unknown"), val_to_str(suboption, val_str, "Unknown")); if (append_col) { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(suboption, val_str, "Unknown")); } return offset; }
/* dissect the "deviceinitaitve" suboption */ static int dissect_PNDCP_Suboption_DeviceInitiative(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id, gboolean is_response) { guint8 suboption; guint16 block_length; guint16 block_info; guint16 block_qualifier; guint16 value; offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_deviceinitiative, &suboption); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); pn_append_info(pinfo, dcp_item, ", DeviceInitiative"); proto_item_append_text(block_item, "DeviceInitiative/DeviceInitiative"); /* BlockInfo? */ if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); block_length -= 2; } /* BlockQualifier? */ if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); block_length -= 2; } /* DeviceInitiativeValue */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_deviceinitiative_value, &value); return offset; }
/* dissect the "manufacturer" suboption */ static int dissect_PNDCP_Suboption_Manuf(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id _U_, gboolean is_response _U_) { guint8 suboption; guint16 block_length; offset = dissect_pn_uint8( tvb, offset, pinfo, tree, hf_pn_dcp_suboption_manuf, &suboption); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); switch (suboption) { default: pn_append_info(pinfo, dcp_item, ", Manufacturer Specific"); proto_item_append_text(block_item, "Manufacturer Specific"); offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
/* dissect the "all" suboption */ static int dissect_PNDCP_Suboption_All(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id _U_, gboolean is_response _U_) { guint8 suboption; guint16 block_length; offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_all, &suboption); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); switch (suboption) { case 255: /* All */ pn_append_info(pinfo, dcp_item, ", All"); proto_item_append_text(block_item, "All/All"); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
static int dissect_PNMRP_PDU(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *item) { guint16 version; guint8 type; guint8 length; gint i; tvbuff_t *new_tvb; /* MRP_Version */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_version, &version); /* the rest of the packet has 4byte alignment regarding to the beginning of the next TLV block! */ /* XXX - do we have to free this new tvb below? */ new_tvb = tvb_new_subset_remaining(tvb, offset); offset = 0; for(i=0; tvb_length_remaining(tvb, offset) > 0; i++) { /* MRP_TLVHeader.Type */ offset = dissect_pn_uint8(new_tvb, offset, pinfo, tree, hf_pn_mrp_type, &type); /* MRP_TLVHeader.Length */ offset = dissect_pn_uint8(new_tvb, offset, pinfo, tree, hf_pn_mrp_length, &length); if(i != 0) { col_append_str(pinfo->cinfo, COL_INFO, ", "); proto_item_append_text(item, ", "); } switch(type) { case(0x00): /* no content */ col_append_str(pinfo->cinfo, COL_INFO, "End"); proto_item_append_text(item, "End"); return offset; break; case(0x01): offset = dissect_PNMRP_Common(new_tvb, offset, pinfo, tree, item); break; case(0x02): offset = dissect_PNMRP_Test(new_tvb, offset, pinfo, tree, item); break; case(0x03): offset = dissect_PNMRP_TopologyChange(new_tvb, offset, pinfo, tree, item); break; case(0x04): offset = dissect_PNMRP_LinkDown(new_tvb, offset, pinfo, tree, item); break; case(0x05): offset = dissect_PNMRP_LinkUp(new_tvb, offset, pinfo, tree, item); break; case(0x7f): offset = dissect_PNMRP_Option(new_tvb, offset, pinfo, tree, item, length); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type); proto_item_append_text(item, "Unknown TLVType 0x%x", type); } } return offset; }
/* dissect a whole DCP PDU */ static void dissect_PNDCP_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *dcp_item) { guint8 service_id; guint8 service_type; guint32 xid; guint16 response_delay; guint16 data_length; int offset = 0; gchar *xid_str; gboolean is_response = FALSE; offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_service_id, &service_id); offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_service_type, &service_type); offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_dcp_xid, &xid); if (service_id == PNDCP_SERVICE_ID_IDENTIFY && service_type == PNDCP_SERVICE_TYPE_REQUEST) { /* multicast header */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_response_delay, &response_delay); } else { /* unicast header */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_reserved16, NULL); } offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_data_length, &data_length); switch (service_id) { case PNDCP_SERVICE_ID_GET: pn_append_info(pinfo, dcp_item, "Get"); break; case PNDCP_SERVICE_ID_SET: pn_append_info(pinfo, dcp_item, "Set"); break; case PNDCP_SERVICE_ID_IDENTIFY: pn_append_info(pinfo, dcp_item, "Ident"); break; case PNDCP_SERVICE_ID_HELLO: pn_append_info(pinfo, dcp_item, "Hello"); break; default: dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_length_remaining(tvb, offset)); return; } switch (service_type) { case PNDCP_SERVICE_TYPE_REQUEST: pn_append_info(pinfo, dcp_item, " Req"); break; case PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS: pn_append_info(pinfo, dcp_item, " Ok "); is_response = TRUE; break; case PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED: pn_append_info(pinfo, dcp_item, " unsupported"); is_response = TRUE; break; default: dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_length_remaining(tvb, offset)); return; } xid_str = wmem_strdup_printf(wmem_packet_scope(), ", Xid:0x%x", xid); pn_append_info(pinfo, dcp_item, xid_str); /* dissect a number of blocks (depending on the remaining length) */ while(data_length) { int ori_offset = offset; if (service_id == PNDCP_SERVICE_ID_GET && service_type == PNDCP_SERVICE_TYPE_REQUEST) { /* Selectors */ offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, dcp_item, hf_pn_dcp_option, TRUE /* append_col */); } else { offset = dissect_PNDCP_Block(tvb, offset, pinfo, tree, dcp_item, service_id, is_response); } /* prevent an infinite loop */ if (offset <= ori_offset || data_length < (offset - ori_offset)) { THROW(ReportedBoundsError); } data_length -= (offset - ori_offset); } }
/* dissect the "control" suboption */ static int dissect_PNDCP_Suboption_Control(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id _U_, gboolean is_response _U_) { guint8 suboption; guint16 block_length; guint16 block_qualifier; gchar *info_str; guint8 block_error; proto_item *item = NULL; offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control, &suboption); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); switch (suboption) { case PNDCP_SUBOPTION_CONTROL_START_TRANS: pn_append_info(pinfo, dcp_item, ", Start-Trans"); proto_item_append_text(block_item, "Control/Start-Transaction"); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); break; case PNDCP_SUBOPTION_CONTROL_END_TRANS: pn_append_info(pinfo, dcp_item, ", End-Trans"); proto_item_append_text(block_item, "Control/End-Transaction"); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); break; case PNDCP_SUBOPTION_CONTROL_SIGNAL: pn_append_info(pinfo, dcp_item, ", Signal"); proto_item_append_text(block_item, "Control/Signal"); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); block_length -= 2; offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); break; case PNDCP_SUBOPTION_CONTROL_RESPONSE: proto_item_append_text(block_item, "Control/Response"); offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, block_item, hf_pn_dcp_suboption_control_response, FALSE /* append_col */); block_error = tvb_get_guint8 (tvb, offset); if (tree) { item = proto_tree_add_uint(tree, hf_pn_dcp_block_error, tvb, offset, 1, block_error); } offset += 1; if (block_error != 0) { expert_add_info_format(pinfo, item, &ei_pn_dcp_block_error_unknown, "%s", val_to_str(block_error, pn_dcp_block_error, "Unknown")); } info_str = wmem_strdup_printf(wmem_packet_scope(), ", Response(%s)", val_to_str(block_error, pn_dcp_block_error, "Unknown")); pn_append_info(pinfo, dcp_item, info_str); proto_item_append_text(block_item, ", BlockError: %s", val_to_str(block_error, pn_dcp_block_error, "Unknown")); break; case PNDCP_SUBOPTION_CONTROL_FACT_RESET: pn_append_info(pinfo, dcp_item, ", Reset FactorySettings"); proto_item_append_text(block_item, "Control/Reset FactorySettings"); offset += 2; block_length -= 2; break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
/* dissect the "device" suboption */ static int dissect_PNDCP_Suboption_Device(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id, gboolean is_response) { guint8 suboption; guint16 block_length; gchar *info_str; guint8 device_role; guint16 vendor_id; guint16 device_id; char *typeofstation; char *nameofstation; char *aliasname; guint16 block_info; guint16 block_qualifier; gboolean have_block_info = FALSE; gboolean have_block_qualifier = FALSE; guint8 device_instance_high; guint8 device_instance_low; /* SuboptionDevice... */ offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption); /* DCPBlockLength */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); /* BlockInfo? */ if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); have_block_info = TRUE; block_length -= 2; } /* BlockQualifier? */ if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); have_block_qualifier = TRUE; block_length -= 2; } switch (suboption) { case PNDCP_SUBOPTION_DEVICE_MANUF: typeofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) typeofstation, offset, block_length); typeofstation[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_typeofstation, tvb, offset, block_length, typeofstation); pn_append_info(pinfo, dcp_item, ", DeviceVendorValue"); proto_item_append_text(block_item, "Device/Manufacturer specific"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info){ proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", DeviceVendorValue: \"%s\"", typeofstation); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION: nameofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) nameofstation, offset, block_length); nameofstation[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_nameofstation, tvb, offset, block_length, nameofstation); pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", NameOfStation:\"%s\"", nameofstation)); proto_item_append_text(block_item, "Device/NameOfStation"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", \"%s\"", nameofstation); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_DEV_ID: offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_vendor_id, &vendor_id); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_id, &device_id); pn_append_info(pinfo, dcp_item, ", Dev-ID"); proto_item_append_text(block_item, "Device/Device ID"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", VendorID: 0x%04x / DeviceID: 0x%04x", vendor_id, device_id); break; case PNDCP_SUBOPTION_DEVICE_DEV_ROLE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_role, &device_role); offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_reserved8, NULL); pn_append_info(pinfo, dcp_item, ", Dev-Role"); proto_item_append_text(block_item, "Device/Device Role"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); if (device_role & 0x01) proto_item_append_text(block_item, ", IO-Device"); if (device_role & 0x02) proto_item_append_text(block_item, ", IO-Controller"); if (device_role & 0x04) proto_item_append_text(block_item, ", IO-Multidevice"); if (device_role & 0x08) proto_item_append_text(block_item, ", PN-Supervisor"); break; case PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS: info_str = wmem_strdup_printf(wmem_packet_scope(), ", Dev-Options(%u)", block_length/2); pn_append_info(pinfo, dcp_item, info_str); proto_item_append_text(block_item, "Device/Device Options"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", %u options", block_length/2); for( ; block_length != 0; block_length -= 2) { offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, NULL /*block_item*/, hf_pn_dcp_option, FALSE /* append_col */); } break; case PNDCP_SUBOPTION_DEVICE_ALIAS_NAME: aliasname = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) aliasname, offset, block_length); aliasname[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_aliasname, tvb, offset, block_length, aliasname); pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", AliasName:\"%s\"", aliasname)); proto_item_append_text(block_item, "Device/AliasName"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", \"%s\"", aliasname); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_high, &device_instance_high); offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_low, &device_instance_low); pn_append_info(pinfo, dcp_item, ", Dev-Instance"); proto_item_append_text(block_item, "Device/Device Instance"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", InstanceHigh: %d, Instance Low: %d", device_instance_high, device_instance_low); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
/* dissect the "IP" suboption */ static int dissect_PNDCP_Suboption_IP(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id, gboolean is_response) { guint8 suboption; guint16 block_length; guint16 block_info; guint16 block_qualifier; guint32 ip; proto_item *item = NULL; /* SuboptionIPParameter */ offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip, &suboption); /* DCPBlockLength */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); switch (suboption) { case PNDCP_SUBOPTION_IP_MAC: /* MACAddressValue? */ pn_append_info(pinfo, dcp_item, ", MAC"); proto_item_append_text(block_item, "IP/MAC"); offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); break; case PNDCP_SUBOPTION_IP_IP: pn_append_info(pinfo, dcp_item, ", IP"); proto_item_append_text(block_item, "IP/IP"); /* BlockInfo? */ if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { block_info = tvb_get_ntohs (tvb, offset); if (tree) { item = proto_tree_add_uint(tree, hf_pn_dcp_suboption_ip_block_info, tvb, offset, 2, block_info); } offset += 2; proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_suboption_ip_block_info, "Undecoded")); block_length -= 2; if (block_info & 0x80) { expert_add_info(pinfo, item, &ei_pn_dcp_ip_conflict); } } /* BlockQualifier? */ if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); block_length -= 2; } /* IPParameterValue ... */ /* IPAddress */ offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_ip, &ip); proto_item_append_text(block_item, ", IP: %s", ip_to_str((guint8*)&ip)); /* Subnetmask */ offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_subnetmask, &ip); proto_item_append_text(block_item, ", Subnet: %s", ip_to_str((guint8*)&ip)); /* StandardGateway */ offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_standard_gateway, &ip); proto_item_append_text(block_item, ", Gateway: %s", ip_to_str((guint8*)&ip)); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }