2 * Routines for Protocol for carrying Authentication for Network Access dissection
3 * Copyright 2006, Peter Racz <racz@ifi.unizh.ch>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 /* This protocol implements PANA as of the IETF RFC 5191.
12 * (Note: This dissector was updated to reflect
13 * draft-ietf-pana-pana-18 which is a workitem of the ietf workgroup
14 * internet area/pana. I believe draft-18 then became RFC 5191).
19 #include <epan/packet.h>
20 #include <epan/conversation.h>
22 #include <wsutil/array.h>
24 void proto_register_pana(void);
25 void proto_reg_handoff_pana(void);
27 static dissector_handle_t pana_handle
;
30 #define PANA_UDP_PORT 3001
33 #define MIN_AVP_SIZE 8
35 #define PANA_FLAG_R 0x8000
36 #define PANA_FLAG_S 0x4000
37 #define PANA_FLAG_C 0x2000
38 #define PANA_FLAG_A 0x1000
39 #define PANA_FLAG_P 0x0800
40 #define PANA_FLAG_I 0x0400
42 #define PANA_FLAG_RES6 0x0200
43 #define PANA_FLAG_RES7 0x0100
44 #define PANA_FLAG_RES8 0x0080
45 #define PANA_FLAG_RES9 0x0040
46 #define PANA_FLAG_RES10 0x0020
47 #define PANA_FLAG_RES11 0x0010
48 #define PANA_FLAG_RES12 0x0008
49 #define PANA_FLAG_RES13 0x0004
50 #define PANA_FLAG_RES14 0x0002
51 #define PANA_FLAG_RES15 0x0001
53 #define PANA_FLAG_RESERVED 0x03ff
55 #define PANA_AVP_FLAG_V 0x8000
57 #define PANA_AVP_FLAG_RES1 0x4000
58 #define PANA_AVP_FLAG_RES2 0x2000
59 #define PANA_AVP_FLAG_RES3 0x1000
60 #define PANA_AVP_FLAG_RES4 0x0800
61 #define PANA_AVP_FLAG_RES5 0x0400
62 #define PANA_AVP_FLAG_RES6 0x0200
63 #define PANA_AVP_FLAG_RES7 0x0100
64 #define PANA_AVP_FLAG_RES8 0x0080
65 #define PANA_AVP_FLAG_RES9 0x0040
66 #define PANA_AVP_FLAG_RES10 0x0020
67 #define PANA_AVP_FLAG_RES11 0x0010
68 #define PANA_AVP_FLAG_RES12 0x0008
69 #define PANA_AVP_FLAG_RES13 0x0004
70 #define PANA_AVP_FLAG_RES14 0x0002
71 #define PANA_AVP_FLAG_RES15 0x0001
73 #define PANA_AVP_FLAG_RESERVED 0x7fff
75 static dissector_handle_t eap_handle
;
77 /* Initialize the protocol and registered fields */
78 static int proto_pana
;
79 static int hf_pana_reserved_type
;
80 static int hf_pana_length_type
;
81 static int hf_pana_msg_type
;
82 static int hf_pana_session_id
;
83 static int hf_pana_seqnumber
;
84 static int hf_pana_response_in
;
85 static int hf_pana_response_to
;
86 static int hf_pana_response_time
;
88 static int hf_pana_flags
;
89 static int hf_pana_flag_r
;
90 static int hf_pana_flag_s
;
91 static int hf_pana_flag_c
;
92 static int hf_pana_flag_a
;
93 static int hf_pana_flag_p
;
94 static int hf_pana_flag_i
;
95 static int hf_pana_avp_code
;
96 static int hf_pana_avp_data_length
;
97 static int hf_pana_avp_flags
;
98 static int hf_pana_avp_flag_v
;
99 static int hf_pana_avp_reserved
;
100 static int hf_pana_avp_vendorid
;
102 static int hf_pana_avp_data_uint64
;
103 static int hf_pana_avp_data_int64
;
104 static int hf_pana_avp_data_uint32
;
105 static int hf_pana_avp_data_int32
;
106 static int hf_pana_avp_data_bytes
;
107 static int hf_pana_avp_data_string
;
108 static int hf_pana_avp_data_enumerated
;
110 #define MSG_TYPE_MAX 5
111 static const value_string msg_type_names
[] = {
112 { 1, "PANA-Client-Initiation" },
114 { 3, "PANA-Termination" },
115 { 4, "PANA-Notification" },
120 static const value_string msg_subtype_names
[] = {
121 { 0x0000, "Answer" },
122 { 0x8000, "Request" },
126 #define AVP_CODE_MAX 13
127 static const value_string avp_code_names
[] = {
129 { 2, "EAP-Payload AVP" },
130 { 3, "Integrity-Algorithm AVP" },
133 { 6, "PRF-Algorithm AVP" },
134 { 7, "Result-Code" },
135 { 8, "Session-Lifetime" },
136 { 9, "Termination-Cause" },
137 { 10, "PaC-Information" },
138 { 11, "Relayed-Message" },
139 { 12, "Encryption-Encap" },
140 { 13, "Encryption-Algorithm" },
145 static const value_string avp_resultcode_names
[] = {
146 { 0, "PANA_SUCCESS" },
147 { 1, "PANA_AUTHENTICATION_REJECTED" },
148 { 2, "PANA_AUTHORIZATION_REJECTED" },
154 PANA_OCTET_STRING
= 1,
170 static const value_string avp_type_names
[]={
171 { PANA_OCTET_STRING
, "OctetString" },
172 { PANA_INTEGER32
, "Integer32" },
173 { PANA_INTEGER64
, "Integer64" },
174 { PANA_UNSIGNED32
, "Unsigned32" },
175 { PANA_UNSIGNED64
, "Unsigned64" },
176 { PANA_FLOAT32
, "Float32" },
177 { PANA_FLOAT64
, "Float64" },
178 { PANA_FLOAT128
, "Float128" },
179 { PANA_GROUPED
, "Grouped" },
180 { PANA_ENUMERATED
, "Enumerated" },
181 { PANA_UTF8STRING
, "UTF8String" },
182 { PANA_EAP
, "OctetString" },
183 { PANA_RESULT_CODE
, "Unsigned32" },
184 { PANA_ENCAPSULATED
, "Encapsulated" },
189 /* Initialize the subtree pointers */
191 static int ett_pana_flags
;
192 static int ett_pana_avp
;
193 static int ett_pana_avp_info
;
194 static int ett_pana_avp_flags
;
197 typedef struct _pana_transaction_t
{
201 } pana_transaction_t
;
203 typedef struct _pana_conv_info_t
{
208 dissect_pana_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
211 * Function for the PANA flags dissector.
214 dissect_pana_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint16_t flags
)
216 static int * const flag_fields
[] = {
226 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_pana_flags
,
227 ett_pana_flags
, flag_fields
, flags
, BMT_NO_TFS
|BMT_NO_FALSE
);
232 * Function for AVP flags dissector.
235 dissect_pana_avp_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint16_t flags
)
237 static int * const flag_fields
[] = {
242 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_pana_avp_flags
,
243 ett_pana_avp_flags
, flag_fields
, flags
, BMT_NO_TFS
|BMT_NO_FALSE
);
248 * Map AVP code to AVP type
250 static pana_avp_types
251 pana_avp_get_type(uint16_t avp_code
, uint32_t vendor_id
)
256 case 1: return PANA_OCTET_STRING
; /* AUTH AVP */
257 case 2: return PANA_EAP
; /* EAP-Payload AVP */
258 case 3: return PANA_UNSIGNED32
; /* Integrity-Algorithm AVP */
259 case 4: return PANA_INTEGER32
; /* Key-Id AVP */
260 case 5: return PANA_OCTET_STRING
; /* Nonce AVP */
261 case 6: return PANA_UNSIGNED32
; /* PRF-Algorithm AVP */
262 case 7: return PANA_RESULT_CODE
; /* Result-Code AVP */
263 case 8: return PANA_UNSIGNED32
; /* Session-Lifetime AVP */
264 case 9: return PANA_ENUMERATED
; /* Termination-Cause AVP */
265 case 10: return PANA_OCTET_STRING
; /* PaC-Information AVP */
266 case 11: return PANA_ENCAPSULATED
; /* Relayed-Message AVP */
267 case 12: return PANA_OCTET_STRING
; /* Encryption-Encap AVP */
268 case 13: return PANA_UNSIGNED32
; /* Encryption-Algorithm AVP */
269 default: return PANA_OCTET_STRING
;
272 return PANA_OCTET_STRING
;
279 * Function for AVP dissector.
282 // NOLINTNEXTLINE(misc-no-recursion)
283 dissect_avps(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*avp_tree
)
292 uint32_t avp_hdr_length
;
293 uint32_t avp_data_length
, result_code
;
296 int32_t buffer_length
;
301 proto_tree
*single_avp_tree
;
302 proto_tree
*avp_eap_tree
;
303 proto_tree
*avp_encap_tree
;
306 buffer_length
= tvb_reported_length(tvb
);
308 /* Go through all AVPs */
309 while (buffer_length
> 0) {
310 avp_code
= tvb_get_ntohs(tvb
, offset
);
311 avp_flags
= tvb_get_ntohs(tvb
, offset
+ 2);
312 avp_data_length
= tvb_get_ntohs(tvb
, offset
+ 4);
314 /* Check AVP flags for vendor specific AVP */
315 if (avp_flags
& PANA_AVP_FLAG_V
) {
316 vendor_id
= tvb_get_ntohl(tvb
, 8);
323 avp_length
= avp_hdr_length
+ avp_data_length
;
326 avp_type
= pana_avp_get_type(avp_code
, vendor_id
);
330 padding
= (4 - (avp_length
% 4)) % 4;
332 single_avp_tree
= proto_tree_add_subtree_format(avp_tree
, tvb
, offset
, avp_length
+ padding
,
333 ett_pana_avp_info
, NULL
, "%s (%s) length: %d bytes (%d padded bytes)",
334 val_to_str(avp_code
, avp_code_names
, "Unknown (%d)"),
335 val_to_str(avp_type
, avp_type_names
, "Unknown (%d)"),
337 avp_length
+ padding
);
340 proto_tree_add_uint_format_value(single_avp_tree
, hf_pana_avp_code
, tvb
,
341 offset
, 2, avp_code
, "%s (%u)",
342 val_to_str(avp_code
, avp_code_names
, "Unknown (%d)"),
347 dissect_pana_avp_flags(single_avp_tree
, tvb
, offset
, avp_flags
);
351 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
355 proto_tree_add_item(single_avp_tree
, hf_pana_avp_reserved
, tvb
, offset
, 2, ENC_NA
);
358 if (avp_flags
& PANA_AVP_FLAG_V
) {
360 proto_tree_add_item(single_avp_tree
, hf_pana_avp_vendorid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
363 if (! (avp_flags
& PANA_AVP_FLAG_V
)) {
367 proto_tree
*avp_group_tree
;
368 avp_group_tree
= proto_tree_add_subtree(single_avp_tree
,
369 tvb
, offset
, avp_data_length
,
370 ett_pana_avp
, NULL
, "Grouped AVP");
371 group_tvb
= tvb_new_subset_length_caplen(tvb
, offset
,
372 MIN(avp_data_length
, tvb_reported_length(tvb
)-offset
),
374 // We recurse here, but we'll run out of packet before we run out of stack.
375 dissect_avps(group_tvb
, pinfo
, avp_group_tree
);
378 case PANA_UTF8STRING
: {
379 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_string
, tvb
,
380 offset
, avp_data_length
, ENC_UTF_8
);
383 case PANA_OCTET_STRING
: {
384 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_bytes
, tvb
,
385 offset
, avp_data_length
, ENC_NA
);
388 case PANA_INTEGER32
: {
389 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_int32
, tvb
,
390 offset
, 4, ENC_BIG_ENDIAN
);
393 case PANA_UNSIGNED32
: {
394 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_uint32
, tvb
,
395 offset
, 4, ENC_BIG_ENDIAN
);
398 case PANA_INTEGER64
: {
399 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_int64
, tvb
,
400 offset
, 8, ENC_BIG_ENDIAN
);
403 case PANA_UNSIGNED64
: {
404 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_uint64
, tvb
,
405 offset
, 8, ENC_BIG_ENDIAN
);
408 case PANA_ENUMERATED
: {
409 proto_tree_add_item(single_avp_tree
, hf_pana_avp_data_enumerated
, tvb
,
410 offset
, 4, ENC_BIG_ENDIAN
);
413 case PANA_RESULT_CODE
: {
414 result_code
= tvb_get_ntohl(tvb
, offset
);
415 proto_tree_add_uint_format(single_avp_tree
, hf_pana_avp_code
, tvb
, offset
, avp_data_length
,
416 result_code
, "Value: %d (%s)",
418 val_to_str(result_code
, avp_code_names
, "Unknown (%d)"));
422 avp_eap_tree
= proto_tree_add_subtree(single_avp_tree
,
423 tvb
, offset
, avp_data_length
,
424 ett_pana_avp
, NULL
, "AVP Value (EAP packet)");
425 eap_tvb
= tvb_new_subset_length(tvb
, offset
, avp_data_length
);
426 DISSECTOR_ASSERT_HINT(eap_handle
, "EAP Dissector not available");
427 call_dissector(eap_handle
, eap_tvb
, pinfo
, avp_eap_tree
);
430 case PANA_ENCAPSULATED
: {
431 avp_encap_tree
= proto_tree_add_subtree(single_avp_tree
,
432 tvb
, offset
, avp_data_length
,
433 ett_pana_avp
, NULL
, "AVP Value (PANA packet)");
434 encap_tvb
= tvb_new_subset_length(tvb
, offset
, avp_data_length
);
435 // We recurse here, but we'll run out of packet before we run out of stack.
436 dissect_pana_pdu(encap_tvb
, pinfo
, avp_encap_tree
);
441 offset
+= avp_data_length
+ padding
;
443 /* Update the buffer length */
444 buffer_length
-= avp_length
+ padding
;
451 * Function for the PANA PDU dissector.
454 // NOLINTNEXTLINE(misc-no-recursion)
455 dissect_pana_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
458 proto_tree
*pana_tree
= NULL
;
464 conversation_t
*conversation
;
465 pana_conv_info_t
*pana_info
;
466 pana_transaction_t
*pana_trans
;
469 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PANA");
470 col_clear(pinfo
->cinfo
, COL_INFO
);
472 /* Get message length, type and flags */
473 msg_length
= tvb_get_ntohs(tvb
, 2);
474 flags
= tvb_get_ntohs(tvb
, 4);
475 msg_type
= tvb_get_ntohs(tvb
, 6);
476 seq_num
= tvb_get_ntohl(tvb
, 12);
477 avp_length
= msg_length
- 16;
479 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Type %s-%s",
480 val_to_str(msg_type
, msg_type_names
, "Unknown (%d)"),
481 val_to_str(flags
& PANA_FLAG_R
, msg_subtype_names
, "Unknown (%d)"));
483 /* Make the protocol tree */
486 ti
= proto_tree_add_item(tree
, proto_pana
, tvb
, 0, -1, ENC_NA
);
487 pana_tree
= proto_item_add_subtree(ti
, ett_pana
);
492 * We need to track some state for this protocol on a per conversation
493 * basis so we can do neat things like request/response tracking
495 conversation
= find_or_create_conversation(pinfo
);
498 * Do we already have a state structure for this conv
500 pana_info
= (pana_conv_info_t
*)conversation_get_proto_data(conversation
, proto_pana
);
502 /* No. Attach that information to the conversation, and add
503 * it to the list of information structures.
505 pana_info
= wmem_new(wmem_file_scope(), pana_conv_info_t
);
506 pana_info
->pdus
=wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
508 conversation_add_proto_data(conversation
, proto_pana
, pana_info
);
511 if(!pinfo
->fd
->visited
){
512 if(flags
&PANA_FLAG_R
){
513 /* This is a request */
514 pana_trans
=wmem_new(wmem_file_scope(), pana_transaction_t
);
515 pana_trans
->req_frame
=pinfo
->num
;
516 pana_trans
->rep_frame
=0;
517 pana_trans
->req_time
=pinfo
->abs_ts
;
518 wmem_map_insert(pana_info
->pdus
, GUINT_TO_POINTER(seq_num
), (void *)pana_trans
);
520 pana_trans
=(pana_transaction_t
*)wmem_map_lookup(pana_info
->pdus
, GUINT_TO_POINTER(seq_num
));
522 pana_trans
->rep_frame
=pinfo
->num
;
526 pana_trans
=(pana_transaction_t
*)wmem_map_lookup(pana_info
->pdus
, GUINT_TO_POINTER(seq_num
));
530 /* create a "fake" pana_trans structure */
531 pana_trans
=wmem_new(pinfo
->pool
, pana_transaction_t
);
532 pana_trans
->req_frame
=0;
533 pana_trans
->rep_frame
=0;
534 pana_trans
->req_time
=pinfo
->abs_ts
;
537 /* print state tracking in the tree */
538 if(flags
&PANA_FLAG_R
){
539 /* This is a request */
540 if(pana_trans
->rep_frame
){
543 it
=proto_tree_add_uint(pana_tree
, hf_pana_response_in
, tvb
, 0, 0, pana_trans
->rep_frame
);
544 proto_item_set_generated(it
);
547 /* This is a reply */
548 if(pana_trans
->req_frame
){
552 it
=proto_tree_add_uint(pana_tree
, hf_pana_response_to
, tvb
, 0, 0, pana_trans
->req_frame
);
553 proto_item_set_generated(it
);
555 nstime_delta(&ns
, &pinfo
->abs_ts
, &pana_trans
->req_time
);
556 it
=proto_tree_add_time(pana_tree
, hf_pana_response_time
, tvb
, 0, 0, &ns
);
557 proto_item_set_generated(it
);
562 proto_tree_add_item(pana_tree
, hf_pana_reserved_type
, tvb
, offset
, 2, ENC_NA
);
566 proto_tree_add_item(pana_tree
, hf_pana_length_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
570 dissect_pana_flags(pana_tree
, tvb
, offset
, flags
);
574 proto_tree_add_uint_format_value(pana_tree
, hf_pana_msg_type
, tvb
,
575 offset
, 2, msg_type
, "%s-%s (%d)",
576 val_to_str(msg_type
, msg_type_names
, "Unknown (%d)"),
577 val_to_str(flags
& PANA_FLAG_R
, msg_subtype_names
, "Unknown (%d)"),
582 proto_tree_add_item(pana_tree
, hf_pana_session_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
585 /* Sequence Number */
586 proto_tree_add_item(pana_tree
, hf_pana_seqnumber
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
592 proto_tree
*avp_tree
;
593 avp_tvb
= tvb_new_subset_length(tvb
, offset
, avp_length
);
594 avp_tree
= proto_tree_add_subtree(pana_tree
, tvb
, offset
, avp_length
, ett_pana_avp
, NULL
, "Attribute Value Pairs");
596 dissect_avps(avp_tvb
, pinfo
, avp_tree
);
603 * Function for the PANA dissector.
605 /* Called either as a "new-style" or a heuristic dissector */
607 dissect_pana(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
613 uint32_t buffer_length
;
617 /* Get actual buffer length */
618 buffer_length
= tvb_captured_length(tvb
);
620 /* Check minimum buffer length */
621 if(buffer_length
< 12) {
625 /* Check minimum packet length */
626 msg_length
= tvb_get_ntohs(tvb
, 2);
627 if(msg_length
< 16) {
631 /* Check the packet length */
632 if(msg_length
!= tvb_reported_length(tvb
)) {
636 /* check that the reserved field is zero */
637 pana_res
= tvb_get_ntohs(tvb
, 0);
642 /* verify that none of the reserved bits are set */
643 flags
= tvb_get_ntohs(tvb
, 4);
644 if (flags
& PANA_FLAG_RESERVED
) {
648 /* verify that we recognize the message type */
649 msg_type
= tvb_get_ntohs(tvb
, 6);
650 if ((msg_type
> MSG_TYPE_MAX
) || (msg_type
== 0)) {
654 avp_length
= msg_length
- 16;
656 /* For bug 1908: check the length of the first AVP, too */
658 if (avp_length
!= 0) {
661 uint32_t first_avp_length
;
664 if (avp_length
< MIN_AVP_SIZE
) {
668 /* Make sure no exceptions since we're just doing a preliminary heuristic check */
669 if ((avp_offset
+ 8) > buffer_length
) {
672 avp_code
= tvb_get_ntohs(tvb
, avp_offset
);
673 if ((avp_code
== 0) || (avp_code
> AVP_CODE_MAX
)) {
676 avp_flags
= tvb_get_ntohs(tvb
, avp_offset
+ 2);
677 if (avp_flags
& PANA_AVP_FLAG_RESERVED
) {
680 /* check whether is the V (vendor) flag on or not */
681 if (avp_flags
& PANA_AVP_FLAG_V
) {
682 first_avp_length
= 12;
684 first_avp_length
= 8;
687 first_avp_length
+= tvb_get_ntohs(tvb
, avp_offset
+ 4);
689 if (first_avp_length
> avp_length
) {
694 dissect_pana_pdu(tvb
, pinfo
, tree
);
696 return tvb_reported_length(tvb
);
701 dissect_pana_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
703 return dissect_pana(tvb
, pinfo
, tree
, data
) != 0;
707 * Register the protocol with Wireshark
710 proto_register_pana(void)
713 static hf_register_info hf
[] = {
714 { &hf_pana_response_in
,
715 { "Response In", "pana.response_in",
716 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
717 "The response to this PANA request is in this frame", HFILL
}
719 { &hf_pana_response_to
,
720 { "Request In", "pana.response_to",
721 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
722 "This is a response to the PANA request in this frame", HFILL
}
724 { &hf_pana_response_time
,
725 { "Response Time", "pana.response_time",
726 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
727 "The time between the Call and the Reply", HFILL
}
729 { &hf_pana_reserved_type
,
730 { "PANA Reserved", "pana.reserved",
731 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
734 { &hf_pana_length_type
,
735 { "PANA Message Length", "pana.length",
736 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
742 { "Flags", "pana.flags",
743 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
747 { "Request", "pana.flags.r",
748 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_R
,
752 { "Start", "pana.flags.s",
753 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_S
,
757 { "Complete","pana.flags.c",
758 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_C
,
762 { "Auth","pana.flags.a",
763 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_A
,
767 { "Ping","pana.flags.p",
768 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_P
,
772 { "IP Reconfig","pana.flags.i",
773 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_FLAG_I
,
778 { "PANA Message Type", "pana.type",
779 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
782 { &hf_pana_session_id
,
783 { "PANA Session ID", "pana.sid",
784 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
787 { &hf_pana_seqnumber
,
788 { "PANA Sequence Number", "pana.seq",
789 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
795 { "AVP Code", "pana.avp.code",
796 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
799 { &hf_pana_avp_data_length
,
800 { "AVP Data Length", "pana.avp.data_length",
801 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
804 { &hf_pana_avp_flags
,
805 { "AVP Flags", "pana.avp.flags",
806 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
809 { &hf_pana_avp_flag_v
,
810 { "Vendor", "pana.avp.flags.v",
811 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), PANA_AVP_FLAG_V
,
814 { &hf_pana_avp_reserved
,
815 { "AVP Reserved", "pana.avp.reserved",
816 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
819 { &hf_pana_avp_vendorid
,
820 { "AVP Vendor ID", "pana.avp.vendorid",
821 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
826 { &hf_pana_avp_data_uint64
,
827 { "Value", "pana.avp.data.uint64",
828 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
831 { &hf_pana_avp_data_int64
,
832 { "Value", "pana.avp.data.int64",
833 FT_INT64
, BASE_DEC
, NULL
, 0x0,
836 { &hf_pana_avp_data_uint32
,
837 { "Value", "pana.avp.data.uint32",
838 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
841 { &hf_pana_avp_data_int32
,
842 { "Value", "pana.avp.data.int32",
843 FT_INT32
, BASE_DEC
, NULL
, 0x0,
846 { &hf_pana_avp_data_bytes
,
847 { "Value", "pana.avp.data.bytes",
848 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
851 { &hf_pana_avp_data_string
,
852 { "UTF8String", "pana.avp.data.string",
853 FT_STRING
, BASE_NONE
, NULL
, 0x0,
856 { &hf_pana_avp_data_enumerated
,
857 { "Value", "pana.avp.data.enum",
858 FT_INT32
, BASE_DEC
, NULL
, 0x0,
864 /* Setup protocol subtree array */
865 static int *ett
[] = {
873 /* Register the protocol name and description */
874 proto_pana
= proto_register_protocol("Protocol for carrying Authentication for Network Access", "PANA", "pana");
876 /* Required function calls to register the header fields and subtrees used */
877 proto_register_field_array(proto_pana
, hf
, array_length(hf
));
878 proto_register_subtree_array(ett
, array_length(ett
));
880 /* Register the dissector handle */
881 pana_handle
= register_dissector("pana", dissect_pana
, proto_pana
);
886 proto_reg_handoff_pana(void)
888 heur_dissector_add("udp", dissect_pana_heur
, "PANA over UDP", "pana_udp", proto_pana
, HEURISTIC_ENABLE
);
890 dissector_add_for_decode_as_with_preference("udp.port", pana_handle
);
892 eap_handle
= find_dissector_add_dependency("eap", proto_pana
);
897 * Editor modelines - https://www.wireshark.org/tools/modelines.html
902 * indent-tabs-mode: nil
905 * vi: set shiftwidth=8 tabstop=8 expandtab:
906 * :indentSize=8:tabSize=8:noTabs=true: