2006-07-14 09:17:11 +00:00
|
|
|
/* packet-pana.c
|
|
|
|
* Routines for Protocol for carrying Authentication for Network Access dissection
|
|
|
|
* Copyright 2006, Peter Racz <racz@ifi.unizh.ch>
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* 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.
|
|
|
|
*/
|
2006-07-14 23:04:35 +00:00
|
|
|
/* This protocol implements PANA as of the internet draft
|
|
|
|
* draft-ietf-pana-pana-11 which is a workitem of the ietf workgroup
|
|
|
|
* internet area/pana
|
|
|
|
*/
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
#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>
|
2006-07-14 23:04:35 +00:00
|
|
|
#include <epan/conversation.h>
|
|
|
|
#include <epan/emem.h>
|
2007-04-18 07:06:56 +00:00
|
|
|
#include <epan/expert.h>
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
#define PANA_UDP_PORT 3001
|
|
|
|
#define PANA_VERSION 1
|
|
|
|
|
|
|
|
#define MIN_AVP_SIZE 8
|
|
|
|
|
|
|
|
#define PANA_FLAG_R 0x8000
|
|
|
|
#define PANA_FLAG_S 0x4000
|
2007-04-16 08:53:33 +00:00
|
|
|
#define PANA_FLAG_C 0x2000
|
|
|
|
#define PANA_FLAG_A 0x1000
|
|
|
|
#define PANA_FLAG_P 0x0800
|
|
|
|
#define PANA_FLAG_E 0x0400
|
2006-07-14 09:17:11 +00:00
|
|
|
#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;
|
2007-04-16 08:53:33 +00:00
|
|
|
static int hf_pana_session_id = -1;
|
2006-07-14 09:17:11 +00:00
|
|
|
static int hf_pana_seqnumber = -1;
|
2006-07-14 23:04:35 +00:00
|
|
|
static int hf_pana_response_in = -1;
|
|
|
|
static int hf_pana_response_to = -1;
|
|
|
|
static int hf_pana_time = -1;
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
static dissector_handle_t pana_handle = NULL;
|
|
|
|
static dissector_handle_t eap_handle = NULL;
|
|
|
|
|
|
|
|
static int hf_pana_flags = -1;
|
|
|
|
static int hf_pana_flag_r = -1;
|
|
|
|
static int hf_pana_flag_s = -1;
|
2007-04-16 08:53:33 +00:00
|
|
|
static int hf_pana_flag_c = -1;
|
|
|
|
static int hf_pana_flag_a = -1;
|
|
|
|
static int hf_pana_flag_p = -1;
|
|
|
|
static int hf_pana_flag_e = -1;
|
2006-07-14 09:17:11 +00:00
|
|
|
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_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 const value_string msg_type_names[] = {
|
2007-04-16 08:53:33 +00:00
|
|
|
{ 1, "PANA-Client-Initiation" },
|
|
|
|
{ 2, "PANA-Auth" },
|
|
|
|
{ 3, "PANA-Termination" },
|
|
|
|
{ 4, "PANA-Notification" },
|
2006-07-14 09:17:11 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string msg_subtype_names[] = {
|
|
|
|
{ 0x0000, "Answer" },
|
|
|
|
{ 0x8000, "Request" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string avp_code_names[] = {
|
2007-04-16 08:53:33 +00:00
|
|
|
{ 3, "EAP-Payload AVP" },
|
|
|
|
{ 4, "Failed-AVP AVP" },
|
|
|
|
{ 5, "Failed-Message-Header AVP" },
|
|
|
|
{ 6, "Key-Id AVP" },
|
|
|
|
{ 7, "Nonce AVP" },
|
|
|
|
{ 8, "Result-Code" },
|
|
|
|
{ 9, "Session-Lifetime" },
|
|
|
|
{ 10, "Termination-Cause" },
|
2006-07-14 09:17:11 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2007-04-14 14:01:53 +00:00
|
|
|
static const value_string avp_resultcode_names[] _U_ = {
|
2007-04-16 08:53:33 +00:00
|
|
|
{ 0, "PANA_SUCCESS" },
|
|
|
|
{ 1, "PANA_AUTHENTICATION_REJECTED" },
|
|
|
|
{ 2, "PANA_AUTHORIZATION_REJECTED" },
|
|
|
|
{ 1001, "PANA_MESSAGE_UNSUPPORTED" },
|
|
|
|
{ 1002, "PANA_UNABLE_TO_DELIVER" },
|
|
|
|
{ 1003, "PANA_INVALID_HDR_BITS" },
|
|
|
|
{ 1004, "PANA_INVALID_AVP_FLAGS" },
|
|
|
|
{ 1005, "PANA_AVP_UNSUPPORTED" },
|
|
|
|
{ 1006, "PANA_INVALID_AVP_DATA" },
|
|
|
|
{ 1007, "PANA_MISSING_AVP" },
|
|
|
|
{ 1008, "PANA_RESOURCES_EXCEEDED" },
|
|
|
|
{ 1009, "PANA_CONTRADICTING_AVPS" },
|
|
|
|
{ 1010, "PANA_AVP_NOT_ALLOWED" },
|
|
|
|
{ 1011, "PANA_AVP_OCCURS_TOO_MANY_TIMES" },
|
|
|
|
{ 1012, "PANA_UNSUPPORTED_VERSION" },
|
|
|
|
{ 1013, "PANA_UNABLE_TO_COMPLY" },
|
|
|
|
{ 1014, "PANA_INVALID_AVP_LENGTH" },
|
|
|
|
{ 1015, "PANA_INVALID_MESSAGE_LENGTH" },
|
2006-07-14 09:17:11 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
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_EAP,
|
|
|
|
PANA_RESULT_CODE
|
|
|
|
} pana_avp_types;
|
|
|
|
|
|
|
|
static const value_string avp_type_names[]={
|
2007-04-16 08:53:33 +00:00
|
|
|
{ PANA_OCTET_STRING, "OctetString" },
|
2006-07-14 09:17:11 +00:00
|
|
|
{ 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_EAP, "OctetString" },
|
|
|
|
{ PANA_RESULT_CODE, "Unsigned32" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
2006-07-14 23:04:35 +00:00
|
|
|
typedef struct _pana_transaction_t {
|
|
|
|
guint32 req_frame;
|
|
|
|
guint32 rep_frame;
|
|
|
|
nstime_t req_time;
|
|
|
|
} pana_transaction_t;
|
|
|
|
|
|
|
|
typedef struct _pana_conv_info_t {
|
2006-08-14 08:29:29 +00:00
|
|
|
emem_tree_t *pdus;
|
2006-07-14 23:04:35 +00:00
|
|
|
} pana_conv_info_t;
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Function for the PANA flags dissector.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dissect_pana_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint16 flags)
|
|
|
|
{
|
|
|
|
proto_item *flags_item=NULL;
|
|
|
|
proto_tree *flags_tree=NULL;
|
|
|
|
|
|
|
|
if(!parent_tree) return;
|
|
|
|
|
|
|
|
flags_item = proto_tree_add_uint(parent_tree, hf_pana_flags, tvb,
|
|
|
|
offset, 2, flags);
|
|
|
|
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);
|
|
|
|
if (flags & PANA_FLAG_R)
|
|
|
|
proto_item_append_text(flags_item, ", Request");
|
|
|
|
else
|
|
|
|
proto_item_append_text(flags_item, ", Answer");
|
|
|
|
proto_tree_add_boolean(flags_tree, hf_pana_flag_s, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_FLAG_S)
|
|
|
|
proto_item_append_text(flags_item, ", S flag set");
|
2007-04-16 08:53:33 +00:00
|
|
|
proto_tree_add_boolean(flags_tree, hf_pana_flag_c, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_FLAG_C)
|
|
|
|
proto_item_append_text(flags_item, ", C flag set");
|
|
|
|
proto_tree_add_boolean(flags_tree, hf_pana_flag_a, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_FLAG_A)
|
|
|
|
proto_item_append_text(flags_item, ", A flag set");
|
|
|
|
proto_tree_add_boolean(flags_tree, hf_pana_flag_p, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_FLAG_P)
|
|
|
|
proto_item_append_text(flags_item, ", P flag set");
|
|
|
|
proto_tree_add_boolean(flags_tree, hf_pana_flag_e, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_FLAG_E)
|
|
|
|
proto_item_append_text(flags_item, ", E flag set");
|
2006-07-14 09:17:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function for AVP flags dissector.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dissect_pana_avp_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint16 flags)
|
|
|
|
{
|
|
|
|
proto_item *avp_flags_item=NULL;
|
|
|
|
proto_tree *avp_flags_tree=NULL;
|
|
|
|
|
|
|
|
if(!parent_tree) return;
|
|
|
|
|
|
|
|
avp_flags_item = proto_tree_add_uint(parent_tree, hf_pana_avp_flags, tvb,
|
|
|
|
offset, 2, flags);
|
|
|
|
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, flags);
|
|
|
|
if (flags & PANA_AVP_FLAG_V)
|
|
|
|
proto_item_append_text(avp_flags_item, ", Vendor");
|
|
|
|
proto_tree_add_boolean(avp_flags_tree, hf_pana_avp_flag_m, tvb, offset, 2, flags);
|
|
|
|
if (flags & PANA_AVP_FLAG_M)
|
|
|
|
proto_item_append_text(avp_flags_item, ", Mandatory");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
2007-04-16 08:53:33 +00:00
|
|
|
case 3: return PANA_EAP; /* EAP-Payload AVP */
|
|
|
|
case 4: return PANA_GROUPED; /* Failed-AVP AVP */
|
|
|
|
case 5: return PANA_OCTET_STRING; /* Failed-Message-Header AVP */
|
|
|
|
case 6: return PANA_INTEGER32; /* Key-Id AVP */
|
|
|
|
case 7: return PANA_OCTET_STRING; /* Nonce AVP */
|
|
|
|
case 8: return PANA_RESULT_CODE; /* Result-Code AVP */
|
|
|
|
case 9: return PANA_UNSIGNED32; /* Session-Lifetime AVP */
|
|
|
|
case 10: return PANA_ENUMERATED; /* Termination-Cause AVP */
|
2006-07-14 09:17:11 +00:00
|
|
|
default: return PANA_OCTET_STRING;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return PANA_OCTET_STRING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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_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) {
|
2007-04-18 07:06:56 +00:00
|
|
|
proto_item *pi;
|
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
/* 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 */
|
|
|
|
dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
|
|
|
|
offset += 2;
|
2007-04-18 07:06:56 +00:00
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
/* AVP Length */
|
2007-04-18 07:06:56 +00:00
|
|
|
pi = proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
|
|
|
|
if (avp_length == 0)
|
|
|
|
expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "AVP with length 0");
|
2006-07-14 09:17:11 +00:00
|
|
|
offset += 2;
|
2007-04-18 07:06:56 +00:00
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
/* Reserved */
|
|
|
|
proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, FALSE);
|
|
|
|
offset += 2;
|
2007-04-18 07:06:56 +00:00
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
/* 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: {
|
|
|
|
const 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_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 && eap_handle != NULL) {
|
|
|
|
call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-04-18 07:06:56 +00:00
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
/* Just check that offset will advance */
|
2007-04-18 07:06:56 +00:00
|
|
|
if ((avp_length+padding)!=0)
|
|
|
|
return;
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
offset += avp_data_length + padding;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the buffer length */
|
|
|
|
buffer_length -= avp_length + padding;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function for the PANA PDU dissector.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
|
2006-07-14 23:04:35 +00:00
|
|
|
proto_tree *pana_tree=NULL;
|
|
|
|
proto_tree *avp_tree=NULL;
|
|
|
|
proto_item *ti=NULL;
|
|
|
|
proto_item *avp_item=NULL;
|
2006-07-14 09:17:11 +00:00
|
|
|
tvbuff_t *avp_tvb;
|
|
|
|
guint16 flags = 0;
|
|
|
|
guint16 msg_type;
|
|
|
|
gint16 msg_length;
|
|
|
|
gint16 avp_length;
|
2007-04-16 08:53:33 +00:00
|
|
|
guint32 session_id;
|
2006-07-14 23:04:35 +00:00
|
|
|
guint32 seq_num;
|
|
|
|
conversation_t *conversation;
|
|
|
|
pana_conv_info_t *pana_info;
|
|
|
|
pana_transaction_t *pana_trans;
|
|
|
|
int offset = 0;
|
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
/* 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);
|
2007-04-16 08:53:33 +00:00
|
|
|
session_id = tvb_get_ntohl(tvb, 8);
|
|
|
|
seq_num = tvb_get_ntohl(tvb, 12);
|
|
|
|
avp_length = msg_length-16;
|
2006-07-14 09:17:11 +00:00
|
|
|
|
|
|
|
/* 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make the protocol tree */
|
|
|
|
if (tree) {
|
|
|
|
ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, FALSE);
|
|
|
|
pana_tree = proto_item_add_subtree(ti, ett_pana);
|
2006-07-14 23:04:35 +00:00
|
|
|
}
|
|
|
|
|
2006-07-14 09:17:11 +00:00
|
|
|
|
2007-04-16 08:53:33 +00:00
|
|
|
/*
|
2006-07-14 23:04:35 +00:00
|
|
|
* We need to track some state for this protocol on a per conversation
|
|
|
|
* basis so we can do neat things like request/response tracking
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Do we have a conversation for this connection?
|
|
|
|
*/
|
2007-04-16 08:53:33 +00:00
|
|
|
conversation = find_conversation(pinfo->fd->num,
|
2006-07-14 23:04:35 +00:00
|
|
|
&pinfo->src, &pinfo->dst,
|
2007-04-16 08:53:33 +00:00
|
|
|
pinfo->ptype,
|
2006-07-14 23:04:35 +00:00
|
|
|
pinfo->srcport, pinfo->destport, 0);
|
|
|
|
if (conversation == NULL) {
|
|
|
|
/* We don't yet have a conversation, so create one. */
|
2007-04-16 08:53:33 +00:00
|
|
|
conversation = conversation_new(pinfo->fd->num,
|
2006-07-14 23:04:35 +00:00
|
|
|
&pinfo->src, &pinfo->dst,
|
|
|
|
pinfo->ptype,
|
|
|
|
pinfo->srcport, pinfo->destport, 0);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Do we already have a state structure for this conv
|
|
|
|
*/
|
|
|
|
pana_info = conversation_get_proto_data(conversation, proto_pana);
|
|
|
|
if (!pana_info) {
|
|
|
|
/* No. Attach that information to the conversation, and add
|
|
|
|
* it to the list of information structures.
|
|
|
|
*/
|
|
|
|
pana_info = se_alloc(sizeof(pana_conv_info_t));
|
2006-08-14 08:29:29 +00:00
|
|
|
pana_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");
|
2006-07-14 23:04:35 +00:00
|
|
|
|
|
|
|
conversation_add_proto_data(conversation, proto_pana, pana_info);
|
|
|
|
}
|
|
|
|
if(!pinfo->fd->flags.visited){
|
|
|
|
if(flags&PANA_FLAG_R){
|
|
|
|
/* This is a request */
|
|
|
|
pana_trans=se_alloc(sizeof(pana_transaction_t));
|
|
|
|
pana_trans->req_frame=pinfo->fd->num;
|
|
|
|
pana_trans->rep_frame=0;
|
|
|
|
pana_trans->req_time=pinfo->fd->abs_ts;
|
|
|
|
se_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans);
|
|
|
|
} else {
|
|
|
|
pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
|
|
|
|
if(pana_trans){
|
|
|
|
pana_trans->rep_frame=pinfo->fd->num;
|
|
|
|
}
|
2006-07-14 09:17:11 +00:00
|
|
|
}
|
2006-07-14 23:04:35 +00:00
|
|
|
} else {
|
|
|
|
pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
|
|
|
|
}
|
|
|
|
if(!pana_trans){
|
|
|
|
/* create a "fake" pana_trans structure */
|
|
|
|
pana_trans=ep_alloc(sizeof(pana_transaction_t));
|
|
|
|
pana_trans->req_frame=0;
|
|
|
|
pana_trans->rep_frame=0;
|
|
|
|
pana_trans->req_time=pinfo->fd->abs_ts;
|
2006-07-14 09:17:11 +00:00
|
|
|
}
|
|
|
|
|
2006-07-14 23:04:35 +00:00
|
|
|
|
|
|
|
/* print state tracking in the tree */
|
|
|
|
if(flags&PANA_FLAG_R){
|
|
|
|
/* This is a request */
|
|
|
|
if(pana_trans->rep_frame){
|
|
|
|
proto_item *it;
|
|
|
|
|
|
|
|
it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame);
|
|
|
|
PROTO_ITEM_SET_GENERATED(it);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* This is a reply */
|
|
|
|
if(pana_trans->req_frame){
|
|
|
|
proto_item *it;
|
|
|
|
nstime_t ns;
|
|
|
|
|
|
|
|
it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame);
|
|
|
|
PROTO_ITEM_SET_GENERATED(it);
|
|
|
|
|
|
|
|
nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time);
|
|
|
|
it=proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
|
|
|
|
PROTO_ITEM_SET_GENERATED(it);
|
|
|
|
}
|
2007-04-16 08:53:33 +00:00
|
|
|
}
|
2006-07-14 23:04:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
dissect_pana_flags(pana_tree, tvb, offset, 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)",
|
2007-04-16 08:53:33 +00:00
|
|
|
val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
|
2006-07-14 23:04:35 +00:00
|
|
|
match_strval(flags & PANA_FLAG_R, msg_subtype_names), msg_type);
|
|
|
|
offset += 2;
|
|
|
|
|
2007-04-16 08:53:33 +00:00
|
|
|
/* Session ID */
|
|
|
|
proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, FALSE);
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
/* Sequence Number */
|
2006-07-14 23:04:35 +00:00
|
|
|
proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, FALSE);
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
/* AVPs */
|
|
|
|
if(avp_length>0){
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2006-07-14 09:17:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function for the PANA dissector.
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
dissect_pana(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
|
|
|
|
guint8 pana_version;
|
|
|
|
guint8 pana_res;
|
|
|
|
guint16 msg_length;
|
|
|
|
guint16 flags;
|
|
|
|
guint32 buffer_length;
|
|
|
|
guint16 msg_type;
|
|
|
|
|
|
|
|
/* Get buffer length */
|
|
|
|
buffer_length = tvb_length(tvb);
|
|
|
|
|
|
|
|
/* Check minimum buffer length */
|
|
|
|
if(buffer_length < 12) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get header fields */
|
|
|
|
pana_version = tvb_get_guint8(tvb, 0);
|
|
|
|
pana_res = tvb_get_guint8(tvb, 1);
|
|
|
|
msg_length = tvb_get_ntohs(tvb, 2);
|
|
|
|
flags = tvb_get_ntohs(tvb, 4);
|
|
|
|
msg_type = tvb_get_ntohs(tvb, 6);
|
|
|
|
|
|
|
|
/* Check version */
|
|
|
|
if(pana_version != PANA_VERSION) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check minimum packet length */
|
|
|
|
if(msg_length < 12) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the packet length and buffer length matching */
|
|
|
|
if(msg_length != buffer_length) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check that the reserved byte is zero */
|
|
|
|
if(pana_res!=0){
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verify that none of the reserved bits are set */
|
|
|
|
if(flags&0x0fff){
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verify that we recognize the message type */
|
2007-04-16 08:53:33 +00:00
|
|
|
if(msg_type>4 || msg_type==0){
|
2006-07-14 09:17:11 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dissect_pana_pdu(tvb, pinfo, tree);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register the protocol with Wireshark
|
|
|
|
*/
|
|
|
|
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 }
|
|
|
|
},
|
2006-07-14 23:04:35 +00:00
|
|
|
{ &hf_pana_response_in,
|
|
|
|
{ "Response In", "pana.response_in",
|
|
|
|
FT_FRAMENUM, BASE_DEC, NULL, 0x0,
|
|
|
|
"The response to this PANA request is in this frame", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_pana_response_to,
|
|
|
|
{ "Request In", "pana.response_to",
|
|
|
|
FT_FRAMENUM, BASE_DEC, NULL, 0x0,
|
|
|
|
"This is a response to the PANA request in this frame", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_pana_time,
|
|
|
|
{ "Time", "pana.time",
|
|
|
|
FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
|
|
|
|
"The time between the Call and the Reply", HFILL }
|
|
|
|
},
|
2006-07-14 09:17:11 +00:00
|
|
|
{ &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,
|
2007-04-16 08:53:33 +00:00
|
|
|
{ "Start", "pana.flags.s",
|
2006-07-14 09:17:11 +00:00
|
|
|
FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_S,
|
|
|
|
"", HFILL }
|
|
|
|
},
|
2007-04-16 08:53:33 +00:00
|
|
|
{ &hf_pana_flag_c,
|
|
|
|
{ "Complete","pana.flags.c",
|
|
|
|
FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_C,
|
|
|
|
"", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_pana_flag_a,
|
|
|
|
{ "Auth","pana.flags.a",
|
|
|
|
FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_A,
|
|
|
|
"", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_pana_flag_p,
|
|
|
|
{ "Ping","pana.flags.p",
|
|
|
|
FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_P,
|
2006-07-14 09:17:11 +00:00
|
|
|
"", HFILL }
|
|
|
|
},
|
2007-04-16 08:53:33 +00:00
|
|
|
{ &hf_pana_flag_e,
|
2007-05-08 19:33:24 +00:00
|
|
|
{ "Error","pana.flags.e",
|
2007-04-16 08:53:33 +00:00
|
|
|
FT_BOOLEAN, 16, TFS(&flags_set_truth), PANA_FLAG_E,
|
2006-07-14 09:17:11 +00:00
|
|
|
"", HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_pana_msg_type,
|
|
|
|
{ "PANA Message Type", "pana.type",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }
|
|
|
|
},
|
2007-04-16 08:53:33 +00:00
|
|
|
{ &hf_pana_session_id,
|
|
|
|
{ "PANA Session ID", "pana.sid",
|
|
|
|
FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
|
|
"", HFILL }
|
|
|
|
},
|
2006-07-14 09:17:11 +00:00
|
|
|
{ &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_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 }
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 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, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_pana(void)
|
|
|
|
{
|
|
|
|
heur_dissector_add("udp", dissect_pana, proto_pana);
|
|
|
|
|
|
|
|
pana_handle = new_create_dissector_handle(dissect_pana, proto_pana);
|
|
|
|
dissector_add_handle("udp.port", pana_handle);
|
|
|
|
|
|
|
|
eap_handle = find_dissector("eap");
|
|
|
|
if(!eap_handle) fprintf(stderr,"PANA warning: EAP dissector not found\n");
|
|
|
|
|
|
|
|
}
|