2 * Routines for EAP Extensible Authentication Protocol dissection
5 * $Id: packet-eap.c,v 1.34 2003/04/20 11:36:13 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <epan/packet.h>
32 #include <epan/conversation.h>
34 #include "reassemble.h"
36 static int proto_eap = -1;
37 static int hf_eap_code = -1;
38 static int hf_eap_identifier = -1;
39 static int hf_eap_len = -1;
40 static int hf_eap_type = -1;
41 static int hf_eap_type_nak = -1;
43 static gint ett_eap = -1;
45 static dissector_handle_t ssl_handle;
48 #define EAP_RESPONSE 2
52 static const value_string eap_code_vals[] = {
53 { EAP_REQUEST, "Request" },
54 { EAP_RESPONSE, "Response" },
55 { EAP_SUCCESS, "Success" },
56 { EAP_FAILURE, "Failure" },
62 1) http://www.iana.org/assignments/ppp-numbers
63 PPP EAP REQUEST/RESPONSE TYPES
64 2) http://www.ietf.org/internet-drafts/draft-ietf-pppext-rfc2284bis-02.txt
69 #define EAP_TYPE_NOTIFY 2
70 #define EAP_TYPE_NAK 3
71 #define EAP_TYPE_TLS 13
72 #define EAP_TYPE_LEAP 17
74 static const value_string eap_type_vals[] = {
75 {EAP_TYPE_ID, "Identity [RFC2284]" },
76 {EAP_TYPE_NOTIFY,"Notification [RFC2284]" },
77 {EAP_TYPE_NAK, "Nak (Response only) [RFC2284]" },
78 { 4, "MD5-Challenge [RFC2284]" },
79 { 5, "One Time Password (OTP) [RFC2289]" },
80 { 6, "Generic Token Card [RFC2284]" },
81 { 7, "?? RESERVED ?? " }, /* ??? */
82 { 8, "?? RESERVED ?? " }, /* ??? */
83 { 9, "RSA Public Key Authentication [Whelan]" },
84 { 10, "DSS Unilateral [Nace]" },
86 { 12, "KEA-VALIDATE [Nace]" },
87 {EAP_TYPE_TLS, "EAP-TLS [RFC2716] [Aboba]" },
88 { 14, "Defender Token (AXENT) [Rosselli]" },
89 { 15, "RSA Security SecurID EAP [Asnes, Liberman]" },
90 { 16, "Arcot Systems EAP [Jerdonek]" },
91 {EAP_TYPE_LEAP,"EAP-Cisco Wireless (LEAP) [Norman]" },
92 { 18, "Nokia IP smart card authentication [Haverinen]" },
93 { 19, "SRP-SHA1 Part 1 [Carlson]" },
94 { 20, "SRP-SHA1 Part 2 [Carlson]" },
95 { 21, "EAP-TTLS [Funk]" },
96 { 22, "Remote Access Service [Fields]" },
97 { 23, "UMTS Authentication and Key Agreement [Haverinen]" },
98 { 24, "EAP-3Com Wireless [Young]" },
99 { 25, "PEAP [Palekar]" },
100 { 26, "MS-EAP-Authentication [Palekar]" },
101 { 27, "Mutual Authentication w/Key Exchange (MAKE)[Berrendonner]" },
102 { 28, "CRYPTOCard [Webb]" },
103 { 29, "EAP-MSCHAP-V2 [Potter]" },
104 { 30, "DynamID [Merlin]" },
105 { 31, "Rob EAP [Ullah]" },
106 { 32, "SecurID EAP [Josefsson]" },
107 { 33, "MS-Authentication-TLV [Palekar]" },
108 { 34, "SentriNET [Kelleher]" },
109 { 35, "EAP-Actiontec Wireless [Chang]" },
110 { 36, "Cogent Systems Biometrics Authentication EAP [Xiong]" },
111 { 37, "AirFortress EAP [Hibbard]" },
112 { 38, "EAP-HTTP Digest [Tavakoli]" },
113 { 39, "SecureSuite EAP [Clements]" },
114 { 40, "DeviceConnect EAP [Pitard]" },
115 { 41, "EAP-SPEKE [Zick]" },
116 { 255, "Vendor-specific [draft-ietf-pppext-rfc2284bis-02.txt]" },
122 * State information for EAP-TLS (RFC2716) and Lightweight EAP:
124 * http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
126 * Attach to all conversations:
128 * a sequence number to be handed to "fragment_add_seq()" as
129 * the fragment sequence number - if it's -1, no reassembly
130 * is in progress, but if it's not, it's the sequence number
131 * to use for the current fragment;
133 * a value to be handed to "fragment_add_seq()" as the
134 * reassembly ID - when a reassembly is started, it's set to
135 * the frame number of the current frame, i.e. the frame
136 * that starts the reassembly;
138 * an indication of the current state of LEAP negotiation,
139 * with -1 meaning no LEAP negotiation is in progress.
141 * Attach to frames containing fragments of EAP-TLS messages the
142 * reassembly ID for those fragments, so we can find the reassembled
143 * data after the first pass through the packets.
145 * Attach to LEAP frames the state of the LEAP negotiation when the
146 * frame was processed, so we can properly dissect
147 * the LEAP message after the first pass through the packets.
149 * Attach to all conversations both pieces of information, to keep
150 * track of EAP-TLS reassembly and the LEAP state machine.
152 static GMemChunk *conv_state_chunk = NULL;
156 guint32 eap_reass_cookie;
160 static GMemChunk *frame_state_chunk = NULL;
163 int info; /* interpretation depends on EAP message type */
166 /*********************************************************************
169 **********************************************************************/
187 #define EAP_TLS_FLAG_L 0x80 /* Length included */
188 #define EAP_TLS_FLAG_M 0x40 /* More fragments */
189 #define EAP_TLS_FLAG_S 0x20 /* EAP-TLS start */
192 * reassembly of EAP-TLS
194 static GHashTable *eaptls_fragment_table = NULL;
196 static int hf_eaptls_fragment = -1;
197 static int hf_eaptls_fragments = -1;
198 static int hf_eaptls_fragment_overlap = -1;
199 static int hf_eaptls_fragment_overlap_conflict = -1;
200 static int hf_eaptls_fragment_multiple_tails = -1;
201 static int hf_eaptls_fragment_too_long_fragment = -1;
202 static int hf_eaptls_fragment_error = -1;
203 static gint ett_eaptls_fragment = -1;
204 static gint ett_eaptls_fragments = -1;
206 static const fragment_items eaptls_frag_items = {
207 &ett_eaptls_fragment,
208 &ett_eaptls_fragments,
209 &hf_eaptls_fragments,
211 &hf_eaptls_fragment_overlap,
212 &hf_eaptls_fragment_overlap_conflict,
213 &hf_eaptls_fragment_multiple_tails,
214 &hf_eaptls_fragment_too_long_fragment,
215 &hf_eaptls_fragment_error,
220 /*********************************************************************
221 **********************************************************************/
224 test_flag(unsigned char flag, unsigned char mask)
226 return ( ( flag & mask ) != 0 );
230 eaptls_defragment_init(void)
232 fragment_table_init(&eaptls_fragment_table);
236 eap_init_protocol(void)
238 if (conv_state_chunk != NULL)
239 g_mem_chunk_destroy(conv_state_chunk);
240 if (frame_state_chunk != NULL)
241 g_mem_chunk_destroy(frame_state_chunk);
243 conv_state_chunk = g_mem_chunk_new("conv_state_chunk",
244 sizeof (conv_state_t),
245 10 * sizeof (conv_state_t),
248 frame_state_chunk = g_mem_chunk_new("frame_state_chunk",
249 sizeof (frame_state_t),
250 100 * sizeof (frame_state_t),
255 dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
263 conversation_t *conversation;
264 conv_state_t *conversation_state;
265 frame_state_t *packet_state;
268 proto_tree *eap_tree = NULL;
270 if (check_col(pinfo->cinfo, COL_PROTOCOL))
271 col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAP");
272 if (check_col(pinfo->cinfo, COL_INFO))
273 col_clear(pinfo->cinfo, COL_INFO);
275 eap_code = tvb_get_guint8(tvb, 0);
277 if (check_col(pinfo->cinfo, COL_INFO))
278 col_add_str(pinfo->cinfo, COL_INFO,
279 val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)"));
282 * Find a conversation to which we belong; create one if we don't find
285 * We use the source and destination addresses, and the *matched* port
286 * number, because if this is running over RADIUS, there's no guarantee
287 * that the source port number for request and the destination port
288 * number for replies will be the same in all messages - the client
289 * may use different port numbers for each request.
291 * We have to pair up the matched port number with the corresponding
292 * address; we determine which that is by comparing it with the
293 * destination port - if it matches, we matched on the destination
294 * port (this is a request), otherwise we matched on the source port
297 * XXX - what if we're running over a TCP or UDP protocol with a
298 * heuristic dissector, meaning the matched port number won't be set?
300 * XXX - what if we have a capture file with captures on multiple
301 * PPP interfaces, with LEAP traffic on all of them? How can we
302 * keep them separate? (Or is that not going to happen?)
304 if (pinfo->destport == pinfo->match_port) {
305 conversation = find_conversation(&pinfo->dst, &pinfo->src,
306 pinfo->ptype, pinfo->destport,
309 conversation = find_conversation(&pinfo->src, &pinfo->dst,
310 pinfo->ptype, pinfo->srcport,
313 if (conversation == NULL) {
314 if (pinfo->destport == pinfo->match_port) {
315 conversation = conversation_new(&pinfo->dst, &pinfo->src,
316 pinfo->ptype, pinfo->destport,
319 conversation = conversation_new(&pinfo->src, &pinfo->dst,
320 pinfo->ptype, pinfo->srcport,
326 * Get the state information for the conversation; attach some if
329 conversation_state = conversation_get_proto_data(conversation, proto_eap);
330 if (conversation_state == NULL) {
332 * Attach state information to the conversation.
334 conversation_state = g_mem_chunk_alloc(conv_state_chunk);
335 conversation_state->eap_tls_seq = -1;
336 conversation_state->eap_reass_cookie = 0;
337 conversation_state->leap_state = -1;
338 conversation_add_proto_data(conversation, proto_eap, conversation_state);
342 * Set this now, so that it gets remembered even if we throw an exception
345 if (eap_code == EAP_FAILURE)
346 conversation_state->leap_state = -1;
348 eap_id = tvb_get_guint8(tvb, 1);
350 eap_len = tvb_get_ntohs(tvb, 2);
355 * This is an EAP fragment inside, for example, RADIUS. If we don't
356 * have all of the packet data, return the negative of the amount of
357 * additional data we need.
359 int reported_len = tvb_reported_length_remaining(tvb, 0);
361 if (reported_len < len)
362 return -(len - reported_len);
366 ti = proto_tree_add_item(tree, proto_eap, tvb, 0, len, FALSE);
367 eap_tree = proto_item_add_subtree(ti, ett_eap);
369 proto_tree_add_uint(eap_tree, hf_eap_code, tvb, 0, 1, eap_code);
373 proto_tree_add_item(eap_tree, hf_eap_identifier, tvb, 1, 1, FALSE);
376 proto_tree_add_uint(eap_tree, hf_eap_len, tvb, 2, 2, eap_len);
386 eap_type = tvb_get_guint8(tvb, 4);
388 if (check_col(pinfo->cinfo, COL_INFO))
389 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
390 val_to_str(eap_type, eap_type_vals,
391 "Unknown type (0x%02X)"));
393 proto_tree_add_uint(eap_tree, hf_eap_type, tvb, 4, 1, eap_type);
397 gint size = len - offset;
400 /*********************************************************************
401 **********************************************************************/
404 proto_tree_add_text(eap_tree, tvb, offset, size,
405 "Identity (%d byte%s): %s",
406 size, plurality(size, "", "s"),
407 tvb_format_text(tvb, offset, size));
409 if(!pinfo->fd->flags.visited)
410 conversation_state->leap_state = 0;
413 /*********************************************************************
414 **********************************************************************/
415 case EAP_TYPE_NOTIFY:
417 proto_tree_add_text(eap_tree, tvb, offset, size,
418 "Notification (%d byte%s): %s",
419 size, plurality(size, "", "s"),
420 tvb_format_text(tvb, offset, size));
423 /*********************************************************************
424 **********************************************************************/
427 proto_tree_add_item(eap_tree, hf_eap_type_nak, tvb,
431 /*********************************************************************
433 **********************************************************************/
436 guint8 flags = tvb_get_guint8(tvb, offset);
437 gboolean more_fragments;
440 int eap_tls_seq = -1;
441 guint32 eap_reass_cookie = 0;
442 gboolean needs_reassembly = FALSE;
444 more_fragments = test_flag(flags,EAP_TLS_FLAG_M);
445 has_length = test_flag(flags,EAP_TLS_FLAG_L);
447 /* Flags field, 1 byte */
449 proto_tree_add_text(eap_tree, tvb, offset, 1, "Flags(0x%X): %s%s%s",
451 has_length ? "Length ":"",
452 more_fragments ? "More " :"",
453 test_flag(flags,EAP_TLS_FLAG_S) ? "Start " :"");
457 /* Length field, 4 bytes, OPTIONAL. */
459 length = tvb_get_ntohl(tvb, offset);
461 proto_tree_add_text(eap_tree, tvb, offset, 4, "Length: %i",length);
470 gboolean save_fragmented;
472 tvb_len = tvb_length_remaining(tvb, offset);
477 EAP/TLS is weird protocol (it comes from
478 Microsoft after all).
480 If we have series of fragmented packets,
481 then there's no way of knowing that from
482 the packet itself, if it is the last packet
483 in series, that is that the packet part of
484 bigger fragmented set of data.
486 The only way to know is, by knowing
487 that we are already in defragmentation
488 "mode" and we are expecing packet
489 carrying fragment of data. (either
490 because we have not received expected
491 amount of data, or because the packet before
492 had "F"ragment flag set.)
494 The situation is alleviated by fact that it
495 is simple ack/nack protcol so there's no
496 place for out-of-order packets like it is
499 Anyway, point of this lengthy essay is that
500 we have to keep state information in the
501 conversation, so that we can put ourselves in
502 defragmenting mode and wait for the last packet,
503 and have to attach state to frames as well, so
504 that we can handle defragmentation after the
505 first pass through the capture.
507 /* See if we have a remembered defragmentation EAP ID. */
508 packet_state = p_get_proto_data(pinfo->fd, proto_eap);
509 if (packet_state == NULL) {
511 * We haven't - does this message require reassembly?
513 if (!pinfo->fd->flags.visited) {
515 * This is the first time we've looked at this frame,
516 * so it wouldn't have any remembered information.
518 * Therefore, we check whether this conversation has
519 * a reassembly operation in progress, or whether
520 * this frame has the Fragment flag set.
522 if (conversation_state->eap_tls_seq != -1) {
524 * There's a reassembly in progress; the sequence number
525 * of the previous fragment is
526 * "conversation_state->eap_tls_seq", and the reassembly
527 * ID is "conversation_state->eap_reass_cookie".
529 * We must include this frame in the reassembly.
530 * We advance the sequence number, giving us the
531 * sequence number for this fragment.
533 needs_reassembly = TRUE;
534 conversation_state->eap_tls_seq++;
536 eap_reass_cookie = conversation_state->eap_reass_cookie;
537 eap_tls_seq = conversation_state->eap_tls_seq;
538 } else if (more_fragments && has_length) {
540 * This message has the Fragment flag set, so it requires
541 * reassembly. It's the message containing the first
542 * fragment (if it's a later fragment, the sequence
543 * number in the conversation state would not be -1).
545 * If it doesn't include a length, however, we can't
546 * do reassembly (either the message is in error, as
547 * the first fragment *must* contain a length, or we
548 * didn't capture the first fragment, and this just
549 * happens to be the first fragment we saw), so we
550 * also check that we have a length;
552 needs_reassembly = TRUE;
553 conversation_state->eap_reass_cookie = pinfo->fd->num;
556 * Start the reassembly sequence number at 0.
558 conversation_state->eap_tls_seq = 0;
560 eap_tls_seq = conversation_state->eap_tls_seq;
561 eap_reass_cookie = conversation_state->eap_reass_cookie;
564 if (needs_reassembly) {
566 * This frame requires reassembly; remember the reassembly
567 * ID for subsequent accesses to it.
569 packet_state = g_mem_chunk_alloc(frame_state_chunk);
570 packet_state->info = eap_reass_cookie;
571 p_add_proto_data(pinfo->fd, proto_eap, packet_state);
576 * This frame has a reassembly cookie associated with it, so
577 * it requires reassembly. We've already done the
578 * reassembly in the first pass, so "fragment_add_seq()"
579 * won't look at the sequence number; set it to 0.
581 * XXX - a frame isn't supposed to have more than one
582 * EAP message in it, but if it includes both an EAP-TLS
583 * message and a LEAP message, we might be mistakenly
584 * concluding it requires reassembly because the "info"
585 * field isn't -1. We could, I guess, pack both EAP-TLS
586 * ID and LEAP state into the structure, but that doesn't
587 * work if you have multiple EAP-TLS or LEAP messages in
590 * But it's not clear how much work we should do to handle
591 * a bogus message such as that; as long as we don't crash
592 * or do something else equally horrible, we may not
593 * have to worry about this at all.
595 needs_reassembly = TRUE;
596 eap_reass_cookie = packet_state->info;
601 We test here to see whether EAP-TLS packet
602 carry fragmented of TLS data.
604 If this is the case, we do reasembly below,
605 otherwise we just call dissector.
607 if (needs_reassembly) {
608 fragment_data *fd_head = NULL;
611 * Yes, this frame contains a fragment that requires
614 save_fragmented = pinfo->fragmented;
615 pinfo->fragmented = TRUE;
616 fd_head = fragment_add_seq(tvb, offset, pinfo,
618 eaptls_fragment_table,
623 if (fd_head != NULL) /* Reassembled */
626 next_tvb = tvb_new_real_data(fd_head->data,
629 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
630 add_new_data_source(pinfo, next_tvb, "Reassembled EAP-TLS");
632 show_fragment_seq_tree(fd_head, &eaptls_frag_items,
633 eap_tree, pinfo, next_tvb);
635 call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
638 * We're finished reassembing this frame.
639 * Reinitialize the reassembly state.
641 if (!pinfo->fd->flags.visited)
642 conversation_state->eap_tls_seq = -1;
645 pinfo->fragmented = save_fragmented;
647 } else { /* this data is NOT fragmented */
648 next_tvb = tvb_new_subset(tvb, offset, tvb_len, size);
649 call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
653 break; /* EAP_TYPE_TLS */
654 /*********************************************************************
655 Cisco's Lightweight EAP (LEAP)
656 http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
657 **********************************************************************/
660 guint8 field,count,namesize;
664 field = tvb_get_guint8(tvb, offset);
665 proto_tree_add_text(eap_tree, tvb, offset, 1,
666 "Version: %i",field);
673 field = tvb_get_guint8(tvb, offset);
674 proto_tree_add_text(eap_tree, tvb, offset, 1,
675 "Reserved: %i",field);
681 count = tvb_get_guint8(tvb, offset);
683 proto_tree_add_text(eap_tree, tvb, offset, 1,
689 /* Data (byte*Count) */
690 /* This part is state-dependent. */
692 /* See if we've already remembered the state. */
693 packet_state = p_get_proto_data(pinfo->fd, proto_eap);
694 if (packet_state == NULL) {
696 * We haven't - compute the state based on the current
697 * state in the conversation.
699 leap_state = conversation_state->leap_state;
701 /* Advance the state machine. */
702 if (leap_state==0) leap_state = 1; else
703 if (leap_state==1) leap_state = 2; else
704 if (leap_state==2) leap_state = 3; else
705 if (leap_state==3) leap_state = 4; else
706 if (leap_state==4) leap_state = -1;
709 * Remember the state for subsequent accesses to this
712 packet_state = g_mem_chunk_alloc(frame_state_chunk);
713 packet_state->info = leap_state;
714 p_add_proto_data(pinfo->fd, proto_eap, packet_state);
717 * Update the conversation's state.
719 conversation_state->leap_state = leap_state;
722 /* Get the remembered state. */
723 leap_state = packet_state->info;
728 proto_tree_add_text(eap_tree, tvb, offset, count,
729 "Peer Challenge [8] Random Value:\"%s\"",
730 tvb_bytes_to_str(tvb, offset, count));
731 } else if (leap_state==2) {
732 proto_tree_add_text(eap_tree, tvb, offset, count,
733 "Peer Response [24] NtChallengeResponse(%s)",
734 tvb_bytes_to_str(tvb, offset, count));
735 } else if (leap_state==3) {
736 proto_tree_add_text(eap_tree, tvb, offset, count,
737 "AP Challenge [8] Random Value:\"%s\"",
738 tvb_bytes_to_str(tvb, offset, count));
739 } else if (leap_state==4) {
740 proto_tree_add_text(eap_tree, tvb, offset, count,
741 "AP Response [24] ChallengeResponse(%s)",
742 tvb_bytes_to_str(tvb, offset, count));
744 proto_tree_add_text(eap_tree, tvb, offset, count,
745 "Data (%d byte%s): \"%s\"",
746 count, plurality(count, "", "s"),
747 tvb_bytes_to_str(tvb, offset, count));
750 } /* END: if (tree) */
756 /* Name (Length-(8+Count)) */
757 namesize = eap_len - (8+count);
759 proto_tree_add_text(eap_tree, tvb, offset, namesize,
760 "Name (%d byte%s): %s",
761 namesize, plurality(count, "", "s"),
762 tvb_format_text(tvb, offset, namesize));
768 break; /* EAP_TYPE_LEAP */
769 /*********************************************************************
770 **********************************************************************/
773 proto_tree_add_text(eap_tree, tvb, offset, size,
774 "Type-Data (%d byte%s) Value: %s",
775 size, plurality(size, "", "s"),
776 tvb_bytes_to_str(tvb, offset, size));
779 /*********************************************************************
780 **********************************************************************/
781 } /* switch (eap_type) */
785 } /* switch (eap_code) */
787 return tvb_length(tvb);
791 dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
793 return dissect_eap_data(tvb, pinfo, tree, FALSE);
797 dissect_eap_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
799 return dissect_eap_data(tvb, pinfo, tree, TRUE);
803 proto_register_eap(void)
805 static hf_register_info hf[] = {
807 "Code", "eap.code", FT_UINT8, BASE_DEC,
808 VALS(eap_code_vals), 0x0, "", HFILL }},
809 { &hf_eap_identifier, {
810 "Id", "eap.id", FT_UINT8, BASE_DEC,
811 NULL, 0x0, "", HFILL }},
813 "Length", "eap.len", FT_UINT16, BASE_DEC,
814 NULL, 0x0, "", HFILL }},
816 "Type", "eap.type", FT_UINT8, BASE_DEC,
817 VALS(eap_type_vals), 0x0, "", HFILL }},
818 { &hf_eap_type_nak, {
819 "Desired Auth Type", "eap.desired_type", FT_UINT8, BASE_DEC,
820 VALS(eap_type_vals), 0x0, "", HFILL }},
821 { &hf_eaptls_fragment,
822 { "EAP-TLS Fragment", "eaptls.fragment",
823 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
824 "EAP-TLS Fragment", HFILL }},
825 { &hf_eaptls_fragments,
826 { "EAP-TLS Fragments", "eaptls.fragments",
827 FT_NONE, BASE_NONE, NULL, 0x0,
828 "EAP-TLS Fragments", HFILL }},
829 { &hf_eaptls_fragment_overlap,
830 { "Fragment overlap", "eaptls.fragment.overlap",
831 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
832 "Fragment overlaps with other fragments", HFILL }},
833 { &hf_eaptls_fragment_overlap_conflict,
834 { "Conflicting data in fragment overlap", "eaptls.fragment.overlap.conflict",
835 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
836 "Overlapping fragments contained conflicting data", HFILL }},
837 { &hf_eaptls_fragment_multiple_tails,
838 { "Multiple tail fragments found", "eaptls.fragment.multipletails",
839 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
840 "Several tails were found when defragmenting the packet", HFILL }},
841 { &hf_eaptls_fragment_too_long_fragment,
842 { "Fragment too long", "eaptls.fragment.toolongfragment",
843 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
844 "Fragment contained data past end of packet", HFILL }},
845 { &hf_eaptls_fragment_error,
846 { "Defragmentation error", "eaptls.fragment.error",
847 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
848 "Defragmentation error due to illegal fragments", HFILL }},
850 static gint *ett[] = {
852 &ett_eaptls_fragment,
853 &ett_eaptls_fragments,
856 proto_eap = proto_register_protocol("Extensible Authentication Protocol",
858 proto_register_field_array(proto_eap, hf, array_length(hf));
859 proto_register_subtree_array(ett, array_length(ett));
860 register_init_routine(&eap_init_protocol);
862 new_register_dissector("eap", dissect_eap, proto_eap);
863 new_register_dissector("eap_fragment", dissect_eap_fragment, proto_eap);
864 register_init_routine(eaptls_defragment_init);
868 proto_reg_handoff_eap(void)
870 dissector_handle_t eap_handle;
873 * Get a handle for the SSL/TLS dissector.
875 ssl_handle = find_dissector("ssl");
877 eap_handle = find_dissector("eap");
878 dissector_add("ppp.protocol", PPP_EAP, eap_handle);