Wireshark-dev: Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
From: Beth <beth.tridium@xxxxxxxxx>
Date: Wed, 20 Jun 2012 08:36:01 -0400
As far as I know, you learn it mostly by doing. The documents such as they are
give you a general idea, then you pick an existing dissector that's similar to the
one you want to write, and do a lot of copy/paste/modify/delete until it looks like
your protocol.
Then you come back here for help figuring out why it doesn't work. ;)
Challenge #1 is getting your development environment set up so that you can build
Wireshark. Challenge #2 is figuring out which functions you have to implement and
which ones you have to call, simply to get your plugin to work in the first place.
I've attached a simple text file that lists the basic functions you need to know in
order to write a dissector plugin. Although it too may be out of date now, as I
probably wrote it for 1.2.... :P
Writing a Wireshark plugin ========================== Required functions for protocol "foo": -------------------------------------- You must create these functions. The names are arbitrary, however it is strongly recommended that you follow these naming conventions so the code will be readable. void proto_register_foo(void) void proto_reg_handoff_foo(void) void dissect_foo(tvbuff_t*, packet_info*, proto_tree*) Function calls necessary for Wireshark to use your plugin: ---------------------------------------------------------- dissector_handle_t find_dissector(const char *name) dissector_handle_t create_dissector_handle(dissector_t dissector, int proto) void dissector_add(const char *name, guint32 pattern, dissector_handle_t handle) int proto_register_protocol(const char *name, const char *short_name, const char *filt_name) void proto_register_field_array(int parent, hf_register_info *hf, int num_records) void proto_register_subtree_array(gint *const *indices, int num_indices) Functions you may need when dissecting packet contents: ------------------------------------------------------- Display columns: ---------------- gint check_col (column_info *cinfo, gint el) void col_clear (column_info *cinfo, gint el) void col_set_str (column_info *cinfo, gint el, const gchar *str) void col_add_fstr (column_info *cinfo, gint el, const gchar *format,...) Processing tvbuff_t: -------------------- guint tvb_length (tvbuff_t *tvb) guint8 tvb_get_guint8 (tvbuff_t *tvb, gint offset) guint tvb_strsize (tvbuff_t *tvb, gint offset) guint16 tvb_get_ntohs (tvbuff_t *tvb, gint offset) tvbuff_t* tvb_new_subset(tvbuff_t* backing, gint backing_offset, gint backing_length, gint reported_length) Generating display tree: ------------------------ proto_item* proto_tree_add_item (proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, gboolean little_endian) proto_item* proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, gint value); proto_tree* proto_item_add_subtree (proto_item *pi, gint idx) void proto_item_append_text (proto_item *pi, const char *format,...) proto_item* proto_item_get_parent(proto_item *ti) proto_tree* proto_item_get_subtree(proto_item *ti) The length of some items cannot be determined until the item has been dissected; to add such an item, add it with a length of -1, and, when the dissection is complete, set the length with 'proto_item_set_len()': void proto_item_set_len(proto_item *ti, gint length); The "ti" argument is the value returned by the call that added the item to the tree, and the "length" argument is the length of the item. Associating a dissector with a parent protocol: ---------------------------------------------- (excerpt from http://www.wireshark.org/lists/wireshark-dev/200608/msg00036.html) "If you have a dissector for a protocol that's associated with a particular numerical value of a particular field in the parent protocol (e.g., a particular value of the Ethernet type field), the parent dissector would call register_dissector_table() in its registration routine to create the dissector table, the child dissector would call dissector_add() on that table in its handoff registration routine, and the parent dissector would call dissector_try_port() during the analysis stage. "There are similar routines for string values. "If you have a dissector for a protocol that can't be associated with particular values in the calling protocol, so you would have to look at the contents of the packet to try to guess what protocol it's for, that's a heuristic dissector. For those, the parent dissector would call register_heur_dissector_list() in its registration routine to create the heuristic dissector table, the child dissector would call heur_dissector_add() on that table in its handoff registration routine, and the parent dissector would call dissector_try_heuristic() during the analysis stage." If protocol is identified by (int) parent field: ------------------------------------------------ dissector_table_t register_dissector_table(const char *name, const char *ui_name, ftenum_t type, int base) gboolean dissector_try_port(dissector_table_t sub_dissectors, guint32 port, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) void dissector_add(const char *abbrev, guint32 pattern, dissector_handle_t handle) Dissector function has prototype: void (*dissector_t)(tvbuff_t *, packet_info *, proto_tree *) If protocol is identified by heuristic: --------------------------------------- void register_heur_dissector_list(const char *name, heur_dissector_list_t *list) gboolean dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) void heur_dissector_add(const char *name, heur_dissector_t dissector, int proto) Heuristic dissector function has prototype: gboolean (*heur_dissector_t)(tvbuff_t *, packet_info *, proto_tree *) Reassembling fragmented packets: -------------------------------- *** 1. Create and initialize tables #include <epan/reassemble.h> static GHashTable *msg_fragment_table = NULL; static GHashTable *msg_reassembled_table = NULL; // Call this once? when protocol is registered static void msg_init_protocol(void) { fragment_table_init(&msg_fragment_table); reassembled_table_init(&msg_reassembled_table); } Also: need to define additional hf globals for use by reassembly code *** 2. Save fragmented state of packet (?) save_fragmented = pinfo->fragmented; *** 3. Extract fragment info from packet (both for frag and for whole PDU) /* protocol-specific */ *** 4. Set fragmented state of packet (?) pinfo->fragmented = TRUE; *** 5. Create vars to hold tvb & frag data tvbuff_t* new_tvb = NULL; fragment_data *frag_msg = NULL; *** 6. Call fragment_add_check to add fragment fragment_data * fragment_add_check( tvbuff_t *tvb, // current tvb being dissected int offset, // offset where frag starts packet_info *pinfo, // current packet info guint32 id, // tag for whole message GHashTable *fragment_table, // list of message fragments (must init first) GHashTable *reassembled_table, // list of reassembled messages (must init first) guint32 frag_offset, guint32 frag_data_len, // fragment length - to the end gboolean more_frags); // does this frag go at the end of the message? e.g.: frag_msg = fragment_add_check(tvb, offset, pinfo, msg_seqid, msg_fragment_table, msg_reassembled_table, msg_ofst, tvb_length_remaining(tvb, offset), isLastFrag); If fragment_add_check returns NULL, then we're not done yet. If frag_msg != NULL, then reassembly is complete. *** 7. Call process_reassembled_data to create new tvb (if done) tvbuff_t * process_reassembled_data( tvbuff_t *tvb, // current tvb being dissected int offset, // offset where frag starts packet_info *pinfo, // current packet info const char *name, fragment_data *fd_head, const fragment_items *fit, gboolean *update_col_infop, proto_tree *tree); e.g.: new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message", frag_msg, &msg_frag_items, NULL, msg_tree); *** 8. Indicate status in col info if (frag_msg) /* Reassembled */ { if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)"); } else /* Not last packet of reassembled Message */ { if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, " (Msg frag %x)", msg_ofst); } *** 9. If message is complete, process it now if (new_tvb) { /* process_reassembled_data returned full packet, process it now */ process_packet(new_tvb,...) } else { /* make a new subset (?) */ next_tvb = tvb_new_subset(tvb, offset, -1, -1); } ** 10. Restore packet's original fragmented state pinfo->fragmented = save_fragmented; Troubleshooting: ================ 1. If you get a Runtime Error from MSVC when you start Wireshark: a. try building 'distclean' and then rebuilding Wireshark. b. make sure your protocol's parent creates the table/list you pass to dissector_add. c. make sure each element in your hf array matches the corresponding types.
- References:
- [Wireshark-dev] Undefined reference to proto_tree_model_new
- From: Evan Huus
- Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
- From: Guy Harris
- Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
- From: Evan Huus
- Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
- From: Guy Harris
- Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
- From: Borz, John (IPG-Roseville R&D)
- [Wireshark-dev] Undefined reference to proto_tree_model_new
- Prev by Date: [Wireshark-dev] Style question passing boolean parameters
- Next by Date: [Wireshark-dev] Problem with protocol in udp por 3800
- Previous by thread: Re: [Wireshark-dev] Undefined reference to proto_tree_model_new
- Next by thread: Re: [Wireshark-dev] [Wireshark-commits] rev 43228: /trunk/ /trunk/plugins/asn1/: packet-asn1.c /trunk/epan/dissectors/: packet-dtls.c packet-ssl.c /trunk/doc/: README.developer /trunk/epan/: libwireshark.def prefs-int.h prefs.c ...
- Index(es):