Wireshark-dev: [Wireshark-dev] [patch] New dissector: PANA
From: Peter Racz <racz@xxxxxxxxxxxx>
Date: Wed, 05 Jul 2006 09:39:55 +0200
Dear developers,

I added a new dissector for the PANA (Protocol for carrying Authentication for
Network Access) protocol, currently specified in the IETF draft
draft-ietf-pana-pana-11. The patch is attached.

Changed files:
- packet-pana.c: new file with the dissector
- Makefile.common: added packet-pana.c to DISSECTOR_SRC

Best regards,
Peter

Index: epan/dissectors/packet-pana.c
===================================================================
--- epan/dissectors/packet-pana.c	(revision 0)
+++ epan/dissectors/packet-pana.c	(revision 0)
@@ -0,0 +1,939 @@
+/* packet-pana.c
+ * Routines for Protocol for carrying Authentication for Network Access dissection
+ * Copyright 2006, Peter Racz <racz@xxxxxxxxxxxx>
+ *
+ * $Id: README.developer 18163 2006-05-15 16:28:49Z kukosa $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/value_string.h>
+
+#define PANA_UDP_PORT 3001
+
+#define MIN_AVP_SIZE 8
+
+#define PANA_FLAG_R 0x8000
+#define PANA_FLAG_S 0x4000
+#define PANA_FLAG_N 0x2000
+#define PANA_FLAG_L 0x1000
+#define PANA_FLAG_RES4 0x0800
+#define PANA_FLAG_RES5 0x0400
+#define PANA_FLAG_RES6 0x0200
+#define PANA_FLAG_RES7 0x0100
+#define PANA_FLAG_RES8 0x0080
+#define PANA_FLAG_RES9 0x0040
+#define PANA_FLAG_RES10 0x0020
+#define PANA_FLAG_RES11 0x0010
+#define PANA_FLAG_RES12 0x0008
+#define PANA_FLAG_RES13 0x0004
+#define PANA_FLAG_RES14 0x0002
+#define PANA_FLAG_RES15 0x0001
+#define PANA_FLAG_RES 0x0fff
+
+#define PANA_AVP_FLAG_V 0x8000
+#define PANA_AVP_FLAG_M 0x4000
+#define PANA_AVP_FLAG_RES2 0x2000
+#define PANA_AVP_FLAG_RES3 0x1000
+#define PANA_AVP_FLAG_RES4 0x0800
+#define PANA_AVP_FLAG_RES5 0x0400
+#define PANA_AVP_FLAG_RES6 0x0200
+#define PANA_AVP_FLAG_RES7 0x0100
+#define PANA_AVP_FLAG_RES8 0x0080
+#define PANA_AVP_FLAG_RES9 0x0040
+#define PANA_AVP_FLAG_RES10 0x0020
+#define PANA_AVP_FLAG_RES11 0x0010
+#define PANA_AVP_FLAG_RES12 0x0008
+#define PANA_AVP_FLAG_RES13 0x0004
+#define PANA_AVP_FLAG_RES14 0x0002
+#define PANA_AVP_FLAG_RES15 0x0001
+#define PANA_AVP_FLAG_RES 0x3fff
+
+
+/* Initialize the protocol and registered fields */
+static int proto_pana = -1;
+static int hf_pana_version_type = -1;
+static int hf_pana_reserved_type = -1;
+static int hf_pana_length_type = -1;
+static int hf_pana_msg_type = -1;
+static int hf_pana_seqnumber = -1;
+
+static dissector_handle_t eap_handle;
+
+static int hf_pana_flags = -1;
+static int hf_pana_flag_r = -1;
+static int hf_pana_flag_s = -1;
+static int hf_pana_flag_n = -1;
+static int hf_pana_flag_l = -1;
+static int hf_pana_flag_res4 = -1;
+static int hf_pana_flag_res5 = -1;
+static int hf_pana_flag_res6 = -1;
+static int hf_pana_flag_res7 = -1;
+static int hf_pana_flag_res8 = -1;
+static int hf_pana_flag_res9 = -1;
+static int hf_pana_flag_res10 = -1;
+static int hf_pana_flag_res11 = -1;
+static int hf_pana_flag_res12 = -1;
+static int hf_pana_flag_res13 = -1;
+static int hf_pana_flag_res14 = -1;
+static int hf_pana_flag_res15 = -1;
+
+static int hf_pana_avp_code = -1;
+static int hf_pana_avp_length = -1;
+static int hf_pana_avp_flags = -1;
+static int hf_pana_avp_flag_v = -1;
+static int hf_pana_avp_flag_m = -1;
+static int hf_pana_avp_flag_res2 = -1;
+static int hf_pana_avp_flag_res3 = -1;
+static int hf_pana_avp_flag_res4 = -1;
+static int hf_pana_avp_flag_res5 = -1;
+static int hf_pana_avp_flag_res6 = -1;
+static int hf_pana_avp_flag_res7 = -1;
+static int hf_pana_avp_flag_res8 = -1;
+static int hf_pana_avp_flag_res9 = -1;
+static int hf_pana_avp_flag_res10 = -1;
+static int hf_pana_avp_flag_res11 = -1;
+static int hf_pana_avp_flag_res12 = -1;
+static int hf_pana_avp_flag_res13 = -1;
+static int hf_pana_avp_flag_res14 = -1;
+static int hf_pana_avp_flag_res15 = -1;
+static int hf_pana_avp_reserved = -1;
+static int hf_pana_avp_vendorid = -1;
+
+static int hf_pana_avp_data_uint64 = -1;
+static int hf_pana_avp_data_int64 = -1;
+static int hf_pana_avp_data_uint32 = -1;
+static int hf_pana_avp_data_int32 = -1;
+static int hf_pana_avp_data_bytes = -1;
+static int hf_pana_avp_data_string = -1;
+static int hf_pana_avp_data_enumerated = -1;
+static int hf_pana_avp_data_addrfamily = -1;
+static int hf_pana_avp_data_ipv4 = -1;
+static int hf_pana_avp_data_ipv6 = -1;
+
+static const value_string msg_type_names[] = {
+	{ 1, "PANA-PAA-Discover" },
+	{ 2, "PANA-Start" },
+	{ 3, "PANA-Auth" },
+	{ 4, "PANA-Reauth" },
+	{ 5, "PANA-Bind" },
+	{ 6, "PANA-Ping" },
+	{ 7, "PANA-Termination" },
+	{ 8, "PANA-Error" },
+	{ 9, "PANA-FirstAuth-End" },
+	{ 10, "PANA-Update" },
+};
+
+static const value_string msg_subtype_names[] = {
+	{ 0x0000, "Answer" },
+	{ 0x8000, "Request" },
+};
+
+static const value_string avp_code_names[] = {
+	{ 1, "Algorithm AVP" },
+	{ 2, "AUTH AVP" },
+	{ 3, "Cookie AVP" },
+	{ 4, "Device-Id AVP" },
+	{ 5, "EAP-Payload AVP" },
+	{ 6, "Failed-AVP AVP" },
+	{ 7, "ISP-Information AVP" },
+	{ 8, "Key-Id AVP" },
+	{ 9, "NAP-Information AVP" },
+	{ 10, "Nonce AVP" },
+	{ 11, "Notification AVP" },
+	{ 12, "PPAC AVP" },
+	{ 13, "Protection-Capability AVP" },
+	{ 14, "Provider-Identifier AVP" },
+	{ 15, "Provider-Name AVP" },
+	{ 16, "Result-Code" },
+	{ 17, "Session-Id" },
+	{ 18, "Session-Lifetime" },
+	{ 19, "Termination-Cause" },
+};
+
+static const value_string avp_resultcode_names[] = {
+	{ 2001, "PANA_SUCCESS" },
+	{ 3001, "PANA_MESSAGE_UNSUPPORTED" },
+	{ 3002, "PANA_UNABLE_TO_DELIVER" },
+	{ 3008, "PANA_INVALID_HDR_BITS" },
+	{ 3009, "PANA_INVALID_AVP_FLAGS" },
+	{ 4001, "PANA_AUTHENTICATION_REJECTED" },
+	{ 5001, "PANA_AVP_UNSUPPORTED" },
+	{ 5002, "PANA_UNKNOWN_SESSION_ID" },
+	{ 5003, "PANA_AUTHORIZATION_REJECTED" },
+	{ 5004, "PANA_INVALID_AVP_DATA" },
+	{ 5005, "PANA_MISSING_AVP" },
+	{ 5006, "PANA_RESOURCES_EXCEEDED" },
+	{ 5007, "PANA_CONTRADICTING_AVPS" },
+	{ 5008, "PANA_AVP_NOT_ALLOWED" },
+	{ 5009, "PANA_AVP_OCCURS_TOO_MANY_TIMES" },
+	{ 5011, "PANA_UNSUPPORTED_VERSION" },
+	{ 5012, "PANA_UNABLE_TO_COMPLY" },
+	{ 5014, "PANA_INVALID_AVP_LENGTH" },
+	{ 5015, "PANA_INVALID_MESSAGE_LENGTH" },
+	{ 5016, "PANA_PROTECTION_CAPABILITY_UNSUPPORTED" },
+	{ 5017, "PANA_PPAC_CAPABILITY_UNSUPPORTED" },
+};
+
+typedef enum {
+  PANA_OCTET_STRING = 1,
+  PANA_INTEGER32,
+  PANA_INTEGER64,
+  PANA_UNSIGNED32,
+  PANA_UNSIGNED64,
+  PANA_FLOAT32,
+  PANA_FLOAT64,
+  PANA_FLOAT128,
+  PANA_GROUPED,
+  PANA_ENUMERATED,
+  PANA_UTF8STRING,
+  PANA_IP_ADDRESS,
+  PANA_EAP,
+  PANA_RESULT_CODE
+} pana_avp_types;
+
+static const value_string avp_type_names[]={
+  {  PANA_OCTET_STRING,    "OctetString" },
+  {  PANA_INTEGER32,       "Integer32" },
+  {  PANA_INTEGER64,       "Integer64" },
+  {  PANA_UNSIGNED32,      "Unsigned32" },
+  {  PANA_UNSIGNED64,      "Unsigned64" },
+  {  PANA_FLOAT32,         "Float32" },
+  {  PANA_FLOAT64,         "Float64" },
+  {  PANA_FLOAT128,        "Float128" },
+  {  PANA_GROUPED,         "Grouped" },
+  {  PANA_ENUMERATED,      "Enumerated" },
+  {  PANA_UTF8STRING,      "UTF8String" },
+  {  PANA_IP_ADDRESS,      "IPAddress" },
+  {  PANA_EAP,			   "OctetString" },
+  {  PANA_RESULT_CODE,     "Unsigned32" },
+};
+
+
+/* Initialize the subtree pointers */
+static gint ett_pana = -1;
+static gint ett_pana_flags = -1;
+static gint ett_pana_avp = -1;
+static gint ett_pana_avp_info = -1;
+static gint ett_pana_avp_flags = -1;
+
+/* Forward declaration we need below */
+void proto_reg_handoff_pana(void);
+static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree);
+static pana_avp_types pana_avp_get_type(guint16 avp_code, guint32 vendor_id);
+
+
+/*
+ * Function for the PANA dissector.
+ */
+static void
+dissect_pana(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+	proto_tree *pana_tree;
+	proto_tree *flags_tree;
+	proto_tree *avp_tree;
+	proto_item *ti;
+	proto_item *flags_item;
+	proto_item *avp_item;
+	
+	tvbuff_t *avp_tvb;
+	
+	guint16 flags = 0;
+	guint16 msg_type;
+	guint16 msg_length;
+	guint16 avp_length;
+	gchar *msg_subtype_str="Unknown";
+	
+	/* Get message length, type and flags */
+	msg_length = tvb_get_ntohs(tvb, 2);
+	flags = tvb_get_ntohs(tvb, 4);	
+	msg_type = tvb_get_ntohs(tvb, 6);
+	avp_length = msg_length-12;
+	
+	if (flags & PANA_FLAG_R)
+		msg_subtype_str = "Request";
+	else
+		msg_subtype_str="Answer";
+
+
+	/* Make the protocol tree */
+	if (tree) {
+
+		gint offset = 0;
+
+		/* create display subtree for the protocol */
+		ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, FALSE);
+		pana_tree = proto_item_add_subtree(ti, ett_pana);
+
+		/* Version */
+		proto_tree_add_item(pana_tree, hf_pana_version_type, tvb, offset, 1, FALSE);
+		offset += 1;
+		/* Reserved field */
+		proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 1, FALSE);
+		offset += 1;
+		/* Length */
+		proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, FALSE);
+		offset += 2;
+		/* Flags */
+		flags_item = proto_tree_add_uint_format_value(pana_tree, hf_pana_flags, tvb,
+					      offset, 2, flags, "0x%02x (%s)", flags, msg_subtype_str);
+		flags_tree = proto_item_add_subtree(flags_item, ett_pana_flags);	
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_r, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_s, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_n, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_l, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res4, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res5, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res6, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res7, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res8, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res9, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res10, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res11, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res12, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res13, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res14, tvb, offset, 2, flags);
+		proto_tree_add_boolean(flags_tree, hf_pana_flag_res15, tvb, offset, 2, flags);
+		offset += 2;
+
+		/* Message Type */
+		proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb, 
+							offset, 2, msg_type, "%s-%s (%d)",
+                            val_to_str(msg_type, msg_type_names, "Unknown (%d)"), 
+                            match_strval(flags & PANA_FLAG_R, msg_subtype_names), 
+                            msg_type);
+		offset += 2;
+
+		proto_tree_add_item(pana_tree, 
+			hf_pana_seqnumber, tvb, offset, 4, FALSE);
+		offset += 4;
+		
+		/* AVPs */	
+		avp_tvb = tvb_new_subset(tvb, offset, avp_length, avp_length);
+		avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs");
+		avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp);
+		
+		if (avp_tree != NULL) {
+			dissect_avps(avp_tvb, pinfo, avp_tree);
+		}
+	}
+	
+	/* Make entries in Protocol column and Info column on summary display */
+	if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA");
+    
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		col_clear(pinfo->cinfo, COL_INFO);
+		col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s",
+               val_to_str(msg_type, msg_type_names, "Unknown (%d)"), 
+               match_strval(flags & PANA_FLAG_R, msg_subtype_names));
+	}
+	
+}
+
+
+/*
+ * Function for AVP dissector.
+ */
+static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree) {
+	
+	gint offset;
+	guint16 avp_code;
+	guint16 avp_flags;
+	guint16 avp_length;
+	guint16 avp_type;
+	guint32 vendor_id;
+	guint16 avp_hdr_length;
+	guint16 avp_data_length;
+	guint16 padding;
+	
+	guint16 buffer_length;
+	int bad_avp = FALSE;
+	
+	tvbuff_t *group_tvb;
+	tvbuff_t *eap_tvb;
+	proto_item *single_avp_item;
+	proto_tree *single_avp_tree;
+	proto_item *avp_flags_item;
+	proto_tree *avp_flags_tree;
+	proto_item *avp_group_item;
+	proto_tree *avp_group_tree;
+	proto_item *avp_eap_item;
+	proto_tree *avp_eap_tree;
+	
+	offset = 0;
+	buffer_length = 0;
+	buffer_length = tvb_length(tvb);
+
+	if (buffer_length <= 0) {
+		proto_tree_add_text(avp_tree, tvb, offset, tvb_length(tvb),	"No Attribute Value Pairs Found");
+		return;
+	}
+	
+	/* Go through all AVPs */
+	while (buffer_length > 0 ) {
+		/* Check buffer length */
+		if (buffer_length < MIN_AVP_SIZE) return;
+		
+		avp_code = tvb_get_ntohs(tvb, offset);
+		avp_flags = tvb_get_ntohs(tvb, offset + 2);
+		avp_length = tvb_get_ntohs(tvb, offset + 4);
+
+		/* Check AVP flags for vendor specific AVP */
+		if (avp_flags & PANA_AVP_FLAG_V) {
+			vendor_id = tvb_get_ntohl(tvb, 8);
+			avp_hdr_length = 12;
+		} else {
+			vendor_id = 0;
+			avp_hdr_length = 8;
+		}
+		
+		/* Check AVP type */
+		avp_type = pana_avp_get_type(avp_code, vendor_id);
+		
+		/* AVP data length */
+		avp_data_length = avp_length - avp_hdr_length;
+		
+		/* Check AVP length */
+		if ((avp_length < MIN_AVP_SIZE) || (avp_length > buffer_length)) bad_avp = TRUE;
+		/* Check AVP flags */
+		if (avp_flags & PANA_AVP_FLAG_RES) bad_avp = TRUE;
+		
+		/* Check padding */
+		padding = (4 - (avp_length % 4)) % 4;
+
+		single_avp_item = proto_tree_add_text(avp_tree, tvb, offset, avp_length + padding,
+								"%s (%s) length: %d bytes (%d padded bytes)",
+								val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
+								val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
+								avp_length,
+								avp_length + padding);
+		
+		single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);
+
+		if (single_avp_tree != NULL) {
+			/* AVP Code */
+			proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb, 
+							offset, 2, avp_code, "%s (%u)", 
+							val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
+							avp_code);
+			offset += 2;
+			/* AVP Flags */
+			avp_flags_item = proto_tree_add_item(single_avp_tree, hf_pana_avp_flags, tvb, offset, 2, FALSE);
+			avp_flags_tree = proto_item_add_subtree(avp_flags_item, ett_pana_avp_flags);	
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_v, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_m, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res2, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res3, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res4, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res5, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res6, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res7, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res8, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res9, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res10, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res11, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res12, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res13, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res14, tvb, offset, 2, avp_flags);
+			proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_res15, tvb, offset, 2, avp_flags);
+			offset += 2;
+			/* AVP Length */
+			proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
+			offset += 2;
+			/* Reserved */
+			proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, FALSE);
+			offset += 2;
+			/* Vendor ID */
+			if (avp_flags & PANA_AVP_FLAG_V) {
+				proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, FALSE);
+				offset += 4;
+			}
+			/* AVP Value */
+			switch(avp_type) {
+				case PANA_GROUPED: {
+					avp_group_item = proto_tree_add_text(single_avp_tree,
+									  tvb, offset, avp_data_length,
+									  "Grouped AVP");
+					avp_group_tree = proto_item_add_subtree(avp_group_item, ett_pana_avp);
+					group_tvb = tvb_new_subset(tvb, offset, 
+									MIN(avp_data_length, tvb_length(tvb)-offset), avp_data_length);
+					if (avp_group_tree != NULL) {
+						dissect_avps(group_tvb, pinfo, avp_group_tree);
+					}
+					break;
+				}
+				case PANA_UTF8STRING: {
+					guint8 *data;
+					data = tvb_get_ptr(tvb, offset, avp_data_length);
+					proto_tree_add_string_format(single_avp_tree, hf_pana_avp_data_string, tvb, 
+							offset, avp_data_length, data,
+							"UTF8String: %*.*s",
+							avp_data_length, avp_data_length, data);
+					break;
+				}
+				case PANA_OCTET_STRING: {
+					proto_tree_add_bytes_format(single_avp_tree, hf_pana_avp_data_bytes, tvb, 
+							offset, avp_data_length,
+						    tvb_get_ptr(tvb, offset, avp_data_length),
+							"Hex Data Highlighted Below");
+					break;
+				}
+				case PANA_INTEGER32: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb, 
+							offset, 4, FALSE);
+					break;
+				}
+				case PANA_UNSIGNED32: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb, 
+							offset, 4, FALSE);
+					break;
+				}
+				case PANA_INTEGER64: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb, 
+							offset, 8, FALSE);
+					break;
+				}
+				case PANA_UNSIGNED64: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb, 
+							offset, 8, FALSE);
+					break;
+				}
+				case PANA_ENUMERATED: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb, 
+							offset, 4, FALSE);
+					break;
+				}
+				case PANA_IP_ADDRESS: {
+					proto_tree_add_item(single_avp_tree, hf_pana_avp_data_addrfamily, tvb, 
+							offset, 2, FALSE);
+					if (tvb_get_ntohs(tvb, offset) == 0x0001) {
+						proto_tree_add_item(single_avp_tree, hf_pana_avp_data_ipv4, tvb, 
+								offset+2, avp_data_length-2, FALSE);
+					} else if (tvb_get_ntohs(tvb, offset) == 0x0002) {
+						proto_tree_add_item(single_avp_tree, hf_pana_avp_data_ipv6, tvb, 
+								offset+2, avp_data_length-2, FALSE);
+					} else {
+						proto_tree_add_bytes_format(single_avp_tree, hf_pana_avp_data_bytes, tvb, 
+								offset, avp_data_length,
+								tvb_get_ptr(tvb, offset, avp_data_length),
+								"Error! Cannot Parse Address Family %d",
+								tvb_get_ntohs(tvb, offset));
+					}
+					break;	
+				}
+				case PANA_RESULT_CODE: {
+					proto_tree_add_text(single_avp_tree, tvb, offset, avp_data_length,
+								"Value: %d (%s)",
+								tvb_get_ntohl(tvb, offset),
+								val_to_str(tvb_get_ntohs(tvb, offset), avp_code_names, "Unknown"));
+					break;
+				}
+				case PANA_EAP: {
+					avp_eap_item = proto_tree_add_text(single_avp_tree,
+									  tvb, offset, avp_data_length,
+									  "AVP Value (EAP packet)");
+					avp_eap_tree = proto_item_add_subtree(avp_eap_item, ett_pana_avp);
+					eap_tvb = tvb_new_subset(tvb, offset, avp_data_length, avp_data_length);
+					if (avp_eap_tree != NULL) {
+						call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
+					}
+					break;
+				}
+			}
+			offset += avp_data_length + padding;
+		}
+		/* Update the buffer length */
+		buffer_length -=  avp_length + padding;
+	}
+	
+}
+
+
+/* Map AVP code to AVP type */
+static pana_avp_types
+pana_avp_get_type(guint16 avp_code, guint32 vendor_id) {
+	
+	if(vendor_id == 0) {
+		switch(avp_code) {
+			case 1: return PANA_UNSIGNED32;		/* Algorithm AVP */
+			case 2: return PANA_OCTET_STRING;	/* AUTH AVP */
+			case 3: return PANA_OCTET_STRING;	/* Cookie AVP */
+			case 4: return PANA_UNSIGNED64;		/* Device-Id AVP, it should be PANA_IP_ADDRESS*/
+			case 5: return PANA_EAP;			/* EAP-Payload AVP */
+			case 6: return PANA_GROUPED;		/* Failed-AVP AVP */
+			case 7: return PANA_GROUPED;		/* ISP-Information AVP */
+			case 8: return PANA_INTEGER32;		/* Key-Id AVP */
+			case 9: return PANA_GROUPED;		/* NAP-Information AVP */
+			case 10: return PANA_OCTET_STRING;	/* Nonce AVP */
+			case 11: return PANA_OCTET_STRING;	/* Notification AVP */
+			case 12: return PANA_UNSIGNED32;	/* Post-PANA-Address-Configuration (PPAC) AVP */
+			case 13: return PANA_UNSIGNED32;	/* Protection-Capability AVP */
+			case 14: return PANA_UNSIGNED32;	/* Provider-Identifier AVP */
+			case 15: return PANA_UTF8STRING;	/* Provider-Name AVP */
+			case 16: return PANA_RESULT_CODE;	/* Result-Code AVP */
+			case 17: return PANA_UTF8STRING;	/* Session-Id AVP */
+			case 18: return PANA_UNSIGNED32;	/* Session-Lifetime AVP */
+			case 19: return PANA_ENUMERATED;	/* Termination-Cause AVP */
+			default: return PANA_OCTET_STRING;
+		}
+	} else {
+		return PANA_OCTET_STRING;
+	}
+}
+
+
+
+void
+proto_register_pana(void)
+{                 
+  module_t *pana_module;
+
+	static hf_register_info hf[] = {
+		{ &hf_pana_version_type,
+			{ "PANA Version", "pana.version", 
+			FT_UINT8, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_reserved_type,
+			{ "PANA Reserved", "pana.reserved",
+			FT_UINT8, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_length_type,
+			{ "PANA Message Length", "pana.length", 
+			FT_UINT16, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+
+
+		{ &hf_pana_flags,
+			{ "Flags", "pana.flags", 
+			FT_UINT8, BASE_HEX, NULL, 0x0,
+		    "", HFILL }
+		},
+		{ &hf_pana_flag_r,
+			{ "Request", "pana.flags.r", 
+		  	FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_R,
+			"", HFILL }
+		},
+		{ &hf_pana_flag_s,
+			{ "Separate", "pana.flags.s", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_S,
+			"", HFILL }
+		},
+		{ &hf_pana_flag_n,
+			{ "NAP Auth","pana.flags.n", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_N,
+			"", HFILL }
+		},
+		{ &hf_pana_flag_l,
+			{ "Stateless Discovery","pana.flags.l", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_L,
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res4,
+			{ "Reserved","pana.flags.res4", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES4, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res5,
+			{ "Reserved","pana.flags.res5", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES5, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res6,
+			{ "Reserved","pana.flags.res6", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES6, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res7,
+			{ "Reserved","pana.flags.res7", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES7, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res8,
+			{ "Reserved","pana.flags.res8", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES8, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res9,
+			{ "Reserved","pana.flags.res9", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES9, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res10,
+			{ "Reserved","pana.flags.res10", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES10, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res11,
+			{ "Reserved","pana.flags.res11", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES11, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res12,
+			{ "Reserved","pana.flags.res12", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES12, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res13,
+			{ "Reserved","pana.flags.res13", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES13, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res14,
+			{ "Reserved","pana.flags.res14", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES14, 
+			"", HFILL }
+		},
+		{ &hf_pana_flag_res15,
+			{ "Reserved","pana.flags.res15", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_RES15, 
+			"", HFILL }
+		},
+
+
+		{ &hf_pana_msg_type,
+			{ "PANA Message Type", "pana.type", 
+			FT_UINT16, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_seqnumber,
+			{ "PANA Sequence Number", "pana.seq", 
+			FT_UINT32, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+
+
+		{ &hf_pana_avp_code,
+			{ "AVP Code", "pana.avp.code", 
+			FT_UINT16, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_length,
+			{ "AVP Length", "pana.avp.length", 
+			FT_UINT16, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flags,
+			{ "AVP Flags", "pana.avp.flags", 
+			FT_UINT16, BASE_HEX, NULL, 0x0,
+		    "", HFILL }
+		},
+		{ &hf_pana_avp_flag_v,
+			{ "Vendor", "pana.avp.flags.v", 
+		  	FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_V,
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_m,
+			{ "Mandatory", "pana.avp.flags.m", 
+		  	FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_M,
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res2,
+			{ "Reserved","pana.avp.flags.res2", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES2, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res3,
+			{ "Reserved","pana.avp.flags.res3", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES3, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res4,
+			{ "Reserved","pana.avp.flags.res4", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES4, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res5,
+			{ "Reserved","pana.avp.flags.res5", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES5, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res6,
+			{ "Reserved","pana.avp.flags.res6", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES6, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res7,
+			{ "Reserved","pana.avp.flags.res7", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES7, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res8,
+			{ "Reserved","pana.avp.flags.res8", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES8, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res9,
+			{ "Reserved","pana.avp.flags.res9", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES9, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res10,
+			{ "Reserved","pana.avp.flags.res10", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES10, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res11,
+			{ "Reserved","pana.avp.flags.res11", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES11, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res12,
+			{ "Reserved","pana.avp.flags.res12", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES12, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res13,
+			{ "Reserved","pana.avp.flags.res13", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES13, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res14,
+			{ "Reserved","pana.avp.flags.res14", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES14, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_flag_res15,
+			{ "Reserved","pana.avp.flags.res15", 
+			FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_AVP_FLAG_RES15, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_reserved,
+			{ "AVP Reserved", "pana.avp.reserved", 
+			FT_UINT16, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_vendorid,
+			{ "AVP Vendor ID", "pana.avp.vendorid", 
+			FT_UINT32, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+
+
+		{ &hf_pana_avp_data_uint64,
+			{ "Value", "pana.avp.data.uint64", 
+			FT_UINT64, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_int64,
+			{ "Value", "pana.avp.data.int64", 
+			FT_INT64, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_uint32,
+			{ "Value", "pana.avp.data.uint32", 
+			FT_UINT32, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_int32,
+			{ "Value", "pana.avp.data.int32", 
+			FT_INT32, BASE_HEX, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_bytes,
+			{ "Value", "pana.avp.data.bytes", 
+			FT_BYTES, BASE_NONE, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_string,
+			{ "Value", "pana.avp.data.string", 
+			FT_STRING, BASE_NONE, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_enumerated,
+			{ "Value", "pana.avp.data.enum", 
+			FT_INT32, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_addrfamily,
+			{ "Address Family", "pana.avp.data.addrfamily", 
+			FT_UINT16, BASE_DEC, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_ipv4,
+			{ "IPv4 Address", "pana.avp.data.ipv4", 
+			FT_IPv4, BASE_NONE, NULL, 0x0, 
+			"", HFILL }
+		},
+		{ &hf_pana_avp_data_ipv6,
+			{ "IPv6 Address", "pana.avp.data.ipv6", 
+			FT_IPv6, BASE_NONE, NULL, 0x0, 
+			"", HFILL }
+		},
+
+	};
+
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_pana,
+		&ett_pana_flags,
+		&ett_pana_avp,
+		&ett_pana_avp_info,
+		&ett_pana_avp_flags,
+	};
+
+	/* Register the protocol name and description */
+	proto_pana = proto_register_protocol("Protocol for carrying Authentication for Network Access",
+	    "PANA", "pana");
+
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_pana, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
+        
+	/* Register preferences module */       
+    pana_module = prefs_register_protocol(proto_pana, proto_reg_handoff_pana);
+     
+}
+
+
+void
+proto_reg_handoff_pana(void)
+{
+	
+	static gboolean initialized = FALSE;
+        
+	if( !initialized ) {
+
+		dissector_handle_t pana_handle;
+
+		pana_handle = create_dissector_handle(dissect_pana, proto_pana);
+		dissector_add("udp.port", PANA_UDP_PORT, pana_handle);
+        
+        initialized = TRUE;
+        
+		eap_handle = find_dissector("eap");
+	}
+}
+
Index: epan/dissectors/Makefile.common
===================================================================
--- epan/dissectors/Makefile.common	(revision 18639)
+++ epan/dissectors/Makefile.common	(working copy)
@@ -489,6 +489,7 @@
 	packet-ospf.c	\
 	packet-p_mul.c	\
 	packet-pagp.c	\
+	packet-pana.c	\
 	packet-pcnfsd.c	\
 	packet-per.c	\
 	packet-pflog.c	\