Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-pana.c
blob40b7d686c25ffe0b351fa2969bb5ac72fae6e9cf
1 /* packet-pana.c
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).
17 #include "config.h"
19 #include <epan/packet.h>
20 #include <epan/conversation.h>
21 #include <epan/tfs.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;
29 #if 0
30 #define PANA_UDP_PORT 3001
31 #endif
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
41 #if 0
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
52 #endif
53 #define PANA_FLAG_RESERVED 0x03ff
55 #define PANA_AVP_FLAG_V 0x8000
56 #if 0
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
72 #endif
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" },
113 { 2, "PANA-Auth" },
114 { 3, "PANA-Termination" },
115 { 4, "PANA-Notification" },
116 { 5, "PANA-Relay" },
117 { 0, NULL }
120 static const value_string msg_subtype_names[] = {
121 { 0x0000, "Answer" },
122 { 0x8000, "Request" },
123 { 0, NULL }
126 #define AVP_CODE_MAX 13
127 static const value_string avp_code_names[] = {
128 { 1, "AUTH AVP" },
129 { 2, "EAP-Payload AVP" },
130 { 3, "Integrity-Algorithm AVP" },
131 { 4, "Key-Id AVP" },
132 { 5, "Nonce 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" },
141 { 0, NULL }
144 #if 0
145 static const value_string avp_resultcode_names[] = {
146 { 0, "PANA_SUCCESS" },
147 { 1, "PANA_AUTHENTICATION_REJECTED" },
148 { 2, "PANA_AUTHORIZATION_REJECTED" },
149 { 0, NULL }
151 #endif
153 typedef enum {
154 PANA_OCTET_STRING = 1,
155 PANA_INTEGER32,
156 PANA_INTEGER64,
157 PANA_UNSIGNED32,
158 PANA_UNSIGNED64,
159 PANA_FLOAT32,
160 PANA_FLOAT64,
161 PANA_FLOAT128,
162 PANA_GROUPED,
163 PANA_ENUMERATED,
164 PANA_UTF8STRING,
165 PANA_EAP,
166 PANA_RESULT_CODE,
167 PANA_ENCAPSULATED
168 } pana_avp_types;
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" },
185 { 0, NULL }
189 /* Initialize the subtree pointers */
190 static int ett_pana;
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 {
198 uint32_t req_frame;
199 uint32_t rep_frame;
200 nstime_t req_time;
201 } pana_transaction_t;
203 typedef struct _pana_conv_info_t {
204 wmem_map_t *pdus;
205 } pana_conv_info_t;
207 static void
208 dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
211 * Function for the PANA flags dissector.
213 static void
214 dissect_pana_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint16_t flags)
216 static int * const flag_fields[] = {
217 &hf_pana_flag_r,
218 &hf_pana_flag_s,
219 &hf_pana_flag_c,
220 &hf_pana_flag_a,
221 &hf_pana_flag_p,
222 &hf_pana_flag_i,
223 NULL,
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.
234 static void
235 dissect_pana_avp_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint16_t flags)
237 static int * const flag_fields[] = {
238 &hf_pana_avp_flag_v,
239 NULL,
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)
254 if(vendor_id == 0) {
255 switch(avp_code) {
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;
271 } else {
272 return PANA_OCTET_STRING;
279 * Function for AVP dissector.
281 static void
282 // NOLINTNEXTLINE(misc-no-recursion)
283 dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
286 int offset;
287 uint16_t avp_code;
288 uint16_t avp_flags;
289 uint32_t avp_length;
290 uint16_t avp_type;
291 uint32_t vendor_id;
292 uint32_t avp_hdr_length;
293 uint32_t avp_data_length, result_code;
294 uint32_t padding;
296 int32_t buffer_length;
298 tvbuff_t *group_tvb;
299 tvbuff_t *eap_tvb;
300 tvbuff_t *encap_tvb;
301 proto_tree *single_avp_tree;
302 proto_tree *avp_eap_tree;
303 proto_tree *avp_encap_tree;
305 offset = 0;
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);
317 avp_hdr_length = 12;
318 } else {
319 vendor_id = 0;
320 avp_hdr_length = 8;
323 avp_length = avp_hdr_length + avp_data_length;
325 /* Check AVP type */
326 avp_type = pana_avp_get_type(avp_code, vendor_id);
329 /* Check padding */
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)"),
336 avp_length,
337 avp_length + padding);
339 /* AVP Code */
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)"),
343 avp_code);
344 offset += 2;
346 /* AVP Flags */
347 dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
348 offset += 2;
350 /* AVP Length */
351 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
352 offset += 2;
354 /* Reserved */
355 proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, ENC_NA);
356 offset += 2;
358 if (avp_flags & PANA_AVP_FLAG_V) {
359 /* Vendor ID */
360 proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, ENC_BIG_ENDIAN);
361 offset += 4;
363 if (! (avp_flags & PANA_AVP_FLAG_V)) {
364 /* AVP Value */
365 switch(avp_type) {
366 case PANA_GROUPED: {
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),
373 avp_data_length);
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);
376 break;
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);
381 break;
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);
386 break;
388 case PANA_INTEGER32: {
389 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
390 offset, 4, ENC_BIG_ENDIAN);
391 break;
393 case PANA_UNSIGNED32: {
394 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
395 offset, 4, ENC_BIG_ENDIAN);
396 break;
398 case PANA_INTEGER64: {
399 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
400 offset, 8, ENC_BIG_ENDIAN);
401 break;
403 case PANA_UNSIGNED64: {
404 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
405 offset, 8, ENC_BIG_ENDIAN);
406 break;
408 case PANA_ENUMERATED: {
409 proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
410 offset, 4, ENC_BIG_ENDIAN);
411 break;
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)",
417 result_code,
418 val_to_str(result_code, avp_code_names, "Unknown (%d)"));
419 break;
421 case PANA_EAP: {
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);
428 break;
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);
437 break;
441 offset += avp_data_length + padding;
443 /* Update the buffer length */
444 buffer_length -= avp_length + padding;
451 * Function for the PANA PDU dissector.
453 static void
454 // NOLINTNEXTLINE(misc-no-recursion)
455 dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
458 proto_tree *pana_tree = NULL;
459 uint16_t flags;
460 uint16_t msg_type;
461 uint32_t msg_length;
462 uint32_t avp_length;
463 uint32_t seq_num;
464 conversation_t *conversation;
465 pana_conv_info_t *pana_info;
466 pana_transaction_t *pana_trans;
467 int offset = 0;
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 */
484 if (tree) {
485 proto_item *ti;
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);
501 if (!pana_info) {
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);
519 } else {
520 pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num));
521 if(pana_trans){
522 pana_trans->rep_frame=pinfo->num;
525 } else {
526 pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num));
529 if(!pana_trans){
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){
541 proto_item *it;
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);
546 } else {
547 /* This is a reply */
548 if(pana_trans->req_frame){
549 proto_item *it;
550 nstime_t ns;
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);
561 /* Reserved field */
562 proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA);
563 offset += 2;
565 /* Length */
566 proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN);
567 offset += 2;
569 /* Flags */
570 dissect_pana_flags(pana_tree, tvb, offset, flags);
571 offset += 2;
573 /* Message Type */
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)"),
578 msg_type);
579 offset += 2;
581 /* Session ID */
582 proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN);
583 offset += 4;
585 /* Sequence Number */
586 proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN);
587 offset += 4;
589 /* AVPs */
590 if(avp_length != 0){
591 tvbuff_t *avp_tvb;
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 */
606 static int
607 dissect_pana(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
610 uint16_t pana_res;
611 uint32_t msg_length;
612 uint16_t flags;
613 uint32_t buffer_length;
614 uint16_t msg_type;
615 uint32_t avp_length;
617 /* Get actual buffer length */
618 buffer_length = tvb_captured_length(tvb);
620 /* Check minimum buffer length */
621 if(buffer_length < 12) {
622 return 0;
625 /* Check minimum packet length */
626 msg_length = tvb_get_ntohs(tvb, 2);
627 if(msg_length < 16) {
628 return 0;
631 /* Check the packet length */
632 if(msg_length != tvb_reported_length(tvb)) {
633 return 0;
636 /* check that the reserved field is zero */
637 pana_res = tvb_get_ntohs(tvb, 0);
638 if (pana_res != 0) {
639 return 0;
642 /* verify that none of the reserved bits are set */
643 flags = tvb_get_ntohs(tvb, 4);
644 if (flags & PANA_FLAG_RESERVED) {
645 return 0;
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)) {
651 return 0;
654 avp_length = msg_length - 16;
656 /* For bug 1908: check the length of the first AVP, too */
658 if (avp_length != 0) {
659 uint32_t avp_offset;
660 uint16_t avp_code;
661 uint32_t first_avp_length;
662 uint16_t avp_flags;
664 if (avp_length < MIN_AVP_SIZE) {
665 return 0;
667 avp_offset = 16;
668 /* Make sure no exceptions since we're just doing a preliminary heuristic check */
669 if ((avp_offset + 8) > buffer_length ) {
670 return 0;
672 avp_code = tvb_get_ntohs(tvb, avp_offset);
673 if ((avp_code == 0) || (avp_code > AVP_CODE_MAX)) {
674 return 0;
676 avp_flags = tvb_get_ntohs(tvb, avp_offset + 2);
677 if (avp_flags & PANA_AVP_FLAG_RESERVED) {
678 return 0;
680 /* check whether is the V (vendor) flag on or not */
681 if (avp_flags & PANA_AVP_FLAG_V) {
682 first_avp_length = 12;
683 } else {
684 first_avp_length = 8;
687 first_avp_length += tvb_get_ntohs(tvb, avp_offset + 4);
689 if (first_avp_length > avp_length) {
690 return 0;
694 dissect_pana_pdu(tvb, pinfo, tree);
696 return tvb_reported_length(tvb);
700 static bool
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
709 void
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,
732 NULL, HFILL }
734 { &hf_pana_length_type,
735 { "PANA Message Length", "pana.length",
736 FT_UINT16, BASE_DEC, NULL, 0x0,
737 NULL, HFILL }
741 { &hf_pana_flags,
742 { "Flags", "pana.flags",
743 FT_UINT8, BASE_HEX, NULL, 0x0,
744 NULL, HFILL }
746 { &hf_pana_flag_r,
747 { "Request", "pana.flags.r",
748 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_R,
749 NULL, HFILL }
751 { &hf_pana_flag_s,
752 { "Start", "pana.flags.s",
753 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_S,
754 NULL, HFILL }
756 { &hf_pana_flag_c,
757 { "Complete","pana.flags.c",
758 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_C,
759 NULL, HFILL }
761 { &hf_pana_flag_a,
762 { "Auth","pana.flags.a",
763 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_A,
764 NULL, HFILL }
766 { &hf_pana_flag_p,
767 { "Ping","pana.flags.p",
768 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_P,
769 NULL, HFILL }
771 { &hf_pana_flag_i,
772 { "IP Reconfig","pana.flags.i",
773 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_FLAG_I,
774 NULL, HFILL }
777 { &hf_pana_msg_type,
778 { "PANA Message Type", "pana.type",
779 FT_UINT16, BASE_DEC, NULL, 0x0,
780 NULL, HFILL }
782 { &hf_pana_session_id,
783 { "PANA Session ID", "pana.sid",
784 FT_UINT32, BASE_HEX, NULL, 0x0,
785 NULL, HFILL }
787 { &hf_pana_seqnumber,
788 { "PANA Sequence Number", "pana.seq",
789 FT_UINT32, BASE_HEX, NULL, 0x0,
790 NULL, HFILL }
794 { &hf_pana_avp_code,
795 { "AVP Code", "pana.avp.code",
796 FT_UINT16, BASE_DEC, NULL, 0x0,
797 NULL, HFILL }
799 { &hf_pana_avp_data_length,
800 { "AVP Data Length", "pana.avp.data_length",
801 FT_UINT16, BASE_DEC, NULL, 0x0,
802 NULL, HFILL }
804 { &hf_pana_avp_flags,
805 { "AVP Flags", "pana.avp.flags",
806 FT_UINT16, BASE_HEX, NULL, 0x0,
807 NULL, HFILL }
809 { &hf_pana_avp_flag_v,
810 { "Vendor", "pana.avp.flags.v",
811 FT_BOOLEAN, 16, TFS(&tfs_set_notset), PANA_AVP_FLAG_V,
812 NULL, HFILL }
814 { &hf_pana_avp_reserved,
815 { "AVP Reserved", "pana.avp.reserved",
816 FT_BYTES, BASE_NONE, NULL, 0x0,
817 NULL, HFILL }
819 { &hf_pana_avp_vendorid,
820 { "AVP Vendor ID", "pana.avp.vendorid",
821 FT_UINT32, BASE_HEX, NULL, 0x0,
822 NULL, HFILL }
826 { &hf_pana_avp_data_uint64,
827 { "Value", "pana.avp.data.uint64",
828 FT_UINT64, BASE_HEX, NULL, 0x0,
829 NULL, HFILL }
831 { &hf_pana_avp_data_int64,
832 { "Value", "pana.avp.data.int64",
833 FT_INT64, BASE_DEC, NULL, 0x0,
834 NULL, HFILL }
836 { &hf_pana_avp_data_uint32,
837 { "Value", "pana.avp.data.uint32",
838 FT_UINT32, BASE_HEX, NULL, 0x0,
839 NULL, HFILL }
841 { &hf_pana_avp_data_int32,
842 { "Value", "pana.avp.data.int32",
843 FT_INT32, BASE_DEC, NULL, 0x0,
844 NULL, HFILL }
846 { &hf_pana_avp_data_bytes,
847 { "Value", "pana.avp.data.bytes",
848 FT_BYTES, BASE_NONE, NULL, 0x0,
849 NULL, HFILL }
851 { &hf_pana_avp_data_string,
852 { "UTF8String", "pana.avp.data.string",
853 FT_STRING, BASE_NONE, NULL, 0x0,
854 NULL, HFILL }
856 { &hf_pana_avp_data_enumerated,
857 { "Value", "pana.avp.data.enum",
858 FT_INT32, BASE_DEC, NULL, 0x0,
859 NULL, HFILL }
864 /* Setup protocol subtree array */
865 static int *ett[] = {
866 &ett_pana,
867 &ett_pana_flags,
868 &ett_pana_avp,
869 &ett_pana_avp_info,
870 &ett_pana_avp_flags
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);
885 void
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
899 * Local variables:
900 * c-basic-offset: 8
901 * tab-width: 8
902 * indent-tabs-mode: nil
903 * End:
905 * vi: set shiftwidth=8 tabstop=8 expandtab:
906 * :indentSize=8:tabSize=8:noTabs=true: