static void dissect_who(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_tree *who_tree = NULL; proto_item *who_ti = NULL; guint8 *server_name; double loadav_5 = 0.0, loadav_10 = 0.0, loadav_15 = 0.0; nstime_t ts; /* Summary information */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WHO"); col_clear(pinfo->cinfo, COL_INFO); ts.nsecs = 0; if (tree) { who_ti = proto_tree_add_item(tree, proto_who, tvb, offset, -1, ENC_NA); who_tree = proto_item_add_subtree(who_ti, ett_who); } if (tree) proto_tree_add_item(who_tree, hf_who_vers, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (tree) proto_tree_add_item(who_tree, hf_who_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 2 filler bytes */ offset += 2; if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_sendtime, tvb, offset, 4, &ts); } offset += 4; if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_recvtime, tvb, offset, 4, &ts); } offset += 4; server_name = tvb_get_stringzpad(wmem_packet_scope(), tvb, offset, 32, ENC_ASCII|ENC_NA); if (tree) proto_tree_add_string(who_tree, hf_who_hostname, tvb, offset, 32, server_name); offset += 32; loadav_5 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_5, tvb, offset, 4, loadav_5); offset += 4; loadav_10 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_10, tvb, offset, 4, loadav_10); offset += 4; loadav_15 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_15, tvb, offset, 4, loadav_15); offset += 4; /* Summary information */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %.02f %.02f %.02f", server_name, loadav_5, loadav_10, loadav_15); if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_boottime, tvb, offset, 4, &ts); offset += 4; dissect_whoent(tvb, offset, who_tree); } }
static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset) { /* Set up structures needed to add the param subtree and manage it */ proto_item *param_item; proto_tree *param_tree; gint offset; guint dcs; guint dcs_cg; /* coding group */ guint dcs_cf; /* compressed flag */ guint dcs_mcm; /* message class meaning flag */ guint dcs_chs; /* character set */ guint dcs_mc; /* message class */ guint dcs_is; /* indication sense */ guint dcs_it; /* indication type */ gchar* bigbuf = (gchar*)ep_alloc(1024); param_item = proto_tree_add_text(tree, tvb, startOffset + 1, endOffset - (startOffset + 1), "%s", cimd_vals_PC[pindex].strptr ); param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p)); proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb, startOffset + 1, CIMD_PC_LENGTH, tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH) ); offset = startOffset + 1 + CIMD_PC_LENGTH + 1; dcs = decimal_int_value(tvb, offset, endOffset - offset); proto_tree_add_uint(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, offset, endOffset - offset, dcs); dcs_cg = (dcs & 0xF0) >> 4; other_decode_bitfield_value(bigbuf, dcs, (dcs_cg <= 0x07 ? 0xC0 : 0xF0), 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_coding_group_indicator, tvb, offset, 1, dcs_cg, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_coding_group_indicator)->name, val_to_str(dcs_cg, cimd_dcs_coding_groups, "Unknown (%d)"), dcs_cg ); if (dcs_cg <= 0x07) { dcs_cf = (dcs & 0x20) >> 5; other_decode_bitfield_value(bigbuf, dcs, 0x20, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_compressed_indicator, tvb, offset, 1, dcs_cf, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_compressed_indicator)->name, val_to_str(dcs_cf, cimd_dcs_compressed, "Unknown (%d)"), dcs_cf ); dcs_mcm = (dcs & 0x10) >> 4; other_decode_bitfield_value(bigbuf, dcs, 0x10, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_meaning_indicator, tvb, offset, 1, dcs_mcm, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_meaning_indicator)->name, val_to_str(dcs_mcm, cimd_dcs_message_class_meaning, "Unknown (%d)"), dcs_mcm ); dcs_chs = (dcs & 0x0C) >> 2; other_decode_bitfield_value(bigbuf, dcs, 0x0C, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1, dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name, val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs ); if (dcs_mcm) { dcs_mc = (dcs & 0x03); other_decode_bitfield_value(bigbuf, dcs, 0x03, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1, dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name, val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc ); } }
/* 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); } } }
static void dissect_gift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *hidden_item; proto_tree *gift_tree, *cmd_tree; gboolean is_request; gint offset = 0; const guchar *line; gint next_offset; int linelen; int tokenlen; const guchar *next_token; /* set "Protocol" column text */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "giFT"); /* determine whether it is a request to or response from the server */ if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* set "Info" column text */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); /* if tree != NULL, build protocol tree */ if (tree) { ti = proto_tree_add_item(tree, proto_gift, tvb, 0, -1, ENC_NA); gift_tree = proto_item_add_subtree(ti, ett_gift); if (is_request) { hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_request, tvb, 0, 0, TRUE); } else { hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_response, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(hidden_item); ti = proto_tree_add_format_text(gift_tree, tvb, offset, next_offset - offset); cmd_tree = proto_item_add_subtree(ti, ett_gift_cmd); tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { if (is_request) { proto_tree_add_string(cmd_tree, hf_gift_request_cmd, tvb, offset, tokenlen, format_text(line, tokenlen)); } else { proto_tree_add_string(cmd_tree, hf_gift_response_cmd, tvb, offset, tokenlen, format_text(line, tokenlen)); } offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; } if (linelen != 0) { if (is_request) { proto_tree_add_string(cmd_tree, hf_gift_request_arg, tvb, offset, linelen, format_text(line, linelen)); } else { proto_tree_add_string(cmd_tree, hf_gift_response_arg, tvb, offset, linelen, format_text(line, linelen)); } } } }
static void dissect_ppi_gps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* These are locals used for processing the current tvb */ guint length; gint length_remaining; int offset = 0; proto_tree *ppi_gps_tree = NULL; proto_tree *my_pt, *gpsflags_flags_tree = NULL; /* used for DeviceType bitmask stuff */ proto_item *ti = NULL, *pt; proto_item *gps_line = NULL; static const int * ppi_gps_present_flags[] = { &hf_ppi_gps_present_gpsflags_flags, &hf_ppi_gps_present_lat, &hf_ppi_gps_present_lon, &hf_ppi_gps_present_alt, &hf_ppi_gps_present_alt_gnd, &hf_ppi_gps_present_gpstime, &hf_ppi_gps_present_fractime, &hf_ppi_gps_present_eph, &hf_ppi_gps_present_epv, &hf_ppi_gps_present_ept, &hf_ppi_gps_present_descr, &hf_ppi_gps_present_appspecific_num, &hf_ppi_gps_present_appspecific_data, &hf_ppi_gps_present_ext, NULL }; /* bits */ int bit; guint32 present, next_present; /* values actually read out, for displaying */ guint32 version, gpsflags_flags; gdouble lat, lon, alt, alt_gnd; nstime_t gps_timestamp; int gps_time_size, already_processed_fractime; /* we use this internally to track if this is a 4 or 8 byte wide timestamp */ gdouble eph, epv, ept; gchar *curr_str; /* these are temporary intermediate values, used in the individual cases below */ guint32 t_lat, t_lon, t_alt, t_alt_gnd; guint32 t_herr, t_verr, t_terr; guint32 t_appspecific_num; /* initialize the timestamp value(s) */ gps_timestamp.secs = gps_timestamp.nsecs = already_processed_fractime = 0; /* Clear out stuff in the info column */ col_clear(pinfo->cinfo,COL_INFO); /* pull out the first three fields of the BASE-GEOTAG-HEADER */ version = tvb_get_guint8(tvb, offset); length = tvb_get_letohs(tvb, offset+2); present = tvb_get_letohl(tvb, offset+4); /* Setup basic column info */ col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_GPS Capture v%u, Length %u", version, length); /* Create the basic dissection tree*/ if (tree) { ti = proto_tree_add_protocol_format(tree, proto_ppi_gps, tvb, 0, length, "GPS:"); gps_line = ti; /*we will make this more useful if we hit lon/lat later */ ppi_gps_tree= proto_item_add_subtree(ti, ett_ppi_gps); proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_version, tvb, offset, 1, version); proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_pad, tvb, offset + 1, 1, ENC_NA); ti = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_length, tvb, offset + 2, 2, length); } /* We support v1 and v2 of GPS tags (identical) */ if (! (version == 1 || version == 2) ) { if (tree) proto_item_append_text(ti, "invalid version (got %d, expected 1 or 2)", version); return; } /* initialize the length of the actual tag contents */ length_remaining = length; /* minimum length check, should atleast be a fixed-size geotagging-base header*/ if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) { /* * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion * plus one "present" bitset. */ if (tree) proto_item_append_text(ti, " (invalid - minimum length is 8)"); return; } /* perform tag-specific max length sanity checking */ if (length > PPI_GPS_MAXTAGLEN ) { if (tree) proto_item_append_text(ti, "Invalid PPI-GPS length (got %d, %d max\n)", length, PPI_GPS_MAXTAGLEN); return; } /* Subtree for the "present flags" bitfield. */ pt = proto_tree_add_bitmask(ppi_gps_tree, tvb, offset + 4, hf_ppi_gps_present, ett_ppi_gps_present, ppi_gps_present_flags, ENC_LITTLE_ENDIAN); offset += PPI_GEOBASE_MIN_HEADER_LEN; length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN; /* The fixed BASE-GEOTAG-HEADER has been handled at this point. move on to the individual fields */ for (; present; present = next_present) { /* clear the least significant bit that is set */ next_present = present & (present - 1); /* extract the least significant bit that is set */ bit = BITNO_32(present ^ next_present); switch (bit) { case PPI_GEOTAG_GPSFLAGS: if (length_remaining < 4) break; gpsflags_flags = tvb_get_letohl(tvb, offset); /* retrieve 32-bit gpsflags bitmask (-not- present bitmask) */ if (tree) { /* first we add the hex flags line */ my_pt = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_gpsflags_flags, tvb, offset , 4, gpsflags_flags); /* then we add a subtree */ gpsflags_flags_tree = proto_item_add_subtree(my_pt, ett_ppi_gps_gpsflags_flags); /* to pin the individual bits on */ proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag0_nofix, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag1_gpsfix, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag2_diffgps, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag3_PPS, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag4_RTK, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag5_floatRTK, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag6_dead_reck, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag7_manual, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag8_sim, tvb, offset, 4, ENC_LITTLE_ENDIAN); } offset+=4; length_remaining-=4; break; case PPI_GEOTAG_LAT: if (length_remaining < 4) break; t_lat = tvb_get_letohl(tvb, offset); lat = ppi_fixed3_7_to_gdouble(t_lat); if (tree) { proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lat, tvb, offset, 4, lat); proto_item_append_text(gps_line, " Lat:%f ", lat); } offset+=4; length_remaining-=4; break; case PPI_GEOTAG_LON: if (length_remaining < 4) break; t_lon = tvb_get_letohl(tvb, offset); lon = ppi_fixed3_7_to_gdouble(t_lon); if (tree) { proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lon, tvb, offset, 4, lon); proto_item_append_text(gps_line, " Lon:%f ", lon); } offset+=4; length_remaining-=4; break; case PPI_GEOTAG_ALT: if (length_remaining < 4) break; t_alt = tvb_get_letohl(tvb, offset); alt = ppi_fixed6_4_to_gdouble(t_alt); if (tree) { proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt, tvb, offset, 4, alt); proto_item_append_text(gps_line, " Alt:%f ", alt); } offset+=4; length_remaining-=4; break; case PPI_GEOTAG_ALT_G: if (length_remaining < 4) break; t_alt_gnd = tvb_get_letohl(tvb, offset); alt_gnd = ppi_fixed6_4_to_gdouble(t_alt_gnd); if (tree) { proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt_gnd, tvb, offset, 4, alt_gnd); proto_item_append_text(gps_line, " Alt_g:%f ", alt_gnd); } offset+=4; length_remaining-=4; break; case PPI_GEOTAG_GPSTIME: if (length_remaining < 4) break; gps_timestamp.secs = tvb_get_letohl(tvb, offset); gps_timestamp.nsecs = 0; gps_time_size = 4; /* This is somewhat tricky, inside the GPSTIME case we test if the optional fractional time */ /* is present. If so, we pull it out, and combine it with GPSTime. */ /* If we do this, we set already_processed_fractime to avoid hitting it below */ if (length_remaining < 4 && (present & PPI_GPS_MASK_FRACTIME)) break; else if (present & PPI_GPS_MASK_FRACTIME) { gps_timestamp.nsecs = tvb_get_letohl(tvb, offset + 4); /* manually offset seconds */ already_processed_fractime = 1; gps_time_size = 8; } proto_tree_add_time(ppi_gps_tree, hf_ppi_gps_gpstime, tvb, offset, gps_time_size, &gps_timestamp); offset += gps_time_size; length_remaining -= gps_time_size; break; case PPI_GEOTAG_FRACTIONALTIME: if (length_remaining < 4) break; if (already_processed_fractime) break; break; case PPI_GEOTAG_EPH: if (length_remaining < 4) break; t_herr = tvb_get_letohl(tvb, offset); eph = ppi_fixed3_6_to_gdouble(t_herr); proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_eph, tvb, offset, 4, eph); offset+=4; length_remaining-=4; break; case PPI_GEOTAG_EPV: if (length_remaining < 4) break; t_verr = tvb_get_letohl(tvb, offset); epv = ppi_fixed3_6_to_gdouble(t_verr); proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_epv, tvb, offset, 4, epv); offset+=4; length_remaining-=4; break; case PPI_GEOTAG_EPT: if (length_remaining < 4) break; t_terr = tvb_get_letohl(tvb, offset); ept = ppi_ns_counter_to_gdouble(t_terr); proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_ept, tvb, offset, 4, ept); offset+=4; length_remaining-=4; break; case PPI_GEOTAG_DESCRIPTIONSTR: if (length_remaining < 32) break; if (tree) { /* proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_descstr, tvb, offset, 32, ENC_ASCII|ENC_NA); */ curr_str = tvb_format_stringzpad(tvb, offset, 32); /* need to append_text this */ proto_tree_add_string(ppi_gps_tree, hf_ppi_gps_descstr, tvb, offset, 32, curr_str); proto_item_append_text(gps_line, " (%s)", curr_str); } offset+=32; length_remaining-=32; break; case PPI_GEOTAG_APPID: if (length_remaining < 4) break; t_appspecific_num = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */ proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_appspecific_num, tvb, offset, 4, t_appspecific_num); offset+=4; length_remaining-=4; break; case PPI_GEOTAG_APPDATA: if (length_remaining < 60) break; proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_appspecific_data, tvb, offset, 60, ENC_NA); offset+=60; length_remaining-=60; break; /* * This indicates a field whose size we do not know, so we cannot proceed. */ default: next_present = 0; /* this will terminate the loop */ expert_add_info_format(pinfo, pt, &ei_ppi_gps_present_bit, "Error: PPI-GEOLOCATION-GPS: unknown bit (%d) set in present field.", bit); continue; } /* switch (bit) */ } /* (for present..)*/ /* If there was any post processing of the elements, it could happen here. */ return; }
static void expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int severity, int hf_index, gboolean use_vaformat, const char *format, va_list ap) { char formatted[ITEM_LABEL_LENGTH]; int tap; expert_info_t *ei; proto_tree *tree; proto_item *ti; if (pinfo == NULL && pi && pi->tree_data) { pinfo = PTREE_DATA(pi)->pinfo; } /* if this packet isn't loaded because of a read filter, don't output anything */ if (pinfo == NULL || pinfo->num == 0) { return; } if (severity > highest_severity) { highest_severity = severity; } /* XXX: can we get rid of these checks and make them programming errors instead now? */ if (pi != NULL && PITEM_FINFO(pi) != NULL) { expert_set_item_flags(pi, group, severity); } if ((pi == NULL) || (PITEM_FINFO(pi) == NULL) || ((guint)severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK))) { col_add_str(pinfo->cinfo, COL_EXPERT, val_to_str(severity, expert_severity_vals, "Unknown (%u)")); } if (use_vaformat) { ws_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); } else { g_strlcpy(formatted, format, ITEM_LABEL_LENGTH); } tree = expert_create_tree(pi, group, severity, formatted); if (hf_index == -1) { /* If no filterable expert info, just add the message */ ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); PROTO_ITEM_SET_GENERATED(ti); } else { /* If filterable expert info, hide the "generic" form of the message, and generate the formatted filterable expert info */ ti = proto_tree_add_none_format(tree, hf_index, NULL, 0, 0, "%s", formatted); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); PROTO_ITEM_SET_HIDDEN(ti); } ti = proto_tree_add_uint_format_value(tree, hf_expert_severity, NULL, 0, 0, severity, "%s", val_to_str_const(severity, expert_severity_vals, "Unknown")); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint_format_value(tree, hf_expert_group, NULL, 0, 0, group, "%s", val_to_str_const(group, expert_group_vals, "Unknown")); PROTO_ITEM_SET_GENERATED(ti); tap = have_tap_listener(expert_tap); if (!tap) return; ei = wmem_new(wmem_packet_scope(), expert_info_t); ei->packet_num = pinfo->num; ei->group = group; ei->severity = severity; ei->hf_index = hf_index; ei->protocol = pinfo->current_proto; ei->summary = wmem_strdup(wmem_packet_scope(), formatted); /* if we have a proto_item (not a faked item), set expert attributes to it */ if (pi != NULL && PITEM_FINFO(pi) != NULL) { ei->pitem = pi; } /* XXX: remove this because we don't have an internal-only function now? */ else { ei->pitem = NULL; } tap_queue_packet(expert_tap, pinfo, ei); }
static gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->fd->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 0; key[3].key = NULL; } else { /* tcp */ key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 0; key[3].key = NULL; } wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if (direction == P2P_DIR_SENT) if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ else if (command_data->command == A_OKAY) { side_id = command_data->arg1; /* IN: remote id */ } else side_id = command_data->arg1; /* IN: remote id */ key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } return offset; }
/* Code to actually dissect the packets */ static void dissect_fcfzs_zoneset(tvbuff_t *tvb, proto_tree *tree, int offset) { int numzones, nummbrs, i, j, len; /* The zoneset structure has the following format */ /* zoneset name (len[not including pad], name, pad), * number of zones, * for each zone, * Zone name (len[not including pad], name, pad), num zone mbrs * for each zone mbr, * zone mbr id type, zone mbr id (len, name, pad) */ if (tree) { /* Zoneset Name */ len = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4, len, ENC_ASCII|ENC_NA); offset += 4 + len + (4-(len % 4)); /* Number of zones */ numzones = tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* For each zone... */ for (i = 0; i < numzones; i++) { len = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4, len, ENC_ASCII|ENC_NA); offset += 4 + len + (4-(len % 4)); nummbrs = tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_fcfzs_nummbrentries, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; for (j = 0; j < nummbrs; j++) { proto_tree_add_item(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN); switch (tvb_get_guint8(tvb, offset)) { case FC_FZS_ZONEMBR_PWWN: case FC_FZS_ZONEMBR_NWWN: proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb, offset+4, 8, tvb_fcwwn_to_str(tvb, offset+4)); break; case FC_FZS_ZONEMBR_DP: proto_tree_add_string_format(tree, hf_fcfzs_mbrid, tvb, offset+4, 3, " ", "0x%x", tvb_get_ntoh24(tvb, offset+4)); break; case FC_FZS_ZONEMBR_FCID: proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb, offset+4, 4, tvb_fc_to_str(tvb, offset+4)); break; case FC_FZS_ZONEMBR_PWWN_LUN: proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb, offset+4, 8, tvb_fcwwn_to_str(tvb, offset+4)); proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, offset+8, 8, ENC_NA); break; case FC_FZS_ZONEMBR_DP_LUN: proto_tree_add_string_format(tree, hf_fcfzs_mbrid, tvb, offset+4, 3, " ", "0x%x", tvb_get_ntoh24(tvb, offset+4)); proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, offset+4, 8, ENC_NA); break; case FC_FZS_ZONEMBR_FCID_LUN: proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb, offset+4, 4, tvb_fc_to_str(tvb, offset+4)); proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, offset+4, 8, ENC_NA); break; default: proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb, offset+4, 8, "Unknown member type format"); } offset += 12; } } } }
static void client_display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info, sock_state_t* state_info) { /* Display the protocol tree for the version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ unsigned int i; const char *AuthMethodStr; sock_state_t new_state_info; /* Either there is an error, or we're done with the state machine (so there's nothing to display) */ if (state_info == NULL) return; proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, ENC_BIG_ENDIAN); ++offset; if (state_info->client == clientStart) { proto_tree *AuthTree; proto_item *ti; guint8 num_auth_methods, auth; ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods"); AuthTree = proto_item_add_subtree(ti, ett_socks_auth); num_auth_methods = tvb_get_guint8(tvb, offset); proto_item_set_len(ti, num_auth_methods+1); proto_tree_add_item( AuthTree, hf_client_auth_method_count, tvb, offset, 1, ENC_NA); ++offset; for( i = 0; i < num_auth_methods; ++i) { auth = tvb_get_guint8( tvb, offset); AuthMethodStr = get_auth_method_name(auth); proto_tree_add_uint_format(AuthTree, hf_client_auth_method, tvb, offset, 1, auth, "Method[%u]: %u (%s)", i, auth, AuthMethodStr); ++offset; } if ((num_auth_methods == 1) && (tvb_bytes_exist(tvb, offset + 2, 1)) && (tvb_get_guint8(tvb, offset + 2) == 0) && (tvb_reported_length_remaining(tvb, offset + 2 + num_auth_methods) > 0)) { new_state_info.client = clientV5Command; client_display_socks_v5(tvb, offset, pinfo, tree, hash_info, &new_state_info); } } else if (state_info->client == clientV5Command) { proto_tree_add_item( tree, hf_socks_cmd, tvb, offset, 1, ENC_NA); ++offset; proto_tree_add_item( tree, hf_socks_reserved, tvb, offset, 1, ENC_NA); ++offset; offset = display_address(tvb, offset, tree); proto_tree_add_item( tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN); } else if ((state_info->client == clientWaitForAuthReply) && (state_info->server == serverInitReply)) { guint16 len; gchar* str; switch(hash_info->authentication_method) { case NO_AUTHENTICATION: break; case USER_NAME_AUTHENTICATION: /* process user name */ len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_username, tvb, offset, len+1, str); offset += (len+1); len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_password, tvb, offset, len+1, str); /* offset += (len+1); */ break; case GSS_API_AUTHENTICATION: proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, ENC_BIG_ENDIAN); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, ENC_NA); break; default: break; } } }
void gcp_analyze_msg(proto_tree* gcp_tree, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids) { gcp_trx_msg_t* t; gcp_ctxs_t contexts = {NULL,NULL}; gcp_ctxs_t* ctx_node; gcp_cmd_msg_t* c; for (t = m->trxs; t; t = t->next) { for (c = t->trx->cmds; c; c = c->next) { gcp_ctx_t* ctx = c->cmd->ctx; for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) { if (ctx_node->ctx->id == ctx->id) { break; } } if (! ctx_node) { ctx_node = ep_new(gcp_ctxs_t); ctx_node->ctx = ctx; ctx_node->next = contexts.next; contexts.next = ctx_node; } } } for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) { gcp_ctx_t* ctx = ctx_node->ctx; proto_item* ctx_item = proto_tree_add_uint(gcp_tree,ids->hf.ctx,gcp_tvb,0,0,ctx->id); proto_tree* ctx_tree = proto_item_add_subtree(ctx_item,ids->ett.ctx); gcp_terms_t *ctx_term; PROTO_ITEM_SET_GENERATED(ctx_item); if (ctx->cmds) { proto_item* history_item = proto_tree_add_text(ctx_tree,gcp_tvb,0,0,"[ Command History ]"); proto_tree* history_tree = proto_item_add_subtree(history_item,ids->ett.ctx_cmds); for (c = ctx->cmds; c; c = c->next) { proto_item* cmd_item = proto_tree_add_uint(history_tree,ids->hf.ctx_cmd,gcp_tvb,0,0,c->cmd->msg->framenum); if (c->cmd->str) proto_item_append_text(cmd_item," %s ",c->cmd->str); PROTO_ITEM_SET_GENERATED(cmd_item); if (c->cmd->error) { proto_item_set_expert_flags(cmd_item, PI_RESPONSE_CODE, PI_WARN); } } } if (( ctx_term = ctx->terms.next )) { proto_item* terms_item = proto_tree_add_text(ctx_tree,gcp_tvb,0,0,"[ Terminations Used ]"); proto_tree* terms_tree = proto_item_add_subtree(terms_item,ids->ett.ctx_terms); for (; ctx_term; ctx_term = ctx_term->next ) { if ( ctx_term->term && ctx_term->term->str) { proto_item* pi = proto_tree_add_string(terms_tree,ids->hf.ctx_term,gcp_tvb,0,0,ctx_term->term->str); proto_tree* term_tree = proto_item_add_subtree(pi,ids->ett.ctx_term); PROTO_ITEM_SET_GENERATED(pi); if (ctx_term->term->type) { pi = proto_tree_add_uint(term_tree,ids->hf.ctx_term_type,gcp_tvb,0,0,ctx_term->term->type); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->bir) { pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_bir,gcp_tvb,0,0,ctx_term->term->bir); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->nsap) { pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_nsap,gcp_tvb,0,0,ctx_term->term->nsap); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->bir && ctx_term->term->nsap) { gchar* tmp_key = ep_strdup_printf("%s:%s",ctx_term->term->nsap,ctx_term->term->bir); gchar* key = g_ascii_strdown(tmp_key, -1); alcap_tree_from_bearer_key(term_tree, gcp_tvb, key); g_free(key); } } } } } }
static void xmpp_bytestreams_activate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element) { proto_tree_add_string(tree, hf_xmpp_query_activate, tvb, element->offset, element->length, xmpp_elem_cdata(element)); xmpp_unknown(tree, tvb, pinfo, element); }
/* * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_context(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.7 and p. 613, 23.3.2: * "context" is a dictionary<string, string> * * dictionary<string, string> == Size + SizeKeyValuePairs * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs * or * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs * */ guint32 Size = 0; /* number of key-value in the dictionary */ guint32 i = 0; const char *s = NULL; (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "context missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (context missing)"); (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 255 ) { /* check for next 4 bytes */ if ( !tvb_bytes_exist(tvb, offset, 4) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "second field of Size missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)"); (*consumed) = -1; return; } /* get second field of Size */ Size = tvb_get_letohl(tvb, offset); offset += 4; (*consumed) += 4; } DBG1("context.Size --> %d\n", Size); if ( Size > icep_max_ice_context_pairs ) { if (item) /* display the XX Size byte when click here */ expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "too long context"); col_append_str(mypinfo->cinfo, COL_INFO, " (too long context)"); (*consumed) = -1; return; } if (Size == 0) { s = "(empty)"; /* display the 0x00 Size byte when click on a empty context */ if (tree) proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s); return; } /* looping through the dictionary */ for ( i = 0; i < Size; i++ ) { /* key */ gint32 consumed_key = 0; char *str_key = NULL; /* value */ gint32 consumed_value = 0; char *str_value = NULL; proto_item *ti = NULL; DBG1("looping through context dictionary, loop #%d\n", i); ti = proto_tree_add_text(tree, tvb, offset, -1, "Invocation Context"); dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_key, tvb, offset, &consumed_key, &str_key); if ( consumed_key == -1 ) { (*consumed) = -1; return; } offset += consumed_key; (*consumed) += consumed_key; dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_value, tvb, offset, &consumed_value, &str_value); if ( consumed_value == -1 ) { (*consumed) = -1; return; } offset += consumed_value; (*consumed) += consumed_value; if (ti) proto_item_set_len(ti, (consumed_key + consumed_value) + 1); } }
/* * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_facet(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.6: * "facet" is a StringSeq, a StringSeq is a: * sequence<string> * * * sequence == Size + SizeElements * sequence = 1byte (0..254) + SizeElements * or * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements * * * p.613. chapter 23.3.2 * "facet has either zero elements (empty) or one element" * * */ guint32 Size = 0; /* number of elements in the sequence */ (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "facet field missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (facet field missing)"); (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 0 ) { if (tree) { /* display the 0x00 Size byte when click on a empty ice_string */ proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, "(empty)"); } return; } if ( Size == 1 ) { gint32 consumed_facet = 0; dissect_ice_string(pinfo, tree, item, hf_icep, tvb, offset, &consumed_facet, NULL); if ( consumed_facet == -1 ) { (*consumed) = -1; return; } /*offset += consumed_facet;*/ (*consumed) += consumed_facet; return; } /* if here => Size > 1 => not possible */ if (item) /* display the XX Size byte when click here */ expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "facet can be max one element"); col_append_str(mypinfo->cinfo, COL_INFO, " (facet can be max one element)"); (*consumed) = -1; return; }
/* * This function dissects an "Ice string", adds hf to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. * * "*dest" is a null terminated version of the dissected Ice string. */ static void dissect_ice_string(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep, tvbuff_t *tvb, guint32 offset, gint32 *consumed, char **dest) { /* p. 586 chapter 23.2.1 and p. 588 chapter 23.2.5 * string == Size + content * string = 1byte (0..254) + string not null terminated * or * string = 1byte (255) + 1int (255..2^32-1) + string not null terminated */ guint32 Size = 0; char *s = NULL; (*consumed) = 0; /* check for first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "1st byte of Size missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (1st byte of Size missing)"); (*consumed) = -1; return; } /* get the Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 255 ) { /* check for next 4 bytes */ if ( !tvb_bytes_exist(tvb, offset, 4) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "second field of Size missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)"); (*consumed) = -1; return; } /* get second field of Size */ Size = tvb_get_letohl(tvb, offset); offset += 4; (*consumed) += 4; } DBG1("string.Size --> %d\n", Size); /* check if the string exists */ if ( !tvb_bytes_exist(tvb, offset, Size) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "missing or truncated string"); col_append_str(mypinfo->cinfo, COL_INFO, " (missing or truncated string)"); (*consumed) = -1; return; } if ( Size > icep_max_ice_string_len ) { if (item) expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "string too long"); col_append_str(mypinfo->cinfo, COL_INFO, " (string too long)"); (*consumed) = -1; return; } if ( Size != 0 ) { s = tvb_get_ephemeral_string(tvb, offset, Size); if (tree) proto_tree_add_string(tree, hf_icep, tvb, offset, Size, s); } else { s = g_strdup("(empty)"); /* display the 0x00 Size byte when click on a empty ice_string */ if (tree) proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, s); } if ( dest != NULL ) *dest = s; /*offset += Size;*/ (*consumed) += Size; return; }
static int nmas_string(tvbuff_t* tvb, int hfinfo, proto_tree *nmas_tree, int offset, gboolean little) { int foffset = offset; guint32 str_length; char *buffer; guint32 i; guint16 c_char; guint32 length_remaining = 0; buffer=ep_alloc(ITEM_LABEL_LENGTH+1); if (little) { str_length = tvb_get_letohl(tvb, foffset); } else { str_length = tvb_get_ntohl(tvb, foffset); } foffset += 4; if(str_length >= ITEM_LABEL_LENGTH) { proto_tree_add_string(nmas_tree, hfinfo, tvb, foffset, length_remaining + 4, "<String too long to process>"); foffset += length_remaining; return foffset; } if(str_length == 0) { proto_tree_add_string(nmas_tree, hfinfo, tvb, offset, 4, "<Not Specified>"); return foffset; } /* * XXX - other than the special-casing of null bytes, * we could just use "proto_tree_add_item()", as for * FT_STRING, FT_STRINGZ, and FT_UINT_STRING fields, * the display representation of an item is generated * using "format_text()", so it handles non-printable * characters. */ for ( i = 0; i < str_length; i++ ) { c_char = tvb_get_guint8(tvb, foffset ); if (c_char<0x20 || c_char>0x7e) { if (c_char != 0x00) { c_char = 0x2e; buffer[i] = c_char & 0xff; } else { i--; str_length--; } } else { buffer[i] = c_char & 0xff; } foffset++; length_remaining--; if(length_remaining==1) { i++; break; } } buffer[i] = '\0'; if (little) { str_length = tvb_get_letohl(tvb, offset); } else { str_length = tvb_get_ntohl(tvb, offset); } proto_tree_add_string(nmas_tree, hfinfo, tvb, offset+4, str_length, buffer); return foffset; }
static int dissect_ccn_interest(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *name_tree; proto_tree *exclude_tree; proto_item *titem; struct ccn_parsed_interest interest; struct ccn_parsed_interest *pi = &interest; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; const unsigned char *bloom; size_t bloom_size = 0; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; const unsigned char *blob; size_t blob_size; ssize_t l; unsigned int i; double lifetime; int res; comps = ccn_indexbuf_create(); res = ccn_parse_interest(ccnb, ccnb_size, pi, comps); if (res < 0) return (res); /* Name */ l = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pi->offset[CCN_PI_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* MinSuffixComponents */ l = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (l > 0) { i = pi->min_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_minsuffixcomponents, tvb, pi->offset[CCN_PI_B_MinSuffixComponents], l, i); } /* MaxSuffixComponents */ l = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (l > 0) { i = pi->max_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_maxsuffixcomponents, tvb, pi->offset[CCN_PI_B_MaxSuffixComponents], l, i); } /* PublisherPublicKeyDigest */ /* Exclude */ l = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (l > 0) { c = ccn_charbuf_create(); d = ccn_buf_decoder_start(&decoder, ccnb + pi->offset[CCN_PI_B_Exclude], l); if (!ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) { ccn_charbuf_destroy(&c); return(-1); } ccn_charbuf_append_string(c, "Exclude: "); ccn_buf_advance(d); if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); ccn_charbuf_append_string(c, "* "); ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_charbuf_append_string(c, "? "); ccn_buf_check_close(d); } while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); comp_size = 0; if (ccn_buf_match_blob(d, &comp, &comp_size)) ccn_buf_advance(d); ccn_uri_append_percentescaped(c, comp, comp_size); ccn_charbuf_append_string(c, " "); ccn_buf_check_close(d); if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); ccn_charbuf_append_string(c, "* "); ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_charbuf_append_string(c, "? "); ccn_buf_check_close(d); } } titem = proto_tree_add_text(tree, tvb, pi->offset[CCN_PI_B_Exclude], l, "%s", ccn_charbuf_as_string(c)); exclude_tree = proto_item_add_subtree(titem, ett_exclude); ccn_charbuf_destroy(&c); } /* ChildSelector */ l = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (l > 0) { i = pi->orderpref; titem = proto_tree_add_uint(tree, hf_ccn_childselector, tvb, pi->offset[CCN_PI_B_ChildSelector], l, i); proto_item_append_text(titem, ", %s", val_to_str(i & 1, VALS(childselectordirection_vals), "")); } /* AnswerOriginKind */ l = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (l > 0) { i = pi->answerfrom; titem = proto_tree_add_uint(tree, hf_ccn_answeroriginkind, tvb, pi->offset[CCN_PI_B_AnswerOriginKind], l, i); } /* Scope */ l = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (l > 0) { i = pi->scope; titem = proto_tree_add_uint(tree, hf_ccn_scope, tvb, pi->offset[CCN_PI_B_Scope], l, i); } /* InterestLifetime */ l = pi->offset[CCN_PI_E_InterestLifetime] - pi->offset[CCN_PI_B_InterestLifetime]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_InterestLifetime, ccnb, pi->offset[CCN_PI_B_InterestLifetime], pi->offset[CCN_PI_E_InterestLifetime], &blob, &blob_size); lifetime = 0.0; for (i = 0; i < blob_size; i++) lifetime = lifetime * 256.0 + (double)blob[i]; lifetime /= 4096.0; titem = proto_tree_add_double(tree, hf_ccn_interestlifetime, tvb, blob - ccnb, blob_size, lifetime); } /* Nonce */ l = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, ", <"); for (i = 0; i < blob_size; i++) col_append_fstr(pinfo->cinfo, COL_INFO, "%02x", blob[i]); col_append_str(pinfo->cinfo, COL_INFO, ">"); } titem = proto_tree_add_item(tree, hf_ccn_nonce, tvb, blob - ccnb, blob_size, FALSE); } return (1); }
static void dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint op; guint sub; guint rlen; proto_item *ti; proto_item *item; proto_tree *fip_tree; proto_tree *subtree; guint dtype; guint dlen; guint desc_offset; guint val; tvbuff_t *desc_tvb; const char *info; const char *text; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIP"); col_clear(pinfo->cinfo, COL_INFO); if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) { col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]"); if (tree) proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, -1, "FIP [packet too short]"); return; } op = tvb_get_ntohs(tvb, 2); sub = tvb_get_guint8(tvb, 5); switch (op) { case FIP_OP_DISC: info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x"); break; case FIP_OP_LS: info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x"); break; case FIP_OP_CTRL: info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x"); break; case FIP_OP_VLAN: info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x"); break; case FIP_OP_VN2VN: info = val_to_str(sub, fip_vn2vn_subcodes, "VN2VN 0x%x"); break; default: info = val_to_str(op, fip_opcodes, "Unknown op 0x%x"); break; } col_add_str(pinfo->cinfo, COL_INFO, info); rlen = tvb_get_ntohs(tvb, 6); ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, FIP_HEADER_LEN + rlen * FIP_BPW, "FIP %s", info); fip_tree = proto_item_add_subtree(ti, ett_fip); proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, ENC_BIG_ENDIAN); switch (op) { case FIP_OP_DISC: proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_LS: proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_CTRL: proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_VLAN: proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_VN2VN: proto_tree_add_item(fip_tree, hf_fip_vn2vn_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; default: proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; } proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, ENC_BIG_ENDIAN); proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags, ett_fip_flags, hf_fip_flags_fields, ENC_BIG_ENDIAN); desc_offset = FIP_HEADER_LEN; rlen *= FIP_BPW; proto_tree_add_bytes_format(fip_tree, hf_fip_descriptors, tvb, desc_offset, rlen, NULL, "Descriptors"); while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) { dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW; if (!dlen) { proto_tree_add_expert(fip_tree, pinfo, &ei_fip_descriptors, tvb, desc_offset, -1); break; } if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) { break; } desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1); dtype = tvb_get_guint8(desc_tvb, 0); desc_offset += dlen; rlen -= dlen; switch (dtype) { case FIP_DT_PRI: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_pri, &item); proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb, 3, 1, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3)); break; case FIP_DT_MAC: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mac, &item); proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb, 2, 6, ENC_NA); proto_item_append_text(item, "%s", tvb_bytes_to_ep_str_punct(desc_tvb, 2, 6, ':')); break; case FIP_DT_MAP_OUI: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_map, &item); text = tvb_fc_to_str(desc_tvb, 5); proto_tree_add_string(subtree, hf_fip_desc_map, desc_tvb, 5, 3, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_NAME: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_name, &item); text = tvb_fcwwn_to_str(desc_tvb, 4); proto_tree_add_string(subtree, hf_fip_desc_name, desc_tvb, 4, 8, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_FAB: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fab, &item); proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb, 2, 2, ENC_BIG_ENDIAN); text = tvb_fc_to_str(desc_tvb, 5); proto_tree_add_string(subtree, hf_fip_desc_fab_map, desc_tvb, 5, 3, text); text = tvb_fcwwn_to_str(desc_tvb, 8); proto_tree_add_string(subtree, hf_fip_desc_fab_name, desc_tvb, 8, 8, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_FCOE_SIZE: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mdl, &item); proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb, 2, 2, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: case FIP_DT_LOGO: case FIP_DT_ELP: { tvbuff_t *ls_tvb; fc_data_t fc_data = {ETHERTYPE_FIP, 0}; subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_caps, &item); ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1); call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data); proto_item_append_text(item, "%u bytes", dlen - 4); } break; case FIP_DT_VN: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vn, &item); proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb, 2, 6, ENC_NA); proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb, 9, 3, ENC_BIG_ENDIAN); text = tvb_fcwwn_to_str(desc_tvb, 12); proto_tree_add_string(subtree, hf_fip_desc_vn_wwpn, desc_tvb, 12, 8, text); proto_item_append_text(item, "MAC %s FC_ID %6.6x", tvb_bytes_to_ep_str_punct(desc_tvb, 2, 6, ':'), tvb_get_ntoh24(desc_tvb, 9)); break; case FIP_DT_FKA: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fka, &item); val = tvb_get_ntohl(desc_tvb, 4); proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka, desc_tvb, 4, 4, val, "%u ms", val); proto_item_append_text(item, "%u ms", val); break; case FIP_DT_VEND: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vend, &item); proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb, 4, 8, ENC_NA); if (tvb_bytes_exist(desc_tvb, 9, -1)) { proto_tree_add_item(subtree, hf_fip_desc_vend_data, desc_tvb, 9, -1, ENC_NA); } break; case FIP_DT_VLAN: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vlan, &item); proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb, 2, 2, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; case FIP_DT_FC4F: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fc4f, &item); fip_desc_fc4f(desc_tvb, subtree, item); break; default: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_unk, &item); proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb, 2, -1, ENC_NA); break; } } }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
static void dissect_gsm_um(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *gsm_um_tree = NULL; proto_item *ti; col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM Um"); if (pinfo->pseudo_header->gsm_um.uplink) { col_set_str(pinfo->cinfo, COL_RES_DL_DST, "BTS"); col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "MS"); } else { switch (pinfo->pseudo_header->gsm_um.channel) { case GSM_UM_CHANNEL_BCCH: case GSM_UM_CHANNEL_CCCH: case GSM_UM_CHANNEL_PCH: case GSM_UM_CHANNEL_AGCH: col_set_str(pinfo->cinfo, COL_RES_DL_DST, "Broadcast"); break; default: col_set_str(pinfo->cinfo, COL_RES_DL_DST, "MS"); break; } col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "BTS"); } if (tree) { const char *channel; ti = proto_tree_add_item(tree, proto_gsm_um, tvb, 0, 0, ENC_NA); gsm_um_tree = proto_item_add_subtree(ti, ett_gsm_um); switch( pinfo->pseudo_header->gsm_um.channel ) { case GSM_UM_CHANNEL_BCCH: channel = "BCCH"; break; case GSM_UM_CHANNEL_CCCH: channel = "CCCH"; break; case GSM_UM_CHANNEL_PCH: channel = "PCH"; break; case GSM_UM_CHANNEL_AGCH: channel = "AGCH"; break; case GSM_UM_CHANNEL_SACCH: channel = "SACCH"; break; case GSM_UM_CHANNEL_FACCH: channel = "FACCH"; break; case GSM_UM_CHANNEL_SDCCH: channel = "SDCCH"; break; default: channel = "Unknown"; break; } if( pinfo->pseudo_header->gsm_um.uplink ) { proto_tree_add_string(gsm_um_tree, hf_gsm_um_direction, tvb, 0, 0, "Uplink"); } else { proto_tree_add_string(gsm_um_tree, hf_gsm_um_direction, tvb, 0, 0, "Downlink"); } proto_tree_add_string(gsm_um_tree, hf_gsm_um_channel, tvb, 0, 0, channel); /* Show the other fields, if we have them (ie. downlink, BTS->MS) */ if( !pinfo->pseudo_header->gsm_um.uplink ) { const char *band; guint downlink, uplink; decode_arfcn(pinfo->pseudo_header->gsm_um.arfcn, &band, &uplink, &downlink); proto_tree_add_uint(gsm_um_tree, hf_gsm_um_arfcn, tvb, 0, 0, pinfo->pseudo_header->gsm_um.arfcn); proto_tree_add_text(gsm_um_tree, tvb, 0, 0, "Band: %s, Frequency: %u.%03uMHz", band, downlink / 1000, downlink % 1000); proto_tree_add_uint(gsm_um_tree, hf_gsm_um_bsic, tvb, 0, 0, pinfo->pseudo_header->gsm_um.bsic); proto_tree_add_uint(gsm_um_tree, hf_gsm_um_frame, tvb, 0, 0, pinfo->pseudo_header->gsm_um.tdma_frame); proto_tree_add_uint(gsm_um_tree, hf_gsm_um_error, tvb, 0, 0, pinfo->pseudo_header->gsm_um.error); proto_tree_add_uint(gsm_um_tree, hf_gsm_um_timeshift, tvb, 0, 0, pinfo->pseudo_header->gsm_um.timeshift); } } /* TODO: If CCCH downlink could work out of PCH or AGCH by peeking at next bytes, uplink is RACH */ switch( pinfo->pseudo_header->gsm_um.channel ) { case GSM_UM_CHANNEL_BCCH: case GSM_UM_CHANNEL_CCCH: case GSM_UM_CHANNEL_PCH: case GSM_UM_CHANNEL_AGCH: if( !pinfo->pseudo_header->gsm_um.uplink ) { tvbuff_t *next_tvb; guint8 pseudo_len, len_left, len_byte; len_left = tvb_length(tvb); len_byte = tvb_get_guint8(tvb, 0); pseudo_len = len_byte >> 2; next_tvb = tvb_new_subset(tvb, 1, MIN(len_left, pseudo_len), -1); if (tree) { proto_tree_add_uint(gsm_um_tree, hf_gsm_um_l2_pseudo_len, tvb, 0, 1, len_byte); } /* Only dissect non-empty frames */ if( tvb_length(next_tvb) ) { call_dissector(dtap_handle, next_tvb, pinfo, tree); } } else {
/* ----------------------------- from netatalk/etc/afpd/status.c */ static gint dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset) { proto_tree *sub_tree; proto_item *ti; guint16 ofs; guint16 flag; guint16 sign_ofs = 0; guint16 adr_ofs = 0; guint16 dir_ofs = 0; guint16 utf_ofs = 0; guint8 nbe; guint8 len; guint8 i; if (!tree) return offset; ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status"); tree = proto_item_add_subtree(ti, ett_dsi_status); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs); ofs = offset +AFPSTATUS_FLAGOFF; ti = proto_tree_add_item(tree, hf_dsi_server_flag, tvb, ofs, 2, ENC_BIG_ENDIAN); sub_tree = proto_item_add_subtree(ti, ett_dsi_status_server_flag); proto_tree_add_item(sub_tree, hf_dsi_server_flag_copyfile , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_passwd , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_no_save_passwd, tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_msg , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_sig , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_tcpip , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_notify , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_reconnect , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_directory , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_utf8_name , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_uuid , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_ext_sleep , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_fast_copy , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_dsi_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, ENC_ASCII|ENC_NA); flag = tvb_get_ntohs(tvb, ofs); if ((flag & AFPSRVRINFO_SRVSIGNATURE)) { ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1; if ((ofs & 1)) ofs++; sign_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs); sign_ofs += offset; if ((flag & AFPSRVRINFO_TCPIP)) { ofs += 2; adr_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs); adr_ofs += offset; } if ((flag & AFPSRVRINFO_SRVDIRECTORY)) { ofs += 2; dir_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs); dir_ofs += offset; } if ((flag & AFPSRVRINFO_SRVUTF8)) { ofs += 2; utf_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "UTF8 server name offset: %d", utf_ofs); utf_ofs += offset; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF); if (ofs) proto_tree_add_item(tree, hf_dsi_server_type, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF); if (ofs) { nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_vers); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_vers, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF); if (ofs) { nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_uams); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_uams, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF); if (ofs) proto_tree_add_item(tree, hf_dsi_server_icon, tvb, ofs, 256, ENC_NA); if (sign_ofs) { proto_tree_add_item(tree, hf_dsi_server_signature, tvb, sign_ofs, 16, ENC_NA); } if (adr_ofs) { proto_tree *adr_tree; unsigned char *tmp; guint16 net; guint8 node; guint16 port; ofs = adr_ofs; nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe); ofs++; adr_tree = proto_item_add_subtree(ti, ett_dsi_addr); for (i = 0; i < nbe; i++) { guint8 type; len = tvb_get_guint8(tvb, ofs); type = tvb_get_guint8(tvb, ofs +1); switch (type) { case 1: /* IP */ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip: %s", tvb_ip_to_str(tvb, ofs+2)); break; case 2: /* IP + port */ port = tvb_get_ntohs(tvb, ofs+6); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%d", tvb_ip_to_str(tvb, ofs+2), port); break; case 3: /* DDP, atalk_addr_to_str want host order not network */ net = tvb_get_ntohs(tvb, ofs+2); node = tvb_get_guint8(tvb, ofs +4); port = tvb_get_guint8(tvb, ofs +5); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp: %u.%u:%u", net, node, port); break; case 4: /* DNS */ case 5: /* SSH tunnel */ if (len > 2) { tmp = tvb_get_string(wmem_packet_scope(), tvb, ofs +2, len -2); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "%s: %s", (type==4)?"dns":"ssh tunnel", tmp); break; } else { ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Malformed address type %d", type); } break; case 6: /* IP6 */ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip6: %s", tvb_ip6_to_str(tvb, ofs+2)); break; case 7: /* IP6 + 2bytes port */ port = tvb_get_ntohs(tvb, ofs+ 2+INET6_ADDRLEN); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip6 %s:%d", tvb_ip6_to_str(tvb, ofs+2), port); break; default: ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknown type : %d", type); break; } len -= 2; sub_tree = proto_item_add_subtree(ti,ett_dsi_addr_line); proto_tree_add_item(sub_tree, hf_dsi_server_addr_len, tvb, ofs, 1, ENC_BIG_ENDIAN); ofs++; proto_tree_add_item(sub_tree, hf_dsi_server_addr_type, tvb, ofs, 1, ENC_BIG_ENDIAN); ofs++; proto_tree_add_item(sub_tree, hf_dsi_server_addr_value,tvb, ofs, len, ENC_NA); ofs += len; } } if (dir_ofs) { ofs = dir_ofs; nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_directory); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } if (utf_ofs) { guint16 ulen; char *tmp; ofs = utf_ofs; ulen = tvb_get_ntohs(tvb, ofs); tmp = tvb_get_string(wmem_packet_scope(), tvb, ofs + 2, ulen); ti = proto_tree_add_text(tree, tvb, ofs, ulen + 2, "UTF8 server name: %s", tmp); sub_tree = proto_item_add_subtree(ti, ett_dsi_utf8_name); proto_tree_add_uint(sub_tree, hf_dsi_utf8_server_name_len, tvb, ofs, 2, ulen); ofs += 2; proto_tree_add_string(sub_tree, hf_dsi_utf8_server_name, tvb, ofs, ulen, tmp); ofs += ulen; } return ofs; }
static int dissect_ipmi_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint hf_parent_item, gint ett_tree, const ipmi_context_t * ctx) { ipmi_packet_data_t * data; ipmi_netfn_t * cmd_list; ipmi_cmd_t * cmd; proto_item * ti; proto_tree * cmd_tree = NULL, * tmp_tree; guint8 prev_level, cc_val; guint offset, siglen, is_resp; const char * cc_str, * netfn_str; /* get packet data */ data = get_packet_data(pinfo); if (!data) { return 0; } /* get prefix length */ siglen = ipmi_getsiglen(ctx->hdr.netfn); /* get response flag */ is_resp = ctx->hdr.netfn & 1; /* check message length */ if (tvb_captured_length(tvb) < ctx->hdr_len + siglen + is_resp + !(ctx->flags & IPMI_D_NO_CKS)) { /* don bother with anything */ return call_data_dissector(tvb, pinfo, tree); } /* save nest level */ prev_level = data->curr_level; /* assign next nest level */ data->curr_level = data->next_level; /* increment next nest level */ data->next_level++; /* check for the first invocation */ if (!data->curr_level) { /* get current frame data */ data->curr_frame = get_frame_data(data, pinfo->num); data->curr_frame_num = pinfo->num; /* copy frame timestamp */ memcpy(&data->curr_frame->ts, &pinfo->abs_ts, sizeof(nstime_t)); /* cache channel and direction */ data->curr_channel = ctx->hdr.channel; data->curr_dir = ctx->hdr.dir; /* remove requests which are too old */ remove_old_requests(data, &pinfo->abs_ts); } if (data->curr_level < MAX_NEST_LEVEL) { if (ctx->hdr.netfn & 1) { /* perform request/response matching */ match_request_response(data, &ctx->hdr, ctx->flags); } else { /* add request to the list for later matching */ add_request(data, &ctx->hdr); } } /* get command list by network function code */ cmd_list = ipmi_getnetfn(ctx->hdr.netfn, tvb_get_ptr(tvb, ctx->hdr_len + is_resp, siglen)); /* get command descriptor */ cmd = ipmi_getcmd(cmd_list, ctx->hdr.cmd); /* check if response */ if (is_resp) { /* get completion code */ cc_val = tvb_get_guint8(tvb, ctx->hdr_len); /* get completion code desc */ cc_str = ipmi_get_completion_code(cc_val, cmd); } else { cc_val = 0; cc_str = NULL; } /* check if not inside a message */ if (!data->curr_level) { /* add packet info */ add_command_info(pinfo, cmd, is_resp, cc_val, cc_str, ctx->flags & IPMI_D_BROADCAST ? TRUE : FALSE); } if (tree) { /* add parent node */ if (!data->curr_level) { ti = proto_tree_add_item(tree, hf_parent_item, tvb, 0, -1, ENC_NA); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else { char str[ITEM_LABEL_LENGTH]; if (is_resp) { g_snprintf(str, ITEM_LABEL_LENGTH, "Rsp, %s, %s", cmd->desc, cc_str); } else { g_snprintf(str, ITEM_LABEL_LENGTH, "Req, %s", cmd->desc); } if (proto_registrar_get_ftype(hf_parent_item) == FT_STRING) { ti = proto_tree_add_string(tree, hf_parent_item, tvb, 0, -1, str); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else cmd_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tree, NULL, str); } if (data->curr_level < MAX_NEST_LEVEL) { /* check if response */ if (ctx->hdr.netfn & 1) { /* get current command data */ ipmi_cmd_data_t * rs_data = data->curr_frame->cmd_data[data->curr_level]; if (rs_data->matched_frame_num) { nstime_t ns; /* add "Request to:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_to, tvb, 0, 0, rs_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); /* calculate delta time */ nstime_delta(&ns, &pinfo->abs_ts, &get_frame_data(data, rs_data->matched_frame_num)->ts); /* add "Response time" field */ ti = proto_tree_add_time(cmd_tree, hf_ipmi_response_time, tvb, 0, 0, &ns); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } else { /* get current command data */ ipmi_cmd_data_t * rq_data = data->curr_frame->cmd_data[data->curr_level]; if (rq_data->matched_frame_num) { /* add "Response in:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_in, tvb, 0, 0, rq_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } } /* set starting offset */ offset = 0; /* check if message is broadcast */ if (ctx->flags & IPMI_D_BROADCAST) { /* skip first byte */ offset++; } /* check if session handle is specified */ if (ctx->flags & IPMI_D_SESSION_HANDLE) { /* add session handle field */ proto_tree_add_item(cmd_tree, hf_ipmi_session_handle, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if responder address is specified */ if (ctx->flags & IPMI_D_TRG_SA) { /* add response address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_trg, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* get NetFn string */ netfn_str = ipmi_getnetfnname(ctx->hdr.netfn, cmd_list); /* Network function + target LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_1, NULL, "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)", ctx->hdr.rs_lun, netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); /* add Net Fn */ proto_tree_add_uint_format(tmp_tree, hf_ipmi_header_netfn, tvb, offset, 1, ctx->hdr.netfn << 2, "NetFn: %s %s (0x%02x)", netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); proto_tree_add_item(tmp_tree, hf_ipmi_header_trg_lun, tvb, offset++, 1, ENC_LITTLE_ENDIAN); /* check if cks1 is specified */ if (!(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks1) { guint8 correct = cks - ctx->cks1; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (correct)", cks); } } /* check if request address is specified */ if (!(ctx->flags & IPMI_D_NO_RQ_SA)) { /* add request address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_src, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if request sequence is specified */ if (!(ctx->flags & IPMI_D_NO_SEQ)) { /* Sequence number + source LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_4, NULL, "%s: 0x%02x, SeqNo: 0x%02x", (ctx->flags & IPMI_D_TMODE) ? "Bridged" : "Source LUN", ctx->hdr.rq_lun, ctx->hdr.rq_seq); if (ctx->flags & IPMI_D_TMODE) { proto_tree_add_item(tmp_tree, hf_ipmi_header_bridged, tvb, offset, 1, ENC_LITTLE_ENDIAN); } else { proto_tree_add_item(tmp_tree, hf_ipmi_header_src_lun, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* print seq no */ proto_tree_add_item(tmp_tree, hf_ipmi_header_sequence, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* command code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_command, tvb, offset++, 1, ctx->hdr.cmd, "%s (0x%02x)", cmd->desc, ctx->hdr.cmd); if (is_resp) { /* completion code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_completion, tvb, offset++, 1, cc_val, "%s (0x%02x)", cc_str, cc_val); } if (siglen) { /* command prefix (if present) */ ti = proto_tree_add_item(cmd_tree, hf_ipmi_header_sig, tvb, offset, siglen, ENC_NA); proto_item_append_text(ti, " (%s)", netfn_str); } } if (tree || (cmd->flags & CMD_CALLRQ)) { /* calculate message data length */ guint data_len = tvb_captured_length(tvb) - ctx->hdr_len - siglen - (is_resp ? 1 : 0) - !(ctx->flags & IPMI_D_NO_CKS); /* create data subset */ tvbuff_t * data_tvb = tvb_new_subset_length(tvb, ctx->hdr_len + siglen + (is_resp ? 1 : 0), data_len); /* Select sub-handler */ ipmi_cmd_handler_t hnd = is_resp ? cmd->parse_resp : cmd->parse_req; if (hnd && tvb_captured_length(data_tvb)) { /* create data field */ tmp_tree = proto_tree_add_subtree(cmd_tree, data_tvb, 0, -1, ett_data, NULL, "Data"); /* save current command */ data->curr_hdr = &ctx->hdr; /* save current completion code */ data->curr_ccode = cc_val; /* call command parser */ hnd(data_tvb, pinfo, tmp_tree); } } /* check if cks2 is specified */ if (tree && !(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks; /* get cks2 offset */ offset = tvb_captured_length(tvb) - 1; /* get cks2 */ cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks2) { guint8 correct = cks - ctx->cks2; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (correct)", cks); } } /* decrement next nest level */ data->next_level = data->curr_level; /* restore previous nest level */ data->curr_level = prev_level; return tvb_captured_length(tvb); }
static void dissect_bfd_authentication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 24; guint8 auth_type; guint8 auth_len; proto_item *ti = NULL; proto_item *auth_item = NULL; proto_tree *auth_tree = NULL; guint8 *password; auth_type = tvb_get_guint8(tvb, offset); auth_len = tvb_get_guint8(tvb, offset + 1); if (tree) { auth_tree = proto_tree_add_subtree_format(tree, tvb, offset, auth_len, ett_bfd_auth, NULL, "Authentication: %s", val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); proto_tree_add_item(auth_tree, hf_bfd_auth_type, tvb, offset, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_item(auth_tree, hf_bfd_auth_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti, " bytes"); proto_tree_add_item(auth_tree, hf_bfd_auth_key, tvb, offset + 2, 1, ENC_BIG_ENDIAN); } switch (auth_type) { case BFD_AUTH_SIMPLE: if (tree) { password = tvb_get_string_enc(wmem_packet_scope(), tvb, offset+3, auth_len-3, ENC_ASCII); proto_tree_add_string(auth_tree, hf_bfd_auth_password, tvb, offset+3, auth_len-3, password); proto_item_append_text(auth_item, ": %s", password); } break; case BFD_AUTH_MD5: case BFD_AUTH_MET_MD5: case BFD_AUTH_SHA1: case BFD_AUTH_MET_SHA1: if (auth_len != get_bfd_required_auth_len(auth_type)) { if (tree) { ti = proto_tree_add_text(auth_tree, tvb, offset, auth_len, "Length of authentication is invalid (%d)", auth_len); proto_item_append_text(auth_item, ": Invalid Authentication Section"); } expert_add_info_format(pinfo, ti, &ei_bfd_auth_len_invalid, "Length of authentication section is invalid for Authentication Type: %s", val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); } if (tree) { proto_tree_add_item(auth_tree, hf_bfd_auth_seq_num, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_text(auth_tree, tvb, offset+8, get_bfd_checksum_len(auth_type), "Checksum: 0x%s", tvb_bytes_to_ep_str(tvb, offset+8, get_bfd_checksum_len(auth_type)) ); } break; default: break; } }
/*FUNCTION:------------------------------------------------------ * NAME * dissect_zbee_secure * DESCRIPTION * Dissects and decrypts secured ZigBee frames. * * Will return a valid tvbuff only if security processing was * successful. If processing fails, then this function will * handle internally and return NULL. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * packet_info *pinfo - pointer to packet information fields * proto_tree *tree - pointer to data tree Wireshark uses to display packet. * guint offset - pointer to the start of the auxiliary security header. * guint64 src64 - extended source address, or 0 if unknown. * RETURNS * tvbuff_t * *--------------------------------------------------------------- */ tvbuff_t * dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset) { proto_tree *sec_tree; zbee_security_packet packet; guint mic_len; gint payload_len; tvbuff_t *payload_tvb; #ifdef HAVE_LIBGCRYPT proto_item *ti; proto_item *key_item; guint8 *enc_buffer; guint8 *dec_buffer; gboolean decrypted; GSList **nwk_keyring; GSList *GSList_i; key_record_t *key_rec = NULL; #endif zbee_nwk_hints_t *nwk_hints; ieee802154_hints_t *ieee_hints; ieee802154_map_rec *map_rec = NULL; static const int * sec_flags[] = { &hf_zbee_sec_key_id, &hf_zbee_sec_nonce, NULL }; /* Init */ memset(&packet, 0, sizeof(zbee_security_packet)); /* Get pointers to any useful frame data from lower layers */ nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0); ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0); /* Create a subtree for the security information. */ sec_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_zbee_sec, NULL, "ZigBee Security Header"); /* Get and display the Security control field */ packet.control = tvb_get_guint8(tvb, offset); /* Patch the security level. */ packet.control &= ~ZBEE_SEC_CONTROL_LEVEL; packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level); /* * Eww, I think I just threw up a little... ZigBee requires this field * to be patched before computing the MIC, but we don't have write-access * to the tvbuff. So we need to allocate a copy of the whole thing just * so we can fix these 3 bits. Memory allocated by tvb_memdup(wmem_packet_scope(),...) * is automatically freed before the next packet is processed. */ #ifdef HAVE_LIBGCRYPT enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_captured_length(tvb)); /* * Override the const qualifiers and patch the security level field, we * know it is safe to overide the const qualifiers because we just * allocated this memory via tvb_memdup(wmem_packet_scope(),...). */ enc_buffer[offset] = packet.control; #endif /* HAVE_LIBGCRYPT */ packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL); packet.key_id = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY); packet.nonce = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE); proto_tree_add_bitmask(sec_tree, tvb, offset, hf_zbee_sec_field, ett_zbee_sec_control, sec_flags, ENC_NA); offset += 1; /* Get and display the frame counter field. */ packet.counter = tvb_get_letohl(tvb, offset); proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter); offset += 4; if (packet.nonce) { /* Get and display the source address of the device that secured this payload. */ packet.src64 = tvb_get_letoh64(tvb, offset); proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN); #if 1 if (!pinfo->fd->flags.visited) { switch ( packet.key_id ) { case ZBEE_SEC_KEY_LINK: if (nwk_hints && ieee_hints) { /* Map this long address with the nwk layer short address. */ nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src, ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); } break; case ZBEE_SEC_KEY_NWK: if (ieee_hints) { /* Map this long address with the ieee short address. */ ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16, ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); } break; /* We ignore the extended source addresses used to encrypt payloads with these * types of keys, because they can emerge from APS tunnels created by nodes whose * short address is not recorded in the packet. */ case ZBEE_SEC_KEY_TRANSPORT: case ZBEE_SEC_KEY_LOAD: break; } } #endif offset += 8; } else { /* Look for a source address in hints */ switch ( packet.key_id ) { case ZBEE_SEC_KEY_NWK: /* use the ieee extended source address for NWK decryption */ if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) packet.src64 = map_rec->addr64; else proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); break; default: /* use the nwk extended source address for APS decryption */ if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) packet.src64 = map_rec->addr64; else proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); break; } } if (packet.key_id == ZBEE_SEC_KEY_NWK) { /* Get and display the key sequence number. */ packet.key_seqno = tvb_get_guint8(tvb, offset); proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno); offset += 1; } /* Determine the length of the MIC. */ switch (packet.level) { case ZBEE_SEC_ENC: case ZBEE_SEC_NONE: default: mic_len=0; break; case ZBEE_SEC_ENC_MIC32: case ZBEE_SEC_MIC32: mic_len=4; break; case ZBEE_SEC_ENC_MIC64: case ZBEE_SEC_MIC64: mic_len=8; break; case ZBEE_SEC_ENC_MIC128: case ZBEE_SEC_MIC128: mic_len=16; break; } /* switch */ /* Get and display the MIC. */ if (mic_len) { /* Display the MIC. */ proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_captured_length(tvb)-mic_len), mic_len, ENC_NA); } /* Check for null payload. */ payload_len = tvb_reported_length_remaining(tvb, offset+mic_len); if (payload_len == 0) return NULL; /********************************************** * Perform Security Operations on the Frame * ********************************************** */ if ((packet.level == ZBEE_SEC_NONE) || (packet.level == ZBEE_SEC_MIC32) || (packet.level == ZBEE_SEC_MIC64) || (packet.level == ZBEE_SEC_MIC128)) { /* Payload is only integrity protected. Just return the sub-tvbuff. */ return tvb_new_subset_length(tvb, offset, payload_len); } #ifdef HAVE_LIBGCRYPT /* Have we captured all the payload? */ if (tvb_captured_length_remaining(tvb, offset+mic_len) < payload_len) { /* * No - don't try to decrypt it. * * XXX - it looks as if the decryption code is assuming we have the * MIC, which won't be the case if the packet was cut short. Is * that in fact that case, or can we still make this work with a * partially-captured packet? */ /* Add expert info. */ expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload_sliced); /* Create a buffer for the undecrypted payload. */ payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); /* Dump the payload to the data dissector. */ call_data_dissector(payload_tvb, pinfo, tree); /* Couldn't decrypt, so return NULL. */ return NULL; } /* Allocate memory to decrypt the payload into. */ dec_buffer = (guint8 *)wmem_alloc(pinfo->pool, payload_len); decrypted = FALSE; if ( packet.src64 ) { if (pinfo->fd->flags.visited) { if ( nwk_hints ) { /* Use previously found key */ switch ( packet.key_id ) { case ZBEE_SEC_KEY_NWK: if ( (key_rec = nwk_hints->nwk) ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, nwk_hints->nwk->key); } break; default: if ( (key_rec = nwk_hints->link) ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, nwk_hints->link->key); } break; } } } /* ( !pinfo->fd->flags.visited ) */ else { /* We only search for sniffed keys in the first pass, * to save time, and because decrypting with keys * transported in future packets is cheating */ /* Lookup NWK and link key in hash for this pan. */ /* This overkill approach is a placeholder for a hash that looks up * a key ring for a link key associated with a pair of devices. */ if ( nwk_hints ) { nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan); if ( nwk_keyring ) { GSList_i = *nwk_keyring; while ( GSList_i && !decrypted ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); if (decrypted) { /* save pointer to the successful key record */ switch (packet.key_id) { case ZBEE_SEC_KEY_NWK: key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); break; default: key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); break; } } else { GSList_i = g_slist_next(GSList_i); } } } /* Loop through user's password table for preconfigured keys, our last resort */ GSList_i = zbee_pc_keyring; while ( GSList_i && !decrypted ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); if (decrypted) { /* save pointer to the successful key record */ switch (packet.key_id) { case ZBEE_SEC_KEY_NWK: key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); break; default: key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); break; } } else { GSList_i = g_slist_next(GSList_i); } } } } /* ( ! pinfo->fd->flags.visited ) */ } /* ( packet.src64 ) */ if ( decrypted ) { if ( tree && key_rec ) { key_item = proto_tree_add_bytes(sec_tree, hf_zbee_sec_key, tvb, 0, ZBEE_SEC_CONST_KEYSIZE, key_rec->key); PROTO_ITEM_SET_GENERATED(key_item); if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) { ti = proto_tree_add_string(sec_tree, hf_zbee_sec_decryption_key, tvb, 0, 0, key_rec->label); } else { ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0, key_rec->frame_num); } PROTO_ITEM_SET_GENERATED(ti); } /* Found a key that worked, setup the new tvbuff_t and return */ payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len); add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload"); /* Done! */ return payload_tvb; } #endif /* HAVE_LIBGCRYPT */ /* Add expert info. */ expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload); /* Create a buffer for the undecrypted payload. */ payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); /* Dump the payload to the data dissector. */ call_data_dissector(payload_tvb, pinfo, tree); /* Couldn't decrypt, so return NULL. */ return NULL; } /* dissect_zbee_secure */
static int dissect_form_urlencoded(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *url_tree; proto_tree *sub; proto_item *ti; gint offset = 0, next_offset; const char *data_name; data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = (char *)(pinfo->private_data); if (! (data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); ti = proto_tree_add_item(tree, hfi_urlencoded, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); url_tree = proto_item_add_subtree(ti, ett_form_urlencoded); while (tvb_reported_length_remaining(tvb, offset) > 0) { const int start_offset = offset; char *key, *value; ti = proto_tree_add_item(url_tree, &hfi_form_keyvalue, tvb, offset, 0, ENC_NA); sub = proto_item_add_subtree(ti, ett_form_keyvalue); next_offset = get_form_key_value(tvb, &key, offset, '='); if (next_offset == -1) break; proto_tree_add_string(sub, &hfi_form_key, tvb, offset, next_offset - offset, key); proto_item_append_text(sub, ": \"%s\"", key); offset = next_offset+1; next_offset = get_form_key_value(tvb, &value, offset, '&'); if (next_offset == -1) break; proto_tree_add_string(sub, &hfi_form_value, tvb, offset, next_offset - offset, value); proto_item_append_text(sub, " = \"%s\"", value); offset = next_offset+1; proto_item_set_len(ti, offset - start_offset); } return tvb_length(tvb); }
static void dissect_cimd_ud(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset) { /* Set up structures needed to add the param subtree and manage it */ proto_item *param_item; proto_tree *param_tree; gchar* payloadText; gchar* tmpBuffer = (gchar*)ep_alloc(1024); gchar* tmpBuffer1 = (gchar*)ep_alloc(1024); int loop,i,poz, bufPoz = 0, bufPoz1 = 0, size, size1, resch; gint g_offset, g_size; gchar token[4]; gchar ch; const char* mapping[128] = { "_Oa" , "_L-", "" , "_Y-", "_e`", "_e'", "_u`", "_i`", "_o`", "_C,", /*10*/ "" , "_O/", "_o/" , "" , "_A*", "_a*", "_gd", "_--", "_gf", "_gg", "_gl", /*21*/ "_go" , "_gp", "_gi" , "_gs", "_gt", "_gx", "_XX", "_AE", "_ae", "_ss", "_E'", /*32*/ "" , "" , "_qq" , "" , "_ox", "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "", "_!!" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "_A\"", "_O\"", "_N~", "_U\"", "_so", "_??" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "_a\"", "_o\"", "_n~", "_n\"","_a`" }; param_item = proto_tree_add_text(tree, tvb, startOffset + 1, endOffset - (startOffset + 1), "%s", cimd_vals_PC[pindex].strptr ); param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p)); proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb, startOffset + 1, CIMD_PC_LENGTH, tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH) ); g_offset = startOffset + 1 + CIMD_PC_LENGTH + 1; g_size = endOffset - g_offset; payloadText = tvb_format_text(tvb, g_offset, g_size); size = (int)strlen(payloadText); for (loop = 0; loop < size; loop++) { if (payloadText[loop] == '_') { if (loop < size - 2) { token[0] = payloadText[loop++]; token[1] = payloadText[loop++]; token[2] = payloadText[loop]; token[3] = '\0'; poz = -1; for (i = 0; i < 128; i++) { if (strcmp(token, mapping[i]) == 0) { poz = i; break; } } if (poz > 0) { tmpBuffer[bufPoz++] = poz; } else { tmpBuffer[bufPoz++] = payloadText[loop-2]; tmpBuffer[bufPoz++] = payloadText[loop-1]; tmpBuffer[bufPoz++] = payloadText[loop]; } } else { if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++]; if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++]; if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++]; } } else { tmpBuffer[bufPoz++] = payloadText[loop]; } } tmpBuffer[bufPoz] = '\0'; size1 = (int)strlen(tmpBuffer); for (loop=0; loop<size1; loop++) { ch = tmpBuffer[loop]; switch ((gint)ch) { case 0x40: resch = 0x0040; break; case 0x01: resch = 0x00A3; break; case 0x02: resch = 0x0024; break; case 0x03: resch = 0x00A5; break; case 0x04: resch = 0x00E8; break; case 0x05: resch = 0x00E9; break; case 0x06: resch = 0x00F9; break; case 0x07: resch = 0x00EC; break; case 0x08: resch = 0x00F2; break; case 0x09: resch = 0x00E7; break; case 0x0B: resch = 0x00D8; break; case 0x0C: resch = 0x00F8; break; case 0x0E: resch = 0x00C5; break; case 0x0F: resch = 0x00E5; break; case 0x11: resch = 0x005F; break; /* case 0x1B14: resch = 0x005E; break; */ /* case 0x1B28: resch = 0x007B; break; */ /* case 0x1B29: resch = 0x007D; break; */ /* case 0x1B2F: resch = 0x005C; break; */ /* case 0x1B3C: resch = 0x005B; break; */ /* case 0x1B3D: resch = 0x007E; break; */ /* case 0x1B3E: resch = 0x005D; break; */ /* case 0x1B40: resch = 0x007C; break; */ case 0x1C: resch = 0x00C6; break; case 0x1D: resch = 0x00E6; break; case 0x1E: resch = 0x00DF; break; case 0x1F: resch = 0x00C9; break; case 0x20: resch = 0x0020; break; case 0x21: resch = 0x0021; break; case 0x22: resch = 0x0022; break; case 0x23: resch = 0x0023; break; case 0xA4: resch = 0x00A4; break; case 0x25: resch = 0x0025; break; case 0x26: resch = 0x0026; break; case 0x27: resch = 0x0027; break; case 0x28: resch = 0x0028; break; case 0x29: resch = 0x0029; break; case 0x2A: resch = 0x002A; break; case 0x2B: resch = 0x002B; break; case 0x2C: resch = 0x002C; break; case 0x2D: resch = 0x002D; break; case 0x2E: resch = 0x002E; break; case 0x2F: resch = 0x002F; break; case 0x30: resch = 0x0030; break; case 0x31: resch = 0x0031; break; case 0x32: resch = 0x0032; break; case 0x33: resch = 0x0033; break; case 0x34: resch = 0x0034; break; case 0x35: resch = 0x0035; break; case 0x36: resch = 0x0036; break; case 0x37: resch = 0x0037; break; case 0x38: resch = 0x0038; break; case 0x39: resch = 0x0039; break; case 0x3A: resch = 0x003A; break; case 0x3B: resch = 0x003B; break; case 0x3C: resch = 0x003C; break; case 0x3D: resch = 0x003D; break; case 0x3E: resch = 0x003E; break; case 0x3F: resch = 0x003F; break; /* case 0x40: resch = 0x00A1; break; */ case 0x41: resch = 0x0041; break; case 0x42: resch = 0x0042; break; /* case 0x42: resch = 0x0392; break; */ case 0x43: resch = 0x0043; break; case 0x44: resch = 0x0044; break; case 0x45: resch = 0x0045; break; case 0x46: resch = 0x0046; break; case 0x47: resch = 0x0047; break; case 0x48: resch = 0x0048; break; case 0x49: resch = 0x0049; break; case 0x4A: resch = 0x004A; break; case 0x4B: resch = 0x004B; break; case 0x4C: resch = 0x004C; break; case 0x4D: resch = 0x004D; break; case 0x4E: resch = 0x004E; break; case 0x4F: resch = 0x004F; break; case 0x50: resch = 0x0050; break; case 0x51: resch = 0x0051; break; case 0x52: resch = 0x0052; break; case 0x53: resch = 0x0053; break; case 0x54: resch = 0x0054; break; case 0x55: resch = 0x0055; break; case 0x56: resch = 0x0056; break; case 0x57: resch = 0x0057; break; case 0x58: resch = 0x0058; break; case 0x59: resch = 0x0059; break; case 0x5A: resch = 0x005A; break; case 0x5B: resch = 0x00C4; break; case 0x5C: resch = 0x00D6; break; case 0x5D: resch = 0x00D1; break; case 0x5E: resch = 0x00DC; break; case 0x5F: resch = 0x00A7; break; case 0x60: resch = 0x00BF; break; case 0x61: resch = 0x0061; break; case 0x62: resch = 0x0062; break; case 0x63: resch = 0x0063; break; case 0x64: resch = 0x0064; break; case 0x65: resch = 0x0065; break; case 0x66: resch = 0x0066; break; case 0x67: resch = 0x0067; break; case 0x68: resch = 0x0068; break; case 0x69: resch = 0x0069; break; case 0x6A: resch = 0x006A; break; case 0x6B: resch = 0x006B; break; case 0x6C: resch = 0x006C; break; case 0x6D: resch = 0x006D; break; case 0x6E: resch = 0x006E; break; case 0x6F: resch = 0x006F; break; case 0x70: resch = 0x0070; break; case 0x71: resch = 0x0071; break; case 0x72: resch = 0x0072; break; case 0x73: resch = 0x0073; break; case 0x74: resch = 0x0074; break; case 0x75: resch = 0x0075; break; case 0x76: resch = 0x0076; break; case 0x77: resch = 0x0077; break; case 0x78: resch = 0x0078; break; case 0x79: resch = 0x0079; break; case 0x7A: resch = 0x007A; break; case 0x7B: resch = 0x00E4; break; case 0x7C: resch = 0x00F6; break; case 0x7D: resch = 0x00F1; break; case 0x7F: resch = 0x00E0; break; default:resch = ch; break; } tmpBuffer1[bufPoz1++] = (gchar)resch; } tmpBuffer1[bufPoz1] = '\0'; proto_tree_add_string(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, g_offset, g_size, tmpBuffer1); }
/* dissect the "device" suboption */ static int dissect_PNDCP_Suboption_Device(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_item *block_item, proto_item *dcp_item, guint8 service_id, gboolean is_response) { guint8 suboption; guint16 block_length; gchar *info_str; guint8 device_role; guint16 vendor_id; guint16 device_id; char *typeofstation; char *nameofstation; char *aliasname; guint16 block_info; guint16 block_qualifier; gboolean have_block_info = FALSE; gboolean have_block_qualifier = FALSE; guint8 device_instance_high; guint8 device_instance_low; /* SuboptionDevice... */ offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption); /* DCPBlockLength */ offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); /* BlockInfo? */ if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); have_block_info = TRUE; block_length -= 2; } /* BlockQualifier? */ if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); have_block_qualifier = TRUE; block_length -= 2; } switch (suboption) { case PNDCP_SUBOPTION_DEVICE_MANUF: typeofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) typeofstation, offset, block_length); typeofstation[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_typeofstation, tvb, offset, block_length, typeofstation); pn_append_info(pinfo, dcp_item, ", DeviceVendorValue"); proto_item_append_text(block_item, "Device/Manufacturer specific"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info){ proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", DeviceVendorValue: \"%s\"", typeofstation); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION: nameofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) nameofstation, offset, block_length); nameofstation[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_nameofstation, tvb, offset, block_length, nameofstation); pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", NameOfStation:\"%s\"", nameofstation)); proto_item_append_text(block_item, "Device/NameOfStation"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", \"%s\"", nameofstation); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_DEV_ID: offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_vendor_id, &vendor_id); offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_id, &device_id); pn_append_info(pinfo, dcp_item, ", Dev-ID"); proto_item_append_text(block_item, "Device/Device ID"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", VendorID: 0x%04x / DeviceID: 0x%04x", vendor_id, device_id); break; case PNDCP_SUBOPTION_DEVICE_DEV_ROLE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_role, &device_role); offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_reserved8, NULL); pn_append_info(pinfo, dcp_item, ", Dev-Role"); proto_item_append_text(block_item, "Device/Device Role"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); if (device_role & 0x01) proto_item_append_text(block_item, ", IO-Device"); if (device_role & 0x02) proto_item_append_text(block_item, ", IO-Controller"); if (device_role & 0x04) proto_item_append_text(block_item, ", IO-Multidevice"); if (device_role & 0x08) proto_item_append_text(block_item, ", PN-Supervisor"); break; case PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS: info_str = wmem_strdup_printf(wmem_packet_scope(), ", Dev-Options(%u)", block_length/2); pn_append_info(pinfo, dcp_item, info_str); proto_item_append_text(block_item, "Device/Device Options"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", %u options", block_length/2); for( ; block_length != 0; block_length -= 2) { offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, NULL /*block_item*/, hf_pn_dcp_option, FALSE /* append_col */); } break; case PNDCP_SUBOPTION_DEVICE_ALIAS_NAME: aliasname = (char *)wmem_alloc(wmem_packet_scope(), block_length+1); tvb_memcpy(tvb, (guint8 *) aliasname, offset, block_length); aliasname[block_length] = '\0'; proto_tree_add_string (tree, hf_pn_dcp_suboption_device_aliasname, tvb, offset, block_length, aliasname); pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", AliasName:\"%s\"", aliasname)); proto_item_append_text(block_item, "Device/AliasName"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", \"%s\"", aliasname); offset += block_length; break; case PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE: offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_high, &device_instance_high); offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_low, &device_instance_low); pn_append_info(pinfo, dcp_item, ", Dev-Instance"); proto_item_append_text(block_item, "Device/Device Instance"); if (have_block_qualifier) { proto_item_append_text(block_item, ", BlockQualifier: %s", val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown")); } if (have_block_info) { proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown")); } proto_item_append_text(block_item, ", InstanceHigh: %d, Instance Low: %d", device_instance_high, device_instance_low); break; default: offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); } return offset; }
/* dissect 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_fix_packet(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 *fix_tree; int pdu_len; int offset = 0; int field_offset, ctrla_offset; int tag_value; char *value; char *tag_str; fix_parameter *tag; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIX"); col_clear(pinfo->cinfo, COL_INFO); /* get at least the fix version: 8=FIX.x.x */ if (fix_marker(tvb, 0) != 0) { /* not a fix packet start but it's a fix packet */ col_set_str(pinfo->cinfo, COL_INFO, "[FIX continuation]"); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); proto_tree_add_item(fix_tree, hf_fix_data, tvb, 0, -1, ENC_NA); return; } pdu_len = tvb_reported_length(tvb); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); /* begin string */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg length */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg type */ if (!(tag = fix_param(tvb, offset)) || tag->value_len < 1) { return; } if (check_col(pinfo->cinfo, COL_INFO)) { const char *msg_type; value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); msg_type = str_to_str(value, messages_val, "FIX Message (%s)"); col_add_str(pinfo->cinfo, COL_INFO, msg_type); } /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ field_offset = 0; while(field_offset < pdu_len && (tag = fix_param(tvb, field_offset)) ) { int i, found; if (tag->tag_len < 1) { field_offset = tag->ctrla_offset + 1; continue; } tag_str = tvb_get_ephemeral_string(tvb, field_offset, tag->tag_len); tag_value = atoi(tag_str); if (tag->value_len < 1) { proto_tree *field_tree; /* XXX - put an error indication here. It's too late to return FALSE; we've already started dissecting, and if a heuristic dissector starts dissecting (either updating the columns or creating a protocol tree) and then gives up, it leaves crud behind that messes up other dissectors that might process the packet. */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: <missing value>", tag_value); field_tree = proto_item_add_subtree(ti, ett_badfield); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); field_offset = tag->ctrla_offset + 1; continue; } /* fix_fields array is sorted by tag_value */ found = 0; if ((i = tag_search(tag_value)) >= 0) { found = 1; } value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); if (found) { if (fix_fields[i].table) { if (tree) { switch (fix_fields[i].type) { case 1: /* strings */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, str_to_str(value, fix_fields[i].table, "unknown %s")); break; case 2: /* char */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(*value, fix_fields[i].table, "unknown %d")); break; default: proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(atoi(value), fix_fields[i].table, "unknown %d")); break; } } } else { proto_item *item; /* checksum */ switch(tag_value) { case 10: { proto_tree *checksum_tree; guint8 sum = 0; const guint8 *data = tvb_get_ptr(tvb, 0, field_offset); gboolean sum_ok; int j; for (j = 0; j < field_offset; j++, data++) { sum += *data; } sum_ok = (atoi(value) == sum); if (sum_ok) { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [correct]", value); } else { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [incorrect should be %d]", value, sum); } checksum_tree = proto_item_add_subtree(item, ett_checksum); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_good, tvb, field_offset, tag->field_len, sum_ok); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_bad, tvb, field_offset, tag->field_len, !sum_ok); PROTO_ITEM_SET_GENERATED(item); if (!sum_ok) expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); } break; default: proto_tree_add_string(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value); break; } } } else if (tree) { proto_tree *field_tree; /* XXX - it could be -1 if the tag isn't a number */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: %s", tag_value, value); field_tree = proto_item_add_subtree(ti, ett_unknow); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); proto_tree_add_item(field_tree, hf_fix_field_value, tvb, tag->value_offset, tag->value_len, ENC_ASCII|ENC_NA); } field_offset = tag->ctrla_offset + 1; tag_str = NULL; } return; }
static void dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint op; guint sub; guint rlen; guint flags; proto_item *ti; proto_item *item; proto_tree *fip_tree; proto_tree *subtree; guint dtype; guint dlen; guint desc_offset; guint val; tvbuff_t *desc_tvb; tvbuff_t *ls_tvb = NULL; const char *info; char *text; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIP"); if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) { col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]"); if (tree) proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, -1, "FIP [packet too short]"); return; } op = tvb_get_ntohs(tvb, 2); sub = tvb_get_guint8(tvb, 5); switch (op) { case FIP_OP_DISC: info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x"); break; case FIP_OP_LS: info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x"); break; case FIP_OP_CTRL: info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x"); break; case FIP_OP_VLAN: info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x"); break; default: info = val_to_str(op, fip_opcodes, "Unknown op 0x%x"); break; } if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, info); rlen = tvb_get_ntohs(tvb, 6); flags = tvb_get_ntohs(tvb, 8); ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, FIP_HEADER_LEN + rlen * FIP_BPW, "FIP %s", info); fip_tree = proto_item_add_subtree(ti, ett_fip); proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, FALSE); proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, FALSE); switch (op) { case FIP_OP_DISC: proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, FALSE); break; case FIP_OP_LS: proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, FALSE); break; case FIP_OP_CTRL: proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, FALSE); break; case FIP_OP_VLAN: proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, FALSE); break; default: proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, FALSE); break; } proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, FALSE); proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags, ett_fip_flags, hf_fip_flags_fields, FALSE); desc_offset = FIP_HEADER_LEN; rlen *= FIP_BPW; proto_tree_add_text(fip_tree, tvb, desc_offset, rlen, "Descriptors:"); while (rlen > 0 && tvb_bytes_exist(tvb, desc_offset, 2)) { dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW; if (!dlen) { proto_tree_add_text(fip_tree, tvb, desc_offset, -1, "Descriptor [length error]"); break; } if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) { break; } desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1); dtype = tvb_get_guint8(desc_tvb, 0); desc_offset += dlen; rlen -= dlen; item = proto_tree_add_text(fip_tree, desc_tvb, 0, -1, "Descriptor: %s ", val_to_str(dtype, fip_desc_types, "Unknown 0x%x")); switch (dtype) { case FIP_DT_PRI: subtree = proto_item_add_subtree(item, ett_fip_dt_pri); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb, 3, 1, FALSE); proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3)); break; case FIP_DT_MAC: subtree = proto_item_add_subtree(item, ett_fip_dt_mac); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb, 2, 6, FALSE); proto_item_append_text(item, "%s", tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':')); break; case FIP_DT_MAP_OUI: subtree = proto_item_add_subtree(item, ett_fip_dt_map); fip_desc_type_len(subtree, desc_tvb); text = fc_to_str(tvb_get_ptr(desc_tvb, 5, 3)); proto_tree_add_string(subtree, hf_fip_desc_map, desc_tvb, 5, 3, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_NAME: subtree = proto_item_add_subtree(item, ett_fip_dt_name); fip_desc_type_len(subtree, desc_tvb); text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 4, 8)); proto_tree_add_string(subtree, hf_fip_desc_name, desc_tvb, 4, 8, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_FAB: subtree = proto_item_add_subtree(item, ett_fip_dt_fab); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb, 2, 2, FALSE); text = fc_to_str(tvb_get_ptr(desc_tvb, 5, 3)); proto_tree_add_string(subtree, hf_fip_desc_fab_map, desc_tvb, 5, 3, text); text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 8, 8)); proto_tree_add_string(subtree, hf_fip_desc_fab_name, desc_tvb, 8, 8, text); proto_item_append_text(item, "%s", text); break; case FIP_DT_FCOE_SIZE: subtree = proto_item_add_subtree(item, ett_fip_dt_mdl); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb, 2, 2, FALSE); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: case FIP_DT_LOGO: case FIP_DT_ELP: subtree = proto_item_add_subtree(item, ett_fip_dt_caps); fip_desc_type_len(subtree, desc_tvb); ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1); call_dissector(fc_handle, ls_tvb, pinfo, subtree); proto_item_append_text(item, "%u bytes", dlen - 4); break; case FIP_DT_VN: subtree = proto_item_add_subtree(item, ett_fip_dt_vn); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb, 2, 6, FALSE); proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb, 9, 3, FALSE); text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 12, 8)); proto_tree_add_string(subtree, hf_fip_desc_vn_wwpn, desc_tvb, 12, 8, text); proto_item_append_text(item, "MAC %s FC_ID %6.6x", tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':'), tvb_get_ntoh24(desc_tvb, 9)); break; case FIP_DT_FKA: subtree = proto_item_add_subtree(item, ett_fip_dt_fka); fip_desc_type_len(subtree, desc_tvb); val = tvb_get_ntohl(desc_tvb, 4); proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka, desc_tvb, 4, 4, val, "%u ms", val); proto_item_append_text(item, "%u ms", val); break; case FIP_DT_VEND: subtree = proto_item_add_subtree(item, ett_fip_dt_vend); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb, 4, 8, FALSE); if (tvb_bytes_exist(desc_tvb, 9, -1)) { proto_tree_add_item(subtree, hf_fip_desc_vend_data, desc_tvb, 9, -1, FALSE); } break; case FIP_DT_VLAN: subtree = proto_item_add_subtree(item, ett_fip_dt_vlan); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb, 2, 2, FALSE); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; default: subtree = proto_item_add_subtree(item, ett_fip_dt_unk); fip_desc_type_len(subtree, desc_tvb); proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb, 2, -1, FALSE); break; } } }
static void dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int direction) { proto_tree *cl_tree = NULL; proto_tree *text_tree = NULL; guint8 *text; int len; int offset; guint32 marker; int command_len; const char *command = ""; gboolean command_finished = FALSE; marker = tvb_get_ntohl(tvb, 0); if (tree) { proto_item *cl_item; cl_item = proto_tree_add_text(tree, tvb, 0, -1, "Connectionless"); cl_tree = proto_item_add_subtree(cl_item, ett_quakeworld_connectionless); proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker, tvb, 0, 4, marker); } /* all the rest of the packet is just text */ offset = 4; text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); /* actually, we should look for a eol char and stop already there */ if (cl_tree) { proto_item *text_item; text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text, tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text); } if (direction == DIR_C2S) { /* client to server commands */ const char *c; Cmd_TokenizeString(text); c = Cmd_Argv(0); /* client to sever commands */ if (strcmp(c,"ping") == 0) { command = "Ping"; command_len = 4; } else if (strcmp(c,"status") == 0) { command = "Status"; command_len = 6; } else if (strcmp(c,"log") == 0) { command = "Log"; command_len = 3; } else if (strcmp(c,"connect") == 0) { int version; int qport; int challenge; const char *infostring; proto_tree *argument_tree = NULL; command = "Connect"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } version = atoi(Cmd_Argv(1)); qport = atoi(Cmd_Argv(2)); challenge = atoi(Cmd_Argv(3)); infostring = Cmd_Argv(4); if (argument_tree) { proto_item *info_item; proto_tree *info_tree; proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_version, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), version); proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_qport, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_length(2), qport); proto_tree_add_int(argument_tree, hf_quakeworld_connectionless_connect_challenge, tvb, offset + Cmd_Argv_start(3), Cmd_Argv_length(3), challenge); info_item = proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_connect_infostring, tvb, offset + Cmd_Argv_start(4), Cmd_Argv_length(4), infostring); info_tree = proto_item_add_subtree( info_item, ett_quakeworld_connectionless_connect_infostring); dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4), wmem_strdup(wmem_packet_scope(), infostring), ett_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key, hf_quakeworld_connectionless_connect_infostring_value); } } else if (strcmp(c,"getchallenge") == 0) { command = "Get Challenge"; command_len = Cmd_Argv_length(0); } else if (strcmp(c,"rcon") == 0) { const char* password; int i; char remaining[MAX_TEXT_SIZE+1]; proto_tree *argument_tree = NULL; command = "Remote Command"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } password = Cmd_Argv(1); if (argument_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_password, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), password); } remaining[0] = '\0'; for (i=2; i<Cmd_Argc() ; i++) { g_strlcat (remaining, Cmd_Argv(i), MAX_TEXT_SIZE+1); g_strlcat (remaining, " ", MAX_TEXT_SIZE+1); } if (text_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_command, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) - Cmd_Argv_start(2), remaining); } } else if (c[0]==A2A_PING && ( c[1]=='\0' || c[1]=='\n')) { command = "Ping"; command_len = 1; } else if (c[0]==A2A_ACK && ( c[1]=='\0' || c[1]=='\n')) { command = "Ack"; command_len = 1; } else { command = "Unknown"; command_len = len - 1; } } else { /* server to client commands */ if (text[0] == S2C_CONNECTION) { command = "Connected"; command_len = 1; } else if (text[0] == A2C_CLIENT_COMMAND) { command = "Client Command"; command_len = 1; /* stringz (command), stringz (localid) */ } else if (text[0] == A2C_PRINT) { command = "Print"; command_len = 1; /* string */ } else if (text[0] == A2A_PING) { command = "Ping"; command_len = 1; } else if (text[0] == S2C_CHALLENGE) { command = "Challenge"; command_len = 1; /* string, atoi */ } else { command = "Unknown"; command_len = len - 1; } } col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command); if (!command_finished) { proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); } /*offset += len;*/ }