WSLUA_METHOD Tvb_offset(lua_State* L) { /* Returns the raw offset (from the beginning of the source Tvb) of a sub Tvb. */ Tvb tvb = checkTvb(L,1); lua_pushnumber(L,tvb_raw_offset(tvb->ws_tvb)); WSLUA_RETURN(1); /* The raw offset of the Tvb. */ }
WSLUA_METHOD Tvb_offset(lua_State* L) { /* Returns the raw offset (from the beginning of the source Tvb) of a sub Tvb. */ Tvb tvb = checkTvb(L,1); if (!tvb) return 0; if (tvb->expired) { luaL_error(L,"expired tvb"); return 0; } lua_pushnumber(L,tvb_raw_offset(tvb->ws_tvb)); WSLUA_RETURN(1); /* The raw offset of the Tvb. */ }
/** Dissector for SoupBinTCP messages */ static void dissect_soupbintcp_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct conv_data *conv_data; struct pdu_data *pdu_data; const char *pkt_name; const char *tmp_buf; proto_item *ti; proto_tree *soupbintcp_tree = NULL; conversation_t *conv = NULL; guint16 expected_len; guint8 pkt_type; gint offset = 0; guint this_seq = 0, next_seq, key; heur_dtbl_entry_t *hdtbl_entry; /* Record the start of the packet to use as a sequence number key */ key = (guint)tvb_raw_offset(tvb); /* Get the 16-bit big-endian SOUP packet length */ expected_len = tvb_get_ntohs(tvb, 0); /* Get the 1-byte SOUP message type */ pkt_type = tvb_get_guint8(tvb, 2); /* Since we use the packet name a few times, get and save that value */ pkt_name = val_to_str(pkt_type, pkt_type_val, "Unknown (%u)"); /* Set the protocol name in the summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SoupBinTCP"); /* Set the packet name in the info column */ col_add_str(pinfo->cinfo, COL_INFO, pkt_name); /* Sequence number tracking * * SOUP does not number packets from client to server (the server * acknowledges all important messages, so the client should use * the acks to figure out if the server received the message, and * otherwise resend it). * * Packets from server to client are numbered, but it's implicit. * The Login Accept packet contains the next sequence number that * the server will send, and the client needs to count the * Sequenced Data packets that it receives to know what their * sequence numbers are. * * So, we grab the next sequence number from the Login Acceptance * packet, and save it in a conversation_t we associate with the * TCP session. Then, for each Sequenced Data packet we receive, * the first time it's processed (when PINFO_FD_VISITED() is * false), we write it into the PDU's frame's private data pointer * and increment the saved sequence number (in the conversation_t). * * If the visited flag is true, then we've dissected this packet * already, and so we can fetch the sequence number from the * frame's private data area. * * In either case, if there's any problem, we report zero as the * sequence number, and try to continue dissecting. */ /* If first dissection of Login Accept, save sequence number */ if (pkt_type == 'A' && !PINFO_FD_VISITED(pinfo)) { tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 13, 20, ENC_ASCII); next_seq = atoi(tmp_buf); /* Create new conversation for this session */ conv = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); /* Store starting sequence number for session's packets */ conv_data = (struct conv_data *)wmem_alloc(wmem_file_scope(), sizeof(struct conv_data)); conv_data->next_seq = next_seq; conversation_add_proto_data(conv, proto_soupbintcp, conv_data); } /* Handle sequence numbering for a Sequenced Data packet */ if (pkt_type == 'S') { if (!PINFO_FD_VISITED(pinfo)) { /* Get next expected sequence number from conversation */ conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (!conv) { this_seq = 0; } else { conv_data = (struct conv_data *)conversation_get_proto_data(conv, proto_soupbintcp); if (conv_data) { this_seq = conv_data->next_seq++; } else { this_seq = 0; } pdu_data = (struct pdu_data *)wmem_alloc( wmem_file_scope(), sizeof(struct pdu_data)); pdu_data->seq_num = this_seq; p_add_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, key, pdu_data); } } else { pdu_data = (struct pdu_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, key); if (pdu_data) { this_seq = pdu_data->seq_num; } else { this_seq = 0; } } col_append_fstr(pinfo->cinfo, COL_INFO, ", SeqNum = %u", this_seq); } if (tree) { /* Create sub-tree for SoupBinTCP details */ ti = proto_tree_add_item(tree, proto_soupbintcp, tvb, 0, -1, ENC_NA); soupbintcp_tree = proto_item_add_subtree(ti, ett_soupbintcp); /* Append the packet name to the sub-tree item */ proto_item_append_text(ti, ", %s", pkt_name); /* Length */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_packet_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Type */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_packet_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; switch (pkt_type) { case '+': /* Debug Message */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_text, tvb, offset, expected_len - 1, ENC_ASCII|ENC_NA); break; case 'A': /* Login Accept */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_session, tvb, offset, 10, ENC_ASCII|ENC_NA); offset += 10; tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII); proto_tree_add_string_format_value(soupbintcp_tree, hf_soupbintcp_next_seq_num, tvb, offset, 20, "X", "%d", atoi(tmp_buf)); break; case 'J': /* Login Reject */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_reject_code, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 'U': /* Unsequenced Data */ /* Display handled by sub-dissector */ break; case 'S': /* Sequenced Data */ proto_item_append_text(ti, ", SeqNum=%u", this_seq); proto_tree_add_string_format_value(soupbintcp_tree, hf_soupbintcp_seq_num, tvb, offset, 0, "X", "%u (Calculated)", this_seq); /* Display handled by sub-dissector */ break; case 'L': /* Login Request */ proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_username, tvb, offset, 6, ENC_ASCII|ENC_NA); offset += 6; proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_password, tvb, offset, 10, ENC_ASCII|ENC_NA); offset += 10; proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_session, tvb, offset, 10, ENC_ASCII|ENC_NA); offset += 10; tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII); proto_tree_add_string_format_value(soupbintcp_tree, hf_soupbintcp_req_seq_num, tvb, offset, 20, "X", "%d", atoi(tmp_buf)); break; case 'H': /* Server Heartbeat */ break; case 'O': /* Logout Request */ break; case 'R': /* Client Heartbeat */ break; case 'Z': /* End of Session */ break; default: /* Unknown */ proto_tree_add_item(tree, hf_soupbintcp_message, tvb, offset, -1, ENC_NA); break; } } /* Call sub-dissector for encapsulated data */ if (pkt_type == 'S' || pkt_type == 'U') { tvbuff_t *sub_tvb; /* Sub-dissector tvb starts at 3 (length (2) + pkt_type (1)) */ sub_tvb = tvb_new_subset_remaining(tvb, 3); #if 0 /* XXX: It's not valid for a soupbintcp subdissector to call */ /* conversation_set_dissector() since the conversation is really */ /* a TCP conversation. (A 'soupbintcp' port type would need to */ /* be defined to be able to use conversation_set_dissector()). */ /* In addition, no current soupbintcp subdissector calls */ /* conversation_set_dissector(). */ /* If this packet is part of a conversation, call dissector * for the conversation if available */ if (try_conversation_dissector(&pinfo->dst, &pinfo->src, pinfo->ptype, pinfo->srcport, pinfo->destport, sub_tvb, pinfo, tree, NULL)) { return; } #endif /* Otherwise, try heuristic dissectors */ if (dissector_try_heuristic(heur_subdissector_list, sub_tvb, pinfo, tree, &hdtbl_entry, NULL)) { return; } /* Otherwise, give up, and just print the bytes in hex */ if (tree) { proto_tree_add_item(soupbintcp_tree, hf_soupbintcp_message, sub_tvb, 0, -1, ENC_NA); } } }