Adding Layer 2 Protocol Dissectors to Ethereal (aka WireShark)


Procedure:

To perform Layer 2 packet decoding, code modifications are made to Ethereal’s LLC protocol handler (packet-llc.c). These modifications will force Ethereal to call a custom Layer 2 dissector when an LLC/SNAP segment is captured that contains the OUI (Organizational Unit Identifier) we are looking for. Other source files might need modification as well to support the additional Layer 2 detection and dissection. Additional source code files will need to be added to the Ethereal project to handle dissection of the Layer 2 packets. Once the LLC protocol handler has been modified newly the detected Layer 2 packets can be handed off to standard Ethereal plugins.

Figure 2, Screen Capture of Ethereal's User Interface with added Layer 2 dissection.

 

Files that may need modification:

  Ethereal file "epan\oui.h"

This header file contains definitions for Organizational Unit Identifiers. If the OUI associated with the new Layer 2 protocol is not already in this file, it will need to be added. For the following example a new constant representing the new OUI is named OUI_MYOUI.

  Ethereal file "epan\dissectors\packet-llc.c"

This source code file contains functions to handle capture and dissection of LLC and SNAP segments. Three major modifications are required in this file. The text description for Layer 2 OUI must be added to the existing list of OUI text descriptions in the oui_vals[ ] array.

const value_string oui_vals[ ] = {
	{ OUI_ENCAP_ETHER, "Encapsulated Ethernet" },
	{ OUI_CISCO,       "Cisco" },
	{ OUI_CISCO_90,    "Cisco IOS 9.0 Compatible" },
	{ OUI_BRIDGED,     "Frame Relay or ATM bridged frames" },
	{ OUI_ATM_FORUM,   "ATM Forum" },
	{ OUI_CABLE_BPDU,  "DOCSIS Spanning Tree" }, /* DOCSIS spanning tree BPDU */
	{ OUI_APPLE_ATALK, "Apple (AppleTalk)" },
/* Begin new code */
	{ OUI_MYOUI,       "My Organization" },
/* End new code */
	{ 0,               NULL }
};		
		
		

The capture_llc() function can also be modified to count the new Layer 2 packets as they arrive during a capture. ( Wireshark 0.99.5 note: this code has been moved out to capture_snap() )

		
void 
capture_llc(const u_char *pd, int offset, packet_counts *ld) {

...

  if (is_snap) {
	oui = pd[offset+3] << 16 | pd[offset+4] << 8 | pd[offset+5];

	if (XDLC_IS_INFORMATION(control)) {
		etype = pntohs(&pd[offset+6]);
		switch (oui) {
		
		case OUI_ENCAP_ETHER:
		case OUI_CISCO_90:
		case OUI_APPLE_ATALK:
			/* No, I have no idea why Apple used
			   one of their own OUIs, rather than
			   OUI_ENCAP_ETHER, and an Ethernet
			   packet type as protocol ID, for
			   AppleTalk data packets - but used
			   OUI_ENCAP_ETHER and an Ethernet
			   packet type for AARP packets. */
			capture_ethertype(etype, offset+8, pd,
				ld);
			break;
		
		case OUI_CISCO:
			capture_ethertype(etype,
					offset + 8, pd, ld);
			break;
/* Begin new code */
		case OUI_MYOUI:			
			/* Example: double check header info, modify accordingly */
			/* Make sure PID is correct */
			if(etype = 0x8001)  
			{
				/* Increment my L2 message counter */
				ld->myl2p++;
			}
			else
			{
				/* We don't know what this is, increment 'other' */
				ld->other++;
			}

			break;
/* End new code */
		default:
			ld->other++;
			break;
		}

	}		
...
}
		
		
		

Finally, the dissect_snap() function needs to be modified to call the Layer 2 dissector in added packet-my-layer2.c source code file when a SNAP segment arrives with the proper Layer 2 OUI. The code comments and structure of the code in these areas show how the developers did not expect anyone to add any new Layer 2 protocol detection to the software.

void
dissect_snap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
    proto_tree *snap_tree, int control, int hf_oui, int hf_type, int hf_pid,
    int bridge_pad)
{
	guint32		oui;
	guint16		etype;
	tvbuff_t	*next_tvb;

	oui =	tvb_get_ntoh24(tvb, offset);
	etype = tvb_get_ntohs(tvb, offset+3);

	if (check_col(pinfo->fd, COL_INFO)) {
		col_append_fstr(pinfo->fd, COL_INFO,
		    "; SNAP, OUI 0x%06X (%s), PID 0x%04X",
		    oui, val_to_str(oui, oui_vals, "Unknown"), etype);
	}
	if (tree) {
		proto_tree_add_uint(snap_tree, hf_oui, tvb, offset, 3, oui);
	}

	switch (oui) {
	...
	
/* Begin new code */
	case OUI_MYOUI:
		/* Show PID */
		proto_tree_add_uint(snap_tree, hf_pid, tvb, offset + 3, 2, etype);
		/* Call my L2 protocol dissector */
		next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
		call_dissector(my_l2_handle, next_tvb, pinfo, tree);
		break;
/* End new code */
...

	default:
		if (tree) {
			proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2,
			    etype);
		}
		next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
		dissect_data(next_tvb, 0, pinfo, tree);
		break;
	}
}		
		
		

Continue....









 

© 2002 Kazimer Corp.
1010 University Ave. PMB #1862
San Diego, CA 92103-3395