Ethereal-dev: Re: [ethereal-dev] WCCP 1.0 Decoder

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Jerry Talkington <jerryt@xxxxxxxxxx>
Date: Sat, 11 Dec 1999 17:11:37 -0800
* Guy Harris (gharris@xxxxxxxxxxxx) done spit this rhetoric:
> > +    	guint8 ip_offset;
> > +	
> > +	proto_tree_add_item_hidden(gre_tree, hf_gre_wccp, offset, sizeof(type), TRUE);
> > +    	offset += sizeof(type);    
> > +	
> > +	ip_offset = pd[offset]; 
> > +	if ((ip_offset & 0x45)) {
> > +		/* we can assume that all wccp packets are streaming ip */
> > +	} else {
> > +		/* WCCP 1 and 2 both use the same type, but v2 has an extra 4 octet header */
> > +		offset += sizeof(guint32);
> > +	}
> 
> That should perhaps be done by
> 
> 	if ((pd[offset] & 0xF0) == 0x40) {
> 		/* it's WCCPv1 */
> 	} else {
> 		/* it's presumably WCCPv2 */
> 	}
> 
> so that IP options don't cause it to misinterpret the packet as WCCP
> encapsulation for v2.
> 
> Note also that "calc_len()" would have to be changed as well, to include
> the extra 4 octets - or perhaps the "calc_len()" code should be pulled
> up into "dissect_gre()" itself, above the first
> "proto_tree_add_item_format()" call.

Okay, here's an updated version.

-- 
Jerry Talkington
NetCache Escalation Engineer
Network Appliance, Inc.

"I believe the children are our future: nasty, brutish and short."
? packet-wccp.c
Index: Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/Makefile.am,v
retrieving revision 1.131
diff -u -r1.131 Makefile.am
--- Makefile.am	1999/12/09 20:41:23	1.131
+++ Makefile.am	1999/12/12 01:04:47
@@ -146,6 +146,7 @@
 	packet-vines.h \
 	packet-vlan.c \
 	packet-vrrp.c \
+	packet-wccp.c\
 	packet-x25.c   \
 	packet-yhoo.c  \
 	packet-yhoo.h  \
Index: packet-gre.c
===================================================================
RCS file: /cvsroot/ethereal/packet-gre.c,v
retrieving revision 1.11
diff -u -r1.11 packet-gre.c
--- packet-gre.c	1999/12/10 21:27:13	1.11
+++ packet-gre.c	1999/12/12 01:04:47
@@ -42,6 +42,7 @@
 
 static gint ett_gre = -1;
 static gint ett_gre_flags = -1;
+static guint32 hf_gre_proto = -1;
 
 /* bit positions for flags in header */
 #define GH_B_C		0x8000
@@ -57,20 +58,23 @@
 
 #define GRE_PPP		0x880B
 #define	GRE_IP		0x0800
+#define GRE_WCCP	0x883e
 
-static int calc_len(guint16, int);
+/* static int calc_len(guint16, int); */
 static void add_flags_and_ver(proto_tree *, guint16, int, int);
 
+static const value_string typevals[] = {
+	{ GRE_PPP, "PPP" },
+	{ GRE_IP,  "IP" },
+	{ GRE_WCCP, "WCCP"},
+	{ 0,       NULL  }
+};
+
 void
 dissect_gre(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
   
   guint16	flags_and_ver = pntohs(pd + offset);
   guint16	type	      = pntohs(pd + offset + sizeof(flags_and_ver));
-  static const value_string typevals[] = {
-    { GRE_PPP, "PPP" },
-    { GRE_IP,  "IP" },
-    { 0,       NULL  }
-  };
   guint16	sre_af;
   guint8	sre_length;
 
@@ -83,25 +87,43 @@
   }
 		
   if (IS_DATA_IN_FRAME(offset) && tree) {
-    gboolean		is_ppp;
+    gboolean		is_ppp = FALSE;
+    gboolean		is_wccp2 = FALSE;
     proto_item *	ti;
     proto_tree *	gre_tree;
+    guint 		len = 4;
 
     is_ppp = (type == GRE_PPP);
+
+    if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R)
+    	len += 4;
+    if (flags_and_ver & GH_B_K)
+    	len += 4;
+    if (flags_and_ver & GH_B_S)
+    	len += 4;
+    if(type == GRE_PPP && flags_and_ver & GH_P_A) {
+  	    len += 4;
+    } else if(type == GRE_WCCP) {
+    	if( (pd[offset + sizeof(flags_and_ver) + sizeof(type)] & 0xF0) != 0x40 ) {
+	/* add the WCCPv2 routing info */
+		len += 4;
+		is_wccp2 = TRUE;
+	}
+    }
 
-    ti = proto_tree_add_item_format(tree, proto_gre, offset,
-      calc_len(flags_and_ver, type), NULL,
-      "Generic Routing Encapsulation (%s)",
-      val_to_str(type, typevals, "0x%04X - unknown"));
+    ti = proto_tree_add_item_format(tree, proto_gre, offset, len, NULL,
+      "Generic Routing Encapsulation (%s)", val_to_str(type, typevals, "0x%04X - unknown"));
     gre_tree = proto_item_add_subtree(ti, ett_gre);
     add_flags_and_ver(gre_tree, flags_and_ver, offset, is_ppp);
 
     offset += sizeof(flags_and_ver);
 
-    proto_tree_add_text(gre_tree, offset, sizeof(type),
-			"Protocol Type: %s (%#04x)",
-			val_to_str(type, typevals, "Unknown"), type);
-    offset += sizeof(type);    
+    proto_tree_add_item(gre_tree, hf_gre_proto, offset, sizeof(type), type);
+    offset += sizeof(type);
+    if(is_wccp2) {
+    	proto_tree_add_text(gre_tree, offset, sizeof(guint32), "WCCPv2 Data");
+    	offset += 4;
+    }
 
     if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
       guint16 checksum = pntohs(pd + offset);
@@ -174,39 +196,19 @@
 
     switch (type) {
       case GRE_PPP:
- 	dissect_payload_ppp(pd, offset, fd, tree);
+	dissect_payload_ppp(pd, offset, fd, tree);
  	break;
       case GRE_IP:
+      case GRE_WCCP:
         dissect_ip(pd, offset, fd, tree);
         break;
       default:
 	dissect_data(pd, offset, fd, gre_tree);
+	break;
     }
   }
 }
 
-static int
-calc_len(guint16 flags_and_ver, int type)
-{
-  int	len = 4;
-  
-  if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R)
-    len += 4;
-  if (flags_and_ver & GH_B_K)
-    len += 4;
-  if (flags_and_ver & GH_B_S)
-    len += 4;
-  switch (type) {
-
-  case GRE_PPP:
-    if (flags_and_ver & GH_P_A)
-      len += 4;
-    break;
-  }
-  
-  return len;
-}
-
 static void
 add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) {
 
@@ -258,16 +260,18 @@
 void
 proto_register_gre(void)
 {
-/*        static hf_register_info hf[] = {
-                { &variable,
-                { "Name",           "gre.abbreviation", TYPE, VALS_POINTER }},
-        };*/
+	static hf_register_info hf[] = {
+		{ &hf_gre_proto,
+			{ "Protocol Type", "gre.proto", FT_UINT16, BASE_HEX, VALS(typevals), 0x0,
+				"The protocol that is GRE encapsulated"}
+		},
+	};
 	static gint *ett[] = {
 		&ett_gre,
 		&ett_gre_flags,
 	};
 
         proto_gre = proto_register_protocol("Generic Routing Encapsulation", "gre");
- /*       proto_register_field_array(proto_gre, hf, array_length(hf));*/
+        proto_register_field_array(proto_gre, hf, array_length(hf));
 	proto_register_subtree_array(ett, array_length(ett));
 }
Index: packet-udp.c
===================================================================
RCS file: /cvsroot/ethereal/packet-udp.c,v
retrieving revision 1.42
diff -u -r1.42 packet-udp.c
--- packet-udp.c	1999/12/09 20:41:26	1.42
+++ packet-udp.c	1999/12/12 01:04:48
@@ -95,6 +95,7 @@
 #define UDP_PORT_RX_LOW 7000
 #define UDP_PORT_RX_HIGH 7009
 #define UDP_PORT_RX_AFS_BACKUPS 7021
+#define UDP_PORT_WCCP	2048
 
 struct hash_struct {
   guint16 proto;
@@ -308,6 +309,8 @@
 	dissect_icp(pd,offset,fd,tree);
  } else if ( PORT_IS(UDP_PORT_ICQ)) {
         dissect_icq(pd,offset,fd,tree);
+ } else if (PORT_IS(UDP_PORT_WCCP) ) {
+ 	dissect_wccp(pd, offset, fd, tree);
  } else {
       /* OK, find a routine in the table, else use the default */
 
Index: packet.h
===================================================================
RCS file: /cvsroot/ethereal/packet.h,v
retrieving revision 1.159
diff -u -r1.159 packet.h
--- packet.h	1999/12/09 04:06:54	1.159
+++ packet.h	1999/12/12 01:04:48
@@ -406,6 +406,7 @@
 void dissect_vines_spp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_vlan(const u_char *, int, frame_data *, proto_tree *);
 void dissect_vrrp(const u_char *, int, frame_data *, proto_tree *);
+void dissect_wccp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_payload_ppp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_x25(const u_char *, int, frame_data *, proto_tree *);
 void dissect_yhoo(const u_char *, int, frame_data *, proto_tree *);