Ethereal-dev: [Ethereal-dev] 802.11 patch

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

From: Carl Miller <chaz@xxxxxxxxxxx>
Date: Fri, 6 Jul 2001 18:05:21 -0700 (PDT)
Hi folks.  We've started using Ethereal as a packet dump viewer in
conjunction with our own in-house 802.11 sniffer, which we've just
modified to save dumps in pcap format.  I've noticied several bugs
in the 802.11 dissection of Ethereal 0.8.18, and I'd like to give
you a patch against that revision that resolves all issues I've
found so far.

The chunks of this patch fall into three categories:
1) straightforward bugfixes for places where the 802.11 spec was
   misread or misunderstood
2) enclosing the parameter of macros in its own set of parentheses
   to keep the intent of the macro intact regardless of what argument
   is passed to it
3) changed verbiage in the "DS status" field to something more
   descriptive

That third category may be controversial.  There's only one chunk that
falls into that category, being the second to last chunk of the patch,
the one headered "@@ -1409,10 +1381,10 @@".  If you feel that I've
strayed too far from the "official terminology of the spec" by getting
more descriptive in more layman-friendly terms, please let me know and
I'll submit an alternate patch to use there.  There is a legitimate bug
in that table, and I'd rather be given a second chance to fix the bug
without a change in verbiage than leave the bug outstanding if you decide
you don't like my first patch.


Thanks for creating such a wonderfully useful tool.  I'm glad to have
the opportunity to contribute to it.  I'm releasing my patch to you
under the terms of the GNU General Public License (GPL), version 2, or
any later version at your option.



-------------------------------------------
Carl Miller               Firmware Engineer
chaz@xxxxxxxxxxx              Gordian, Inc.
(714) 850-0205       http://www.gordian.com





--- packet-ieee80211.c.orig	Fri Jul  6 12:48:27 2001
+++ packet-ieee80211.c	Fri Jul  6 17:36:41 2001
@@ -68,32 +68,32 @@
 /* ************************************************************************* */
 /*  Define some very useful macros that are used to analyze frame types etc. */
 /* ************************************************************************* */
-#define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))	/* Create key to (sub)type */
-#define COOK_PROT_VERSION(x)  ((x & 0x3))
-#define COOK_FRAME_TYPE(x)    ((x & 0xC) >> 2)
-#define COOK_FRAME_SUBTYPE(x) ((x & 0xF0) >> 4)
-#define COOK_ADDR_SELECTOR(x) (((x & 0x2)) && ((x & 0x1)))
-#define COOK_ASSOC_ID(x)      ((x & 0x3FFF))
-#define COOK_FRAGMENT_NUMBER(x) (x & 0x000F)
-#define COOK_SEQUENCE_NUMBER(x) ((x & 0xFFF0) >> 4)
-#define COOK_FLAGS(x)           ((x & 0xFF00) >> 8)
-#define COOK_DS_STATUS(x)       (x & 0x3)
+#define COMPOSE_FRAME_TYPE(x) ((((x) & 0x0C)<< 2)+(((x) & 0xF0) >> 4))	/* Create key to (sub)type */
+#define COOK_PROT_VERSION(x)  ((x) & 0x3)
+#define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
+#define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
+#define COOK_ADDR_SELECTOR(x) (((x) & 0x0300) >> 8)
+#define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
+#define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
+#define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
+#define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
+#define COOK_DS_STATUS(x)       ((x) & 0x3)
 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
 col_add_str(fd,COL_INFO,info);
 
-#define IS_TO_DS(x)            ((x & 0x1))
-#define IS_FROM_DS(x)          ((x & 0x2))
-#define HAVE_FRAGMENTS(x)      ((x & 0x4))
-#define IS_RETRY(x)            ((x & 0x8))
-#define POWER_MGT_STATUS(x)    ((x & 0x10))
-#define HAS_MORE_DATA(x)       ((x & 0x20))
-#define IS_WEP(x)              ((x & 0x40))
-#define IS_STRICTLY_ORDERED(x) ((x & 0x80))
-
-#define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
-#define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
-#define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
-#define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
+#define IS_TO_DS(x)            ((x) & 0x0100)
+#define IS_FROM_DS(x)          ((x) & 0x0200)
+#define HAVE_FRAGMENTS(x)      ((x) & 0x0400)
+#define IS_RETRY(x)            ((x) & 0x0800)
+#define POWER_MGT_STATUS(x)    ((x) & 0x1000)
+#define HAS_MORE_DATA(x)       ((x) & 0x2000)
+#define IS_WEP(x)              ((x) & 0x4000)
+#define IS_STRICTLY_ORDERED(x) ((x) & 0x8000)
+
+#define MGT_RESERVED_RANGE(x) ((((x)>=0x06)&&((x)<=0x07))||(((x)>=0x0D)&&((x)<=0x0F)))
+#define CTRL_RESERVED_RANGE(x) (((x)>=0x10)&&((x)<=0x19))
+#define DATA_RESERVED_RANGE(x) (((x)>=0x28)&&((x)<=0x2f))
+#define SPEC_RESERVED_RANGE(x) (((x)>=0x30)&&((x)<=0x3f))
 
 
 /* ************************************************************************* */
@@ -144,8 +144,8 @@
 /* ************************************************************************* */
 /*          Macros used to extract information about fixed fields            */
 /* ************************************************************************* */
-#define ESS_SET(x) ((x & 0x0001))
-#define IBSS_SET(x) ((x & 0x0002))
+#define ESS_SET(x) ((x) & 0x0001)
+#define IBSS_SET(x) ((x) & 0x0002)
 
 
 
@@ -283,7 +283,7 @@
 {
   guint16 frame_control;
 
-  frame_control = pntohs (pd);
+  frame_control = pletohs (pd);
   return ((IS_FROM_DS(frame_control))
 	  && (IS_TO_DS(frame_control))) ? 30 : 24;
 }
@@ -388,14 +388,8 @@
       dataptr = tvb_get_ptr (tvb, offset, 8);
       memset (out_buff, 0, SHORT_STR);
       snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
-		BIT_SWAP (dataptr[7]),
-		BIT_SWAP (dataptr[6]),
-		BIT_SWAP (dataptr[5]),
-		BIT_SWAP (dataptr[4]),
-		BIT_SWAP (dataptr[3]),
-		BIT_SWAP (dataptr[2]),
-		BIT_SWAP (dataptr[1]),
-		BIT_SWAP (dataptr[0]));
+		dataptr[7], dataptr[6], dataptr[5], dataptr[4],
+		dataptr[3], dataptr[2], dataptr[1], dataptr[0]);
 
       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
       break;
@@ -403,110 +397,86 @@
 
     case FIELD_BEACON_INTERVAL:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
       proto_tree_add_uint (tree, ff_beacon_interval, tvb, offset, 2,
-			   pntohs (temp16));
+			   pletohs (temp16));
       break;
 
 
     case FIELD_CAP_INFO:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[0] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
 
       cap_item = proto_tree_add_uint_format (tree, ff_capture, 
 					     tvb, offset, 2,
-					     pntohs (temp16),
+					     pletohs (temp16),
 					     "Capability Information: %04X",
-					     pntohs (temp16));
+					     pletohs (temp16));
       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
-			      pntohs (temp16));
+			      pletohs (temp16));
       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
-			      pntohs (temp16));
+			      pletohs (temp16));
       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
-			      pntohs (temp16));
-      if (ESS_SET (pntohs (temp16)) != 0)	/* This is an AP */
+			      pletohs (temp16));
+      if (ESS_SET (pletohs (temp16)) != 0)	/* This is an AP */
 	proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
-			     ((pntohs (temp16) & 0xC) >> 2));
+			     ((pletohs (temp16) & 0xC) >> 2));
 
       else			/* This is a STA */
 	proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
-			     ((pntohs (temp16) & 0xC) >> 2));
+			     ((pletohs (temp16) & 0xC) >> 2));
       break;
 
 
     case FIELD_AUTH_ALG:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
       proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2,
-			   pntohs (temp16));
+			   pletohs (temp16));
       break;
 
 
     case FIELD_AUTH_TRANS_SEQ:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
       proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2,
-			   pntohs (temp16));
+			   pletohs (temp16));
       break;
 
 
     case FIELD_CURRENT_AP_ADDR:
       dataptr = tvb_get_ptr (tvb, offset, 6);
-      memset (out_buff, 0, SHORT_STR);
-      out_buff[0] = BIT_SWAP (dataptr[5]);
-      out_buff[1] = BIT_SWAP (dataptr[4]);
-      out_buff[2] = BIT_SWAP (dataptr[3]);
-      out_buff[3] = BIT_SWAP (dataptr[2]);
-      out_buff[4] = BIT_SWAP (dataptr[1]);
-      out_buff[5] = BIT_SWAP (dataptr[0]);
-
-      proto_tree_add_string (tree, ff_current_ap, tvb, offset, 6, out_buff);
+      proto_tree_add_ether (tree, ff_current_ap, tvb, offset, 6, dataptr);
       break;
 
 
     case FIELD_LISTEN_IVAL:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
       proto_tree_add_uint (tree, ff_listen_ival, tvb, offset, 2,
-			   pntohs (temp16));
+			   pletohs (temp16));
       break;
 
 
     case FIELD_REASON_CODE:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pntohs (temp16));
+      temp16 = (guint16 *) dataptr;
+      proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pletohs (temp16));
       break;
 
 
     case FIELD_ASSOC_ID:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pntohs (temp16));
+      temp16 = (guint16 *) dataptr;
+      proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pletohs (temp16));
       break;
 
     case FIELD_STATUS_CODE:
       dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      temp16 = (guint16 *) dataptr;
       proto_tree_add_uint (tree, ff_status_code, tvb, offset, 2,
-			   pntohs (temp16));
+			   pletohs (temp16));
       break;
     }
 }
@@ -616,7 +586,7 @@
 
       snprintf (out_buff, SHORT_STR,
 		"Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
-		"Hop Index %2d", pntohs (tag_data_ptr), tag_data_ptr[2],
+		"Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
 		tag_data_ptr[3], tag_data_ptr[4]);
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
@@ -650,7 +620,7 @@
       snprintf (out_buff, SHORT_STR,
 		"CFP count %u, CFP period %u, CFP max duration %u, "
 		"CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
-		pntohs (tag_data_ptr + 2), pntohs (tag_data_ptr + 4));
+		pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
 			     tag_len, out_buff);
@@ -682,7 +652,7 @@
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
-		pntohs (tag_data_ptr));
+		pletohs (tag_data_ptr));
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
 			     tag_len, out_buff);
@@ -791,11 +761,11 @@
 
       if ((COMPOSE_FRAME_TYPE(fcf))==CTRL_PS_POLL) 
 	proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
-			    COOK_ASSOC_ID(tvb_get_ntohs(tvb,2)));
+			    COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
      
       else
 	  proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
-			       tvb_get_ntohs (tvb, 2));
+			       tvb_get_letohs (tvb, 2));
     }
 
   /* Perform tasks which are common to a certain frame type */
@@ -808,11 +778,13 @@
 
 
       if (check_col (pinfo->fd, COL_DEF_SRC))
-	col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X",
+	col_add_fstr (pinfo->fd, COL_DEF_SRC,
+                      "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
 		      src[0], src[1], src[2], src[3], src[4], src[5]);
 
       if (check_col (pinfo->fd, COL_DEF_DST))
-	col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X",
+	col_add_fstr (pinfo->fd, COL_DEF_DST,
+                      "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
 		      dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
 
       if (tree)
@@ -827,11 +799,11 @@
 				tvb_get_ptr (tvb, 16, 6));
 
 	  proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-			       COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+			       COOK_FRAGMENT_NUMBER (tvb_get_letohs
 						     (tvb, 22)));
 
 	  proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-			       COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+			       COOK_SEQUENCE_NUMBER (tvb_get_letohs
 						     (tvb, 22)));
 	  cap_len = cap_len - MGT_FRAME_LEN - 4;
 	}
@@ -859,14 +831,14 @@
 
 
 	case DATA_ADDR_T2:
-	  src = tvb_get_ptr (tvb, 16, 6);
-	  dst = tvb_get_ptr (tvb, 4, 6);
+	  src = tvb_get_ptr (tvb, 10, 6);
+	  dst = tvb_get_ptr (tvb, 16, 6);
 	  break;
 
 
 	case DATA_ADDR_T3:
-	  src = tvb_get_ptr (tvb, 10, 6);
-	  dst = tvb_get_ptr (tvb, 16, 6);
+	  src = tvb_get_ptr (tvb, 16, 6);
+	  dst = tvb_get_ptr (tvb, 4, 6);
 	  break;
 
 
@@ -902,42 +874,42 @@
 	      proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
 				    tvb_get_ptr (tvb, 16, 6));
 	      proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-				   COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+				   COOK_FRAGMENT_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-				   COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+				   COOK_SEQUENCE_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      break;
 	      
 	      
 	    case DATA_ADDR_T2:
-	      proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
 				    tvb_get_ptr (tvb, 4, 6));
-	      proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
 				    tvb_get_ptr (tvb, 10, 6));
-	      proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
 				    tvb_get_ptr (tvb, 16, 6));
 	      proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-				   COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+				   COOK_FRAGMENT_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-				   COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+				   COOK_SEQUENCE_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      break;
    
 
 	    case DATA_ADDR_T3:
-	      proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
 				    tvb_get_ptr (tvb, 4, 6));
-	      proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
 				    tvb_get_ptr (tvb, 10, 6));
-	      proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
+	      proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
 				    tvb_get_ptr (tvb, 16, 6));
 	      proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-				   COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+				   COOK_FRAGMENT_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-				   COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+				   COOK_SEQUENCE_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      break;
 	      
@@ -950,10 +922,10 @@
 	      proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
 				    tvb_get_ptr (tvb, 16, 6));
 	      proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-				   COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+				   COOK_FRAGMENT_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-				   COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+				   COOK_SEQUENCE_NUMBER (tvb_get_letohs
 							 (tvb, 22)));
 	      proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6,
 				    tvb_get_ptr (tvb, 24, 6));
@@ -1132,7 +1104,7 @@
       break;
 
     case MGT_DISASS:
-      COL_SHOW_INFO (pinfo->fd, "Dissassociate");
+      COL_SHOW_INFO (pinfo->fd, "Disassociation");
       if (tree)
 	{
 	  fixed_tree =
@@ -1409,10 +1381,10 @@
 {
 
   static const value_string tofrom_ds[] = {
-    {0, "Not leaving DS or network is operating in AD-HOC mode ( To DS: 0  From DS: 0)"},
-    {1, "Frame is exiting DS (To DS: 0  From DS: 1)"},
-    {2, "Frame is entering DS (To DS: 1  From DS: 0)"},
-    {3, "Frame part of WDS (To DS: 1  From DS: 1)"},
+    {0, "Transmitter and Receiver are endpoints of packet (To DS: 0  From DS: 0)"},
+    {1, "Receiver is not final destination of packet (To DS: 1  From DS: 0)"},
+    {2, "Transmitter is not original source of packet (To DS: 0  From DS: 1)"},
+    {3, "Neither transmitter nor receiver are packet endpoints (To DS: 1  From DS: 1)"},
     {0, NULL}
   };
 
@@ -1427,8 +1399,8 @@
   };
 
   static const true_false_string more_frags = {
-    "MSDU/MMPDU is fragmented",
-    "No fragments"
+    "More fragments to follow",
+    "No more fragments"
   };
 
   static const true_false_string retry_flags = {