This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

How do I have my dissector handle a protocol running on top of UDP?

0

Hi all, I'm using tshark for some specific dissectors. I have to modify the function dissect_data(...) in packet-data.c. In my scenario, most of the packet must go through this function. My objective is: at the end of this function, I want to clear all data of this packet before going to the next in order to free memory. So, my question is:

  • Is it possible to clear all data at the end of this function (dissect_data)? if YES, how can I do this?
  • Can I free the tree by proto_tree_free(proto_tree *tree) after processing each packet?
  • Is it possible to use some functions like: epan_cleanup();packet_cleanup();cleanup_dissection();

Here is the function dissect_data(...)

static void
dissect_data(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
{
    gint bytes;
    bytes = tvb_length_remaining(tvb, 0);
    if (bytes > 0) {
        tvbuff_t   *data_tvb;
        proto_item *ti;
        proto_tree *data_tree;

        // This is my modification. The output tvb is the same, nothing change.
        tvb = decode_sonnh(tvb,pinfo,tree);

        if (new_pane) {
            guint8 *real_data = (guint8 *)tvb_memdup(tvb, 0, bytes);
            data_tvb = tvb_new_child_real_data(tvb,real_data,bytes,bytes);
            tvb_set_free_cb(data_tvb, g_free);
            add_new_data_source(pinfo, data_tvb, "Not dissected data bytes");
        } else {
            data_tvb = tvb;
        }
        ti = proto_tree_add_protocol_format(tree, proto_data, tvb,
            0,
            bytes, "Data (%d byte%s)", bytes,
            plurality(bytes, "", "s"));
        data_tree = proto_item_add_subtree(ti, ett_data);

        proto_tree_add_item(data_tree, hf_data_data, data_tvb, 0, bytes, ENC_NA);

        if (show_as_text) {
            proto_tree_add_item(data_tree, hf_data_text, data_tvb, 0, bytes, ENC_ASCII|ENC_NA);
        }

        if(generate_md5_hash) {
            const guint8 *cp;
            md5_state_t   md_ctx;
            md5_byte_t    digest[16];
            const gchar  *digest_string;

            cp = tvb_get_ptr(tvb, 0, bytes);

            md5_init(&md_ctx);
            md5_append(&md_ctx, cp, bytes);
            md5_finish(&md_ctx, digest);

            digest_string = bytestring_to_str(digest, 16, '\0');
            ti = proto_tree_add_string(data_tree, hf_data_md5_hash, tvb, 0, 0, digest_string);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        ti = proto_tree_add_int(data_tree, hf_data_len, data_tvb, 0, 0, bytes);
        PROTO_ITEM_SET_GENERATED (ti);
    }

}

asked 24 Dec ‘14, 20:30

hoangsonk49's gravatar image

hoangsonk49
81282933
accept rate: 28%

edited 27 Dec ‘14, 15:38

Guy%20Harris's gravatar image

Guy Harris ♦♦
17.4k335196

I have to modify the function dissect_data(…) in packet-data.c. In my scenario, most of the packet must go through this function.

Why must it go through that function? dissect_data() is what’s used when the data being dissected is of an unknown protocol or is raw data (such as that transported by “read” and “write” requests in remote file system protocols such as SMB, NFS, or AFP). If you’re trying to dissect the data, it’s not of an unknown protocol, it’s of whatever protocol you’re trying to dissect - hacking dissect_data() to call another dissector is always the wrong answer, you should be hacking whatever’s calling dissect_data() so that it calls your dissector instead.

(26 Dec ‘14, 17:00) Guy Harris ♦♦

Hi Harris, the data stream I received from the network is unknown protocol. After my decode function, it becomes the data of sccp. I know It should be better to create a new dissector to decode so that it can be recognized as sccp data and should not go through dissect_data(…) function as described in the method [1]:

  • [1] Expected: data stream -> my dissector to decode -> sccp -> …
  • [2] In fact: data stream -> [unknown protocol] packet-data -> my dissector to decode -> sccp -> …

But I choose [2] because I don’t know how to get the data stream before it goes to dissect_data(…) in the source code. So, I have to use the data in dissect_data(…) of packet-data.c as as described in the method [2].

(26 Dec ‘14, 17:39) hoangsonk49

Hi Harris, the data stream I received from the network is unknown protocol. After my decode function, it becomes the data of sccp.

The data stream you receive from the network is for some known protocol, otherwise you wouldn’t have a decode function to apply to it!

But I choose [2] because I don’t know how to get the data stream before it goes to dissect_data(…) in the source code.

In what protocol is your data stream encapsulated? TCP? IP? Ethernet? If you read a capture file into Wireshark without your decode function, presumably, in the “packet details” pane, there will be some protocol that appears before it. That’s the place where dissect_data() gets called.

(26 Dec ‘14, 18:01) Guy Harris ♦♦

Hi Harris. The protocol before it is UDP . Here is the pcap file. Thanks for suggestion. I ’ll try to rewrite the dissector.

(26 Dec ‘14, 18:22) hoangsonk49


2 Answers:

2

You need to either:

  1. have your dissector register in the "udp" dissector table, with dissector_add_uint(), for the UDP ports it uses, if it uses the same UDP ports all the time;
  2. have your dissector have a preference to specify the UDP ports, and have it register in the "udp" dissector table using those port numbers;
  3. have your dissector register in the "udp" dissector table with dissector_add_for_decode_as(), so that you can use the "decode as" mechanisms to specify that a particular UDP conversation should be dissected using your protocol;
  4. if your protocol's packets have some data pattern at the beginning if the protocol's packet that makes it possible to guess what packets are packets with that protocol, make your dissector a "heuristic" dissector and register it in the "udp" heuristic dissector list with heur_dissector_add().

answered 27 Dec '14, 15:37

Guy%20Harris's gravatar image

Guy Harris ♦♦
17.4k335196
accept rate: 19%

edited 28 Dec '14, 02:16

0

No you cannot, because the dissection engine memory is owned by the dissection engine, not you dissector. The engine knows when memory can be freed, or not, and does so when appropriate. There have been some serious work in this area with current versions of Wireshark, so this might relieve you situation.

If you are looking at the out-of-memory problems you can encounter when having a long capture, or large file, there are other ways to address this. The root cause is that Wireshark accumulates 'state' from the network traffic it sees. This allows Wireshark to do all the amazing things it does. On the downside, this state data cannot be freed until the capture file is closed.

So, either capture using dumpcap for long term captures, or use editcap to split your large capture file in order for it to be loaded. But these are only general recommendation. There could be more specific suggestions possible for your particular situation.

answered 25 Dec '14, 08:06

Jaap's gravatar image

Jaap ♦
11.7k16101
accept rate: 14%

Hi Jaap, I split file by using :

tshark -i 6 -P -w logs/call_log.pcap -b filesize:655350

In another situation, I dissected the CAMEL packet successfully without any problem of memory.In the current situation,the packet is not a standard so it must be decoded before going through SCCP dissector to be output as CAMEL standard.If CAMEL packet has no problem of memory,so I think there is something wrong in my decode function which are related to the memory allocation. It increases about 1.5% of 32GB in 10 minutes until reach 95% before Stop. Here is the decode function:

decode_sonnh(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
{
        tvbuff_t *tvb_sonnh;
        tvbuff_t *tvb_tmp;
        ...    
        if (...)
        {    
             ...    
            guint8 sccp_sonnh[1000];
            guint8 sccp_sonnh_tmp[1000];
            guint8 real_data_sonnh[1000];
        for(i=0;i<bytes;i++)
        {
        value = tvb_get_guint8(tvb, i);
            value1= tvb_get_guint8(tvb, i+1);

            if(...)
            {
                nStart = ...
                break;
            }
        }

        if(...)
        {       
            ...
            tvb_tmp = tvb_new_subset_remaining(tvb, nStart);                
            ...
            bytes = tvb_length_remaining(tvb_tmp,0);
            real_data_sonnh[0]=...;
            real_data_sonnh[1]=...;
            real_data_sonnh[2]=...;
            real_data_sonnh[3]=... + nSccp_Called_Length;
            real_data_sonnh[4]=real_data_sonnh[3] + nSccp_Calling_Length;
            for(...)
            {
                real_data_sonnh[5+i]=sccp_sonnh[i];
            }
                real_data_sonnh[5+nSccp_length]=...;

            for(...)
            {
                real_data_sonnh[6+nSccp_length+i]=tvb_get_guint8(tvb_tmp, i);
            }
                tvb_sonnh = tvb_new_real_data(&real_data_sonnh,bytes+nSccp_length+6,bytes+nSccp_length+6); 
                dissect_sccp(tvb_sonnh,pinfo,tree ); // Wireshark takes care this dissection.Result is CAMEL packet
                if(tvb_sonnh)
                {
                    tvb_free(tvb_sonnh);
                    tvb_sonnh = NULL;
                }
                ...

        }
        else
        {
            ...
        }
    }
    else
    {
        ...
    }
 }</code></pre><p>is there any problem with the memory allocation? Please correct me if I did something wrong. Thank you.</p></div><div id="comment-38712-info" class="comment-info"><span class="comment-age">(25 Dec '14, 18:53)</span> <span class="comment-user userinfo">hoangsonk49</span></div></div><span id="38713"></span><div id="comment-38713" class="comment"><div id="post-38713-score" class="comment-score"></div><div class="comment-text"><p>It could be related to the SCCP dissector keeping state information. If you are using the 1.99 branch, you can have a look at the -b switch, as described here: <a href="https://blog.wireshark.org/2014/07/to-infinity-and-beyond-capturing-forever-with-tshark/">https://blog.wireshark.org/2014/07/to-infinity-and-beyond-capturing-forever-with-tshark/</a></p></div><div id="comment-38713-info" class="comment-info"><span class="comment-age">(26 Dec '14, 00:50)</span> <span class="comment-user userinfo">Pascal Quantin</span></div></div><span id="38714"></span><div id="comment-38714" class="comment"><div id="post-38714-score" class="comment-score"></div><div class="comment-text"><p>Hi Pascal, I'm using the -b switch as mentioned at the top of the comment</p><blockquote><p>tshark -i 6 -P -w logs/call_log.pcap -b filesize:655350</p></blockquote></div><div id="comment-38714-info" class="comment-info"><span class="comment-age">(26 Dec '14, 01:27)</span> <span class="comment-user userinfo">hoangsonk49</span></div></div></div><div id="comment-tools-38708" class="comment-tools"></div><div class="clear"></div><div id="comment-38708-form-container" class="comment-form-container"></div><div class="clear"></div></div></td></tr></tbody></table>