static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network) { guint8 *ptr_addr,addr[5]; address ip_addr; addr[0]=network; addr[1]=tvb_get_guint8(tvb,0); addr[2]=tvb_get_guint8(tvb,1); addr[3]=tvb_get_guint8(tvb,2); addr[4]=0; ptr_addr=addr; if (network==0) ptr_addr=&addr[1]; SET_ADDRESS(&ip_addr, AT_IPv4, 4, ptr_addr); igrp_vektor_tree = proto_tree_add_subtree_format(igrp_vektor_tree, tvb, 0 ,14, ett_igrp_net, NULL, "Entry for network %s", address_to_str(wmem_packet_scope(), &ip_addr)); proto_tree_add_ipv4(igrp_vektor_tree, hf_igrp_network, tvb, 0, 3, *((guint32*)ptr_addr)); proto_tree_add_item(igrp_vektor_tree, hf_igrp_delay, tvb, 3, 3, ENC_BIG_ENDIAN); proto_tree_add_item(igrp_vektor_tree, hf_igrp_bandwidth, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(igrp_vektor_tree, hf_igrp_mtu, tvb, 9, 2, tvb_get_ntohs(tvb,9), "%d bytes", tvb_get_ntohs(tvb,9)); proto_tree_add_item(igrp_vektor_tree, hf_igrp_reliability, tvb, 11, 1, ENC_BIG_ENDIAN); proto_tree_add_item(igrp_vektor_tree, hf_igrp_load, tvb, 12, 1, ENC_BIG_ENDIAN); proto_tree_add_item(igrp_vektor_tree, hf_igrp_hop_count, tvb, 13, 1, ENC_BIG_ENDIAN); }
WSLUA_METHOD TvbRange_le_ipv4(lua_State* L) { /* Get an Little Endian IPv4 Address from a TvbRange. */ TvbRange tvbr = checkTvbRange(L,1); Address addr; guint32* ip_addr; if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } if (tvbr->len != 4) WSLUA_ERROR(TvbRange_ipv4,"The range must be 4 octets long"); addr = (address *)g_malloc(sizeof(address)); ip_addr = (guint32 *)g_malloc(sizeof(guint32)); *ip_addr = tvb_get_ipv4(tvbr->tvb->ws_tvb,tvbr->offset); *((guint32 *)ip_addr) = GUINT32_SWAP_LE_BE(*((guint32 *)ip_addr)); SET_ADDRESS(addr, AT_IPv4, 4, ip_addr); pushAddress(L,addr); WSLUA_RETURN(1); /* The IPv4 Address */ }
static int Address_tipc(lua_State* L) { Address addr = g_malloc(sizeof(address)); SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); pushAddress(L,addr); return 1; }
static void update_unicast_addr(unicast_addr_t *req_addr, unicast_addr_t *ack_addr) { if (ack_addr->addr.type!=AT_NONE && ack_addr->port!=0) { memcpy(req_addr->addr_buf, ack_addr->addr_buf, sizeof(req_addr->addr_buf)); SET_ADDRESS(&req_addr->addr, ack_addr->addr.type, ack_addr->addr.len, req_addr->addr_buf); req_addr->port = ack_addr->port; } }
/* dissect a bt dht values list from tvb, start at offset. it's like "l6:....6:....e" */ static int dissect_bt_dht_values(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label ) { proto_item *ti; proto_tree *sub_tree; proto_item *value_ti; proto_tree *value_tree; address addr; guint peer_index; guint string_len_start; guint string_len; guint16 port; ti = proto_tree_add_item( tree, hf_bt_dht_peers, tvb, offset, 0, ENC_NA ); sub_tree = proto_item_add_subtree( ti, ett_bt_dht_peers); peer_index = 0; /* we has confirmed that the first byte is 'l' */ offset += 1; /* dissect bt-dht values */ while( tvb_get_guint8(tvb,offset)!='e' ) { string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ offset += 1; /* 4 bytes ip, 2 bytes port */ for( ; string_len>=6; string_len-=6, offset+=6 ) { peer_index += 1; SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) ); port = tvb_get_letohl( tvb, offset+4 ); value_ti = proto_tree_add_none_format( sub_tree, hf_bt_dht_peer, tvb, offset, 6, "%d\t%s:%u", peer_index, ep_address_to_str( &addr ), port ); value_tree = proto_item_add_subtree( value_ti, ett_bt_dht_peers); proto_tree_add_item( value_tree, hf_ip, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item( value_tree, hf_port, tvb, offset+4, 2, ENC_BIG_ENDIAN); } /* truncated data */ if( string_len>0 ) { proto_tree_add_item( tree, hf_truncated_data, tvb, offset, string_len, ENC_NA ); offset += string_len; } } proto_item_set_text( ti, "%s: %d peers", label, peer_index ); col_append_fstr( pinfo->cinfo, COL_INFO, "reply=%d peers ", peer_index ); *result = ep_strdup_printf("%d peers", peer_index); return offset; }
static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label ) { proto_item *ti; proto_tree *sub_tree; proto_item *node_ti; proto_tree *node_tree; guint node_index; guint string_len_start; guint string_len; address addr; guint16 port; guint8 *id; ti = proto_tree_add_item( tree, hf_bt_dht_nodes, tvb, offset, 0, ENC_NA ); sub_tree = proto_item_add_subtree( ti, ett_bt_dht_nodes); node_index = 0; string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ offset += 1; /* 20 bytes id, 4 bytes ip, 2 bytes port */ for( ; string_len>=26; string_len-=26, offset+=26 ) { node_index += 1; id = tvb_bytes_to_str(tvb, offset, 20 ); SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) ); port = tvb_get_letohl( tvb, offset+24 ); node_ti = proto_tree_add_none_format( sub_tree, hf_bt_dht_node, tvb, offset, 26, "%d\t%s %s:%u", node_index, id, ep_address_to_str( &addr ), port ); node_tree = proto_item_add_subtree( node_ti, ett_bt_dht_peers); proto_tree_add_item( node_tree, hf_bt_dht_id, tvb, offset, 20, ENC_NA); proto_tree_add_item( node_tree, hf_ip, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item( node_tree, hf_port, tvb, offset+24, 2, ENC_BIG_ENDIAN); } if( string_len>0 ) { proto_tree_add_item( tree, hf_truncated_data, tvb, offset, string_len, ENC_NA ); offset += string_len; } proto_item_set_text( ti, "%s: %d nodes", label, node_index ); col_append_fstr( pinfo->cinfo, COL_INFO, "reply=%d nodes ", node_index ); *result = ep_strdup_printf("%d", node_index); return offset; }
static gboolean is_broadcast(address* addr) { static address broadcast_addr; static const guint8 broadcast_addr_bytes[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; SET_ADDRESS(&broadcast_addr, AT_ETHER, 6, broadcast_addr_bytes); return ADDRESSES_EQUAL(addr, &broadcast_addr); }
/* Set up an MSRP conversation using the info given */ void msrp_add_address( packet_info *pinfo, address *addr, int port, const gchar *setup_method, guint32 setup_frame_number) { address null_addr; conversation_t* p_conv; struct _msrp_conversation_info *p_conv_data = NULL; /* * If this isn't the first time this packet has been processed, * we've already done this work, so we don't need to do it * again. */ if (pinfo->fd->flags.visited) { return; } SET_ADDRESS(&null_addr, AT_NONE, 0, NULL); /* * Check if the ip address and port combination is not * already registered as a conversation. */ p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_TCP, port, 0, NO_ADDR_B | NO_PORT_B); /* * If not, create a new conversation. */ if (!p_conv) { p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_TCP, (guint32)port, 0, NO_ADDR2 | NO_PORT2); } /* Set dissector */ conversation_set_dissector(p_conv, msrp_handle); /* * Check if the conversation has data associated with it. */ p_conv_data = (struct _msrp_conversation_info *)conversation_get_proto_data(p_conv, proto_msrp); /* * If not, add a new data item. */ if (!p_conv_data) { /* Create conversation data */ p_conv_data = wmem_new0(wmem_file_scope(), struct _msrp_conversation_info); conversation_add_proto_data(p_conv, proto_msrp, p_conv_data); }
WSLUA_CONSTRUCTOR Address_ip(lua_State* L) { /* Creates an Address Object representing an IP address. */ #define WSLUA_ARG_Address_ip_HOSTNAME 1 /* The address or name of the IP host. */ Address addr = g_malloc(sizeof(address)); guint32* ip_addr = g_malloc(sizeof(guint32)); const gchar* name = luaL_checkstring(L,WSLUA_ARG_Address_ip_HOSTNAME); if (! get_host_ipaddr(name, (guint32*)ip_addr)) { *ip_addr = 0; } SET_ADDRESS(addr, AT_IPv4, 4, ip_addr); pushAddress(L,addr); WSLUA_RETURN(1); /* The Address object */ }
WSLUA_METHOD TvbRange_ether(lua_State* L) { /* Get an Ethernet Address from a TvbRange. */ TvbRange tvbr = checkTvbRange(L,1); Address addr; guint8* buff; if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } if (tvbr->len != 6) WSLUA_ERROR(TvbRange_ether,"The range must be 6 bytes long"); addr = g_new(address,1); buff = (guint8 *)tvb_memdup(NULL,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len); SET_ADDRESS(addr, AT_ETHER, 6, buff); pushAddress(L,addr); WSLUA_RETURN(1); /* The Ethernet Address */ }
static void dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *tr_tree, *bf_tree; proto_item *ti, *hidden_item; guint8 rcf1, rcf2; tvbuff_t *next_tvb; volatile int frame_type; volatile int fixoffset = 0; volatile int source_routed = 0; volatile guint8 trn_rif_bytes; volatile guint8 actual_rif_bytes; volatile guint8 c1_nonsr; volatile guint8 c2_nonsr; volatile guint16 first2_sr; tvbuff_t *volatile tr_tvb; static tr_hdr trh_arr[4]; static int trh_current=0; tr_hdr *volatile trh; /* non-source-routed version of source addr */ static guint8 trn_shost_nonsr[6]; /* has to be static due to SET_ADDRESS */ int x; /* Token-Ring Strings */ const char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" }; trh_current++; if(trh_current==4){ trh_current=0; } trh=&trh_arr[trh_current]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR"); if (fix_linux_botches) x = check_for_old_linux_tvb((tvbuff_t*) tvb); else x = 0; if (x != 0) { /* Actually packet starts x bytes into what we have got but with all source routing compressed. See comment above */ tr_tvb = tvb_new_subset_remaining((tvbuff_t*) tvb, x); } else { tr_tvb = tvb; } /* Get the data */ trh->fc = tvb_get_guint8(tr_tvb, 1); SET_ADDRESS(&trh->src, AT_ETHER, 6, tvb_get_ptr(tr_tvb, 8, 6)); SET_ADDRESS(&trh->dst, AT_ETHER, 6, tvb_get_ptr(tr_tvb, 2, 6)); /* if the high bit on the first byte of src hwaddr is 1, then this packet is source-routed */ memcpy(trn_shost_nonsr, trh->src.data, 6); source_routed = trn_shost_nonsr[0] & 128; trn_shost_nonsr[0] &= 127; frame_type = (trh->fc & 192) >> 6; if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Token-Ring %s", fc[frame_type]); trn_rif_bytes = tvb_get_guint8(tr_tvb, 14) & 31; if (fix_linux_botches) { /* the Linux 2.0 TR code strips source-route bits in * order to test for SR. This can be removed from most * packets with oltr, but not all. So, I try to figure out * which packets should have been SR here. I'll check to * see if there's a SNAP or IPX field right after * my RIF fields. * * The Linux 2.4.18 code, at least appears to do the * same thing, from a capture I got from somebody running * 2.4.18 (RH 7.1, so perhaps this is a Red Hat * "improvement"). */ if (frame_type == 1 && !source_routed && trn_rif_bytes > 0) { TRY { c1_nonsr = tvb_get_guint8(tr_tvb, 14); c2_nonsr = tvb_get_guint8(tr_tvb, 15); if (c1_nonsr != c2_nonsr) { first2_sr = tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e); if ( ( first2_sr == 0xaaaa && tvb_get_guint8(tr_tvb, trn_rif_bytes + 0x10) == 0x03) || first2_sr == 0xe0e0 || first2_sr == 0xe0aa ) { source_routed = 1; } } } CATCH(BoundsError) { /* We had no information beyond the TR header. Just assume * this is a normal (non-Linux) TR header. */ ; } ENDTRY; } }
static void dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *netrom_tree; int offset; const guint8 *src_addr; const guint8 *dst_addr; const guint8 *user_addr; const guint8 *node_addr; #if 0 guint8 src_ssid; guint8 dst_ssid; #endif guint8 op_code; guint8 cct_index; guint8 cct_id; void *saved_private_data; tvbuff_t *next_tvb = NULL; col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM" ); col_clear( pinfo->cinfo, COL_INFO ); offset = 0; /* source */ src_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); SET_ADDRESS(&pinfo->dl_src, AT_AX25, AX25_ADDR_LEN, src_addr); SET_ADDRESS(&pinfo->src, AT_AX25, AX25_ADDR_LEN, src_addr); /* src_ssid = *(src_addr + 6); */ offset += AX25_ADDR_LEN; /* step over src addr */ /* destination */ dst_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); SET_ADDRESS(&pinfo->dl_dst, AT_AX25, AX25_ADDR_LEN, dst_addr); SET_ADDRESS(&pinfo->dst, AT_AX25, AX25_ADDR_LEN, dst_addr); /* dst_ssid = *(dst_addr + 6); */ offset += AX25_ADDR_LEN; /* step over dst addr */ offset += 1; /* step over ttl */ cct_index = tvb_get_guint8( tvb, offset ); offset += 1; /* step over cct index*/ cct_id = tvb_get_guint8( tvb, offset ); offset += 1; /* step over cct id */ offset += 1; /* step over n_s */ offset += 1; /* step over n_r */ /* frame type */ op_code = tvb_get_guint8( tvb, offset ) & 0x0f; offset += 1; /* step over op_code */ col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str_const( op_code, op_code_vals_text, "Unknown" )); if ( tree ) { /* create display subtree for the protocol */ ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE, "NET/ROM, Src: %s (%s), Dst: %s (%s)", get_ax25_name( src_addr ), ax25_to_str( src_addr ), get_ax25_name( dst_addr ), ax25_to_str( dst_addr ) ); netrom_tree = proto_item_add_subtree( ti, ett_netrom ); offset = 0; /* source */ proto_tree_add_ax25( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, src_addr ); offset += AX25_ADDR_LEN; /* destination */ proto_tree_add_ax25( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, dst_addr ); offset += AX25_ADDR_LEN; /* ttl */ proto_tree_add_item( netrom_tree, hf_netrom_ttl, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; switch ( op_code ) { case NETROM_PROTOEXT : /* cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_CONNREQ : /* cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_CONNACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* my cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* my cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_DISCREQ : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_DISCACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_INFO : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* n_s */ proto_tree_add_item( netrom_tree, hf_netrom_n_s, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* n_r */ proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_INFOACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* n_r */ proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; default : offset += 1; offset += 1; offset += 1; offset += 1; break; } /* type */ dissect_netrom_type( tvb, offset, pinfo, netrom_tree, hf_netrom_type, ett_netrom_type, &netrom_type_items ); offset += 1; switch ( op_code ) { case NETROM_PROTOEXT : break; case NETROM_CONNREQ : /* proposed window size */ proto_tree_add_item( netrom_tree, hf_netrom_pwindow, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; user_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); proto_tree_add_ax25( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, user_addr ); offset += AX25_ADDR_LEN; node_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); proto_tree_add_ax25( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, node_addr ); offset += AX25_ADDR_LEN; break; case NETROM_CONNACK : /* accepted window size */ proto_tree_add_item( netrom_tree, hf_netrom_awindow, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_DISCREQ : break; case NETROM_DISCACK : break; case NETROM_INFO : break; case NETROM_INFOACK : break; default : break; } } /* Call sub-dissectors here */ saved_private_data = pinfo->private_data; next_tvb = tvb_new_subset_remaining(tvb, offset); switch ( op_code ) { case NETROM_PROTOEXT : if ( cct_index == NETROM_PROTO_IP && cct_id == NETROM_PROTO_IP ) call_dissector( ip_handle , next_tvb, pinfo, tree ); else call_dissector( default_handle , next_tvb, pinfo, tree ); break; case NETROM_INFO : default : call_dissector( default_handle , next_tvb, pinfo, tree ); break; } pinfo->private_data = saved_private_data; }
static void dissect_fddi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean bitswapped) { proto_tree *fh_tree = NULL; proto_item *ti, *hidden_item; const gchar *fc_str; proto_tree *fc_tree; static guchar src[6], dst[6]; guchar src_swapped[6], dst_swapped[6]; tvbuff_t *next_tvb; static fddi_hdr fddihdrs[4]; static int fddihdr_num = 0; fddi_hdr *fddihdr; fddihdr_num++; if (fddihdr_num >= 4) { fddihdr_num = 0; } fddihdr = &fddihdrs[fddihdr_num]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FDDI"); fddihdr->fc = tvb_get_guint8(tvb, FDDI_P_FC + FDDI_PADDING); fc_str = fddifc_to_str(fddihdr->fc); col_add_str(pinfo->cinfo, COL_INFO, fc_str); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_fddi, tvb, 0, FDDI_HEADER_SIZE+FDDI_PADDING, "Fiber Distributed Data Interface, %s", fc_str); fh_tree = proto_item_add_subtree(ti, ett_fddi); ti = proto_tree_add_uint_format(fh_tree, hf_fddi_fc, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc, "Frame Control: 0x%02x (%s)", fddihdr->fc, fc_str); fc_tree = proto_item_add_subtree(ti, ett_fddi_fc); proto_tree_add_uint(fc_tree, hf_fddi_fc_clf, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); switch ((fddihdr->fc) & FDDI_FC_CLFF) { case FDDI_FC_SMT: proto_tree_add_uint(fc_tree, hf_fddi_fc_smt_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; case FDDI_FC_MAC: if (fddihdr->fc != FDDI_FC_RT) proto_tree_add_uint(fc_tree, hf_fddi_fc_mac_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; case FDDI_FC_LLC_ASYNC: if (!((fddihdr->fc) & FDDI_FC_ASYNC_R)) proto_tree_add_uint(fc_tree, hf_fddi_fc_prio, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; } } /* Extract the destination address, possibly bit-swapping it. */ if (bitswapped) swap_mac_addr(dst, tvb, FDDI_P_DHOST + FDDI_PADDING); else tvb_memcpy(tvb, dst, FDDI_P_DHOST + FDDI_PADDING, sizeof(dst)); swap_mac_addr(dst_swapped, tvb, FDDI_P_DHOST + FDDI_PADDING); /* XXX - copy them to some buffer associated with "pi", rather than just making "dst" static? */ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, &dst[0]); SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, &dst[0]); SET_ADDRESS(&fddihdr->dst, AT_ETHER, 6, &dst[0]); if (fh_tree) { proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst); PROTO_ITEM_SET_HIDDEN(hidden_item); /* hide some bit-swapped mac address fields in the proto_tree, just in case */ hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* Extract the source address, possibly bit-swapping it. */ if (bitswapped) swap_mac_addr(src, tvb, FDDI_P_SHOST + FDDI_PADDING); else tvb_memcpy(tvb, src, FDDI_P_SHOST + FDDI_PADDING, sizeof(src)); swap_mac_addr(src_swapped, tvb, FDDI_P_SHOST + FDDI_PADDING); /* XXX - copy them to some buffer associated with "pi", rather than just making "src" static? */ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, &src[0]); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, &src[0]); SET_ADDRESS(&fddihdr->src, AT_ETHER, 6, &src[0]); if (fh_tree) { proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src); PROTO_ITEM_SET_HIDDEN(hidden_item); /* hide some bit-swapped mac address fields in the proto_tree, just in case */ hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); } next_tvb = tvb_new_subset_remaining(tvb, FDDI_HEADER_SIZE + FDDI_PADDING); tap_queue_packet(fddi_tap, pinfo, fddihdr); switch (fddihdr->fc) { /* From now, only 802.2 SNAP (Async. LCC frame) is supported */ case FDDI_FC_LLC_ASYNC + 0 : case FDDI_FC_LLC_ASYNC + 1 : case FDDI_FC_LLC_ASYNC + 2 : case FDDI_FC_LLC_ASYNC + 3 : case FDDI_FC_LLC_ASYNC + 4 : case FDDI_FC_LLC_ASYNC + 5 : case FDDI_FC_LLC_ASYNC + 6 : case FDDI_FC_LLC_ASYNC + 7 : case FDDI_FC_LLC_ASYNC + 8 : case FDDI_FC_LLC_ASYNC + 9 : case FDDI_FC_LLC_ASYNC + 10 : case FDDI_FC_LLC_ASYNC + 11 : case FDDI_FC_LLC_ASYNC + 12 : case FDDI_FC_LLC_ASYNC + 13 : case FDDI_FC_LLC_ASYNC + 14 : case FDDI_FC_LLC_ASYNC + 15 : call_dissector(llc_handle, next_tvb, pinfo, tree); return; default : call_dissector(data_handle,next_tvb, pinfo, tree); return; } /* fc */ } /* dissect_fddi */
void add_hostlist_table_data(conv_hash_t *ch, const address *addr, guint32 port, gboolean sender, int num_frames, int num_bytes, hostlist_dissector_info_t *host_info, port_type port_type_val) { hostlist_talker_t *talker=NULL; int talker_idx=0; /* XXX should be optimized to allocate n extra entries at a time instead of just one */ /* if we dont have any entries at all yet */ if(ch->conv_array==NULL){ ch->conv_array=g_array_sized_new(FALSE, FALSE, sizeof(hostlist_talker_t), 10000); ch->hashtable = g_hash_table_new_full(host_hash, host_match, /* key_equal_func */ g_free, /* key_destroy_func */ NULL); /* value_destroy_func */ } else { /* try to find it among the existing known conversations */ host_key_t existing_key; existing_key.myaddress = *addr; existing_key.port = port; if (g_hash_table_lookup_extended(ch->hashtable, &existing_key, NULL, (gpointer *) &talker_idx)) { talker = &g_array_index(ch->conv_array, hostlist_talker_t, talker_idx); } } /* if we still dont know what talker this is it has to be a new one and we have to allocate it and append it to the end of the list */ if(talker==NULL){ host_key_t *new_key; hostlist_talker_t host; COPY_ADDRESS(&host.myaddress, addr); host.dissector_info = host_info; host.ptype=port_type_val; host.port=port; host.rx_frames=0; host.tx_frames=0; host.rx_bytes=0; host.tx_bytes=0; host.modified = TRUE; g_array_append_val(ch->conv_array, host); talker_idx= ch->conv_array->len - 1; talker=&g_array_index(ch->conv_array, hostlist_talker_t, talker_idx); /* hl->hosts address is not a constant but address.data is */ new_key = g_new(host_key_t,1); SET_ADDRESS(&new_key->myaddress, talker->myaddress.type, talker->myaddress.len, talker->myaddress.data); new_key->port = port; g_hash_table_insert(ch->hashtable, new_key, GUINT_TO_POINTER(talker_idx)); } /* if this is a new talker we need to initialize the struct */ talker->modified = TRUE; /* update the talker struct */ if( sender ){ talker->tx_frames+=num_frames; talker->tx_bytes+=num_bytes; } else { talker->rx_frames+=num_frames; talker->rx_bytes+=num_bytes; } }
void add_conversation_table_data_with_conv_id( conv_hash_t *ch, const address *src, const address *dst, guint32 src_port, guint32 dst_port, conv_id_t conv_id, int num_frames, int num_bytes, nstime_t *ts, nstime_t *abs_ts, ct_dissector_info_t *ct_info, port_type ptype) { const address *addr1, *addr2; guint32 port1, port2; conv_item_t *conv_item = NULL; unsigned int conversation_idx = 0; if (src_port > dst_port) { addr1 = src; addr2 = dst; port1 = src_port; port2 = dst_port; } else if (src_port < dst_port) { addr2 = src; addr1 = dst; port2 = src_port; port1 = dst_port; } else if (CMP_ADDRESS(src, dst) < 0) { addr1 = src; addr2 = dst; port1 = src_port; port2 = dst_port; } else { addr2 = src; addr1 = dst; port2 = src_port; port1 = dst_port; } /* if we dont have any entries at all yet */ if (ch->conv_array == NULL) { ch->conv_array = g_array_sized_new(FALSE, FALSE, sizeof(conv_item_t), 10000); ch->hashtable = g_hash_table_new_full(conversation_hash, conversation_equal, /* key_equal_func */ g_free, /* key_destroy_func */ NULL); /* value_destroy_func */ } else { /* try to find it among the existing known conversations */ conv_key_t existing_key; existing_key.addr1 = *addr1; existing_key.addr2 = *addr2; existing_key.port1 = port1; existing_key.port2 = port2; existing_key.conv_id = conv_id; if (g_hash_table_lookup_extended(ch->hashtable, &existing_key, NULL, (gpointer *) &conversation_idx)) { conv_item = &g_array_index(ch->conv_array, conv_item_t, conversation_idx); } } /* if we still dont know what conversation this is it has to be a new one and we have to allocate it and append it to the end of the list */ if (conv_item == NULL) { conv_key_t *new_key; conv_item_t new_conv_item; COPY_ADDRESS(&new_conv_item.src_address, addr1); COPY_ADDRESS(&new_conv_item.dst_address, addr2); new_conv_item.dissector_info = ct_info; new_conv_item.ptype = ptype; new_conv_item.src_port = port1; new_conv_item.dst_port = port2; new_conv_item.conv_id = conv_id; new_conv_item.rx_frames = 0; new_conv_item.tx_frames = 0; new_conv_item.rx_bytes = 0; new_conv_item.tx_bytes = 0; new_conv_item.modified = TRUE; if (ts) { memcpy(&new_conv_item.start_time, ts, sizeof(new_conv_item.start_time)); memcpy(&new_conv_item.stop_time, ts, sizeof(new_conv_item.stop_time)); memcpy(&new_conv_item.start_abs_time, abs_ts, sizeof(new_conv_item.start_abs_time)); } else { nstime_set_unset(&new_conv_item.start_abs_time); nstime_set_unset(&new_conv_item.start_time); nstime_set_unset(&new_conv_item.stop_time); } g_array_append_val(ch->conv_array, new_conv_item); conversation_idx = ch->conv_array->len - 1; conv_item = &g_array_index(ch->conv_array, conv_item_t, conversation_idx); /* ct->conversations address is not a constant but src/dst_address.data are */ new_key = g_new(conv_key_t, 1); SET_ADDRESS(&new_key->addr1, conv_item->src_address.type, conv_item->src_address.len, conv_item->src_address.data); SET_ADDRESS(&new_key->addr2, conv_item->dst_address.type, conv_item->dst_address.len, conv_item->dst_address.data); new_key->port1 = port1; new_key->port2 = port2; new_key->conv_id = conv_id; g_hash_table_insert(ch->hashtable, new_key, GUINT_TO_POINTER(conversation_idx)); } /* update the conversation struct */ conv_item->modified = TRUE; if ( (!CMP_ADDRESS(src, addr1)) && (!CMP_ADDRESS(dst, addr2)) && (src_port==port1) && (dst_port==port2) ) { conv_item->tx_frames += num_frames; conv_item->tx_bytes += num_bytes; } else { conv_item->rx_frames += num_frames; conv_item->rx_bytes += num_bytes; } if (ts) { if (nstime_cmp(ts, &conv_item->stop_time) > 0) { memcpy(&conv_item->stop_time, ts, sizeof(conv_item->stop_time)); } else if (nstime_cmp(ts, &conv_item->start_time) < 0) { memcpy(&conv_item->start_time, ts, sizeof(conv_item->start_time)); memcpy(&conv_item->start_abs_time, abs_ts, sizeof(conv_item->start_abs_time)); } } }
static void dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *ftp_tree = NULL; proto_tree *reqresp_tree = NULL; proto_item *ti, *hidden_item; gint offset = 0; const guchar *line; guint32 code; gchar code_str[4]; gboolean is_port_request = FALSE; gboolean is_pasv_response = FALSE; gboolean is_epasv_response = FALSE; gint next_offset; int linelen; int tokenlen; const guchar *next_token; guint32 pasv_ip; guint32 ftp_ip; guint16 ftp_port; address ftp_ip_address; gboolean ftp_nat; conversation_t *conversation; ftp_ip_address = pinfo->src; if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTP"); /* * Find the end of the first line. * * Note that "tvb_find_line_end()" will return a value that is * not longer than what's in the buffer, so the "tvb_get_ptr()" * call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); if (tree) { ti = proto_tree_add_item(tree, proto_ftp, tvb, offset, -1, ENC_NA); ftp_tree = proto_item_add_subtree(ti, ett_ftp); if (is_request) { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); } else { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* * Put the line into the protocol tree. */ ti = proto_tree_add_text(ftp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp); } if (is_request) { /* * Extract the first token, and, if there is a first * token, add it as the request. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { if (tree) { proto_tree_add_item(reqresp_tree, hf_ftp_request_command, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); } if (strncmp(line, "PORT", tokenlen) == 0) is_port_request = TRUE; } } else { /* * This is a response; the response code is 3 digits, * followed by a space or hyphen, possibly followed by * text. * * If the line doesn't start with 3 digits, it's part of * a continuation. * * XXX - keep track of state in the first pass, and * treat non-continuation lines not beginning with digits * as errors? */ if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) { /* * One-line reply, or first or last line * of a multi-line reply. */ tvb_get_nstringz0(tvb, offset, sizeof(code_str), code_str); code = strtoul(code_str, NULL, 10); if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_response_code, tvb, offset, 3, code); } /* * See if it's a passive-mode response. * * XXX - does anybody do FOOBAR, as per RFC * 1639, or has that been supplanted by RFC 2428? */ if (code == 227) is_pasv_response = TRUE; /* * Responses to EPSV command, as per RFC 2428 * XXX - handle IPv6? */ if (code == 229) is_epasv_response = TRUE; /* * Skip the 3 digits and, if present, the * space or hyphen. */ if (linelen >= 4) next_token = line + 4; else next_token = line + linelen; } else { /* * Line doesn't start with 3 digits; assume it's * a line in the middle of a multi-line reply. */ next_token = line; } } offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; if (tree) { /* * Add the rest of the first line as request or * reply data. */ if (linelen != 0) { if (is_request) { proto_tree_add_item(reqresp_tree, hf_ftp_request_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } else { proto_tree_add_item(reqresp_tree, hf_ftp_response_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; } /* * If this is a PORT request or a PASV response, handle it. */ if (is_port_request) { if (parse_port_pasv(line, linelen, &ftp_ip, &ftp_port)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_active_ip, tvb, 0, 0, ftp_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_active_port, tvb, 0, 0, ftp_port); } SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&ftp_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { if (tree) { proto_tree_add_boolean( reqresp_tree, hf_ftp_active_nat, tvb, 0, 0, ftp_nat); } } } } if (is_pasv_response) { if (linelen != 0) { /* * This frame contains a PASV response; set up a * conversation for the data. */ if (parse_port_pasv(line, linelen, &pasv_ip, &ftp_port)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_pasv_ip, tvb, 0, 0, pasv_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, ftp_port); } SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&pasv_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { if (tree) { proto_tree_add_boolean(reqresp_tree, hf_ftp_pasv_nat, tvb, 0, 0, ftp_nat); } } /* * We use "ftp_ip_address", so that if * we're NAT'd we look for the un-NAT'd * connection. * * XXX - should this call to * "find_conversation()" just use * "ftp_ip_address" and "server_port", and * wildcard everything else? */ conversation = find_conversation(pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { /* * XXX - should this call to "conversation_new()" * just use "ftp_ip_address" and "server_port", * and wildcard everything else? * * XXX - what if we did find a conversation? As * we create it only on the first pass through the * packets, if we find one, it's presumably an * unrelated conversation. Should we remove the * old one from the hash table and put this one in * its place? Can the conversation code handle * conversations not in the hash table? Or should * we make conversations support start and end * frames, as circuits do, and treat this as an * indication that one conversation was closed and * a new one was opened? */ conversation = conversation_new( pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (is_epasv_response) { if (linelen != 0) { /* * This frame contains an EPSV response; set up a * conversation for the data. */ if (parse_extended_pasv_response(line, linelen, &ftp_port)) { /* Add port number to tree */ if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, ftp_port); } /* Find/create conversation for data */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (tree) { /* * Show the rest of the request or response as text, * a line at a time. * XXX - only if there's a continuation indicator? */ while (tvb_offset_exists(tvb, offset)) { /* * Find the end of the line. */ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* * Put this line. */ proto_tree_add_text(ftp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } }
static void dissect_bat_batman_v5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct batman_packet_v5 *batman_packeth; const guint8 *old_orig_addr, *orig_addr; guint32 old_orig, orig; gint i; tvbuff_t *next_tvb; guint length_remaining; int offset = 0; batman_packeth = ep_alloc(sizeof(struct batman_packet_v5)); batman_packeth->version = tvb_get_guint8(tvb, 0); batman_packeth->flags = tvb_get_guint8(tvb, 1); batman_packeth->ttl = tvb_get_guint8(tvb, 2); batman_packeth->gwflags = tvb_get_guint8(tvb, 3); batman_packeth->seqno = tvb_get_ntohs(tvb, 4); batman_packeth->gwport = tvb_get_ntohs(tvb, 6); orig_addr = tvb_get_ptr(tvb, 8, 4); orig = tvb_get_ipv4(tvb, 8); SET_ADDRESS(&batman_packeth->orig, AT_IPv4, 4, orig_addr); old_orig_addr = tvb_get_ptr(tvb, 12, 4); old_orig = tvb_get_ipv4(tvb, 12); SET_ADDRESS(&batman_packeth->old_orig, AT_IPv4, 4, old_orig_addr); batman_packeth->tq = tvb_get_guint8(tvb, 16); batman_packeth->hna_len = tvb_get_guint8(tvb, 17); /* Set info column */ if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Seq=%u", batman_packeth->seqno); /* Set tree info */ if (tree) { proto_item *ti = NULL, *tf, *tgw; proto_tree *bat_batman_tree = NULL, *flag_tree = NULL; if (PTREE_DATA(tree)->visible) { ti = proto_tree_add_protocol_format(tree, proto_bat_plugin, tvb, 0, BATMAN_PACKET_V5_SIZE, "B.A.T.M.A.N., Orig: %s (%s)", get_hostname(orig), ip_to_str(batman_packeth->orig.data)); } else { ti = proto_tree_add_item(tree, proto_bat_plugin, tvb, 0, BATMAN_PACKET_V5_SIZE, FALSE); } bat_batman_tree = proto_item_add_subtree(ti, ett_bat_batman); /* items */ proto_tree_add_item(bat_batman_tree, hf_bat_batman_version, tvb, offset, 1, FALSE); offset += 1; tf = proto_tree_add_item(bat_batman_tree, hf_bat_batman_flags, tvb, offset, 1, FALSE); /* <flags> */ flag_tree = proto_item_add_subtree(tf, ett_bat_batman_flags); proto_tree_add_boolean(flag_tree, hf_bat_batman_flags_unidirectional, tvb, offset, 1, batman_packeth->flags); proto_tree_add_boolean(flag_tree, hf_bat_batman_flags_directlink, tvb, offset, 1, batman_packeth->flags); /* </flags> */ offset += 1; proto_tree_add_item(bat_batman_tree, hf_bat_batman_ttl, tvb, offset, 1, FALSE); offset += 1; tgw = proto_tree_add_item(bat_batman_tree, hf_bat_batman_gwflags, tvb, offset, 1, FALSE); dissect_bat_gwflags(tvb, batman_packeth->gwflags, offset, tgw); offset += 1; proto_tree_add_item(bat_batman_tree, hf_bat_batman_seqno, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(bat_batman_tree, hf_bat_batman_gwport, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_ipv4(bat_batman_tree, hf_bat_batman_orig, tvb, offset, 4, orig); offset += 4; proto_tree_add_ipv4(bat_batman_tree, hf_bat_batman_old_orig, tvb, offset, 4, old_orig); offset += 4; proto_tree_add_item(bat_batman_tree, hf_bat_batman_tq, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(bat_batman_tree, hf_bat_batman_hna_len, tvb, offset, 1, FALSE); offset += 1; tap_queue_packet(bat_tap, pinfo, batman_packeth); for (i = 0; i < batman_packeth->hna_len; i++) { next_tvb = tvb_new_subset(tvb, offset, 5, 5); if (have_tap_listener(bat_follow_tap)) { tap_queue_packet(bat_follow_tap, pinfo, next_tvb); } dissect_bat_hna(next_tvb, pinfo, bat_batman_tree); offset += 5; } } length_remaining = tvb_reported_length_remaining(tvb, offset); if (length_remaining != 0) { next_tvb = tvb_new_subset_remaining(tvb, offset); if (have_tap_listener(bat_follow_tap)) { tap_queue_packet(bat_follow_tap, pinfo, next_tvb); } dissect_bat_batman(next_tvb, pinfo, tree); } }
static int dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const char *opcode_str; proto_tree *slimp3_tree = NULL; proto_item *ti = NULL, *hidden_item; gint i1; gint offset = 0; guint16 opcode; guchar lcd_char; char lcd_str[MAX_LCD_STR_LEN + 1]; int to_server = FALSE; int old_protocol = FALSE; address tmp_addr; gboolean in_str; int lcd_strlen; /* * If it doesn't begin with a known opcode, reject it, so that * traffic that happens to be do or from one of our ports * doesn't get misidentified as SliMP3 traffic. */ if (!tvb_bytes_exist(tvb, offset, 1)) return 0; /* not even an opcode */ opcode = tvb_get_guint8(tvb, offset); opcode_str = match_strval(opcode, slimp3_opcode_vals); if (opcode_str == NULL) return 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SliMP3"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, opcode_str); } if (tree) { ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, ENC_NA); slimp3_tree = proto_item_add_subtree(ti, ett_slimp3); proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb, offset, 1, opcode); } /* The new protocol (v1.3 and later) uses an IANA-assigned port number. * It usually uses the same number for both sizes of the conversation, so * the port numbers can't always be used to determine client and server. * The new protocol places the clients MAC address in the packet, so that * is used to identify packets originating at the client. */ if ((pinfo->destport == UDP_PORT_SLIMP3_V2) && (pinfo->srcport == UDP_PORT_SLIMP3_V2)) { SET_ADDRESS(&tmp_addr, AT_ETHER, 6, tvb_get_ptr(tvb, offset+12, 6)); to_server = ADDRESSES_EQUAL(&tmp_addr, &pinfo->dl_src); } else if (pinfo->destport == UDP_PORT_SLIMP3_V2) { to_server = TRUE; } else if (pinfo->srcport == UDP_PORT_SLIMP3_V2) { to_server = FALSE; } if (pinfo->destport == UDP_PORT_SLIMP3_V1) { to_server = TRUE; old_protocol = TRUE; } else if (pinfo->srcport == UDP_PORT_SLIMP3_V1) { to_server = FALSE; old_protocol = TRUE; } switch (opcode) { case SLIMP3_IR: /* IR code * * [0] 'i' as in "IR" * [1] 0x00 * [2..5] player's time since startup in ticks @625 KHz * [6] IR code id, ff=JVC, 02=SLIMP3 * [7] number of meaningful bits - 16 for JVC, 32 for SLIMP3 * [8..11] the 32-bit IR code * [12..17] reserved */ if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); i1 = tvb_get_ntohl(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)", i1/625000, i1); i1 = tvb_get_guint8(tvb, offset+6); proto_tree_add_text(slimp3_tree, tvb, offset+6, 1, "Code identifier: 0x%0x: %s", i1, val_to_str(i1, slimp3_ir_types, "Unknown")); proto_tree_add_text(slimp3_tree, tvb, offset+7, 1, "Code bits: %d", tvb_get_guint8(tvb, offset+7)); i1 = tvb_get_ntohl(tvb, offset+8); /* Check the code to figure out which remote is being used. */ if (tvb_get_guint8(tvb, offset+6) == 0x02 && tvb_get_guint8(tvb, offset+7) == 32) { /* This is the custom SLIMP3 remote. */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: %s: 0x%0x", val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown"), i1); } else if (tvb_get_guint8(tvb, offset+6) == 0xff && tvb_get_guint8(tvb, offset+7) == 16) { /* This is a JVC DVD player remote */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: %s: 0x%0x", val_to_str(i1, slimp3_ir_codes_jvc, "Unknown"), i1); } else { /* Unknown code; just write it */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: 0x%0x", i1); } } if (check_col(pinfo->cinfo, COL_INFO)) { i1 = tvb_get_ntohl(tvb, offset+8); if (tvb_get_guint8(tvb, offset+6) == 0x02 && tvb_get_guint8(tvb, offset+7) == 32) { col_append_fstr(pinfo->cinfo, COL_INFO, ", SLIMP3: %s", val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown (0x%0x)")); } else if (tvb_get_guint8(tvb, offset+6) == 0xff && tvb_get_guint8(tvb, offset+7) == 16) { col_append_fstr(pinfo->cinfo, COL_INFO, ", JVC: %s", val_to_str(i1, slimp3_ir_codes_jvc, "Unknown (0x%0x)")); } else { /* Unknown code; just write it */ col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%0x", i1); } } break; case SLIMP3_DISPLAY: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_display, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); /* Loop through the commands */ i1 = 18; in_str = FALSE; lcd_strlen = 0; while (i1 < tvb_reported_length_remaining(tvb, offset)) { switch(tvb_get_guint8(tvb, offset + i1)) { case 0: in_str = FALSE; lcd_strlen = 0; proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1)); i1 += 2; break; case 3: lcd_char = tvb_get_guint8(tvb, offset + i1 + 1); if (!isprint(lcd_char)) lcd_char = '.'; if (ti && in_str) { lcd_strlen += 2; proto_item_append_text(ti, "%c", lcd_char); proto_item_set_len(ti, lcd_strlen); } else { ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "String: %c", lcd_char); in_str = TRUE; lcd_strlen = 2; } i1 += 2; break; case 2: in_str = FALSE; lcd_strlen = 0; ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset + i1 + 1), slimp3_display_commands, "Unknown (0x%0x)")); if ((tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) { proto_item_append_text(ti, ": %s", val_to_str(tvb_get_guint8(tvb, offset + i1 + 2), slimp3_display_fset8, "Unknown (0x%0x)")); i1 += 2; } i1 += 2; break; default: proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Unknown 0x%0x, 0x%0x", tvb_get_guint8(tvb, offset + i1), tvb_get_guint8(tvb, offset + i1 + 1)); i1 += 2; break; } } } if (check_col(pinfo->cinfo, COL_INFO)) { i1 = 18; lcd_strlen = 0; while (tvb_offset_exists(tvb, offset + i1) && lcd_strlen < MAX_LCD_STR_LEN) { switch (tvb_get_guint8(tvb, offset + i1)) { case 0: lcd_str[lcd_strlen++] = '.'; break; case 2: lcd_str[lcd_strlen++] = '|'; if (tvb_offset_exists(tvb, offset + i1 + 1) && (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) i1 += 2; break; case 3: if (tvb_offset_exists(tvb, offset + i1 + 1)) { if (lcd_strlen < 1 || lcd_str[lcd_strlen-1] != ' ' || tvb_get_guint8(tvb, offset + i1 + 1) != ' ') { lcd_char = tvb_get_guint8(tvb, offset + i1 + 1); lcd_str[lcd_strlen++] = isprint(lcd_char) ? lcd_char : '.'; } } } i1 += 2; } lcd_str[lcd_strlen] = '\0'; if (lcd_strlen > 0) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", lcd_str); } break; case SLIMP3_CONTROL: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_control, tvb, offset+1, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_stream_control, "Unknown (0x%0x)")); } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_stream_control, "Unknown (0x%0x)")); } break; case SLIMP3_HELLO: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_hello, tvb, offset+1, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (to_server) { guint8 fw_ver = 0; /* Hello response; client->server */ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Response (Client --> Server)"); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d", tvb_get_guint8(tvb, offset+1)); fw_ver = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)", fw_ver>>4, fw_ver & 0xf, fw_ver); } else { /* Hello request; server->client */ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Request (Server --> Client)"); } } break; case SLIMP3_I2C: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_i2c, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (to_server) { /* Hello response; client->server */ proto_tree_add_text(slimp3_tree, tvb, offset, -1, "I2C Response (Client --> Server)"); } else { /* Hello request; server->client */ proto_tree_add_text(slimp3_tree, tvb, offset, -1, "I2C Request (Server --> Client)"); } } if (check_col(pinfo->cinfo, COL_INFO)) { if (to_server) { col_append_str(pinfo->cinfo, COL_INFO, ", Response"); } else { col_append_str(pinfo->cinfo, COL_INFO, ", Request"); } } break; case SLIMP3_DATA_REQ: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_request, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+2, 2, "Requested offset: %d bytes.", tvb_get_ntohs(tvb, offset+2)*2); } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Offset: %d bytes", tvb_get_ntohs(tvb, offset+2)*2); } break; case SLIMP3_DATA: /* MPEG data (v1.3 and later) * * [0] 'm' * [1..5] reserved * [6..7] Write pointer (in words) * [8..9] reserved * [10..11] Sequence number * [12..17] reserved * [18..] MPEG data */ if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (old_protocol) { proto_tree_add_text(slimp3_tree, tvb, offset, -1, "Length: %d bytes", tvb_reported_length_remaining(tvb, offset+18)); proto_tree_add_text(slimp3_tree, tvb, offset+2, 2, "Buffer offset: %d bytes.", tvb_get_ntohs(tvb, offset+2) * 2); } else { proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_mpg_control, "Unknown (0x%0x)")); proto_tree_add_text(slimp3_tree, tvb, offset, -1, "Length: %d bytes", tvb_reported_length_remaining(tvb, offset+18)); proto_tree_add_text(slimp3_tree, tvb, offset+6, 2, "Write Pointer: %d", tvb_get_ntohs(tvb, offset+6) * 2); proto_tree_add_text(slimp3_tree, tvb, offset+10, 2, "Sequence: %d", tvb_get_ntohs(tvb, offset+10)); } } if (check_col(pinfo->cinfo, COL_INFO)) { if (old_protocol) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %d bytes, Offset: %d bytes.", tvb_reported_length_remaining(tvb, offset+18), tvb_get_ntohs(tvb, offset+2) * 2); } else { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, %d bytes at %d, Sequence: %d", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_mpg_control, "Unknown (0x%0x)"), tvb_reported_length_remaining(tvb, offset+18), tvb_get_ntohs(tvb, offset+6) * 2, tvb_get_ntohs(tvb, offset+10)); } } break; case SLIMP3_DISC_REQ: if (tree) { guint8 fw_ver; hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_request, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d.", tvb_get_guint8(tvb, offset+1)); fw_ver = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)", fw_ver>>4, fw_ver & 0xf, fw_ver); } if (check_col(pinfo->cinfo, COL_INFO)) { guint8 fw_ver = tvb_get_guint8(tvb, offset+2); col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d", tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf); }
static void dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; proto_tree *ipx_tree = NULL; proto_item *ti = NULL, *hidden_item; const guint8 *src_net_node, *dst_net_node; guint8 ipx_hops; char *str; guint16 first_socket, second_socket; guint32 ipx_snet, ipx_dnet; static ipxhdr_t ipxh_arr[4]; static int ipx_current=0; ipxhdr_t *ipxh; ipx_current++; if(ipx_current==4){ ipx_current=0; } ipxh=&ipxh_arr[ipx_current]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX"); col_clear(pinfo->cinfo, COL_INFO); /* Calculate here for use in pinfo and in tree */ ipxh->ipx_dsocket = tvb_get_ntohs(tvb, 16); ipxh->ipx_ssocket = tvb_get_ntohs(tvb, 28); ipxh->ipx_type = tvb_get_guint8(tvb, 5); ipxh->ipx_length = tvb_get_ntohs(tvb, 2); pinfo->ptype = PT_IPX; pinfo->srcport = ipxh->ipx_ssocket; pinfo->destport = ipxh->ipx_dsocket; /* Adjust the tvbuff length to include only the IPX datagram. */ set_actual_length(tvb, ipxh->ipx_length); src_net_node = tvb_get_ptr(tvb, 18, 10); dst_net_node = tvb_get_ptr(tvb, 6, 10); SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node); SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node); SET_ADDRESS(&ipxh->ipx_src, AT_IPX, 10, src_net_node); SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node); SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node); SET_ADDRESS(&ipxh->ipx_dst, AT_IPX, 10, dst_net_node); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)", socket_text(ipxh->ipx_dsocket), ipxh->ipx_dsocket); if (tree) { ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, ENC_NA); ipx_tree = proto_item_add_subtree(ti, ett_ipx); } str=ep_address_to_str(&pinfo->net_src); hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_src, tvb, 0, 0, str); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_addr, tvb, 0, 0, str); PROTO_ITEM_SET_HIDDEN(hidden_item); str=ep_address_to_str(&pinfo->net_dst); hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_dst, tvb, 0, 0, str); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_addr, tvb, 0, 0, str); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipxh->ipx_length, "Length: %d bytes", ipxh->ipx_length); ipx_hops = tvb_get_guint8(tvb, 4); proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops, "Transport Control: %d hops", ipx_hops); proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipxh->ipx_type); /* Destination */ ipx_dnet = tvb_get_ntohl(tvb, 6); proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4, ipx_dnet); hidden_item = proto_tree_add_ipxnet(ipx_tree, hf_ipx_net, tvb, 6, 4, ipx_dnet); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_item(ipx_tree, hf_ipx_dnode, tvb, 10, 6, ENC_NA); hidden_item = proto_tree_add_item(ipx_tree, hf_ipx_node, tvb, 10, 6, ENC_NA); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2, ipxh->ipx_dsocket); hidden_item = proto_tree_add_uint(ipx_tree, hf_ipx_socket, tvb, 16, 2, ipxh->ipx_dsocket); PROTO_ITEM_SET_HIDDEN(hidden_item); /* Source */ ipx_snet = tvb_get_ntohl(tvb, 18); proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4, ipx_snet); hidden_item = proto_tree_add_ipxnet(ipx_tree, hf_ipx_net, tvb, 18, 4, ipx_snet); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_item(ipx_tree, hf_ipx_snode, tvb, 22, 6, ENC_NA); hidden_item = proto_tree_add_item(ipx_tree, hf_ipx_node, tvb, 22, 6, ENC_NA); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2, ipxh->ipx_ssocket); hidden_item = proto_tree_add_uint(ipx_tree, hf_ipx_socket, tvb, 28, 2, ipxh->ipx_ssocket); PROTO_ITEM_SET_HIDDEN(hidden_item); /* Make the next tvbuff */ next_tvb = tvb_new_subset_remaining(tvb, IPX_HEADER_LEN); /* * Let the subdissector know what type of IPX packet this is. */ pinfo->ipxptype = ipxh->ipx_type; /* * Check the socket numbers before we check the packet type; * we've seen non-NCP packets with a type of NCP and a * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP * packets with a type of NCP and a destination socket of * IPX_SOCKET_SAP. * * We've seen NCP packets with a type of NCP, a source socket of * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE, * and we've seen NCP packets with a type of NCP, a source socket of * IPX_SOCKET_IPX_MESSAGE, and a destination socket of * IPX_SOCKET_NCP, so testing the destination socket first doesn't * always give the right answer. We've also seen SAP packets with * a source socket of IPX_SOCKET_SAP and a destination socket of * IPX_SOCKET_IPX_MESSAGE. * * Unfortunately, we've also seen packets with a source socket * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets, * not SMB packets, so testing the lower-valued socket first * also doesn't always give the right answer. * * So we start out assuming we should test the lower-numbered * socket number first, but, if the higher-numbered socket is * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a * NMPI query, and test only that socket. */ if (ipxh->ipx_ssocket > ipxh->ipx_dsocket) { first_socket = ipxh->ipx_dsocket; second_socket = ipxh->ipx_ssocket; } else { first_socket = ipxh->ipx_ssocket; second_socket = ipxh->ipx_dsocket; } tap_queue_packet(ipx_tap, pinfo, ipxh); if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) { if (dissector_try_uint(ipx_socket_dissector_table, first_socket, next_tvb, pinfo, tree)) return; } if (dissector_try_uint(ipx_socket_dissector_table, second_socket, next_tvb, pinfo, tree)) return; /* * Neither of them are known; try the packet type, which will * at least let us, for example, dissect SPX packets as SPX. */ if (dissector_try_uint(ipx_type_dissector_table, ipxh->ipx_type, next_tvb, pinfo, tree)) return; call_dissector(data_handle,next_tvb, pinfo, tree); }
/* Set up an T38 conversation */ void t38_add_address(packet_info *pinfo, address *addr, int port, int other_port, const gchar *setup_method, guint32 setup_frame_number) { address null_addr; conversation_t* p_conversation; t38_conv* p_conversation_data = NULL; /* * If this isn't the first time this packet has been processed, * we've already done this work, so we don't need to do it * again. */ if ((pinfo->fd->flags.visited) || (t38_udp_handle == NULL)) { return; } SET_ADDRESS(&null_addr, AT_NONE, 0, NULL); /* * Check if the ip address and port combination is not * already registered as a conversation. */ p_conversation = find_conversation( setup_frame_number, addr, &null_addr, PT_UDP, port, other_port, NO_ADDR_B | (!other_port ? NO_PORT_B : 0)); /* * If not, create a new conversation. */ if ( !p_conversation || p_conversation->setup_frame != setup_frame_number) { p_conversation = conversation_new( setup_frame_number, addr, &null_addr, PT_UDP, (guint32)port, (guint32)other_port, NO_ADDR2 | (!other_port ? NO_PORT2 : 0)); } /* Set dissector */ conversation_set_dissector(p_conversation, t38_udp_handle); /* * Check if the conversation has data associated with it. */ p_conversation_data = (t38_conv*)conversation_get_proto_data(p_conversation, proto_t38); /* * If not, add a new data item. */ if ( ! p_conversation_data ) { /* Create conversation data */ p_conversation_data = wmem_new(wmem_file_scope(), t38_conv); conversation_add_proto_data(p_conversation, proto_t38, p_conversation_data); } /* * Update the conversation data. */ g_strlcpy(p_conversation_data->setup_method, setup_method, MAX_T38_SETUP_METHOD_SIZE); p_conversation_data->setup_frame_number = setup_frame_number; p_conversation_data->src_t38_info.reass_ID = 0; p_conversation_data->src_t38_info.reass_start_seqnum = -1; p_conversation_data->src_t38_info.reass_data_type = 0; p_conversation_data->src_t38_info.last_seqnum = -1; p_conversation_data->src_t38_info.packet_lost = 0; p_conversation_data->src_t38_info.burst_lost = 0; p_conversation_data->src_t38_info.time_first_t4_data = 0; p_conversation_data->dst_t38_info.reass_ID = 0; p_conversation_data->dst_t38_info.reass_start_seqnum = -1; p_conversation_data->dst_t38_info.reass_data_type = 0; p_conversation_data->dst_t38_info.last_seqnum = -1; p_conversation_data->dst_t38_info.packet_lost = 0; p_conversation_data->dst_t38_info.burst_lost = 0; p_conversation_data->dst_t38_info.time_first_t4_data = 0; }
static int dissect_ppcap_source_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree * ppcap_tree1, int offset) { int key1; guint16 msg_len; msg_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(ppcap_tree1, hf_ppcap_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; key1 = tvb_get_ntohs(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (key1 == 1) { proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(ppcap_tree1, hf_ppcap_spc, tvb, offset, 3, ENC_BIG_ENDIAN); /*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_opc->pc = (guint32 )tvb_get_ntoh24(tvb, offset); mtp3_addr_opc->type = ITU_STANDARD; mtp3_addr_opc->ni = 0; /*SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);*/ SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len-1; return offset; } else if (key1 == 2) { proto_tree_add_item(ppcap_tree1, hf_ppcap_opc, tvb, offset, msg_len, ENC_BIG_ENDIAN); /*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_opc->pc = tvb_get_ntohl(tvb, offset); mtp3_addr_opc->type = ITU_STANDARD; mtp3_addr_opc->ni = 0; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); } else if (key1 == 3) { if (msg_len%16 != 0) { proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_source_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset)); TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv4, tvb, offset, 4); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } else { struct e_in6_addr value; tvb_get_ipv6(tvb, offset, &value); proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_source_ip_address2, tvb, offset, msg_len, &value); TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv6, tvb, offset, 6); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } } else if (key1 == 4) { proto_tree_add_item(ppcap_tree1, hf_ppcap_source_nodeid, tvb, offset, msg_len, ENC_ASCII|ENC_NA); TVB_SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, tvb, offset, msg_len); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len; return offset; }
static void dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto) { proto_tree *udp_tree = NULL; proto_item *ti, *hidden_item, *port_item; guint len; guint reported_len; vec_t cksum_vec[4]; guint32 phdr[2]; guint16 computed_cksum; int offset = 0; e_udphdr *udph; proto_tree *checksum_tree; proto_item *item; conversation_t *conv = NULL; struct udp_analysis *udpd = NULL; proto_tree *process_tree; udph=ep_new(e_udphdr); SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data); SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data); col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite"); col_clear(pinfo->cinfo, COL_INFO); udph->uh_sport=tvb_get_ntohs(tvb, offset); udph->uh_dport=tvb_get_ntohs(tvb, offset+2); col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s", get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport)); if (tree) { if (udp_summary_in_tree) { if (ip_proto == IP_PROTO_UDP) { ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8, "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } else { ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8, "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } } else { ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA); } udp_tree = proto_item_add_subtree(ti, ett_udp); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport, "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport); /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code * further assumes that 3 attempts are made per hop */ if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1 ); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport, "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport); if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1 ); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (ip_proto == IP_PROTO_UDP) { udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (udph->uh_ulen < 8) { /* Bogus length - it includes the header, so it must be >= 8. */ /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen); return; } if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) { /* Bogus length - it goes past the end of the IP payload */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb)); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen); } else { if (tree) { proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen); /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */ hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 0, udph->uh_sum_cov); PROTO_ITEM_SET_HIDDEN(hidden_item); } } } else { udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen; udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) { /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */ if (tree) { hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); } item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))", udph->uh_sum_cov, udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u", udph->uh_sum_cov, udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]", udph->uh_sum_cov, udph->uh_ulen); if (!udplite_ignore_checksum_coverage) return; } else { if (tree) { hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov); } } } udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen; udph->uh_sum = tvb_get_ntohs(tvb, offset+6); reported_len = tvb_reported_length(tvb); len = tvb_length(tvb); if (udph->uh_sum == 0) { /* No checksum supplied in the packet. */ if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (none)", 0); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (Illegal)", 0); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)"); col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]"); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); } } else if (!pinfo->fragmented && len >= reported_len && len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov && udph->uh_sum_cov >=8) { /* The packet isn't part of a fragmented datagram and isn't truncated, so we can checksum it. XXX - make a bigger scatter-gather list once we do fragment reassembly? */ if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) || ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) { /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = (const guint8 *)pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; switch (pinfo->src.type) { case AT_IPv4: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen); else phdr[0] = g_htonl((ip_proto<<16) | reported_len); cksum_vec[2].len = 4; break; case AT_IPv6: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl(udph->uh_ulen); else phdr[0] = g_htonl(reported_len); phdr[1] = g_htonl(ip_proto); cksum_vec[2].len = 8; break; default: /* UDP runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov); cksum_vec[3].len = udph->uh_sum_cov; computed_cksum = in_cksum(&cksum_vec[0], 4); if (computed_cksum == 0) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum, in_cksum_shouldbe(udph->uh_sum, computed_cksum)); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]"); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } /* Skip over header */ offset += 8; pinfo->ptype = PT_UDP; pinfo->srcport = udph->uh_sport; pinfo->destport = udph->uh_dport; tap_queue_packet(udp_tap, pinfo, udph); /* find(or create if needed) the conversation for this udp session */ if (udp_process_info) { conv=find_or_create_conversation(pinfo); udpd=get_udp_conversation_data(conv,pinfo); } if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) { ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information"); PROTO_ITEM_SET_GENERATED(ti); process_tree = proto_item_add_subtree(ti, ett_udp_process_info); if (udpd->fwd && udpd->fwd->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0, udpd->fwd->process_uid, "%u", udpd->fwd->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0, udpd->fwd->process_pid, "%u", udpd->fwd->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0, udpd->fwd->username, "%s", udpd->fwd->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0, udpd->fwd->command, "%s", udpd->fwd->command); } if (udpd->rev->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0, udpd->rev->process_uid, "%u", udpd->rev->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0, udpd->rev->process_pid, "%u", udpd->rev->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0, udpd->rev->username, "%s", udpd->rev->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0, udpd->rev->command, "%s", udpd->rev->command); } } /* * Call sub-dissectors. * * XXX - should we do this if this is included in an error packet? * It might be nice to see the details of the packet that caused the * ICMP error, but it might not be nice to have the dissector update * state based on it. * Also, we probably don't want to run UDP taps on those packets. * * We definitely don't want to do it for an error packet if there's * nothing left in the packet. */ if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0) decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport, udph->uh_ulen); }
static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree; proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL; guint8 cnf_proto_id; guint8 cnf_hdr_len; guint8 cnf_vers; guint8 cnf_ttl; guint8 cnf_type; char flag_string[6+1]; const char *pdu_type_string; proto_tree *type_tree; guint16 segment_length; guint16 du_id = 0; guint16 segment_offset = 0; guint16 total_length; guint16 cnf_cksum; cksum_status_t cksum_status; int offset; guchar src_len, dst_len, nsel, opt_len = 0; const guint8 *dst_addr, *src_addr; guint next_length; proto_tree *discpdu_tree; gboolean save_in_error_pkt; fragment_head *fd_head; tvbuff_t *next_tvb; gboolean update_col_info = TRUE; gboolean save_fragmented; heur_dtbl_entry_t *hdtbl_entry; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP"); col_clear(pinfo->cinfo, COL_INFO); cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID); if (cnf_proto_id == NLPID_NULL) { col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset"); ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id, "Inactive subset"); next_tvb = tvb_new_subset_remaining(tvb, 1); if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0) call_dissector(data_handle,tvb, pinfo, tree); return; } /* return if version not known */ cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS); if (cnf_vers != ISO8473_V1) { call_dissector(data_handle,tvb, pinfo, tree); return; } /* fixed part decoding */ cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN); ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id); ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1, cnf_hdr_len); if (cnf_hdr_len < FIXED_PART_LEN) { /* Header length is less than the length of the fixed part of the header. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < minimum length %u", FIXED_PART_LEN); return; } proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1, cnf_vers); cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL); proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1, cnf_ttl, "Holding Time : %u (%u.%u secs)", cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5); cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE); pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals, "Unknown (0x%02x)"); flag_string[0] = '\0'; if (cnf_type & CNF_SEG_OK) g_strlcat(flag_string, "S ", 7); if (cnf_type & CNF_MORE_SEGS) g_strlcat(flag_string, "M ", 7); if (cnf_type & CNF_ERR_OK) g_strlcat(flag_string, "E ", 7); ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1, cnf_type, "PDU Type : 0x%02x (%s%s)", cnf_type, flag_string, pdu_type_string); type_tree = proto_item_add_subtree(ti, ett_clnp_type); proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA); /* If we don't have the full header - i.e., not enough to see the segmentation part and determine whether this datagram is segmented or not - set the Info column now; we'll get an exception before we set it otherwise. */ if (tvb_length(tvb) < cnf_hdr_len) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); } segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN); ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2, segment_length); if (segment_length < cnf_hdr_len) { /* Segment length is less than the header length. */ expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length, "PDU length < header length %u", cnf_hdr_len); return; } cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM); cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum); switch (cksum_status) { default: /* * No checksum present, or not enough of the header present to * checksum it. */ proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum); break; case CKSUM_OK: /* * Checksum is correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (correct)", cnf_cksum); break; case CKSUM_NOT_OK: /* * Checksum is not correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (incorrect)", cnf_cksum); break; } opt_len = cnf_hdr_len; opt_len -= FIXED_PART_LEN; /* Fixed part of Header */ /* address part */ offset = P_CLNP_ADDRESS_PART; if (opt_len < 1) { /* Header length is less than the minimum value in CLNP, including the destination address length. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1); return; } dst_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1, dst_len); } offset += 1; opt_len -= 1; if (opt_len < dst_len) { /* Header length is less than the minimum value, including the destination address length and the destination address. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len); return; } dst_addr = tvb_get_ptr(tvb, offset, dst_len); nsel = tvb_get_guint8(tvb, offset + dst_len - 1); SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr); SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len, dst_addr, "%s", print_nsap_net(dst_addr, dst_len)); offset += dst_len; opt_len -= dst_len; if (opt_len < 1) { /* Header length is less than the minimum value, including the destination address length, the destination address, and the source address length. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1); return; } src_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb, offset, 1, src_len); } offset += 1; opt_len -= 1; if (opt_len < src_len) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, and the source address. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + src_len); return; } src_addr = tvb_get_ptr(tvb, offset, src_len); SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb, offset, src_len, src_addr, "%s", print_nsap_net(src_addr, src_len)); offset += src_len; opt_len -= src_len; /* Segmentation Part */ if (cnf_type & CNF_SEG_OK) { if (opt_len < SEGMENTATION_PART_LEN) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, the source address, and the segmentation part. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN); return; } du_id = tvb_get_ntohs(tvb, offset); proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); segment_offset = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); total_length = tvb_get_ntohs(tvb, offset + 4); ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2, "Total length : %6u", total_length); if (total_length < segment_length) { /* Reassembled length is less than the length of this segment. */ expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length, "Total length < segment length %u", segment_length); return; } offset += SEGMENTATION_PART_LEN; opt_len -= SEGMENTATION_PART_LEN; } dissect_osi_options(opt_len, tvb, offset, clnp_tree); offset += opt_len; /* If clnp_reassemble is on, this is a segment, we have all the * data in the segment, and the checksum is valid, then just add the * segment to the hashtable. */ save_fragmented = pinfo->fragmented; if (clnp_reassemble && (cnf_type & CNF_SEG_OK) && ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) && tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) && segment_length > cnf_hdr_len && cksum_status != CKSUM_NOT_OK) { fd_head = fragment_add_check(&clnp_reassembly_table, tvb, offset, pinfo, du_id, NULL, segment_offset, segment_length - cnf_hdr_len, cnf_type & CNF_MORE_SEGS); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP", fd_head, &clnp_frag_items, &update_col_info, clnp_tree); } else { /* If this is the first segment, dissect its contents, otherwise just show it as a segment. XXX - if we eventually don't save the reassembled contents of all segmented datagrams, we may want to always reassemble. */ if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) { /* Not the first segment - don't dissect it. */ next_tvb = NULL; } else { /* First segment, or not segmented. Dissect what we have here. */ /* Get a tvbuff for the payload. Set its length to the segment length, and flag it as a fragment, so going past the end reports FragmentBoundsError, i.e. "there's data missing because this isn't reassembled", not ReportedBoundsError, i.e. "the dissector ran past the end of the packet, so the packet must not have been constructed properly". */ next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len); tvb_set_fragment(next_tvb); /* * If this is the first segment, but not the only segment, * tell the next protocol that. */ if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS)) pinfo->fragmented = TRUE; else pinfo->fragmented = FALSE; } } if (next_tvb == NULL) { /* Just show this as a segment. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)", pdu_type_string, flag_string, segment_offset); /* As we haven't reassembled anything, we haven't changed "pi", so we don't have to restore it. */ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); pinfo->fragmented = save_fragmented; return; } if (tvb_offset_exists(tvb, offset)) { switch (cnf_type & CNF_TYPE) { case DT_NPDU: case MD_NPDU: /* Continue with COTP if any data. XXX - if this isn't the first Derived PDU of a segmented Initial PDU, skip that? */ if (nsel==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) { if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; } } if (nsel == (guchar)tp_nsap_selector || always_decode_transport) { if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be COTP or CLTP */ } } if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be one of the protocols in the heuristic list */ } break; case ER_NPDU: /* The payload is the header and "none, some, or all of the data part of the discarded PDU", i.e. it's like an ICMP error; dissect it as a CLNP PDU. */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); next_length = tvb_length_remaining(tvb, offset); if (next_length != 0) { /* We have payload; dissect it. */ ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length, "Discarded PDU"); discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu); /* Save the current value of the "we're inside an error packet" flag, and set that flag; subdissectors may treat packets that are the payload of error packets differently from "real" packets. */ save_in_error_pkt = pinfo->flags.in_error_pkt; pinfo->flags.in_error_pkt = TRUE; call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree); /* Restore the "we're inside an error packet" flag. */ pinfo->flags.in_error_pkt = save_in_error_pkt; } pinfo->fragmented = save_fragmented; return; /* we're done with this PDU */ case ERQ_NPDU: case ERP_NPDU: /* XXX - dissect this */ break; } } col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); call_dissector(data_handle,next_tvb, pinfo, tree); pinfo->fragmented = save_fragmented; } /* dissect_clnp */
void ManageInterfacesDialog::addRemoteInterfaces(GList* rlist, remote_options *roptions) { GList *if_entry, *lt_entry; if_info_t *if_info; char *if_string = NULL; gchar *descr, *str = NULL, *link_type_name = NULL, *auth_str; if_capabilities_t *caps; gint linktype_count; bool monitor_mode, found = false; GSList *curr_addr; int ips = 0; guint i; if_addr_t *addr; data_link_info_t *data_link_info; GString *ip_str; link_row *linkr = NULL; interface_t device; guint num_interfaces = global_capture_opts.all_ifaces->len; for (if_entry = g_list_first(rlist); if_entry != NULL; if_entry = g_list_next(if_entry)) { auth_str = NULL; if_info = (if_info_t *)if_entry->data; for (i = 0; i < num_interfaces; i++) { device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device.hidden) continue; if (strcmp(device.name, if_info->name) == 0) { found = TRUE; break; } } if (found) { found = FALSE; continue; } ip_str = g_string_new(""); str = ""; ips = 0; device.name = g_strdup(if_info->name); /* Is this interface hidden and, if so, should we include it anyway? */ descr = capture_dev_user_descr_find(if_info->name); if (descr != NULL) { /* Yes, we have a user-supplied description; use it. */ if_string = g_strdup_printf("%s: %s", descr, if_info->name); g_free(descr); } else { /* No, we don't have a user-supplied description; did we get one from the OS or libpcap? */ if (if_info->vendor_description != NULL) { /* Yes - use it. */ if_string = g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name); } else { /* No. */ if_string = g_strdup(if_info->name); } } /* else descr != NULL */ if (if_info->loopback) { device.display_name = g_strdup_printf("%s (loopback)", if_string); } else { device.display_name = g_strdup(if_string); } #ifdef CAN_SET_CAPTURE_BUFFER_SIZE if ((device.buffer = capture_dev_user_buffersize_find(if_string)) == -1) { device.buffer = global_capture_opts.default_options.buffer_size; } #endif if (!capture_dev_user_pmode_find(if_string, &device.pmode)) { device.pmode = global_capture_opts.default_options.promisc_mode; } if (!capture_dev_user_snaplen_find(if_string, &device.has_snaplen, &device.snaplen)) { device.has_snaplen = global_capture_opts.default_options.has_snaplen; device.snaplen = global_capture_opts.default_options.snaplen; } device.cfilter = g_strdup(global_capture_opts.default_options.cfilter); monitor_mode = prefs_capture_device_monitor_mode(if_string); #ifdef HAVE_PCAP_REMOTE if (roptions->remote_host_opts.auth_type == CAPTURE_AUTH_PWD) { auth_str = g_strdup_printf("%s:%s", roptions->remote_host_opts.auth_username, roptions->remote_host_opts.auth_password); } #endif caps = capture_get_if_capabilities(if_string, monitor_mode, auth_str, NULL, main_window_update); g_free(auth_str); for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { address addr_str; char* temp_addr_str = NULL; if (ips != 0) { g_string_append(ip_str, "\n"); } addr = (if_addr_t *)curr_addr->data; switch (addr->ifat_type) { case IF_AT_IPv4: SET_ADDRESS(&addr_str, AT_IPv4, 4, &addr->addr.ip4_addr); temp_addr_str = (char*)address_to_str(NULL, &addr_str); g_string_append(ip_str, temp_addr_str); break; case IF_AT_IPv6: SET_ADDRESS(&addr_str, AT_IPv6, 16, addr->addr.ip6_addr); temp_addr_str = (char*)address_to_str(NULL, &addr_str); g_string_append(ip_str, temp_addr_str); break; default: /* In case we add non-IP addresses */ break; } wmem_free(NULL, temp_addr_str); } /* for curr_addr */ linktype_count = 0; device.links = NULL; if (caps != NULL) { #ifdef HAVE_PCAP_CREATE device.monitor_mode_enabled = monitor_mode; device.monitor_mode_supported = caps->can_set_rfmon; #endif for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { data_link_info = (data_link_info_t *)lt_entry->data; linkr = (link_row *)g_malloc(sizeof(link_row)); /* * For link-layer types libpcap/WinPcap doesn't know about, the * name will be "DLT n", and the description will be null. * We mark those as unsupported, and don't allow them to be * used. */ if (data_link_info->description != NULL) { str = g_strdup_printf("%s", data_link_info->description); linkr->dlt = data_link_info->dlt; } else { str = g_strdup_printf("%s (not supported)", data_link_info->name); linkr->dlt = -1; } if (linktype_count == 0) { link_type_name = g_strdup(str); device.active_dlt = data_link_info->dlt; } linkr->name = g_strdup(str); g_free(str); device.links = g_list_append(device.links, linkr); linktype_count++; } /* for link_types */ } else { #if defined(HAVE_PCAP_CREATE) device.monitor_mode_enabled = FALSE; device.monitor_mode_supported = FALSE; #endif device.active_dlt = -1; link_type_name = g_strdup("default"); } device.addresses = g_strdup(ip_str->str); device.no_addresses = ips; device.remote_opts.src_type= roptions->src_type; if (device.remote_opts.src_type == CAPTURE_IFREMOTE) { device.local = FALSE; } device.remote_opts.remote_host_opts.remote_host = g_strdup(roptions->remote_host_opts.remote_host); device.remote_opts.remote_host_opts.remote_port = g_strdup(roptions->remote_host_opts.remote_port); device.remote_opts.remote_host_opts.auth_type = roptions->remote_host_opts.auth_type; device.remote_opts.remote_host_opts.auth_username = g_strdup(roptions->remote_host_opts.auth_username); device.remote_opts.remote_host_opts.auth_password = g_strdup(roptions->remote_host_opts.auth_password); device.remote_opts.remote_host_opts.datatx_udp = roptions->remote_host_opts.datatx_udp; device.remote_opts.remote_host_opts.nocap_rpcap = roptions->remote_host_opts.nocap_rpcap; device.remote_opts.remote_host_opts.nocap_local = roptions->remote_host_opts.nocap_local; #ifdef HAVE_PCAP_SETSAMPLING device.remote_opts.sampling_method = roptions->sampling_method; device.remote_opts.sampling_param = roptions->sampling_param; #endif device.selected = TRUE; global_capture_opts.num_selected++; g_array_append_val(global_capture_opts.all_ifaces, device); g_string_free(ip_str, TRUE); } /*for*/ showRemoteInterfaces(); }
static void dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int fcs_len) { proto_item *ti = NULL; eth_hdr *ehdr; gboolean is_802_2; proto_tree *fh_tree = NULL; const guint8 *src_addr, *dst_addr; static eth_hdr ehdrs[4]; static int ehdr_num=0; proto_tree *tree; proto_item *addr_item; proto_tree *addr_tree=NULL; ehdr_num++; if(ehdr_num>=4){ ehdr_num=0; } ehdr=&ehdrs[ehdr_num]; tree=parent_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet"); src_addr=tvb_get_ptr(tvb, 6, 6); SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src_addr); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src_addr); SET_ADDRESS(&ehdr->src, AT_ETHER, 6, src_addr); dst_addr=tvb_get_ptr(tvb, 0, 6); SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst_addr); SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst_addr); SET_ADDRESS(&ehdr->dst, AT_ETHER, 6, dst_addr); ehdr->type = tvb_get_ntohs(tvb, 12); tap_queue_packet(eth_tap, pinfo, ehdr); /* * In case the packet is a non-Ethernet packet inside * Ethernet framing, allow heuristic dissectors to take * a first look before we assume that it's actually an * Ethernet packet. */ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, parent_tree, NULL)) return; if (ehdr->type <= IEEE_802_3_MAX_LEN) { /* Oh, yuck. Cisco ISL frames require special interpretation of the destination address field; fortunately, they can be recognized by checking the first 5 octets of the destination address, which are 01-00-0C-00-00 for ISL frames. */ if ((tvb_get_guint8(tvb, 0) == 0x01 || tvb_get_guint8(tvb, 0) == 0x0C) && tvb_get_guint8(tvb, 1) == 0x00 && tvb_get_guint8(tvb, 2) == 0x0C && tvb_get_guint8(tvb, 3) == 0x00 && tvb_get_guint8(tvb, 4) == 0x00) { dissect_isl(tvb, pinfo, parent_tree, fcs_len); return; } } /* * If the type/length field is <= the maximum 802.3 length, * and is not zero, this is an 802.3 frame, and it's a length * field; it might be an Novell "raw 802.3" frame, with no * 802.2 LLC header, or it might be a frame with an 802.2 LLC * header. * * If the type/length field is >= the minimum Ethernet II length, * this is an Ethernet II frame, and it's a type field. * * If the type/length field is > maximum 802.3 length and < minimum * Ethernet II length, then this is an invalid packet. * * If the type/length field is zero (ETHERTYPE_UNK), this is * a frame used internally by the Cisco MDS switch to contain * Fibre Channel ("Vegas"). We treat that as an Ethernet II * frame; the dissector for those frames registers itself with * an ethernet type of ETHERTYPE_UNK. */ if (ehdr->type > IEEE_802_3_MAX_LEN && ehdr->type < ETHERNET_II_MIN_LEN) { tvbuff_t *next_tvb; col_add_fstr(pinfo->cinfo, COL_INFO, "Ethernet Unknown: Invalid length/type: 0x%04x (%d)", ehdr->type, ehdr->type); ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "Ethernet Unknown, Src: %s (%s), Dst: %s (%s)", get_ether_name(src_addr), ether_to_str(src_addr), get_ether_name(dst_addr), ether_to_str(dst_addr)); fh_tree = proto_item_add_subtree(ti, ett_ether); addr_item = proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if (addr_item) addr_tree = proto_item_add_subtree(addr_item, ett_addr); proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item = proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if (addr_item) addr_tree = proto_item_add_subtree(addr_item, ett_addr); proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); ti = proto_tree_add_item(fh_tree, hf_eth_invalid_lentype, tvb, 12, 2, ENC_BIG_ENDIAN); expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid length/type: 0x%04x (%d)", ehdr->type, ehdr->type); next_tvb = tvb_new_subset_remaining(tvb, 14); call_dissector(data_handle, next_tvb, pinfo, parent_tree); return; } if (ehdr->type <= IEEE_802_3_MAX_LEN && ehdr->type != ETHERTYPE_UNK) { is_802_2 = check_is_802_2(tvb, fcs_len); col_add_fstr(pinfo->cinfo, COL_INFO, "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw ")); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw ")); fh_tree = proto_item_add_subtree(ti, ett_ieee8023); } /* if IP is not referenced from any filters we dont need to worry about generating any tree items. We must do this after we created the actual protocol above so that proto hier stat still works though. */ if(!proto_field_is_referenced(parent_tree, proto_eth)){ tree=NULL; fh_tree=NULL; } addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_len, hf_eth_trailer, fcs_len); } else { if (eth_interpret_as_fw1_monitor) { if ((dst_addr[0] == 'i') || (dst_addr[0] == 'I') || (dst_addr[0] == 'o') || (dst_addr[0] == 'O')) { call_dissector(fw1_handle, tvb, pinfo, parent_tree); return; } } col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II"); if (parent_tree) { if (PTREE_DATA(parent_tree)->visible) { ti = proto_tree_add_protocol_format(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "Ethernet II, Src: %s (%s), Dst: %s (%s)", get_ether_name(src_addr), ether_to_str(src_addr), get_ether_name(dst_addr), ether_to_str(dst_addr)); } else { ti = proto_tree_add_item(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, ENC_NA); } fh_tree = proto_item_add_subtree(ti, ett_ether2); } addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); if (tvb_get_guint8(tvb, 6) & 0x01) { expert_add_info_format(pinfo, addr_item, PI_PROTOCOL, PI_WARN, "Source MAC must not be a group address: IEEE 802.3-2002, Section 3.2.3(b)"); } } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_type, hf_eth_trailer, fcs_len); } }
static void dissect_sll(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pkttype; guint16 protocol; guint16 hatype, halen; const guint8 *src; proto_item *ti; tvbuff_t *next_tvb; proto_tree *fh_tree = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SLL"); col_clear(pinfo->cinfo, COL_INFO); pkttype = tvb_get_ntohs(tvb, 0); /* * Set "pinfo->p2p_dir" if the packet wasn't received * promiscuously. */ switch (pkttype) { case LINUX_SLL_HOST: case LINUX_SLL_BROADCAST: case LINUX_SLL_MULTICAST: pinfo->p2p_dir = P2P_DIR_RECV; break; case LINUX_SLL_OUTGOING: pinfo->p2p_dir = P2P_DIR_SENT; break; } col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pkttype, packet_type_vals, "Unknown (%u)")); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_sll, tvb, 0, SLL_HEADER_SIZE, "Linux cooked capture"); fh_tree = proto_item_add_subtree(ti, ett_sll); proto_tree_add_item(fh_tree, hf_sll_pkttype, tvb, 0, 2, ENC_BIG_ENDIAN); } /* * XXX - check the link-layer address type value? * For now, we just assume 6 means Ethernet. */ hatype = tvb_get_ntohs(tvb, 2); halen = tvb_get_ntohs(tvb, 4); if (tree) { proto_tree_add_uint(fh_tree, hf_sll_hatype, tvb, 2, 2, hatype); proto_tree_add_uint(fh_tree, hf_sll_halen, tvb, 4, 2, halen); } switch (halen) { case 4: src = tvb_get_ptr(tvb, 6, 4); SET_ADDRESS(&pinfo->dl_src, AT_IPv4, 4, src); SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src); if (tree) { proto_tree_add_item(fh_tree, hf_sll_src_ipv4, tvb, 6, 4, ENC_BIG_ENDIAN); } break; case 6: src = tvb_get_ptr(tvb, 6, 6); SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src); if (tree) { proto_tree_add_ether(fh_tree, hf_sll_src_eth, tvb, 6, 6, src); } break; case 0: break; default: if (tree) { proto_tree_add_item(fh_tree, hf_sll_src_other, tvb, 6, halen > 8 ? 8 : halen, ENC_NA); } break; } protocol = tvb_get_ntohs(tvb, 14); next_tvb = tvb_new_subset_remaining(tvb, SLL_HEADER_SIZE); if (protocol <= 1536) { /* yes, 1536 - that's how Linux does it */ /* * "proto" is *not* a length field, it's a Linux internal * protocol type. * We therefore cannot say how much of the packet will * be trailer data. * XXX - do the same thing we do for packets with Ethertypes? */ proto_tree_add_uint(fh_tree, hf_sll_ltype, tvb, 14, 2, protocol); if(!dissector_try_uint(sll_linux_dissector_table, protocol, next_tvb, pinfo, tree)) { call_dissector(data_handle, next_tvb, pinfo, tree); } } else { switch (hatype) { case ARPHRD_IPGRE: proto_tree_add_uint(fh_tree, hf_sll_gretype, tvb, 14, 2, protocol); dissector_try_uint(gre_dissector_table, protocol, next_tvb, pinfo, tree); break; default: ethertype(protocol, tvb, SLL_HEADER_SIZE, pinfo, tree, fh_tree, hf_sll_etype, hf_sll_trailer, 0); break; } } }
static int dissect_ppcap_destination_address(tvbuff_t *tvb, packet_info * pinfo, proto_tree * ppcap_tree1, int offset) { int key2; guint16 msg_len; msg_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(ppcap_tree1, hf_ppcap_destreserved, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; key2 = tvb_get_ntohs(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (key2 == 1) { ssn = tvb_get_guint8(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn1, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(ppcap_tree1, hf_ppcap_spc1, tvb, offset, 3, ENC_BIG_ENDIAN); /*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_dpc->pc = (guint32)tvb_get_ntoh24(tvb, offset); mtp3_addr_dpc->type = ITU_STANDARD; mtp3_addr_dpc->ni = 0; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len-1; return offset; } else if (key2 == 2) { proto_tree_add_item(ppcap_tree1, hf_ppcap_dpc, tvb, offset, 4, ENC_BIG_ENDIAN); /*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_dpc->pc = tvb_get_ntohl(tvb, offset); mtp3_addr_dpc->type = ITU_STANDARD; mtp3_addr_dpc->ni = 0; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); } else if (key2 == 3) { if (msg_len%16 != 0) { proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_destination_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset)); TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv4, tvb, offset, 4); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } else { struct e_in6_addr value; tvb_get_ipv6(tvb, offset,&value); proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_destination_ip_address2, tvb, offset, msg_len, &value); TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv6, tvb, offset, 6); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } } else if (key2 == 4) { char *string; string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, msg_len, ENC_UTF_8|ENC_NA); proto_tree_add_string(ppcap_tree1, hf_ppcap_destination_nodeid, tvb, offset, msg_len, string); TVB_SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, tvb, offset, msg_len); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } if (msg_len%4) msg_len = msg_len+(4-(msg_len%4)); offset += msg_len; return offset; }
void Packet_UDP::dissect_udp(tvbuff_t *tvb, packet_info *pinfo, TreeItem *tree) { TreeItem *udp_tree = NULL; int len; int reported_len; int offset = 0; e_udphdr *udph; tvbuff_t next_tvb; udph = (e_udphdr *)malloc(sizeof(e_udphdr)); SET_ADDRESS(&udph->ip_src,pinfo->src.type,pinfo->src.len,pinfo->src.data); SET_ADDRESS(&udph->ip_dst,pinfo->dst.type,pinfo->dst.len,pinfo->dst.data); udph->uh_sport = Tvbuff::tvb_get_ntohs(tvb,offset); udph->uh_dport = Tvbuff::tvb_get_ntohs(tvb,offset+2); if(tree) { udp_tree = Proto::proto_tree_add_protocol(tree,offset,8,"User Datagram Protocol,Src Port:%u,Dst Port:%u", udph->uh_sport,udph->uh_dport); Proto::proto_tree_add_uint(udp_tree,&hf_udp[0],offset,2,udph->uh_sport); Proto::proto_tree_add_uint(udp_tree,&hf_udp[1],offset+2,2,udph->uh_dport); } udph->uh_ulen = udph->uh_sum_cov = Tvbuff::tvb_get_ntohs(tvb,offset+4); if(udph->uh_ulen < 8) { if(tree) Proto::proto_tree_add_text_format(udp_tree,offset+4,2,"Length:%u (bogus,must be >= 8)",udph->uh_ulen); return; } if(udph->uh_ulen > tvb->reported_length) { if(tree) Proto::proto_tree_add_text_format(udp_tree,offset+4,2,"Length: %u (bogus, payload length %u)",udph->uh_ulen,tvb->reported_length); } else { if(tree) Proto::proto_tree_add_uint(udp_tree,&hf_udp[2],offset+4,2,udph->uh_ulen); } udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen; udph->uh_sum = Tvbuff::tvb_get_ntohs(tvb,offset+6); reported_len = tvb->reported_length; len = tvb->length; if(udph->uh_sum == 0) { /* No checksum supplied in the packet.*/ if(tree) Proto::proto_tree_add_text_format(udp_tree,offset+6,2,"Checksum: 0x%04 (none)",0); } else if(len >= reported_len && len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov && udph->uh_sum_cov >= 8) { if(tree) Proto::proto_tree_add_text_format(udp_tree,offset+6,2,"Checksum: 0x%04x",udph->uh_sum); } else { if(tree) Proto::proto_tree_add_text_format(udp_tree,offset+6,2,"Checksum: 0x%04x [unchecked,not all data available]",udph->uh_sum); } /* Skip over header */ offset += 8; /* add protocol_info */ Dissector::add_protocol_info(pinfo,"udp",pinfo->offset,offset); /* set next protocol's start position and decompressed flag */ Proto::set_start_decomp(pinfo->begin+offset,pinfo->iscompression); pinfo->begin += offset; pinfo->offset = offset; /* Call sub-dissectors */ next_tvb.length = tvb->length - offset; next_tvb.reported_length = tvb->reported_length - offset; next_tvb.real_data = tvb->real_data + offset; if(next_tvb.length) Dissector::call_dissector_by_name("data",&next_tvb,pinfo,Proto::proto_tree_get_root(tree)); }
static gboolean dissect_mpeg_audio_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 h; struct mpa mpa; int data_size = 0; asn1_ctx_t asn1_ctx; int offset = 0; static const char *version_names[] = { "1", "2", "2.5" }; if (!tvb_bytes_exist(tvb, 0, 4)) return FALSE; /* not enough data for an MPEG audio frame */ h = tvb_get_ntohl(tvb, 0); MPA_UNMARSHAL(&mpa, h); if (!MPA_SYNC_VALID(&mpa)) return FALSE; if (!MPA_VERSION_VALID(&mpa)) return FALSE; if (!MPA_LAYER_VALID(&mpa)) return FALSE; col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MPEG-%s", version_names[mpa_version(&mpa)]); col_add_fstr(pinfo->cinfo, COL_INFO, "Audio Layer %d", mpa_layer(&mpa) + 1); if (MPA_BITRATE_VALID(&mpa) && MPA_FREQUENCY_VALID(&mpa)) { data_size = (int)(MPA_DATA_BYTES(&mpa) - sizeof mpa); if (check_col(pinfo->cinfo, COL_DEF_SRC)) { SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL); col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%d kb/s", mpa_bitrate(&mpa) / 1000); } if (check_col(pinfo->cinfo, COL_DEF_DST)) { SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL); col_add_fstr(pinfo->cinfo, COL_DEF_DST, "%g kHz", mpa_frequency(&mpa) / (float)1000); } } if (tree == NULL) return TRUE; asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo); offset = dissect_mpeg_audio_Audio(tvb, offset, &asn1_ctx, tree, proto_mpeg_audio); if (data_size > 0) { unsigned int padding; proto_tree_add_item(tree, hf_mpeg_audio_data, tvb, offset / 8, data_size, FALSE); offset += data_size * 8; padding = mpa_padding(&mpa); if (padding > 0) { proto_tree_add_item(tree, hf_mpeg_audio_padbytes, tvb, offset / 8, padding, FALSE); offset += padding * 8; } } return TRUE; }
static void dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree) { guint32 label, dpc, opc; proto_item *label_item, *label_dpc_item, *label_opc_item; proto_item *hidden_item; proto_tree *label_tree; proto_tree *pc_subtree; int hf_dpc_string; int hf_opc_string; switch (mtp3_standard) { case ITU_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET); opc = (label & ITU_OPC_MASK) >> 14; dpc = label & ITU_DPC_MASK; hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); PROTO_ITEM_SET_HIDDEN(hidden_item); label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); if(mtp3_addr_dpc->ni == 0) { pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); } label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); if(mtp3_addr_opc->ni == 0) { pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); } proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: if (mtp3_standard == ANSI_STANDARD) { hf_dpc_string = hf_mtp3_ansi_dpc; hf_opc_string = hf_mtp3_ansi_opc; } else /* CHINESE_ITU_STANDARD */ { hf_dpc_string = hf_mtp3_chinese_dpc; hf_opc_string = hf_mtp3_chinese_opc; } /* Create the Routing Label Tree */ label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); /* create and fill the DPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network, hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc); /* Store dpc for mtp3_addr below */ dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET); /* create and fill the OPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network, hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc); /* Store opc for mtp3_addr below */ opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET); /* SLS */ if (mtp3_standard == ANSI_STANDARD) { if (mtp3_use_ansi_5_bit_sls) proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); else proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } else /* CHINESE_ITU_STANDARD */ { proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } break; case JAPAN_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); } label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); } hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (mtp3_use_japan_5_bit_sls) { proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } else { proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); } mtp3_addr_opc->type = mtp3_standard; mtp3_addr_opc->pc = opc; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); mtp3_addr_dpc->type = mtp3_standard; mtp3_addr_dpc->pc = dpc; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); }