static gboolean dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) { gint offset = 0, start = 0, frame_len = 0; gint bytes_remaining = tvb_captured_length (tvb); guint8 pflags, sof = 0, eof = 0; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *fcip_tree = NULL; tvbuff_t *next_tvb; fc_data_t fc_data; if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) { return FALSE; } if (check_port && ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) { return FALSE; } while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) { if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) { return FALSE; } else if (offset == -2) { /* We need more data to desegment */ return (TRUE); } start = offset; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP"); frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4; if (bytes_remaining < frame_len) { if(fcip_desegment && pinfo->can_desegment) { /* * This frame doesn't have all of the data for * this message, but we can do reassembly on it. * * Tell the TCP dissector where the data for this * message starts in the data it handed us, and * how many more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = frame_len - bytes_remaining; return (TRUE); } } pflags = tvb_get_guint8 (tvb, start+8); if (tree) { if (FCIP_IS_SF (pflags)) { ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP"); } else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); eof = tvb_get_guint8 (tvb, offset+frame_len - 4); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), val_to_str (eof, fcip_eof_vals, "0x%x")); } else { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), "NA"); } fcip_tree = proto_item_add_subtree (ti, ett_fcip); /* Dissect the Common FC Encap header */ dissect_fcencap_header (tvb, fcip_tree, offset); offset += FCIP_ENCAP_HEADER_LEN; if (!FCIP_IS_SF (pflags)) { /* print SOF */ proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN); /* print EOF */ offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4); if (tvb_bytes_exist (tvb, offset, 4)) { proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN); } } } /* Call the FC Dissector if this is carrying an FC frame */ if (!FCIP_IS_SF(pflags)) { /* Set the SOF/EOF flags in the packet_info header */ fc_data.sof_eof = 0; if (sof) { if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) { fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME; } else if (sof == FCIP_SOFf) { fc_data.sof_eof = FC_DATA_SOF_SOFF; } if (eof != FCIP_EOFn) { fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME; } else if (eof != FCIP_EOFt) { fc_data.sof_eof |= FC_DATA_EOF_INVALID; } } /* Special frame bit is not set */ next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4); if (fc_handle) { fc_data.ethertype = 0; call_dissector_with_data(fc_handle, next_tvb, pinfo, tree, &fc_data); } else if (data_handle) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { col_set_str(pinfo->cinfo, COL_INFO, "Special Frame"); if (FCIP_IS_CH (pflags)) { col_append_str(pinfo->cinfo, COL_INFO, "(Changed)"); } dissect_fcip_sf (tvb, fcip_tree, offset+4); } bytes_remaining -= frame_len; } return (TRUE); }
static gboolean ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { ros_info_t *rinfo; gint32 opcode_lcl = 0; const gchar *opname = NULL; const gchar *suffix = NULL; new_dissector_t opdissector = NULL; const value_string *lookup; proto_item *item=NULL; proto_tree *ros_tree=NULL; struct SESSION_DATA_STRUCTURE* session = NULL; session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) ); if((session != NULL) && ((rinfo = (ros_info_t*)g_hash_table_lookup(protocol_table, oid)) != NULL)) { if(tree){ item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, ENC_NA); ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto)); } col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name); /* if this is a bind operation */ if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) { /* use the in-built operation codes */ if((session->ros_op & ROS_OP_PDU_MASK) == ROS_OP_ERROR) opcode_lcl = err_ros_bind; else opcode_lcl = op_ros_bind; } else /* otherwise just take the opcode */ opcode_lcl = session->ros_op & ROS_OP_OPCODE_MASK; /* default lookup in the operations */ lookup = rinfo->opr_code_strings; switch(session->ros_op & ROS_OP_PDU_MASK) { case ROS_OP_ARGUMENT: opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, TRUE); suffix = "_argument"; break; case ROS_OP_RESULT: opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, FALSE); suffix = "_result"; break; case ROS_OP_ERROR: opdissector = ros_lookup_err_dissector(opcode_lcl, rinfo->err_code_dissectors); lookup = rinfo->err_code_strings; break; default: break; } if(opdissector) { opname = val_to_str(opcode_lcl, lookup, "Unknown opcode (%d)"); col_set_str(pinfo->cinfo, COL_INFO, opname); if(suffix) col_append_str(pinfo->cinfo, COL_INFO, suffix); (*opdissector)(tvb, pinfo, ros_tree, NULL); return TRUE; } } return FALSE; }
static void dissect_nv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *nv_tree, *nv_header_tree, *nv_var_tree,*nv_varheader_tree; gint offset = 0; char szText[200]; int nMax = sizeof(szText)-1; gint i; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TC-NV"); col_clear(pinfo->cinfo, COL_INFO); NvSummaryFormater(tvb, offset, szText, nMax); col_append_str(pinfo->cinfo, COL_INFO, szText); if (tree) { guint16 nv_count; ti = proto_tree_add_item(tree, proto_nv, tvb, 0, -1, ENC_NA); nv_tree = proto_item_add_subtree(ti, ett_nv); proto_item_append_text(ti,": %s",szText); ti = proto_tree_add_item(nv_tree, hf_nv_header, tvb, offset, NvParserHDR_Len, ENC_NA); nv_header_tree = proto_item_add_subtree(ti, ett_nv_header); ti= proto_tree_add_item(nv_header_tree, hf_nv_publisher, tvb, offset, sizeof(guint8)*6, ENC_NA); NvPublisherFormater(tvb, offset, szText, nMax); proto_item_set_text(ti, "%s", szText); offset+=(sizeof(guint8)*6); proto_tree_add_item(nv_header_tree, hf_nv_count, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); nv_count = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16); proto_tree_add_item(nv_header_tree, hf_nv_cycleindex, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset = NvParserHDR_Len; for ( i=0; i < nv_count; i++ ) { guint16 var_length = tvb_get_letohs(tvb, offset+4); ti = proto_tree_add_item(nv_tree, hf_nv_variable, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len+var_length, ENC_NA); NvVarHeaderFormater(tvb, offset, szText, nMax); proto_item_set_text(ti, "%s", szText); nv_var_tree = proto_item_add_subtree(ti, ett_nv_var); ti = proto_tree_add_item(nv_var_tree, hf_nv_varheader, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len, ENC_NA); nv_varheader_tree = proto_item_add_subtree(ti, ett_nv_varheader); proto_tree_add_item(nv_varheader_tree, hf_nv_id, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(nv_varheader_tree, hf_nv_hash, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(nv_varheader_tree, hf_nv_length, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(nv_varheader_tree, hf_nv_quality, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(nv_var_tree, hf_nv_data, tvb, offset, var_length, ENC_NA); offset+=var_length; } } }
int dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *xdlc_tree, int hf_xdlc_control, gint ett_xdlc_control, const xdlc_cf_items *cf_items_nonext, const xdlc_cf_items *cf_items_ext, const value_string *u_modifier_short_vals_cmd, const value_string *u_modifier_short_vals_resp, gboolean is_response, gboolean is_extended, gboolean append_info) { guint16 control; int control_len; const xdlc_cf_items *cf_items; const char *control_format; guint16 poll_final; char *info; proto_tree *tc, *control_tree; const gchar *frame_type = NULL; const gchar *modifier; info=(char *)ep_alloc(80); switch (tvb_get_guint8(tvb, offset) & 0x03) { case XDLC_S: /* * Supervisory frame. */ if (is_extended) { control = tvb_get_letohs(tvb, offset); control_len = 2; cf_items = cf_items_ext; control_format = "Control field: %s (0x%04X)"; } else { control = tvb_get_guint8(tvb, offset); control_len = 1; cf_items = cf_items_nonext; control_format = "Control field: %s (0x%02X)"; } switch (control & XDLC_S_FTYPE_MASK) { case XDLC_RR: frame_type = "RR"; break; case XDLC_RNR: frame_type = "RNR"; break; case XDLC_REJ: frame_type = "REJ"; break; case XDLC_SREJ: frame_type = "SREJ"; break; } if (is_extended) { poll_final = (control & XDLC_P_F_EXT); g_snprintf(info, 80, "S%s, func=%s, N(R)=%u", (poll_final ? (is_response ? " F" : " P") : ""), frame_type, (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT); } else { poll_final = (control & XDLC_P_F); g_snprintf(info, 80, "S%s, func=%s, N(R)=%u", (poll_final ? (is_response ? " F" : " P") : ""), frame_type, (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT); } if (append_info) { col_append_str(pinfo->cinfo, COL_INFO, ", "); col_append_str(pinfo->cinfo, COL_INFO, info); } else { col_add_str(pinfo->cinfo, COL_INFO, info); } if (xdlc_tree) { tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb, offset, control_len, control, control_format, info, control); control_tree = proto_item_add_subtree(tc, ett_xdlc_control); proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_n_r, tvb, offset, control_len, control); if (poll_final) { proto_tree_add_boolean(control_tree, (is_response ? *cf_items->hf_xdlc_f : *cf_items->hf_xdlc_p), tvb, offset, control_len, control); } proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_s_ftype, tvb, offset, control_len, control); /* This will always say it's a supervisory frame */ proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u, tvb, offset, control_len, control); } break; case XDLC_U: /* * Unnumbered frame. * * XXX - is this two octets, with a P/F bit, in HDLC extended * operation? It's one octet in LLC, even though the control * field of I and S frames is a 2-byte extended-operation field * in LLC. Given that there are no sequence numbers in the * control field of a U frame, there doesn't appear to be any * need for it to be 2 bytes in extended operation. */ if (u_modifier_short_vals_cmd == NULL) u_modifier_short_vals_cmd = modifier_short_vals_cmd; if (u_modifier_short_vals_resp == NULL) u_modifier_short_vals_resp = modifier_short_vals_resp; control = tvb_get_guint8(tvb, offset); control_len = 1; cf_items = cf_items_nonext; control_format = "Control field: %s (0x%02X)"; if (is_response) { modifier = val_to_str(control & XDLC_U_MODIFIER_MASK, u_modifier_short_vals_resp, "Unknown"); } else { modifier = val_to_str(control & XDLC_U_MODIFIER_MASK, u_modifier_short_vals_cmd, "Unknown"); } poll_final = (control & XDLC_P_F); g_snprintf(info, 80, "U%s, func=%s", (poll_final ? (is_response ? " F" : " P") : ""), modifier); if (append_info) { col_append_str(pinfo->cinfo, COL_INFO, ", "); col_append_str(pinfo->cinfo, COL_INFO, info); } else { col_add_str(pinfo->cinfo, COL_INFO, info); } if (xdlc_tree) { tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb, offset, control_len, control, control_format, info, control); control_tree = proto_item_add_subtree(tc, ett_xdlc_control); if (poll_final) { proto_tree_add_boolean(control_tree, (is_response ? *cf_items->hf_xdlc_f: *cf_items->hf_xdlc_p), tvb, offset, control_len, control); } proto_tree_add_uint(control_tree, (is_response ? *cf_items->hf_xdlc_u_modifier_resp : *cf_items->hf_xdlc_u_modifier_cmd), tvb, offset, control_len, control); /* This will always say it's an unnumbered frame */ proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u, tvb, offset, control_len, control); } break; default: /* * Information frame. */ if (is_extended) { control = tvb_get_letohs(tvb, offset); control_len = 2; cf_items = cf_items_ext; control_format = "Control field: %s (0x%04X)"; poll_final = (control & XDLC_P_F_EXT); g_snprintf(info, 80, "I%s, N(R)=%u, N(S)=%u", ((control & XDLC_P_F_EXT) ? " P" : ""), (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT, (control & XDLC_N_S_EXT_MASK) >> XDLC_N_S_EXT_SHIFT); } else {
/* note that even if ajp13_tree is null on the first pass, we still * need to dissect the packet in order to determine if there is a * content-length, and thus if there is a subsequent automatic * request-body transmitted in the next request packet. if there is a * content-length, we record the fact in the conversation context. * ref the top of this file for comments explaining the multi-pass * thing. */ static void display_req_forward(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 meth; guint8 cod; const gchar *ver; guint16 ver_len; const gchar *uri; guint16 uri_len; const gchar *raddr; guint16 raddr_len; const gchar *rhost; guint16 rhost_len; const gchar *srv; guint16 srv_len; guint nhdr; guint i; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* PACKET CODE */ cod = tvb_get_guint8(tvb, 4); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; if ( cod == MTYPE_CPING ) { col_append_str(pinfo->cinfo, COL_INFO, "CPING" ); return; } /* HTTP METHOD (ENCODED AS INTEGER) */ meth = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(meth, http_method_codes, "Unknown method %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_method, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; /* HTTP VERSION STRING */ ver = ajp13_get_nstring(tvb, pos, &ver_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_ver, tvb, pos, ver_len+2, ver); pos=pos+ver_len+2; /* skip over size + chars + trailing null */ /* URI */ uri = ajp13_get_nstring(tvb, pos, &uri_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_uri, tvb, pos, uri_len+2, uri); pos=pos+uri_len+2; /* skip over size + chars + trailing null */ col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", uri, ver); /* REMOTE ADDRESS */ raddr = ajp13_get_nstring(tvb, pos, &raddr_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_raddr, tvb, pos, raddr_len+2, raddr); pos=pos+raddr_len+2; /* skip over size + chars + trailing null */ /* REMOTE HOST */ rhost = ajp13_get_nstring(tvb, pos, &rhost_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rhost, tvb, pos, rhost_len+2, rhost); pos=pos+rhost_len+2; /* skip over size + chars + trailing null */ /* SERVER NAME */ srv = ajp13_get_nstring(tvb, pos, &srv_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_srv, tvb, pos, srv_len+2, srv); pos=pos+srv_len+2; /* skip over size + chars + trailing null */ /* SERVER PORT */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_port, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* IS SSL? */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_sslp, tvb, pos, 1, ENC_NA); pos+=1; /* NUM HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; cd->content_length = 0; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar* hname = NULL; int hpos = pos; int cl = 0; const gchar *hval; guint16 hval_len, hname_len; /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(req_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, *req_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s", hval); pos+=hval_len+2; if (hid == 0x08) cl = 1; } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval), "%s: %s", hname, hval); pos+=hval_len+2; } if (cl) { cl = atoi(hval); cd->content_length = cl; } } /* ATTRIBUTES */ while(tvb_reported_length_remaining(tvb, pos) > 0) { guint8 aid; const gchar* aname = NULL; const gchar* aval; guint16 aval_len, aname_len; int apos = pos; /* ATTRIBUTE CODE/NAME */ aid = tvb_get_guint8(tvb, pos); pos+=1; if (aid == 0xFF) { /* request terminator */ break; } if (aid == 0x0A) { /* req_attribute - name and value follow */ aname = ajp13_get_nstring(tvb, pos, &aname_len); pos+=aname_len+2; aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; proto_tree_add_string_format(ajp13_tree, hf_ajp13_req_attribute, tvb, apos, 1+aname_len+2+aval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", aname, aval), "%s: %s", aname, aval); } else if (aid == 0x0B ) { /* ssl_key_length */ if (ajp13_tree) { proto_tree_add_uint(ajp13_tree, hf_ajp13_ssl_key_size, tvb, apos, 1+2, tvb_get_ntohs(tvb, pos)); } pos+=2; } else { if (aid >= array_length(req_attributes)) aid = 0; aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; proto_tree_add_string_format(ajp13_tree, *req_attributes[aid], tvb, apos, 1+aval_len+2, aval, "%s", aval); } } }
/* Decoder State Machine. Currently only used to snoop on client-user-name as sent by the client up connection establishment. */ static void rlogin_state_machine(rlogin_hash_entry_t *hash_info, tvbuff_t *tvb, packet_info *pinfo) { guint length; gint stringlen; /* Won't change state if already seen this packet */ if (pinfo->fd->flags.visited) { return; } /* rlogin stream decoder */ /* Just watch for the second packet from client with the user name and */ /* terminal type information. */ if (pinfo->destport != RLOGIN_PORT) { return; } /* exit if already passed username in conversation */ if (hash_info->state == DONE) { return; } /* exit if no data */ length = tvb_length(tvb); if (length == 0) { return; } if (hash_info->state == NONE) { /* new connection*/ if (tvb_get_guint8(tvb, 0) != '\0') { /* We expected a null, but didn't get one; quit. */ hash_info->state = DONE; return; } else { if (length <= 1) { /* Still waiting for data */ hash_info->state = USER_INFO_WAIT; } else { /* Have info, store frame number */ hash_info->state = DONE; hash_info->info_framenum = pinfo->fd->num; } } } /* expect user data here */ /* TODO: may need to do more checking here? */ else if (hash_info->state == USER_INFO_WAIT) { /* Store frame number here */ hash_info->state = DONE; hash_info->info_framenum = pinfo->fd->num; /* Work out length of string to copy */ stringlen = tvb_strnlen(tvb, 0, NAME_LEN); if (stringlen == -1) stringlen = NAME_LEN - 1; /* no '\0' found */ else if (stringlen > NAME_LEN - 1) stringlen = NAME_LEN - 1; /* name too long */ /* Copy and terminate string into hash name */ tvb_memcpy(tvb, (guint8 *)hash_info->user_name, 0, stringlen); hash_info->user_name[stringlen] = '\0'; col_append_str(pinfo->cinfo, COL_INFO, ", (User information)"); } }
static void dissect_cwids(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *wlan_tvb; proto_tree *ti, *cwids_tree; volatile int offset = 0; guint16 capturelen; void *pd_save; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CWIDS"); col_set_str(pinfo->cinfo, COL_INFO, "Cwids: "); /* FIXME: col_set_fence(pinfo->cinfo, all-cols, only addr-cols?); */ cwids_tree = NULL; while(tvb_length_remaining(tvb, offset) > 0) { ti = proto_tree_add_item(tree, proto_cwids, tvb, offset, 28, ENC_NA); cwids_tree = proto_item_add_subtree(ti, ett_cwids); proto_tree_add_item(cwids_tree, hf_cwids_version, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(cwids_tree, hf_cwids_unknown1, tvb, offset, 7, ENC_NA); offset += 7; proto_tree_add_item(cwids_tree, hf_cwids_channel, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(cwids_tree, hf_cwids_unknown2, tvb, offset, 6, ENC_NA); offset += 6; proto_tree_add_item(cwids_tree, hf_cwids_reallength, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; capturelen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(cwids_tree, hf_cwids_capturelen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(cwids_tree, hf_cwids_unknown3, tvb, offset, 8, ENC_NA); offset += 8; wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen); /* Continue after ieee80211 dissection errors */ pd_save = pinfo->private_data; TRY { call_dissector(ieee80211_handle, wlan_tvb, pinfo, tree); } CATCH2(BoundsError, ReportedBoundsError) { expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_ERROR, "Malformed or short IEEE80211 subpacket"); /* Restore the private_data structure in case one of the * called dissectors modified it (and, due to the exception, * was unable to restore it). */ pinfo->private_data = pd_save; col_append_str(pinfo->cinfo, COL_INFO, " [Malformed or short IEEE80211 subpacket] " ); col_set_fence(pinfo->cinfo, COL_INFO); #if 0 wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen); /* FIXME: Why does this throw an exception? */ proto_tree_add_text(cwids_tree, wlan_tvb, offset, capturelen, "[Malformed or short IEEE80211 subpacket]"); #else tvb_new_subset(tvb, offset, capturelen, capturelen); #endif ; } ENDTRY; offset += capturelen; }
void show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned long exception, const char *exception_message) { static const char dissector_error_nomsg[] = "Dissector writer didn't bother saying what the error was"; proto_item *item; switch (exception) { case ScsiBoundsError: col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]"); /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0, "SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto); /* Don't record ScsiBoundsError exceptions as expert events - they merely * reflect a normal SCSI condition. * (any case where it's caused by something else is a bug). */ /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/ break; case BoundsError: col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]"); /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0, "[Packet size limited during capture: %s truncated]", pinfo->current_proto); /* Don't record BoundsError exceptions as expert events - they merely * reflect a capture done with a snapshot length too short to capture * all of the packet * (any case where it's caused by something else is a bug). */ /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/ break; case ReportedBoundsError: show_reported_bounds_error(tvb, pinfo, tree); break; case DissectorError: col_append_fstr(pinfo->cinfo, COL_INFO, "[Dissector bug, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0, "[Dissector bug, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); g_warning("Dissector bug, protocol %s, in packet %u: %s", pinfo->current_proto, pinfo->fd->num, exception_message == NULL ? dissector_error_nomsg : exception_message); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "%s", exception_message == NULL ? dissector_error_nomsg : exception_message); break; default: /* XXX - we want to know, if an unknown exception passed until here, don't we? */ g_assert_not_reached(); } }
static int dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { proto_tree *rtsp_tree = NULL; proto_tree *sub_tree = NULL; proto_item *ti = NULL; const guchar *line; gint next_offset; const guchar *linep, *lineend; int orig_offset; int first_linelen, linelen; int line_end_offset; int colon_offset; gboolean is_request_or_reply; gboolean body_requires_content_len; gboolean saw_req_resp_or_header; guchar c; rtsp_type_t rtsp_type; gboolean is_header; int datalen; int content_length; int reported_datalen; int value_offset; int value_len; e164_info_t e164_info; gint rdt_feature_level = 0; gchar *media_type_str_lower_case = NULL; int semi_colon_offset; int par_end_offset; /* * Is this a request or response? * * Note that "tvb_find_line_end()" will return a value that * is not longer than what's in the buffer, so the * "tvb_get_ptr()" call won't throw an exception. */ first_linelen = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); /* * Is the first line a request or response? */ line = tvb_get_ptr(tvb, offset, first_linelen); is_request_or_reply = is_rtsp_request_or_reply(line, first_linelen, &rtsp_type); if (is_request_or_reply) { /* * Yes, it's a request or response. * Do header desegmentation if we've been told to, * and do body desegmentation if we've been told to and * we find a Content-Length header. */ if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo, rtsp_desegment_headers, rtsp_desegment_body)) { /* * More data needed for desegmentation. */ return -1; } } /* * RFC 2326 says that a content length must be specified * in requests that have a body, although section 4.4 speaks * of a server closing the connection indicating the end of * a reply body. * * We assume that an absent content length in a request means * that we don't have a body, and that an absent content length * in a reply means that the reply body runs to the end of * the connection. If the first line is neither, we assume * that whatever follows a blank line should be treated as a * body; there's not much else we can do, as we're jumping * into the message in the middle. * * XXX - if there was no Content-Length entity header, we should * accumulate all data until the end of the connection. * That'd require that the TCP dissector call subdissectors * for all frames with FIN, even if they contain no data, * which would require subdissectors to deal intelligently * with empty segments. */ if (rtsp_type == RTSP_REQUEST) body_requires_content_len = TRUE; else body_requires_content_len = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* * Put the first line from the buffer into the summary * if it's an RTSP request or reply (but leave out the * line terminator). * Otherwise, just call it a continuation. * * Note that "tvb_find_line_end()" will return a value that * is not longer than what's in the buffer, so the * "tvb_get_ptr()" call won't throw an exception. */ line = tvb_get_ptr(tvb, offset, first_linelen); if (is_request_or_reply) if ( rtsp_type == RTSP_REPLY ) { col_set_str(pinfo->cinfo, COL_INFO, "Reply: "); col_append_str(pinfo->cinfo, COL_INFO, format_text(line, first_linelen)); } else col_add_str(pinfo->cinfo, COL_INFO, format_text(line, first_linelen)); else col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); } orig_offset = offset; if (tree) { ti = proto_tree_add_item(tree, proto_rtsp, tvb, offset, -1, FALSE); rtsp_tree = proto_item_add_subtree(ti, ett_rtsp); } /* * We haven't yet seen a Content-Length header. */ content_length = -1; /* * Process the packet data, a line at a time. */ saw_req_resp_or_header = FALSE; /* haven't seen anything yet */ while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * We haven't yet concluded that this is a header. */ is_header = FALSE; /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (linelen < 0) return -1; line_end_offset = offset + linelen; /* * colon_offset may be -1 */ colon_offset = tvb_find_guint8(tvb, offset, linelen, ':'); /* * Get a buffer that refers to the line. */ line = tvb_get_ptr(tvb, offset, linelen); lineend = line + linelen; /* * OK, does it look like an RTSP request or response? */ is_request_or_reply = is_rtsp_request_or_reply(line, linelen, &rtsp_type); if (is_request_or_reply) goto is_rtsp; /* * No. Does it look like a blank line (as would appear * at the end of an RTSP request)? */ if (linelen == 0) goto is_rtsp; /* Yes. */ /* * No. Does it look like a header? */ linep = line; while (linep < lineend) { c = *linep++; /* * This must be a CHAR to be part of a token; that * means it must be ASCII. */ if (!isascii(c)) break; /* not ASCII, thus not a CHAR */ /* * This mustn't be a CTL to be part of a token. * * XXX - what about leading LWS on continuation * lines of a header? */ if (iscntrl(c)) break; /* CTL, not part of a header */ switch (c) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case '\\': case '"': case '/': case '[': case ']': case '?': case '=': case '{': case '}': /* * It's a tspecial, so it's not * part of a token, so it's not * a field name for the beginning * of a header. */ goto not_rtsp; case ':': /* * This ends the token; we consider * this to be a header. */ is_header = TRUE; goto is_rtsp; case ' ': case '\t': /* * LWS (RFC-2616, 4.2); continue the previous * header. */ goto is_rtsp; } } /* * We haven't seen the colon, but everything else looks * OK for a header line. * * If we've already seen an RTSP request or response * line, or a header line, and we're at the end of * the tvbuff, we assume this is an incomplete header * line. (We quit this loop after seeing a blank line, * so if we've seen a request or response line, or a * header line, this is probably more of the request * or response we're presumably seeing. There is some * risk of false positives, but the same applies for * full request or response lines or header lines, * although that's less likely.) * * We throw an exception in that case, by checking for * the existence of the next byte after the last one * in the line. If it exists, "tvb_ensure_bytes_exist()" * throws no exception, and we fall through to the * "not RTSP" case. If it doesn't exist, * "tvb_ensure_bytes_exist()" will throw the appropriate * exception. */ if (saw_req_resp_or_header) tvb_ensure_bytes_exist(tvb, offset, linelen + 1); not_rtsp: /* * We don't consider this part of an RTSP request or * reply, so we don't display it. */ break; is_rtsp: /* * Process this line. */ if (linelen == 0) { /* * This is a blank line, which means that * whatever follows it isn't part of this * request or reply. */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; break; } /* * Not a blank line - either a request, a reply, or a header * line. */ saw_req_resp_or_header = TRUE; if (rtsp_tree) { switch (rtsp_type) { case RTSP_REQUEST: process_rtsp_request(tvb, offset, line, linelen, next_offset, rtsp_tree); break; case RTSP_REPLY: process_rtsp_reply(tvb, offset, line, linelen, next_offset, rtsp_tree); break; case RTSP_NOT_FIRST_LINE: /* Drop through, it may well be a header line */ break; } } if (is_header) { /* We know that colon_offset must be set */ /* Skip whitespace after the colon. */ value_offset = colon_offset + 1; while ((value_offset < line_end_offset) && ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t')) { value_offset++; } value_len = line_end_offset - value_offset; /* * Process some headers specially. */ #define HDR_MATCHES(header) \ ( (size_t)linelen > STRLEN_CONST(header) && \ g_ascii_strncasecmp(line, (header), STRLEN_CONST(header)) == 0) if (HDR_MATCHES(rtsp_transport)) { proto_tree_add_string(rtsp_tree, hf_rtsp_transport, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); /* * Based on the port numbers specified * in the Transport: header, set up * a conversation that will be dissected * with the appropriate dissector. */ rtsp_create_conversation(pinfo, line, linelen, rdt_feature_level); } else if (HDR_MATCHES(rtsp_content_type)) { proto_tree_add_string(rtsp_tree, hf_rtsp_content_type, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); offset = offset + STRLEN_CONST(rtsp_content_type); /* Skip wsp */ offset = tvb_skip_wsp(tvb, offset, value_len); semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';'); if ( semi_colon_offset != -1) { /* m-parameter present */ par_end_offset = tvb_skip_wsp_return(tvb, semi_colon_offset-1); value_len = par_end_offset - offset; } media_type_str_lower_case = ascii_strdown_inplace( (gchar *)tvb_get_ephemeral_string(tvb, offset, value_len)); } else if (HDR_MATCHES(rtsp_content_length)) { proto_tree_add_uint(rtsp_tree, hf_rtsp_content_length, tvb, offset, linelen, atoi(tvb_format_text(tvb, value_offset, value_len))); /* * Only the amount specified by the * Content-Length: header should be treated * as payload. */ content_length = rtsp_get_content_length(line, linelen); } else if (HDR_MATCHES(rtsp_Session)) { /* Put the value into the protocol tree */ proto_tree_add_string(rtsp_tree, hf_rtsp_session, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); } else if (HDR_MATCHES(rtsp_X_Vig_Msisdn)) { /* * Extract the X_Vig_Msisdn string */ if (colon_offset != -1) { /* Put the value into the protocol tree */ ti = proto_tree_add_string(rtsp_tree, hf_rtsp_X_Vig_Msisdn,tvb, offset, linelen , tvb_format_text(tvb, value_offset, value_len)); sub_tree = proto_item_add_subtree(ti, ett_rtsp_method); e164_info.e164_number_type = CALLING_PARTY_NUMBER; e164_info.nature_of_address = 0; e164_info.E164_number_str = tvb_get_ephemeral_string(tvb, value_offset, value_len); e164_info.E164_number_length = value_len; dissect_e164_number(tvb, sub_tree, value_offset, value_len, e164_info); } } else if (HDR_MATCHES(rtsp_rdt_feature_level)) { rdt_feature_level = atoi(tvb_format_text(tvb, value_offset, value_len)); proto_tree_add_uint(rtsp_tree, hf_rtsp_rdtfeaturelevel, tvb, offset, linelen, atoi(tvb_format_text(tvb, value_offset, value_len))); } else { /* Default case for headers. Show line as text */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } } else if (rtsp_type == RTSP_NOT_FIRST_LINE) { /* Catch-all for all other lines... Show line as text. TODO: should these be shown as errors? */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } offset = next_offset; } /* * Have now read all of the lines of this message. * * If a content length was supplied, the amount of data to be * processed as RTSP payload is the minimum of the content * length and the amount of data remaining in the frame. * * If no content length was supplied (or if a bad content length * was supplied), the amount of data to be processed is the amount * of data remaining in the frame. */ datalen = tvb_length_remaining(tvb, offset); reported_datalen = tvb_reported_length_remaining(tvb, offset); if (content_length != -1) { /* * Content length specified; display only that amount * as payload. */ if (datalen > content_length) datalen = content_length; /* * XXX - limit the reported length in the tvbuff we'll * hand to a subdissector to be no greater than the * content length. * * We really need both unreassembled and "how long it'd * be if it were reassembled" lengths for tvbuffs, so * that we throw the appropriate exceptions for * "not enough data captured" (running past the length), * "packet needed reassembly" (within the length but * running past the unreassembled length), and * "packet is malformed" (running past the reassembled * length). */ if (reported_datalen > content_length) reported_datalen = content_length; } else { /* * No content length specified; if this message doesn't * have a body if no content length is specified, process * nothing as payload. */ if (body_requires_content_len) datalen = 0; } if (datalen > 0) { /* * There's stuff left over; process it. */ tvbuff_t *new_tvb; /* * Now create a tvbuff for the Content-type stuff and * dissect it. * * The amount of data to be processed that's * available in the tvbuff is "datalen", which * is the minimum of the amount of data left in * the tvbuff and any specified content length. * * The amount of data to be processed that's in * this frame, regardless of whether it was * captured or not, is "reported_datalen", * which, if no content length was specified, * is -1, i.e. "to the end of the frame. */ new_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen); if (media_type_str_lower_case && dissector_try_string(media_type_dissector_table, media_type_str_lower_case, new_tvb, pinfo, rtsp_tree)){ }else { /* * Fix up the top-level item so that it doesn't * include the SDP stuff. */ if (ti != NULL) proto_item_set_len(ti, offset); if (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR) { /* * This is interleaved stuff; don't * treat it as raw data - set "datalen" * to 0, so we won't skip the offset * past it, which will cause our * caller to process that stuff itself. */ datalen = 0; } else { proto_tree_add_text(rtsp_tree, tvb, offset, datalen, "Data (%d bytes)", reported_datalen); } } /* * We've processed "datalen" bytes worth of data * (which may be no data at all); advance the * offset past whatever data we've processed. */ offset += datalen; } return offset - orig_offset; }
static int dissect_dvb_s2_bb(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo) { proto_item *ti; proto_tree *dvb_s2_bb_tree; guint8 input8, matype1; guint16 input16, bb_data_len = 0, user_packet_length; int sub_dissected = 0, flag_is_ms = 0, new_off = 0; static const int * bb_header_bitfields[] = { &hf_dvb_s2_bb_matype1_gs, &hf_dvb_s2_bb_matype1_mis, &hf_dvb_s2_bb_matype1_acm, &hf_dvb_s2_bb_matype1_issyi, &hf_dvb_s2_bb_matype1_npd, &hf_dvb_s2_bb_matype1_ro, NULL }; col_append_str(pinfo->cinfo, COL_PROTOCOL, "BB "); col_append_str(pinfo->cinfo, COL_INFO, "Baseband "); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_dvb_s2_bb, tvb, cur_off, DVB_S2_BB_HEADER_LEN, ENC_NA); dvb_s2_bb_tree = proto_item_add_subtree(ti, ett_dvb_s2_bb); matype1 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1); new_off += 1; if (BIT_IS_CLEAR(matype1, DVB_S2_BB_MIS_POS)) flag_is_ms = 1; proto_tree_add_bitmask_with_flags(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, hf_dvb_s2_bb_matype1, ett_dvb_s2_bb_matype1, bb_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_FLAGS); input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2); new_off += 1; if (flag_is_ms) { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "Input Stream Identifier (ISI): %d", input8); } else { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "reserved"); } user_packet_length = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_UPL); new_off += 2; proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_upl, tvb, cur_off + DVB_S2_BB_OFFS_UPL, 2, input16, "User Packet Length: %d bits (%d bytes)", (guint16) input16, (guint16) input16 / 8); bb_data_len = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_DFL); bb_data_len /= 8; new_off += 2; proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_dfl, tvb, cur_off + DVB_S2_BB_OFFS_DFL, 2, input16, "%d bits (%d bytes)", input16, input16 / 8); new_off += 1; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_sync, tvb, cur_off + DVB_S2_BB_OFFS_SYNC, 1, ENC_BIG_ENDIAN); new_off += 2; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_syncd, tvb, cur_off + DVB_S2_BB_OFFS_SYNCD, 2, ENC_BIG_ENDIAN); new_off += 1; proto_tree_add_checksum(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_CRC, hf_dvb_s2_bb_crc, hf_dvb_s2_bb_crc_status, &ei_dvb_s2_bb_crc, pinfo, compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, cur_off), ENC_NA, PROTO_CHECKSUM_VERIFY); switch (matype1 & DVB_S2_BB_TSGS_MASK) { case DVB_S2_BB_TSGS_GENERIC_CONTINUOUS: /* Check GSE constraints on the BB header per 9.2.1 of ETSI TS 102 771 */ if (BIT_IS_SET(matype1, DVB_S2_BB_ISSYI_POS)) { expert_add_info(pinfo, ti, &ei_dvb_s2_bb_issy_invalid); } if (BIT_IS_SET(matype1, DVB_S2_BB_NPD_POS)) { expert_add_info(pinfo, ti, &ei_dvb_s2_bb_npd_invalid); } if (user_packet_length != 0x0000) { expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_upl_invalid, "UPL is 0x%04x. It must be 0x0000 for GSE packets.", user_packet_length); } while (bb_data_len) { /* start DVB-GSE dissector */ sub_dissected = dissect_dvb_s2_gse(tvb, cur_off + new_off, tree, pinfo, bb_data_len); new_off += sub_dissected; if ((sub_dissected <= bb_data_len) && (sub_dissected >= DVB_S2_GSE_MINSIZE)) { bb_data_len -= sub_dissected; if (bb_data_len < DVB_S2_GSE_MINSIZE) bb_data_len = 0; } else { bb_data_len = 0; } } break; case DVB_S2_BB_TSGS_GENERIC_PACKETIZED: proto_tree_add_item(tree, hf_dvb_s2_bb_packetized, tvb, cur_off + new_off, bb_data_len, ENC_NA); new_off += bb_data_len; break; case DVB_S2_BB_TSGS_TRANSPORT_STREAM: proto_tree_add_item(tree, hf_dvb_s2_bb_transport, tvb, cur_off + new_off, bb_data_len, ENC_NA); new_off += bb_data_len; break; default: proto_tree_add_item(tree, hf_dvb_s2_bb_reserved, tvb, cur_off + new_off,bb_data_len, ENC_NA); new_off += bb_data_len; expert_add_info(pinfo, ti, &ei_dvb_s2_bb_reserved); break; } return new_off; }
static void dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *drda_tree = NULL; proto_tree *drdaroot_tree = NULL; proto_item *ti = NULL; gint offset = 0; static gint iPreviousFrameNumber = -1; guint16 iCommand; guint16 iLength; guint8 iFormatFlags; guint8 iDSSType; guint8 iDSSFlags; guint16 iParameterCP; proto_tree *drda_tree_sub; gint iLengthParam; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA"); if (check_col(pinfo->cinfo, COL_INFO)) { /* This is a trick to know whether this is the first PDU in this packet or not */ if (iPreviousFrameNumber != (gint) pinfo->fd->num) col_clear(pinfo->cinfo, COL_INFO); else col_append_str(pinfo->cinfo, COL_INFO, " | "); } iPreviousFrameNumber = pinfo->fd->num; if (tvb_length(tvb) >= 10) { iCommand = tvb_get_ntohs(tvb, offset + 8); iLength = tvb_get_ntohs(tvb, offset + 0); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)")); } if (tree) { ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, FALSE); proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_vals, "Unknown (0x%02x)")); drdaroot_tree = proto_item_add_subtree(ti, ett_drda); ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM); proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)")); drda_tree = proto_item_add_subtree(ti, ett_drda_ddm); proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, FALSE); proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, FALSE); { drda_tree_sub = NULL; iFormatFlags = tvb_get_guint8(tvb, offset + 3); iDSSType = iFormatFlags & 0x0F; iDSSFlags = iFormatFlags >> 4; ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, FALSE); drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType); } proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, FALSE); proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, FALSE); proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, FALSE); /* The number of attributes is variable */ for (offset = 10; offset <= iLength; ) { if (tvb_length_remaining(tvb, offset) >= 2) { iLengthParam = tvb_get_ntohs(tvb, offset + 0); if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10; if (tvb_length_remaining(tvb, offset) >= iLengthParam) { drda_tree_sub = NULL; iParameterCP = tvb_get_ntohs(tvb, offset + 2); ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam, DRDA_TEXT_PARAM); proto_item_append_text(ti, " (%s)", val_to_str(iParameterCP, drda_opcode_vals, "Unknown (0x%02x)")); drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param); proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, FALSE); proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, FALSE); proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, FALSE); proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, FALSE); if (iCommand == DRDA_CP_SQLSTT) { /* Extract SQL statement from packet */ tvbuff_t* next_tvb = NULL; next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4); add_new_data_source(pinfo, next_tvb, "SQL statement"); proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, FALSE); proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, FALSE); } } offset += iLengthParam; } else { break; } } } }
/* *** Code to actually dissect the packets *** */ static int dissect_dvb_s2_gse(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo, int bytes_available) { int new_off = 0; int frag_len; guint16 gse_hdr, data_len, padding_len, gse_proto = 0; proto_item *ti; proto_tree *dvb_s2_gse_tree; tvbuff_t *next_tvb; static const int * gse_header_bitfields[] = { &hf_dvb_s2_gse_hdr_start, &hf_dvb_s2_gse_hdr_stop, &hf_dvb_s2_gse_hdr_labeltype, &hf_dvb_s2_gse_hdr_length, NULL }; col_append_str(pinfo->cinfo, COL_INFO, " GSE"); /* get the GSE header */ gse_hdr = tvb_get_ntohs(tvb, cur_off + DVB_S2_GSE_OFFS_HDR); /* check if this is just padding, which takes up the rest of the frame */ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { padding_len = bytes_available; proto_tree_add_uint_format(tree, hf_dvb_s2_gse_padding, tvb, cur_off + new_off, padding_len, padding_len, "DVB-S2 GSE Padding, Length: %d", padding_len); col_append_str(pinfo->cinfo, COL_INFO, " pad"); new_off += padding_len; return new_off; } else { /* Not padding, parse as a GSE Header */ new_off += 2; frag_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK)+2; ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, cur_off, frag_len, ENC_NA); dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse); proto_tree_add_bitmask_with_flags(dvb_s2_gse_tree, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, hf_dvb_s2_gse_hdr, ett_dvb_s2_gse_hdr, gse_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_TFS); if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); new_off += 2; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) { gse_proto = tvb_get_ntohs(tvb, cur_off + new_off); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); new_off += 2; if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 6 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "6 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, tvb, cur_off + new_off, 6, ENC_NA); new_off += 6; } else if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 3 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "3 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, tvb, cur_off + new_off, 3, ENC_BIG_ENDIAN); new_off += 3; } else { /* 0 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "0 "); } if (gse_proto < 0x0600 && gse_proto >= 0x100) { /* Only display optional extension headers */ /* TODO: needs to be tested */ /* TODO: implementation needs to be checked (len of ext-header??) */ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } } else { /* correct cinfo */ col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); } next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off); if (dvb_s2_full_dissection) { switch (gse_proto) { case ETHERTYPE_IP: new_off += call_dissector(ip_handle, next_tvb, pinfo, tree); break; case ETHERTYPE_IPv6: new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree); break; default: if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; break; } } else { if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; } /* add crc32 if last fragment */ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_BIG_ENDIAN); new_off += DVB_S2_GSE_CRC32_LEN; } } return new_off; }
/* The dissector itself */ static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { // Here are all the variables proto_item *item; proto_item *stream_item; proto_tree *chdr_tree; proto_item *header_item; proto_tree *header_tree; proto_tree *stream_tree; proto_item *response_item; proto_tree *response_tree; proto_item *cmd_item; proto_tree *cmd_tree; gint len; gint flag_offset; guint8 *bytes; guint8 hdr_bits = 0; guint8 pkt_type = 0; gboolean flag_has_time = 0; gboolean flag_is_data = 0; gboolean flag_is_fc = 0; gboolean flag_is_cmd = 0; gboolean flag_is_resp = 0; gboolean flag_is_eob = 0; gboolean flag_is_error = 0; unsigned long long timestamp; gboolean is_network; gint endianness; gint id_pos_usb[4] = {7, 6, 5, 4}; gint id_pos_net[4] = {4, 5, 6, 7}; gint id_pos[4] = {7, 6, 5, 4}; if(pinfo->match_uint == CHDR_PORT){ is_network = TRUE; flag_offset = 0; endianness = ENC_BIG_ENDIAN; memcpy(id_pos, id_pos_net, 4 * sizeof(gint)); } else{ // Parsing a USB capture is_network = FALSE; flag_offset = 3; endianness = ENC_LITTLE_ENDIAN; memcpy(id_pos, id_pos_usb, 4 * sizeof(gint)); } len = tvb_reported_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR"); /* This throws a warning: */ /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len));*/ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR"); if (tree){ int chdr_size = -1; if (len >= 4){ chdr_size = 8; bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 4); hdr_bits = (bytes[flag_offset] & 0xF0) >> 4; pkt_type = hdr_bits >> 2; flag_is_data = (pkt_type == 0); flag_is_fc = (pkt_type == 1); flag_is_cmd = (pkt_type == 2); flag_is_resp = (pkt_type == 3); flag_is_eob = flag_is_data && (hdr_bits & 0x1); flag_is_error = flag_is_resp && (hdr_bits & 0x1); flag_has_time = hdr_bits & 0x2; if (flag_has_time) chdr_size += 8; // 64-bit timestamp } /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_chdr, tvb, 0, min(len, chdr_size), ENC_NA); if (len >= 4) { chdr_tree = proto_item_add_subtree(item, ett_chdr); /* Header info. First, a top-level header tree item: */ header_item = proto_tree_add_item(chdr_tree, hf_chdr_hdr, tvb, flag_offset, 1, endianness); header_tree = proto_item_add_subtree(header_item, ett_chdr_header); proto_item_append_text(header_item, ", Packet type: %s", val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES, "Unknown (0x%x)") ); /* Let us query hdr.type */ proto_tree_add_string( header_tree, hf_chdr_type, tvb, flag_offset, 1, val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES_SHORT, "invalid") ); /* And other flags */ proto_tree_add_boolean(header_tree, hf_chdr_has_time, tvb, flag_offset, 1, flag_has_time); if (flag_is_data) { proto_tree_add_boolean(header_tree, hf_chdr_eob, tvb, flag_offset, 1, flag_is_eob); } if (flag_is_resp) { proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, flag_is_error); } /* These lines add sequence, packet_size and stream ID */ proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, (is_network ? 0:2), 2, endianness); proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, (is_network ? 2:0), 2, endianness); if (len >= 8){ /* stream id can be broken down to 4 sections. these are collapsed in a subtree */ stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness); stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id); proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, id_pos[0], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_src_ep, tvb, id_pos[1], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, id_pos[2], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_ep, tvb, id_pos[3], 1, ENC_NA); /* Block ports (only add them if address points to a device) */ bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 8); if (bytes[id_pos[0]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_src_blockport, tvb, id_pos[1], 1, ENC_NA); } if (bytes[id_pos[2]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_dst_blockport, tvb, id_pos[3], 1, ENC_NA); } /* Append SID in sid_t hex format */ proto_item_append_text(stream_item, " (%02X:%02X>%02X:%02X)", bytes[id_pos[0]], bytes[id_pos[1]], bytes[id_pos[2]], bytes[id_pos[3]] ); /* if has_time flag is present interpret timestamp */ if ((flag_has_time) && (len >= 16)){ if (is_network) item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness); else{ bytes = (guint8*) tvb_get_string(wmem_packet_scope(), tvb, 8, sizeof(unsigned long long)); timestamp = get_timestamp(bytes, sizeof(unsigned long long)); proto_tree_add_uint64(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, timestamp); } } int remaining_bytes = (len - chdr_size); int show_raw_payload = (remaining_bytes > 0); if (flag_is_cmd && remaining_bytes == 8) { cmd_item = proto_tree_add_item(chdr_tree, hf_chdr_cmd, tvb, chdr_size, 8, endianness); cmd_tree = proto_item_add_subtree(cmd_item, ett_chdr_cmd); proto_tree_add_item(cmd_tree, hf_chdr_cmd_address, tvb, chdr_size, 4, endianness); proto_tree_add_item(cmd_tree, hf_chdr_cmd_value, tvb, chdr_size + 4, 4, endianness); } else if (flag_is_resp) { response_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_response, tvb, chdr_size, 8, endianness); response_tree = proto_item_add_subtree(response_item, ett_chdr_response); proto_tree_add_item(response_tree, hf_chdr_ext_status_code, tvb, chdr_size, 4, endianness); /* This will show the 12-bits of sequence ID in the last 2 bytes */ proto_tree_add_item(response_tree, hf_chdr_ext_seq_num, tvb, (chdr_size + 4 + (is_network ? 2 : 0)), 2, endianness); } else if (show_raw_payload) { proto_tree_add_item(chdr_tree, hf_chdr_payload, tvb, chdr_size, -1, ENC_NA); } } } }
/* Parse Short Message, only if UDH present * (otherwise this function is not called). * Call WSP dissector if port matches WSP traffic. */ static void parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree) { tvbuff_t *sm_tvb = NULL; proto_item *ti; proto_tree *subtree, *tree; guint8 udh_len, udh, len; guint sm_len = tvb_reported_length(tvb); guint sm_data_len; guint32 i = 0; /* Multiple Messages UDH */ gboolean is_fragmented = FALSE; fragment_head *fd_sm = NULL; guint16 sm_id = 0; guint16 frags = 0; guint16 frag = 0; gboolean save_fragmented = FALSE; gboolean try_gsm_sms_ud_reassemble = FALSE; /* SMS Message reassembly */ gboolean reassembled = FALSE; guint32 reassembled_in = 0; /* Port Number UDH */ guint16 p_src = 0; guint16 p_dst = 0; gboolean ports_available = FALSE; udh_len = tvb_get_guint8(tvb, i++); ti = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len); tree = proto_item_add_subtree(ti, ett_udh); while (i < udh_len) { udh = tvb_get_guint8(tvb, i++); len = tvb_get_guint8(tvb, i++); subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei, tvb, i-2, 2+len, udh); switch (udh) { case 0x00: /* Multiple messages - 8-bit message ID */ if (len == 3) { sm_id = tvb_get_guint8(tvb, i++); frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-3, 1, sm_id); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x08: /* Multiple messages - 16-bit message ID */ if (len == 4) { sm_id = tvb_get_ntohs(tvb, i); i += 2; frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-4, 2, sm_id); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x04: /* Port Number UDH - 8-bit address */ if (len == 2) { /* Port fields */ p_dst = tvb_get_guint8(tvb, i++); p_src = tvb_get_guint8(tvb, i++); proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst, tvb, i-2, 1, p_dst); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src, tvb, i-1, 1, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x05: /* Port Number UDH - 16-bit address */ if (len == 4) { /* Port fields */ p_dst = tvb_get_ntohs(tvb, i); i += 2; p_src = tvb_get_ntohs(tvb, i); i += 2; proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst, tvb, i-4, 2, p_dst); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src, tvb, i-2, 2, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; default: i += len; break; } } if (tvb_reported_length_remaining(tvb, i) <= 0) return; /* No more data */ /* * XXX - where does the "1" come from? If it weren't there, * "sm_data_len" would, I think, be the same as * "tvb_reported_length_remaining(tvb, i)". * * I think that the above check ensures that "sm_len" won't * be less than or equal to "udh_len", so it ensures that * "sm_len" won't be less than "1 + udh_len", so we don't * have to worry about "sm_data_len" being negative. */ sm_data_len = sm_len - (1 + udh_len); if (sm_data_len == 0) return; /* no more data */ /* * Try reassembling the packets. * XXX - fragment numbers are 1-origin, but the fragment number * field could be 0. * Should we flag a fragmented message with a fragment number field * of 0? * What if the fragment count is 0? Should we flag that as well? */ if (is_fragmented && frag != 0 && frags != 0 && tvb_bytes_exist(tvb, i, sm_data_len)) { try_gsm_sms_ud_reassemble = TRUE; save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; fd_sm = fragment_add_seq_check(&sm_reassembly_table, tvb, i, pinfo, sm_id, /* guint32 ID for fragments belonging together */ NULL, frag-1, /* guint32 fragment sequence number */ sm_data_len, /* guint32 fragment length */ (frag != frags)); /* More fragments? */ if (fd_sm) { reassembled = TRUE; reassembled_in = fd_sm->reassembled_in; } sm_tvb = process_reassembled_data(tvb, i, pinfo, "Reassembled Short Message", fd_sm, &sm_frag_items, NULL, sm_tree); if (reassembled) { /* Reassembled */ col_append_str(pinfo->cinfo, COL_INFO, " (Short Message Reassembled)"); } else { /* Not last packet of reassembled Short Message */ col_append_fstr(pinfo->cinfo, COL_INFO, " (Short Message fragment %u of %u)", frag, frags); } } /* Else: not fragmented */ if (! sm_tvb) /* One single Short Message, or not reassembled */ sm_tvb = tvb_new_subset_remaining(tvb, i); /* Try calling a subdissector */ if (sm_tvb) { if ((reassembled && pinfo->fd->num == reassembled_in) || frag==0 || (frag==1 && try_dissect_1st_frag)) { /* Try calling a subdissector only if: * - the Short Message is reassembled in this very packet, * - the Short Message consists of only one "fragment", * - the preference "Always Try Dissection for 1st SM fragment" * is switched on, and this is the SM's 1st fragment. */ if (ports_available) { gboolean disallow_write = FALSE; /* TRUE if we changed writability of the columns of the summary */ if (prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo)) { disallow_write = TRUE; col_set_writable(pinfo->cinfo, FALSE); } if (port_number_udh_means_wsp) { call_dissector(wsp_handle, sm_tvb, pinfo, top_tree); } else { if (! dissector_try_uint(gsm_sms_dissector_table, p_src, sm_tvb, pinfo, top_tree)) { if (! dissector_try_uint(gsm_sms_dissector_table, p_dst, sm_tvb, pinfo, top_tree)) { if (sm_tree) { /* Only display if needed */ proto_tree_add_text(sm_tree, sm_tvb, 0, -1, "Short Message body"); } } } } if (disallow_write) col_set_writable(pinfo->cinfo, TRUE); } else { /* No ports IE */ proto_tree_add_text(sm_tree, sm_tvb, 0, -1, "Short Message body"); } } else { /* The packet is not reassembled, * or it is reassembled in another packet */ proto_tree_add_text(sm_tree, sm_tvb, 0, -1, "Unreassembled Short Message fragment %u of %u", frag, frags); } } if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */ pinfo->fragmented = save_fragmented; return; }
static void dissect_rsh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *rsh_tree=NULL; /* Variables for extracting and displaying data from the packet */ guchar *field_stringz; /* Temporary storage for each field we extract */ gint length; guint offset = 0; conversation_t *conversation; rsh_hash_entry_t *hash_info; conversation = find_or_create_conversation(pinfo); /* Retrieve information from conversation * or add it if it isn't there yet */ hash_info = conversation_get_proto_data(conversation, proto_rsh); if(!hash_info){ hash_info = se_alloc(sizeof(rsh_hash_entry_t)); hash_info->first_packet_number = pinfo->fd->num; hash_info->second_packet_number = 0; hash_info->third_packet_number = 0; hash_info->fourth_packet_number = 0; hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */ /* Start with empty username and command strings */ hash_info->client_username=NULL; hash_info->server_username=NULL; hash_info->command=NULL; /* These will be set on the first pass by the first * four packets of the conversation */ hash_info->first_packet_state = NONE; hash_info->second_packet_state = NONE; hash_info->third_packet_state = NONE; hash_info->fourth_packet_state = NONE; conversation_add_proto_data(conversation, proto_rsh, hash_info); } /* Store the number of the first three packets of this conversation * as we reach them the first time */ if(!hash_info->second_packet_number && pinfo->fd->num > hash_info->first_packet_number){ /* We're on the second packet of the conversation */ hash_info->second_packet_number = pinfo->fd->num; } else if(hash_info->second_packet_number && !hash_info->third_packet_number && pinfo->fd->num > hash_info->second_packet_number) { /* We're on the third packet of the conversation */ hash_info->third_packet_number = pinfo->fd->num; } else if(hash_info->third_packet_number && !hash_info->fourth_packet_number && pinfo->fd->num > hash_info->third_packet_number) { /* We're on the fourth packet of the conversation */ hash_info->fourth_packet_number = pinfo->fd->num; } /* Save this packet's state so we can retrieve it if this packet * is selected again later. If the packet's state was already stored, * then retrieve it */ if(pinfo->fd->num == hash_info->first_packet_number){ if(hash_info->first_packet_state == NONE){ hash_info->first_packet_state = hash_info->state; } else { hash_info->state = hash_info->first_packet_state; } } if(pinfo->fd->num == hash_info->second_packet_number){ if(hash_info->second_packet_state == NONE){ hash_info->second_packet_state = hash_info->state; } else { hash_info->state = hash_info->second_packet_state; } } if(pinfo->fd->num == hash_info->third_packet_number){ if(hash_info->third_packet_state == NONE){ hash_info->third_packet_state = hash_info->state; } else { hash_info->state = hash_info->third_packet_state; } } if(pinfo->fd->num == hash_info->fourth_packet_number){ if(hash_info->fourth_packet_state == NONE){ hash_info->fourth_packet_state = hash_info->state; } else { hash_info->state = hash_info->fourth_packet_state; } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSH"); if(check_col(pinfo->cinfo, COL_INFO)){ /* First, clear the info column */ col_clear(pinfo->cinfo, COL_INFO); /* Client username */ if(hash_info->client_username && preference_info_show_client_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Client username:%s ", hash_info->client_username); } /* Server username */ if(hash_info->server_username && preference_info_show_server_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Server username:%s ", hash_info->server_username); } /* Command */ if(hash_info->command && preference_info_show_command == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command); } } /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_rsh, tvb, 0, -1, ENC_NA); rsh_tree = proto_item_add_subtree(ti, ett_rsh); /* If this packet doesn't end with a null terminated string, * then it must be session data only and we can skip looking * for the other fields. */ if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){ hash_info->state = WAIT_FOR_DATA; } if(hash_info->state == WAIT_FOR_STDERR_PORT && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the stderr_port field. * It is optional, so it may only be 1 character long * (the NULL) */ if(length == 1 || (isdigit_string(field_stringz) && length <= RSH_STDERR_PORT_LEN)){ proto_tree_add_string(rsh_tree, hf_rsh_stderr_port, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_CLIENT_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_CLIENT_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the username field */ if(length != 1 && length <= RSH_CLIENT_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_client_username, tvb, offset, length, (gchar*)field_stringz); /* Store the client username so we can display it in the * info column of the entire conversation */ if(!hash_info->client_username){ hash_info->client_username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_SERVER_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_SERVER_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the password field */ if(length != 1 && length <= RSH_SERVER_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_server_username, tvb, offset, length, (gchar*)field_stringz); /* Store the server username so we can display it in the * info column of the entire conversation */ if(!hash_info->server_username){ hash_info->server_username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_COMMAND; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; /* Next field we are looking for */ hash_info->state = WAIT_FOR_COMMAND; } if(hash_info->state == WAIT_FOR_COMMAND && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the command field */ if(length != 1 && length <= RSH_COMMAND_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_command, tvb, offset, length, (gchar*)field_stringz); /* Store the command so we can display it in the * info column of the entire conversation */ if(!hash_info->command){ hash_info->command=se_strdup((gchar*)field_stringz); } } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } } if(hash_info->state == WAIT_FOR_DATA && tvb_length_remaining(tvb, offset)){ if(pinfo->destport == RSH_PORT){ /* Packet going to the server */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(rsh_tree, tvb, 0, -1, "Client -> Server Data"); col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data"); } else { /* This packet must be going back to the client */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(rsh_tree, tvb, 0, -1, "Server -> Client Data"); col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data"); } } /* We haven't seen all of the fields yet */ if(hash_info->state < WAIT_FOR_DATA){ col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment"); } }
static int dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo) { proto_tree *hdrs_tree = NULL; proto_tree *hdr_tree = NULL; proto_item *hdr = NULL; proto_item *handle_item; gint item_length = -1; guint8 hdr_id, i; if (tvb_length_remaining(tvb, offset) > 0) { proto_item *hdrs; hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers"); hdrs_tree = proto_item_add_subtree(hdrs, ett_btobex_hdrs); } else { return offset; } while (tvb_length_remaining(tvb, offset) > 0) { hdr_id = tvb_get_guint8(tvb, offset); switch(0xC0 & hdr_id) { case 0x00: /* null terminated unicode */ item_length = tvb_get_ntohs(tvb, offset+1); break; case 0x40: /* byte sequence */ item_length = tvb_get_ntohs(tvb, offset+1); break; case 0x80: /* 1 byte */ item_length = 2; break; case 0xc0: /* 4 bytes */ item_length = 5; break; } hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s", val_to_str_ext_const(hdr_id, &header_id_vals_ext, "Unknown")); hdr_tree = proto_item_add_subtree(hdr, ett_btobex_hdr); proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; switch(0xC0 & hdr_id) { case 0x00: /* null terminated unicode */ { proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if ((item_length - 3) > 0) { char *str; display_unicode_string(tvb, hdr_tree, offset, &str); proto_item_append_text(hdr_tree, " (\"%s\")", str); col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str); } else { col_append_str(pinfo->cinfo, COL_INFO, " \"\""); } offset += item_length - 3; } break; case 0x40: /* byte sequence */ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA); if (((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19)) { /* target or who */ for(i=0; target_vals[i].strptr != NULL; i++) { if (tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0) { proto_item_append_text(handle_item, ": %s", target_vals[i].strptr); proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr); col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr); } } } if (!tvb_strneql(tvb, offset, "<?xml", 5)) { tvbuff_t* next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(xml_handle, next_tvb, pinfo, tree); } else if (is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3)) { proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3)); col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3)); } offset += item_length - 3; break; case 0x80: /* 1 byte */ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; break; case 0xc0: /* 4 bytes */ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; default: break; } } return offset; }
/**************************************************************** * Main dissection function ****************************************************************/ static void dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct tcpinfo *tcpinfo = (struct tcpinfo *)pinfo->private_data; conversation_t *conversation; rlogin_hash_entry_t *hash_info; guint length; gint ti_offset; /* Get or create conversation */ conversation = find_or_create_conversation(pinfo); /* Get or create data associated with this conversation */ hash_info = (rlogin_hash_entry_t *)conversation_get_proto_data(conversation, proto_rlogin); if (!hash_info) { /* Populate new data struct... */ hash_info = wmem_new(wmem_file_scope(), rlogin_hash_entry_t); hash_info->state = NONE; hash_info->info_framenum = 0; /* no frame has the number 0 */ hash_info->user_name[0] = '\0'; /* ... and store in conversation */ conversation_add_proto_data(conversation, proto_rlogin, hash_info); } /* Set protocol column text */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin"); /* Set info column */ /* Show user-name if available */ if (hash_info->user_name[0]) { col_add_fstr(pinfo->cinfo, COL_INFO, "User name: %s, ", hash_info->user_name); } else { col_clear(pinfo->cinfo, COL_INFO); } /* Work out packet content summary for display */ length = tvb_length(tvb); if (length != 0) { /* Initial NULL byte represents part of connection handshake */ if (tvb_get_guint8(tvb, 0) == '\0') { col_append_str(pinfo->cinfo, COL_INFO, (pinfo->destport == RLOGIN_PORT) ? "Start Handshake" : "Startup info received"); } else if (tcpinfo->urgent && length >= tcpinfo->urgent_pointer) { /* Urgent pointer inside current data represents a control message */ col_append_str(pinfo->cinfo, COL_INFO, "Control Message"); } else { /* Search for 2 consecutive ff bytes (signifies window change control message) */ ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff); if (ti_offset != -1 && tvb_bytes_exist(tvb, ti_offset + 1, 1) && tvb_get_guint8(tvb, ti_offset + 1) == 0xff) { col_append_str(pinfo->cinfo, COL_INFO, "Terminal Info"); } else { /* Show any text data in the frame */ int bytes_to_copy = tvb_length(tvb); if (bytes_to_copy > 128) { /* Truncate to 128 bytes for display */ bytes_to_copy = 128; } /* Add data into info column */ col_append_fstr(pinfo->cinfo, COL_INFO, "Data: %s", tvb_format_text(tvb, 0, bytes_to_copy)); } } } /* See if conversation state needs to be updated */ rlogin_state_machine(hash_info, tvb, pinfo); /* Dissect in detail */ rlogin_display(hash_info, tvb, pinfo, tree, tcpinfo); }
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; }
static void dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { xml_frame_t *xml_frame; gboolean out_packet; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; proto_tree *xmpp_tree = NULL; proto_item *xmpp_item = NULL; xmpp_element_t *packet = NULL; /*check if desegment * now it checks that last char is '>', * TODO checks that first element in packet is closed*/ int indx; gchar last_char; if (xmpp_desegment) { indx = tvb_reported_length(tvb) - 1; if (indx >= 0) { last_char = tvb_get_guint8(tvb, indx); while ((last_char <= ' ') && (indx - 1 >= 0)) { indx--; last_char = tvb_get_guint8(tvb, indx); } if ((indx >= 0) && (last_char != '>')) { pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); if (xmpp_info && xmpp_info->ssl_proceed && xmpp_info->ssl_proceed < pinfo->fd->num) { call_dissector(ssl_handle, tvb, pinfo, tree); return; } /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/ xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA); xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp); call_dissector(xml_handle, tvb, pinfo, xmpp_tree); /* If XML dissector is disabled, we can't do much */ if (!proto_is_protocol_enabled(find_protocol_by_id(dissector_handle_get_protocol_index(xml_handle)))) { col_append_str(pinfo->cinfo, COL_INFO, "(XML dissector disabled, can't dissect XMPP)"); expert_add_info_format(pinfo, xmpp_item, PI_UNDECODED, PI_WARN, "XML dissector disabled, can't dissect XMPP"); return; } /*if stream end occurs then return*/ if(xmpp_stream_close(xmpp_tree,tvb, pinfo)) { if(xmpp_tree) xmpp_proto_tree_hide_first_child(xmpp_tree); return; } if(!pinfo->private_data) return; /*data from XML dissector*/ xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child; if(!xml_frame) return; if (!xmpp_info) { xmpp_info = se_new(xmpp_conv_info_t); xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp"); xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions"); xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions"); xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions"); xmpp_info->ssl_start = 0; xmpp_info->ssl_proceed = 0; conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info); } if (pinfo->match_uint == pinfo->destport) out_packet = TRUE; else out_packet = FALSE; while(xml_frame) { packet = xmpp_xml_frame_to_element_t(xml_frame, NULL, tvb); DISSECTOR_ASSERT(packet); if (strcmp(packet->name, "iq") == 0) { xmpp_iq_reqresp_track(pinfo, packet, xmpp_info); xmpp_jingle_session_track(pinfo, packet, xmpp_info); xmpp_gtalk_session_track(pinfo, packet, xmpp_info); } if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) { xmpp_ibb_session_track(pinfo, packet, xmpp_info); } if (tree) { /* we are being asked for details */ proto_item *outin_item; if (out_packet) outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, TRUE); else outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(outin_item); /*it hides tree generated by XML dissector*/ xmpp_proto_tree_hide_first_child(xmpp_tree); if (strcmp(packet->name, "iq") == 0) { xmpp_iq(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "presence") == 0) { xmpp_presence(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "message") == 0) { xmpp_message(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "auth") == 0) { xmpp_auth(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "challenge") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE"); } else if (strcmp(packet->name, "response") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE"); } else if (strcmp(packet->name, "success") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS"); } else if (strcmp(packet->name, "failure") == 0) { xmpp_failure(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "xml") == 0) { xmpp_xml_header(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "stream") == 0) { xmpp_stream(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "features") == 0) { xmpp_features(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "starttls") == 0) { xmpp_starttls(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else if (strcmp(packet->name, "proceed") == 0) { xmpp_proceed(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else { xmpp_proto_tree_show_first_child(xmpp_tree); expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name); col_clear(pinfo->cinfo, COL_INFO); col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET "); } /*appends to COL_INFO information about src or dst*/ if (pinfo->match_uint == pinfo->destport) { xmpp_attr_t *to = xmpp_get_attr(packet, "to"); if (to) col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value); } else { xmpp_attr_t *from = xmpp_get_attr(packet, "from"); if (from) col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value); } } xmpp_element_t_tree_free(packet); xml_frame = xml_frame->next_sibling; } }
static void _dissect_uasip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, e_ua_direction direction) { proto_item *uasip_item; proto_tree *uasip_tree; guint8 opcode; gint offset = 0; if (noesip_enabled) { col_append_str(pinfo->cinfo, COL_PROTOCOL, "/NOE"); } else { col_append_str(pinfo->cinfo, COL_PROTOCOL, "/DL"); } opcode = tvb_get_guint8(tvb, offset); offset++; ua_tap_info.opcode = opcode; ua_tap_info.expseq = 0; ua_tap_info.sntseq = 0; col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)")); uasip_item = proto_tree_add_protocol_format(tree, proto_uasip, tvb, 0, 5, "SIP/NOE Protocol, %s", val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)")); uasip_tree = proto_item_add_subtree(uasip_item, ett_uasip); proto_tree_add_uint(uasip_tree, hf_uasip_opcode, tvb, 0, 1, opcode); switch(opcode) { case UAUDP_CONNECT: { if (!tree) break; while(tvb_offset_exists(tvb, offset)) { guint8 T = tvb_get_guint8(tvb, offset+0); guint8 L = tvb_get_guint8(tvb, offset+1); switch(T) { case UAUDP_CONNECT_VERSION: rTLV(uasip_tree, &hf_uasip_version, tvb, offset, L); break; case UAUDP_CONNECT_WINDOW_SIZE: rTLV(uasip_tree, &hf_uasip_window_size, tvb, offset, L); break; case UAUDP_CONNECT_MTU: rTLV(uasip_tree, &hf_uasip_mtu, tvb, offset, L); break; case UAUDP_CONNECT_UDP_LOST: rTLV(uasip_tree, &hf_uasip_udp_lost, tvb, offset, L); break; case UAUDP_CONNECT_UDP_LOST_REINIT: rTLV(uasip_tree, &hf_uasip_udp_lost_reinit, tvb, offset, L); break; case UAUDP_CONNECT_KEEPALIVE: rTLV(uasip_tree, &hf_uasip_keepalive, tvb, offset, L); break; case UAUDP_CONNECT_QOS_IP_TOS: rTLV(uasip_tree, &hf_uasip_qos_ip_tos, tvb, offset, L); break; case UAUDP_CONNECT_QOS_8021_VLID: rTLV(uasip_tree, &hf_uasip_qos_8021_vlid, tvb, offset, L); break; case UAUDP_CONNECT_QOS_8021_PRI: rTLV(uasip_tree, &hf_uasip_qos_8021_pri, tvb, offset, L); break; default: break; } offset += (2 + L); } } break; case UAUDP_NACK: { proto_tree_add_uint(uasip_tree, hf_uasip_expseq, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); ua_tap_info.expseq = tvb_get_ntohs(tvb, offset+0); /*offset += 2;*/ if (noesip_enabled) { col_add_fstr(pinfo->cinfo, COL_INFO, "NACK"); } else { col_add_fstr(pinfo->cinfo, COL_INFO, "NACK exp:%d", ua_tap_info.expseq); } } break; case UAUDP_DATA: { int datalen; proto_tree_add_uint(uasip_tree, hf_uasip_expseq, tvb, offset+0, 2, tvb_get_ntohs(tvb, offset+0)); proto_tree_add_uint(uasip_tree, hf_uasip_sntseq, tvb, offset+2, 2, tvb_get_ntohs(tvb, offset+2)); ua_tap_info.expseq = tvb_get_ntohs(tvb, offset+0); ua_tap_info.sntseq = tvb_get_ntohs(tvb, offset+2); offset += 4; datalen = (tvb_length(tvb) - offset); if (noesip_enabled) { if (datalen > 0) { if (direction == SYS_TO_TERM) { call_dissector(ua_sys_to_term_handle, tvb_new_subset(tvb, offset, datalen, datalen), pinfo, tree); } else if (direction == TERM_TO_SYS) { call_dissector(ua_term_to_sys_handle, tvb_new_subset(tvb, offset, datalen, datalen), pinfo, tree); } else { col_add_str(pinfo->cinfo, COL_INFO, "DATA - Couldn't resolve direction."); } } else { col_add_str(pinfo->cinfo, COL_INFO, "ACK"); } } else { if (datalen > 0) { col_add_fstr(pinfo->cinfo, COL_INFO, "DATA exp:%d", ua_tap_info.expseq); col_append_fstr(pinfo->cinfo, COL_INFO, " snt:%d", ua_tap_info.sntseq); } else { col_add_fstr(pinfo->cinfo, COL_INFO, "ACK exp:%d", ua_tap_info.expseq); col_append_fstr(pinfo->cinfo, COL_INFO, " snt:%d", ua_tap_info.sntseq); } } } break; default: break; } #if 0 tap_queue_packet(uasip_tap, pinfo, &ua_tap_info); #endif }
static void dissect_status (packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 flags) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item=proto_tree_add_uint(parent_tree, hf_sbccs_dib_status, tvb, offset, 1, flags); tree=proto_item_add_subtree(item, ett_sbccs_dib_status); } proto_tree_add_boolean(tree, hf_sbccs_dib_status_attention, tvb, offset, 1, flags); if (flags & 0x80) { proto_item_append_text(item, " Attention"); col_append_str(pinfo->cinfo, COL_INFO, " Attention"); } flags &= (~( 0x80 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_modifier, tvb, offset, 1, flags); if (flags & 0x40) { proto_item_append_text(item, " Status Modifier"); col_append_str(pinfo->cinfo, COL_INFO, " Status Modifier"); } flags &= (~( 0x40 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_cue, tvb, offset, 1, flags); if (flags & 0x20) { proto_item_append_text(item, " Control-Unit End"); col_append_str(pinfo->cinfo, COL_INFO, " Control-Unit End"); } flags &= (~( 0x20 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_busy, tvb, offset, 1, flags); if (flags & 0x10) { proto_item_append_text(item, " Busy"); col_append_str(pinfo->cinfo, COL_INFO, " Busy"); } flags &= (~( 0x10 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_channelend, tvb, offset, 1, flags); if (flags & 0x08) { proto_item_append_text(item, " Channel End"); col_append_str(pinfo->cinfo, COL_INFO, " Channel End"); } flags &= (~( 0x08 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_deviceend, tvb, offset, 1, flags); if (flags & 0x04) { proto_item_append_text(item, " Device End"); col_append_str(pinfo->cinfo, COL_INFO, " Device End"); } flags &= (~( 0x04 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_unit_check, tvb, offset, 1, flags); if (flags & 0x02) { proto_item_append_text(item, " Unit Check"); col_append_str(pinfo->cinfo, COL_INFO, " Unit Check"); } flags &= (~( 0x02 )); proto_tree_add_boolean(tree, hf_sbccs_dib_status_unit_exception, tvb, offset, 1, flags); if (flags & 0x01) { proto_item_append_text(item, " Unit Exception"); col_append_str(pinfo->cinfo, COL_INFO, " Unit Exception"); } /*flags &= (~( 0x01 ));*/ }
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *tns_tree) { proto_tree *data_tree = NULL, *ti; proto_item *hidden_item; int is_sns = 0; if ( tvb_bytes_exist(tvb, offset+2, 4) ) { if ( tvb_get_guint8(tvb, offset+2) == 0xDE && tvb_get_guint8(tvb, offset+3) == 0xAD && tvb_get_guint8(tvb, offset+4) == 0xBE && tvb_get_guint8(tvb, offset+5) == 0xEF ) { is_sns = 1; } } if ( tree ) { if ( is_sns ) { data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Secure Network Services"); } else { data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data"); } hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_data, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } if ( tree ) { proto_tree *df_tree = NULL; ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, ENC_BIG_ENDIAN); df_tree = proto_item_add_subtree(ti, ett_tns_data_flag); proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( is_sns ) { col_append_str(pinfo->cinfo, COL_INFO, ", SNS"); } else { col_append_str(pinfo->cinfo, COL_INFO, ", Data"); } call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, data_tree); return; }
/* dissect a response. more work to do here. */ static void display_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 mcode = 0; int i; /* MAGIC */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; /* PDU LENGTH */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* MESSAGE TYPE CODE */ mcode = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(mcode, mtype_codes, "Unknown message code %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; switch (mcode) { case MTYPE_END_RESPONSE: if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_reusep, tvb, pos, 1, ENC_BIG_ENDIAN); /*pos+=1;*/ break; case MTYPE_SEND_HEADERS: { const gchar *rsmsg; guint16 rsmsg_len; guint16 nhdr; guint16 rcode_num; /* HTTP RESPONSE STATUS CODE */ rcode_num = tvb_get_ntohs(tvb, pos); col_append_fstr(pinfo->cinfo, COL_INFO, ":%d", rcode_num); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rstatus, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HTTP RESPONSE STATUS MESSAGE */ rsmsg = ajp13_get_nstring(tvb, pos, &rsmsg_len); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", rsmsg); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rsmsg, tvb, pos, rsmsg_len+2, rsmsg); pos+=rsmsg_len+2; /* NUMBER OF HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar *hval; guint16 hval_len, hname_len; const gchar* hname = NULL; int hpos = pos; /* int cl = 0; TODO: Content-Length header (encoded by 0x08) is special */ /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(rsp_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format_value(ajp13_tree, *rsp_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s", hval); pos+=hval_len+2; #if 0 /* TODO: Content-Length header (encoded by 0x08) is special */ if (hid == 0x08) cl = 1; #endif } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval), "%s: %s", hname, hval); pos+=hval_len+2; } } break; } case MTYPE_GET_BODY_CHUNK: { guint16 rlen; rlen = tvb_get_ntohs(tvb, pos); cd->content_length = rlen; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rlen, tvb, pos, 2, ENC_BIG_ENDIAN); /*pos+=2;*/ break; } case MTYPE_CPONG: break; default: /* MESSAGE DATA (COPOUT) */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_data, tvb, pos+2, -1, ENC_UTF_8|ENC_NA); break; } }
static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *tns_tree) { proto_tree *connect_tree = NULL, *ti; proto_item *hidden_item; int cd_offset; int cd_len; int tns_offset = offset-8; if ( tree ) { connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_connect, NULL, "Connect"); hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_connect, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } col_append_str(pinfo->cinfo, COL_INFO, ", Connect"); if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_version, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree *sopt_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_service_options, tvb, offset, 2, ENC_BIG_ENDIAN); sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag); dissect_tns_service_options(tvb, offset, sopt_tree); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree *ntp_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_nt_proto_characteristics, tvb, offset, 2, ENC_BIG_ENDIAN); ntp_tree = proto_item_add_subtree(ti, ett_tns_ntp_flag); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_hangon, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_crel, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_tduio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_srun, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_dtest, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_cbio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_asio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_pio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_grant, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_handoff, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigpipe, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigurg, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_urgentio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_fdio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_testop, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb, offset, 2, ENC_NA); } offset += 2; cd_len = tvb_get_ntohs(tvb, offset); if ( connect_tree ) { proto_tree_add_uint(connect_tree, hf_tns_connect_data_length, tvb, offset, 2, cd_len); } offset += 2; cd_offset = tvb_get_ntohs(tvb, offset); if ( connect_tree ) { proto_tree_add_uint(connect_tree, hf_tns_connect_data_offset, tvb, offset, 2, cd_offset); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags0, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } offset += 1; if ( connect_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags1, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } offset += 1; /* * XXX - sometimes it appears that this stuff isn't present * in the packet. */ if (offset + 16 <= tns_offset+cd_offset) { if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb, offset, 8, ENC_BIG_ENDIAN); } /* offset += 8;*/ } if ( connect_tree && cd_len > 0) { proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb, tns_offset+cd_offset, -1, ENC_ASCII|ENC_NA); } return; }
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ? * It seems to me that invalid fields should just add an expert item * or cause a "Malformed" exception. */ static void dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request, length_ok; proto_tree *elcom_tree; proto_item *ti, *hidden_item; gint offset = 0; guint elcom_len; guint8 elcom_msg_type; guint8 *suffix; /* Check that there's enough data */ if (tvb_length(tvb) < 3) return; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ELCOM"); col_clear(pinfo->cinfo, COL_INFO); is_request = (pinfo->match_uint == pinfo->destport); elcom_len = tvb_get_ntohs(tvb, 0); length_ok = (tvb_reported_length(tvb) == (elcom_len+2)); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s", is_request ? "Request" : "Response", elcom_len, length_ok ? "" : " (incorrect)"); elcom_msg_type = tvb_get_guint8(tvb, 2); switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* starting after elcom_len and elcom_msg_type, initiator + responder + userdata fields must be there */ if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return; /* check also that those field lengths are valid */ if (tvb_get_guint8(tvb, 3) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return; if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return; /* finally believe that there is valid suffix */ suffix = tvb_get_string_enc(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix); break; case P_RELRQ: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Release"); break; case P_DATRQ: col_append_str(pinfo->cinfo, COL_INFO, " Data"); break; } switch (elcom_msg_type) { case P_CONRQ: case P_RELRQ: col_append_str(pinfo->cinfo, COL_INFO, " Request"); break; case P_CONRS: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Response"); break; } if (!tree) return; ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA); elcom_tree = proto_item_add_subtree(ti, ett_elcom); hidden_item = proto_tree_add_boolean(elcom_tree, is_request ? hf_elcom_request : hf_elcom_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* 2 first bytes are the frame length */ offset = 0; ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = +2; if (! length_ok) { proto_item_append_text(ti, " (incorrect)"); } elcom_msg_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d")); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return; switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* * Connection request/release assiciated PDU's, * /ELCOM-90 P Protocol spec/ p. 85... */ /* We need the length here, hardcode the LOWADR_LEN = 21 */ ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_NA); offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset, hf_elcom_initiator_endian, hf_elcom_initiator_ip, hf_elcom_initiator_port, hf_elcom_initiator_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_NA); offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset, hf_elcom_responder_endian, hf_elcom_responder_ip, hf_elcom_responder_port, hf_elcom_responder_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; /* Rest of the payload is USER-DATA, 0..82 bytes */ ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA); offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset); break; case P_RELRQ: proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_RELRS: proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_DATRQ: ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA); offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset); break; default: proto_item_append_text(ti, " <<--- meaning WHAT??"); break; } if (tvb_length_remaining(tvb, offset) > 0) { /* We should not get here, but if we do, show what is left over: */ proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA); } }
/* Code to actually dissect the packets */ static void dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 addr_field, comp_field, npdu_field1, nsapi, dcomp=0, pcomp=0; guint16 offset=0, npdu=0, segment=0, npdu_field2; tvbuff_t *next_tvb, *npdu_tvb; gint len; gboolean first, more_frags, unack; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *address_field_item, *compression_field_item, *npdu_field_item; proto_tree *sndcp_tree = NULL, *address_field_tree, *compression_field_tree, *npdu_field_tree; /* Make entries in Protocol column and clear Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNDCP"); col_clear(pinfo->cinfo, COL_INFO); /* create display subtree for the protocol */ if (tree) { ti = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, ENC_NA); sndcp_tree = proto_item_add_subtree(ti, ett_sndcp); } /* get address field from next byte */ addr_field = tvb_get_guint8(tvb,offset); nsapi = addr_field & 0xF; first = addr_field & MASK_F; more_frags = addr_field & MASK_M; unack = addr_field & MASK_T; /* add subtree for the address field */ if (tree) { address_field_item = proto_tree_add_uint_format(sndcp_tree,hf_sndcp_nsapi, tvb, offset,1, nsapi, "Address field NSAPI: %d", nsapi ); address_field_tree = proto_item_add_subtree(address_field_item, ett_sndcp_address_field); proto_tree_add_boolean(address_field_tree, hf_sndcp_x, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_f, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_t, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_m, tvb,offset,1, addr_field ); proto_tree_add_uint(address_field_tree, hf_sndcp_nsapib, tvb, offset, 1, addr_field ); } offset++; /* get compression pointers from next byte if this is the first segment */ if (first) { comp_field = tvb_get_guint8(tvb,offset); dcomp = comp_field & 0xF0; pcomp = comp_field & 0x0F; /* add subtree for the compression field */ if (tree) { if (!pcomp) { if (!dcomp) { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "No compression"); } else { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data compression"); } } else { if (!dcomp) { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Protocol compression"); } else { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data and Protocol compression"); } } compression_field_tree = proto_item_add_subtree(compression_field_item, ett_sndcp_compression_field); proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field ); proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field ); } offset++; /* get N-PDU number from next byte for acknowledged mode (only for first segment) */ if (!unack) { npdu = npdu_field1 = tvb_get_guint8(tvb,offset); col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1); if (tree) { npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Acknowledged mode, N-PDU %d", npdu_field1 ); npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field); proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 ); } offset++; } } /* get segment and N-PDU number from next two bytes for unacknowledged mode */ if (unack) { npdu_field2 = tvb_get_ntohs(tvb, offset); segment = (npdu_field2 & 0xF000) >> 12; npdu = (npdu_field2 & 0x0FFF); col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment); if (tree) { npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,2, "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment ); npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field); proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 ); proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 ); } offset += 2; } /* handle N-PDU data, reassemble if necessary */ if (first && !more_frags) { next_tvb = tvb_new_subset_remaining (tvb, offset); if (!dcomp && !pcomp) { call_dissector(ip_handle, next_tvb, pinfo, tree); } else { call_dissector(data_handle, next_tvb, pinfo, tree); } } else { /* Try reassembling fragments */ fragment_head *fd_npdu = NULL; guint32 reassembled_in = 0; gboolean save_fragmented = pinfo->fragmented; len = tvb_length_remaining(tvb, offset); if(len<=0){ return; } pinfo->fragmented = TRUE; if (unack) fd_npdu = fragment_add_seq_check(&npdu_reassembly_table, tvb, offset, pinfo, npdu, NULL, segment, len, more_frags); else fd_npdu = fragment_add(&npdu_reassembly_table, tvb, offset, pinfo, npdu, NULL, offset, len, more_frags); npdu_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled N-PDU", fd_npdu, &npdu_frag_items, NULL, sndcp_tree); if (fd_npdu) { /* Reassembled */ reassembled_in = fd_npdu->reassembled_in; if (pinfo->fd->num == reassembled_in) { /* Reassembled in this very packet: * We can safely hand the tvb to the IP dissector */ call_dissector(ip_handle, npdu_tvb, pinfo, tree); } else { /* Not reassembled in this packet */ col_append_fstr(pinfo->cinfo, COL_INFO, " (N-PDU payload reassembled in packet %u)", fd_npdu->reassembled_in); if (tree) { proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload"); } } } else { /* Not reassembled yet, or not reassembled at all */ if (unack) col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment); else col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)"); if (tree) { proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload"); } } /* Now reset fragmentation information in pinfo */ pinfo->fragmented = save_fragmented; } }
static void dissect_rtp_events( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti; proto_tree *rtp_events_tree; unsigned int offset = 0; struct _rtp_conversation_info *p_conv_data; guint8 rtp_evt; guint8 octet; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTP EVENT"); col_clear(pinfo->cinfo, COL_INFO); /* Get event fields */ rtp_evt = tvb_get_guint8(tvb, offset ); /* get tap info */ rtp_event_info.info_rtp_evt = rtp_evt; p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name("rtp"), 0); if (p_conv_data) rtp_event_info.info_setup_frame_num = p_conv_data->frame_number; else rtp_event_info.info_setup_frame_num = 0; col_add_fstr( pinfo->cinfo, COL_INFO, "Payload type=RTP Event, %s", val_to_str_ext( rtp_evt, &rtp_event_type_values_ext, "Unknown (%u)" )); ti = proto_tree_add_item( tree, proto_rtp_events, tvb, offset, -1, ENC_NA ); rtp_events_tree = proto_item_add_subtree( ti, ett_rtp_events ); proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_event, tvb, offset, 1, rtp_evt); offset++; octet = tvb_get_guint8(tvb, offset); proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_end, tvb, offset, 1, octet); proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_reserved, tvb, offset, 1, octet); proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_volume, tvb, offset, 1, octet); offset++; /* The duration field indicates the duration of the event or segment * being reported, in timestamp units. */ rtp_event_info.info_duration = tvb_get_ntohs(tvb, offset); proto_tree_add_item ( rtp_events_tree, hf_rtp_events_duration, tvb, offset, 2, ENC_BIG_ENDIAN); /* set the end info for the tap */ if (octet & 0x80) { rtp_event_info.info_end = TRUE; } else { rtp_event_info.info_end = FALSE; } /* Make end-of-event packets obvious in the info column */ if ((octet & 0x80)) { col_append_str(pinfo->cinfo, COL_INFO, " (end)"); } tap_queue_packet(rtp_event_tap, pinfo, &rtp_event_info); }
static void dissect_gsm_cell_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 sms_encoding, total_pages, current_page; guint32 offset = 0; guint len, text_len; guint32 msg_key; proto_item *cbs_page_item = NULL; proto_tree *cbs_page_tree = NULL; guint16 serial_number, message_id; tvbuff_t *cbs_page_tvb = NULL; tvbuff_t *cbs_msg_tvb = NULL; fragment_head * frag_data = NULL; len = tvb_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast"); col_append_str(pinfo->cinfo, COL_INFO, " (CBS Page)"); cbs_page_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "GSM Cell Broadcast"); cbs_page_tree = proto_item_add_subtree(cbs_page_item, ett_gsm_cbs_page); serial_number = tvb_get_ntohs(tvb, offset); offset += dissect_cbs_serial_number(tvb, cbs_page_tree, offset); message_id = tvb_get_ntohs(tvb, offset); offset += dissect_cbs_message_identifier(tvb, cbs_page_tree, offset); sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_page_tree, offset++); total_pages = tvb_get_guint8(tvb, offset); current_page = (total_pages & 0xF0) >> 4; total_pages &= 0x0F; proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_current_page, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_total_pages, tvb, offset++, 1, ENC_BIG_ENDIAN); cbs_page_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_page_tree, pinfo, offset ); if (cbs_page_tvb != NULL) { text_len = tvb_length(cbs_page_tvb); while (text_len && (tvb_get_guint8(cbs_page_tvb, text_len-1) == '\r')) { text_len--; } if (tree != NULL) { proto_item *item = proto_tree_add_text(cbs_page_tree, tvb, offset, -1, "Cell Broadcast Page Contents"); proto_tree *cbs_page_subtree = proto_item_add_subtree(item, ett_gsm_cbs_page_content); len = tvb_length(cbs_page_tvb); proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content, cbs_page_tvb, 0, text_len, tvb_get_string(wmem_packet_scope(), cbs_page_tvb, 0, text_len)); len -= text_len; if (len) { proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content_padding, cbs_page_tvb, text_len, len, tvb_get_string(wmem_packet_scope(), cbs_page_tvb, text_len, len)); } } if (text_len) { cbs_page_tvb = tvb_new_subset(cbs_page_tvb, 0, text_len, text_len); if (total_pages == 1) { /* no need for reassembly */ cbs_msg_tvb = cbs_page_tvb; } else { /* now we have a complete page, try to concatenate the full message */ /* we can use the serial number and message ID as keys, as they are the same for all pages of a message */ msg_key = (serial_number << 16) + message_id; frag_data = fragment_add_seq_check(&gsm_cbs_reassembly_table, cbs_page_tvb, 0, pinfo, msg_key, NULL, (current_page -1), text_len, (current_page!=total_pages)); cbs_msg_tvb = process_reassembled_data(cbs_page_tvb, 0, pinfo, "Reassembled Cell Broadcast message", frag_data, &gsm_page_items, NULL, cbs_page_tree); } } } if (cbs_msg_tvb != NULL) { proto_item *cbs_msg_item = NULL; proto_tree *cbs_msg_tree = NULL; len = tvb_length(cbs_msg_tvb); col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)"); cbs_msg_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, cbs_msg_tvb, 0, len, "GSM Cell Broadcast Message"); cbs_msg_tree = proto_item_add_subtree(cbs_msg_item, ett_cbs_msg); proto_tree_add_string(cbs_msg_tree, hf_gsm_cbs_message_content, cbs_msg_tvb, 0, len, tvb_get_string(wmem_packet_scope(), cbs_msg_tvb, 0, len)); } }
static gint dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ttree = NULL; proto_tree *titem = NULL; proto_item *pitem = NULL; gint offset = 0; usb_conv_info_t *usb_conv_info; tvbuff_t *next_tvb = NULL; hci_data_t *hci_data; gint p2p_dir_save; guint32 session_id; fragment_head *reassembled; /* Reject the packet if data is NULL */ if (data == NULL) return 0; usb_conv_info = (usb_conv_info_t *)data; titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA); ttree = proto_item_add_subtree(titem, ett_hci_usb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB"); p2p_dir_save = pinfo->p2p_dir; pinfo->p2p_dir = (usb_conv_info->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV; switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent"); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd"); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction"); break; } if (usb_conv_info->is_setup) { proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint; hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t); if (usb_conv_info->device_protocol == 0xE00104) hci_data->interface_id = HCI_INTERFACE_AMP; else hci_data->interface_id = HCI_INTERFACE_USB; hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address; hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table; hci_data->bdaddr_to_name_table = bdaddr_to_name_table; hci_data->localhost_bdaddr = localhost_bdaddr; hci_data->localhost_name = localhost_name; pinfo->ptype = PT_BLUETOOTH; next_tvb = tvb_new_subset_remaining(tvb, offset); if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02) { fragment_info_t *fragment_info; fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id); if (fragment_info == NULL) { fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t); fragment_info->fragment_id = 0; fragment_info->remaining_length = 0; wmem_tree_insert32(fragment_info_table, session_id, fragment_info); } if (fragment_info->fragment_id == 0) { switch(usb_conv_info->endpoint) { case 0: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3; break; case 1: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2; break; case 2: fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4; break; } } fragment_info->remaining_length -= tvb_ensure_length_remaining(tvb, offset); fragment_add_seq_check(&hci_usb_reassembly_table, tvb, offset, pinfo, session_id, NULL, fragment_info->fragment_id, tvb_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE); if (fragment_info->remaining_length > 0) fragment_info->fragment_id += 1; else fragment_info->fragment_id = 0; } reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id); if (reassembled && pinfo->fd->num < reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); col_append_str(pinfo->cinfo, COL_INFO, " Fragment"); } else if (reassembled && pinfo->fd->num == reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); if (reassembled->len > tvb_ensure_length_remaining(tvb, offset)) { next_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled HCI_USB", reassembled, &hci_usb_msg_frag_items, NULL, ttree); } switch(usb_conv_info->endpoint) { case 0: call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data); break; case 1: call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data); break; case 2: call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data); break; } } else { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); } if (usb_conv_info->endpoint == 0x03) { call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data); } else if (usb_conv_info->endpoint > 0x03) { proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA); } offset += tvb_length_remaining(tvb, offset); pinfo->p2p_dir = p2p_dir_save; return offset; }
/* Code to actually dissect the packets */ static void dissect_lsc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *lsc_tree; guint8 op_code; guint32 stream; guint expected_len; /* Protocol is LSC, packet summary is not yet known */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSC"); col_clear(pinfo->cinfo, COL_INFO); /* Too little data? */ if (tvb_length(tvb) < LSC_MIN_LEN) { col_set_str(pinfo->cinfo, COL_INFO, "[Too short]"); return; } /* Get the op code */ op_code = tvb_get_guint8(tvb, 2); /* And the stream handle */ stream = tvb_get_ntohl(tvb, 4); /* Check the data length against what we actually received */ switch (op_code) { case LSC_PAUSE: expected_len = LSC_PAUSE_LEN; break; case LSC_RESUME: expected_len = LSC_RESUME_LEN; break; case LSC_STATUS: expected_len = LSC_STATUS_LEN; break; case LSC_RESET: expected_len = LSC_RESET_LEN; break; case LSC_JUMP: expected_len = LSC_JUMP_LEN; break; case LSC_PLAY: expected_len = LSC_PLAY_LEN; break; case LSC_DONE: case LSC_PAUSE_REPLY: case LSC_RESUME_REPLY: case LSC_STATUS_REPLY: case LSC_RESET_REPLY: case LSC_JUMP_REPLY: case LSC_PLAY_REPLY: expected_len = LSC_REPLY_LEN; break; default: /* Unrecognized op code */ expected_len = LSC_MIN_LEN; break; } /* Display the op code in the summary */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s, session %.8u", val_to_str(op_code, op_code_vals, "Unknown op code (0x%x)"), stream); if (tvb_length(tvb) < expected_len) col_append_str(pinfo->cinfo, COL_INFO, " [Too short]"); else if (tvb_length(tvb) > expected_len) col_append_str(pinfo->cinfo, COL_INFO, " [Too long]"); } if (tree) { /* Create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_lsc, tvb, 0, -1, ENC_NA); lsc_tree = proto_item_add_subtree(ti, ett_lsc); /* Add already fetched items to the tree */ proto_tree_add_uint(lsc_tree, hf_lsc_op_code, tvb, 2, 1, op_code); proto_tree_add_uint_format_value(lsc_tree, hf_lsc_stream_handle, tvb, 4, 4, stream, "%.8u", stream); /* Add rest of LSC header */ proto_tree_add_uint(lsc_tree, hf_lsc_version, tvb, 0, 1, tvb_get_guint8(tvb, 0)); proto_tree_add_uint(lsc_tree, hf_lsc_trans_id, tvb, 1, 1, tvb_get_guint8(tvb, 1)); /* Only replies contain a status code */ if (isReply(op_code)) proto_tree_add_uint(lsc_tree, hf_lsc_status_code, tvb, 3, 1, tvb_get_guint8(tvb, 3)); /* Add op code specific parts */ switch (op_code) { case LSC_PAUSE: proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 8, 4, tvb_get_ntohl(tvb, 8)); break; case LSC_RESUME: proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4, tvb_get_ntohl(tvb, 8)); proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2, tvb_get_ntohs(tvb, 12)); proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2, tvb_get_ntohs(tvb, 14)); break; case LSC_JUMP: case LSC_PLAY: proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4, tvb_get_ntohl(tvb, 8)); proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 12, 4, tvb_get_ntohl(tvb, 12)); proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 16, 2, tvb_get_ntohs(tvb, 16)); proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 18, 2, tvb_get_ntohs(tvb, 18)); break; case LSC_DONE: case LSC_PAUSE_REPLY: case LSC_RESUME_REPLY: case LSC_STATUS_REPLY: case LSC_RESET_REPLY: case LSC_JUMP_REPLY: case LSC_PLAY_REPLY: proto_tree_add_int(lsc_tree, hf_lsc_current_npt, tvb, 8, 4, tvb_get_ntohl(tvb, 8)); proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2, tvb_get_ntohs(tvb, 12)); proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2, tvb_get_ntohs(tvb, 14)); proto_tree_add_uint(lsc_tree, hf_lsc_mode, tvb, 16, 1, tvb_get_guint8(tvb, 16)); break; default: break; } } }