Ethereal source code analysis, compilation, and usage steps
Ethereal is a packet capture software, and is the predecessor of Wireshark, a well-known packet capture software.
: Http://www.ethereal.com/distribution/all-versions/
Ethereal depends on GTK +, glib, and Libpcap.
GTK +: ftp://ftp.gtk.org/pub/gtk/v1.2/
Glib: ftp://ftp.gtk.org/pub/gtk/v1.2/
Libpcap: http://www.tcpdump.org/
The version I used here is
Glib-1.2.9.tar.gz
Gtk316-1.2.9.tar.gz
Libpcap-1.2.0rc1.tar.gz
Ethereal-0.8.10.tar.gz
All source code packages are stored in the/OPT directory.
[Source code compilation]
Compile libpcap
Tar-zxvf libpcap-1.2.0rc1.tar.gz
Mkdir/ usr/local/libpcap-1.2.0
CD libpcap-1.2.0
./Configure -- prefix =/usr/local/libpcap-1.2.0/
Make
Make install
// Go to the/usr/local/libpcap-1.2.0/include/directory, copy the pcap subdirectory, and rename it to net
CD/usr/local/libpcap-1.2.0/include/
CP-R./pcap./Net
Compile glib
Tar-zxvf glib-1.2.9.tar.gz
Mkdir/usr/local/glib-1.2.9
CD glib-1.2.9
./Configure -- prefix =/usr/local/glib-1.2.9/
Make
// The error gstrfuncs. c 870: Error: Expected ') 'Before String constant will be reported during compilation. In this case, you need to modify the source code gstrfuncs. C,
Comment out the g_warning function call and make the same changes to the following errors:
Make install
Compile GTK +
Tar-zxvf gtkw.-1.2.9.tar.gz
Mkdir/usr/local/GTK +-1.2.9
Cd gtk +-1.2.9
./Configure -- prefix =/usr/local/GTK +-1.2.9/-- With-glib-Prefix =/usr/local/glib-1.2.9/-- disable-glibtest
Make
Make install
Compile Ethereal
Tar-zxvf ethereal-0.8.10.tar.gz
Mkdir/usr/local/ethereal-0.8.10
CD ethereal-0.8.10
// Modify the configure file
Vim./configure
Go to # evidently, some systems have pcap. H, etc. In */include/pcap,
Replace the directory in for pcap_dir in/usr/include/pcap/usr/local/include/pcap with our own libpcap directory.
For pcap_dir in/usr/local/libpcap-1.2.0/include
. /Configure -- prefix =/usr/local/ethereal-0.8.10/-- With-glib-Prefix =/usr/local/glib-1.2.9/-- With-GTK-Prefix =/usr/ local/GTK +-1.2.9/-- includedir =/usr/local/libpcap-1.2.0/include/-- libdir =/usr/local/libpcap-1.2.0/lib/-- disable-gtktest -- disable-glibtest
Make
// An error occurs during compilation:
Capture. C: 112 error: the static statement for 'sync _ pipe' appears after the non-static statement
Captrue. h: 35: error: the previous declaration of 'sync _ pipe 'Here
Modify the capture. C source file and remove the keyword static of static int sync_pipe [2];. Make the same modification for the following errors:
Make install
[Ethereal usage]
Before use, the export libpcap, glib, and GTK +
Export LD_LIBRARY_PATH =/usr/local/The libpcap-1.2.0/lib: $ LD_LIBRARY_PATH
Export LD_LIBRARY_PATH =/usr/local/glib-1.2.9/lib: $ LD_LIBRARY_PATH
Export LD_LIBRARY_PATH =/usr/local/GTK +-1.2.9/lib: $ LD_LIBRARY_PATH
Ethereal-0.8.10 default fonts used-*-lucidatypewriter-Medium-r-normal-*-120-*-iso8859-1 loaded on GTK +-1.2.9 failed,
Use the xlsfonts program to view available fonts and find that the fixed font can be loaded successfully.
CD, USR, local, ethereal-0.8.10, bin/
./Ethereal-m fixed-B fixed
[Ethereal source code analysis]
Ethereal Process
The main function selects whether to call do_capture or capture based on the parameter, and do_capture calls capture internally.
Capture uses libpcap to capture Nic packets.
Dfilter_compile displays the filter compilation function.
Dfilter_apply applies the compiled display filter function to the Protocol tree.
Follow_stream_cb outputs the captured data packets in the default ASCII format according to the display filter.
Important data structures
Typedef struct _ capture_file {file_t FH;/* the captured packet file handle */INT filed;/* the captured packet file descriptor */gchar * filename; /* The name of the captured data packet file */gboolean is_tempfile;/* Is it a captured data packet file or a temporary file? */Gboolean user_saved;/* If the captured data packet file is temporary, has it been saved by the user? */Long f_len;/* the length of the data packet file */guint16 cd_t;/* the file type of the data packet file */INT lnk_t;/* The link layer type of the captured data packet */guint32 vers; /* version */guint32 count;/* Number of data packets */gfloat unfiltered_count;/* unfiltered quantity for display of filter progress bars */guint32 drops; /* lost data packet */guint32 esec;/* number of seconds */guint32 EUSEC;/* Number of milliseconds */guint32 snap; /* the length of the captured data packet */gboolean update_progbar;/* set it to true when we update the progress bar */long progbar_quantum; /* number of bytes read during each progress bar update */long progbar_nextstep;/* time when the progress bar should be updated next */gchar * iface; /* Network Interface */gchar * save_file;/* Name of the file where the user saves the captured data packet */INT save_file_fd; /* the descriptor of the captured data packet file */wtap * wth;/* wiretap session */dfilter * rfcode; /* compiled read filter program */gchar * dfilter;/* display filter string */colfilter * colors;/* color of the colored data packet window */dfilter * dfcode; /* compiled display filter program */# ifdef have_libpcap gchar * cfilter;/* capture packet filter expression used by libpcap */bpf_prog fcode; /* compiled libpcap capture filter program */# endif gchar * sfilter;/* Find the filter string */gboolean sbackward;/* It is true when searching backward, forward is false */guint8 Pd [wtap_max_packet_size];/* data packet */frame_data * plist;/* data packet list */frame_data * plist_end; /* the last frame in the data packet linked list */frame_data * first_displayed;/* The first display frame */frame_data * last_displayed;/* The Last display frame */column_info Cinfo; /* column format information */frame_data * current_frame;/* frame data of the current frame */INT current_row;/* row of the current frame */gboolean current_frame_is_selected; /* if the current frame is selected, it is true */proto_tree * protocol_tree;/* protocol tree of the selected data packet */file * print_fh; /* the file handle to be printed */} capture_file; typedef struct _ frame_data {struct _ frame_data * Next;/* The next node of the linked list */struct _ frame_data * Prev; /* the previous node of the linked list */guint32 num;/* frame number */guint32 pkt_len;/* package length */guint32 cap_len; /* Actual captured data length */guint32 rel_secs;/* relative seconds */guint32 rel_usecs;/* relative milliseconds */guint32 abs_secs; /* absolute seconds */guint32 abs_usecs;/* absolute milliseconds */guint32 del_secs;/* Number of difference seconds */guint32 del_usecs; /* milliseconds */long file_off;/* file offset */column_info * Cinfo;/* column format information */Gint row; /* the row serial number of this data packet */INT lnk_t;/* encapsulation type of each data packet */gboolean passed_dfilter;/* true = display, false = not display */char_enc encoding; /* character encoding (ASCII, ebcdic ...) */Union pseudo-header pseudo do_header;/* "pseudo-header" from wiretap */} frame_data; typedef strugnode proto_tree; typedef struct _ packet_info {int Len; int captured_len; address dl_src; /* Mac Source Address */address dl_dst;/* Mac Destination Address */address net_src;/* IP Source Address */address net_dst;/* IP Destination Address */address SRC; /* Source Address */address DST;/* Destination Address */guint32 ipproto; port_type ptype;/* type of the following two ports */guint32 srcport; /* Source Port */guint32 destport;/* destination port */guint32 match_port; int iplen; int iphdrlen;} packet_info; typedef struct _ address {address_type type; /* address type */INT Len;/* address length (in bytes) */const guint8 * data;/* data that forms the address */} address;
When the menu "capture"-> "options" is opened, the system process capture_prep_cb (gtkwidget * w, gpointer d) | _ if_list = get_interface_list (); // obtain available NICs | _ // display various configuration controls | _ gtk_signal_connect (gtk_object (OK _bt), "clicked", gtk_signal_func (capture_prep_ OK _cb), gtk_object (cap_open_w )); // register the signal. When you click "OK", call the capture_prep_ OK _cb function handler (gtkwidget * OK _bt, gpointer parent_w) | _ if_text = g_strdup (gtk_entry_get_text (gtk_entry (GTK _ Combo (if_cb)-> entry); // obtain the specified Nic | _ filter_text = gtk_entry_get_text (gtk_entry (filter_te); // obtain the Libpcap filter expression | _ cf. cfilter = g_strdup (filter_text); // fill the current libpcap filter expression in CF | _ save_file = gtk_entry_get_text (gtk_entry (file_te )); // obtain the path of the file to be saved | _ do_capture (save_file); // start to capture data do_capture (char * capfile_name) | _ if (capfile_name! = NULL) {cf. save_file_fd = open (capfile_name, o_rdwr | o_trunc | o_creat, 0600) ;}// if capfile_name is not empty, open the file in the given path and save the file handle | _ else {cf. save_file_fd = create_tempfile (tmpname, sizeof tmpname, "Ether");} // create a temporary file and save the file handle | _ close_cap_file (& CF, info_bar ); // reset the fields related to the CF struct | _ if (sync_mode) // If the synchronization mode is Fork () // create the sub-process execlp (ethereal_path, // start ethereal I = read (sync_pipe [0], & C, 1) with appropriate parameters; // The parent process reads the content written to the pipeline by the child process. I = = 0? // The sub-process exits abnormally, closes the MPs queue, deletes the file, and returns the prompt C ==; break; // jumps out of the loop if (! Isdigit (c) // The sub-process fails to process. The parent process closes the MPs queue and deletes the file. A prompt is displayed, and byte_count = byte_count * 10 + C-'0' is returned '; // calculate byte_count | _ if (byte_count = 0) {err = start_tail_cap_file (cf. save_file, is_tempfile, & CF) ;}// successful. Open the recorded file else {I = read (sync_pipe [0], MSG, byte_count);} // failed, receive the error message sent by the sub-process, displayed | _ else // not in synchronization mode capture_succeeded = capture (); // call capture to capture packets | _ if (capture_succeeded) // open_cap_file (cf. save_file, is _ Tempfile, & CF) // open the captured data file read_cap_file (& CF); // read the file | _ success = wtap_loop (CF-> wth, 0, wtap_dispatch_cb, (u_char *) Cf, & ERR); // enter wtap_loop. Call the wtap_dispatch_cb function every time a packet is obtained. | _ CF-> lnk_t = wtap_file_encap (CF-> WTH ); // set the wtap descriptor encapsulation type | _ wtap_close (CF-> WTH); // disable the wtap descriptor wtap_dispatch_cb (u_char * user, const struct wtap_pkthdr * phdr, int offset, const u_char * BUF); // The wtap callback function. This function is called every time the wtap obtains a data packet. | _ FD ATA = (frame_data *) g_malloc (sizeof (frame_data); // The requested memory is used to save the data of one frame. | _ protocol_tree = proto_tree_create_root (); // create a protocol tree | _ dissect_packet (BUF, fdata, protocol_tree); // analyze a data packet | _ proto_tree_add_item_format () // Add a tree in the security protocol tree format | _ fh_tree = proto_item_add_subtree (Ti, ett_frame); // Add a subtree | _ proto_tree_add_item (fh_tree, hf_frame_arrival_time, // Add the frame arrival time | _ proto_tree_add_item (fh_tree, hf_frame_time_delta ,/ /Interval between adding frames and the arrival time of the previous package | _ proto_tree_add_item (fh_tree, hf_frame_number, // sequence number of adding frames | _ proto_tree_add_item_format (fh_tree, hf_frame_packet_len, // length of the package for adding frames | _ proto_tree_add_item_format (fh_tree, hf_frame_capture_len, // Add the length of the actually captured package | _ blk_packetinfo (); // set null packet information the relevant field of the data structure | _ case wtap_encap_ethernet: dissect_eth (PD, 0, FD, tree); // according to the encapsulation type of the data packet, parsing | _ set_address (& Pi. dl_src, at_ether, 6, & PD [Offset + 6]); // Set the Mac source address | _ set_address (& Pi. dl_dst, at_ether, 6, & PD [Offset + 0]); // set the Mac Destination Address | _ etype = pntohs (& PD [Offset + 12]); // obtain the Ethernet data type | _ proto_tree_add_item_format // Add a tree in the security protocol tree format | _ proto_item_add_subtree // Add a subtree | _ proto_tree_add_item (fh_tree, hf_eth_dst, offset + 0, 6, & PD [Offset + 0]); // Add the target Mac | _ proto_tree_add_item (fh_tree, hf_eth_src, offset + 6, 6, & PD [Offset + 6]); // Add source MAC | _ ethertype (etype, offset, PD, F D, tree, fh_tree, hf_eth_type); // analyze data packets based on the Ethernet type | _ proto_tree_add_item (fh_tree, item_id, offset-2, 2, etype ); // Add a type | _ dissect_ip (PD, offset, FD, tree); // analyze the IP data packet | _ passed = dfilter_apply (CF-> rfcode, protocol_tree, CF-> PD); // application display filter | _ proto_tree_free (protocol_tree); // release protocol tree resources | _ CF-> plist = fdata; // point the CF-> plist pointer to the analyzed data fdata | _ add_packet_to_packet_list (fdata, CF, Buf); // Add the analyzed data to the data Package list when you enter an expression in the display filter edit box and press the Enter key, the system process is filter_activate_cb (gtkwidget * w, gpointer data) | _ char * s = gtk_entry_get_text (gtk_entry (w); // obtain the edit box string | _ filter_packets (& CF, g_strdup (s) // use this filter expression to filter data packets, then re-display it on the list control | _ dfilter_compile (dftext, & dfcode) // compile the filter, which contains the analysis syntax process | _ g_free (CF-> dfilter ); // release the dfilter field of the CF struct | _ CF-> dfilter = dftext; // re-assign the dfilter field of the CF struct | _ dfilter_destroy (CF-> dfcode ); // release the CF struct Dfcode FIELD | _ CF-> dfcode = dfcode; // re-assign the dfcode field of the CF struct | _ colorize_packets (CF); // traverse the linked list of parsed packets, display the compliant packet | _ conversation_init (); // initialize the session table | _ init_all_protocols (); // initialize a specific protocol variable | _ gtk_clist_freeze (gtk_clist (packet_list); // disable the data packet list control | _ gtk_clist_clear (gtk_clist (packet_list )); // clear the data packet list | _ For (FD = CF-> plist; FD! = NULL; FD = FD-> next) // traverse the data packet linked list {wtap_seek_read (CF-> cd_t, CF-> FH, FD-> file_off, CF-> PD, FD-> cap_len); // read the data packet content add_packet_to_packet_list (FD, CF, CF-> PD ); // Add this data packet to the data packet list control} | _ gtk_clist_moveto (gtk_clist (packet_list), CF-> current_row,-1, 0.0, 0.0 ); // move to the row of the data packet specified by current_row | _ gtk_clist_select_row (gtk_clist (packet_list), CF-> current_row,-1 ); // select this row | _ gtk_clist_thaw (gtk_clist (packet_list); // enable the data packet list control. When you select a row in the data column, call packet_list_select_cb (gtkwidget * w, Gint row, gint Col, gpointer EVT) | _ blank_packetinfo (); // related fields in the data structure of null packet information | _ select_packet (& CF, row ); // select the data packet of this row | _ wtap_seek_read (); // obtain the data of this frame | _ proto_tree_create_root (); // create a protocol tree | _ dissect_packet (); analysis of this frame of data packet when the selected TCP packet is "follow TCP stream" Operation follow_stream_cb (gtkwidget * w, gpointer data) | _ tmp_fd = create_tempfile (filename1, sizeof filename1, "Follow"); // create a temporary file | _ data_out_file = fdopen (tmp_fd, "W"); // open this temporary file | _ reset_tcp_reassembly (); // reset TCP Assembly | _ follow_filter = build_follow_filter (& PI); // generate the follow filter expression | _ filter_packets (& CF, follow_filter ); // filter data packets | _ dfilter_compile (dftext, & dfcode); // compile the filter | _ df = dfilter_new (); // create a new filter | _ dfilter_scanner_text (dfilter_text ); // tell the scanner to use a filter expression string as the input | _ retval = dfilter_parse (); // analysis syntax | _ dfilter_scanner_cleanup (); // clear scanner rules | _ colorize_packets (CF ); // color the filtered data packet | _ follow_load_text (text, filename1, true); // display the analyzed data to the text control.