2 * Routines for EAP Extensible Authentication Protocol dissection
5 * $Id: packet-eap.c,v 1.35 2004/02/03 18:22:32 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
73 #define EAP_TYPE_TTLS 21
75 static const value_string eap_type_vals[] = {
76 {EAP_TYPE_ID, "Identity [RFC2284]" },
77 {EAP_TYPE_NOTIFY,"Notification [RFC2284]" },
78 {EAP_TYPE_NAK, "Nak (Response only) [RFC2284]" },
79 { 4, "MD5-Challenge [RFC2284]" },
80 { 5, "One Time Password (OTP) [RFC2289]" },
81 { 6, "Generic Token Card [RFC2284]" },
82 { 7, "?? RESERVED ?? " }, /* ??? */
83 { 8, "?? RESERVED ?? " }, /* ??? */
84 { 9, "RSA Public Key Authentication [Whelan]" },
85 { 10, "DSS Unilateral [Nace]" },
87 { 12, "KEA-VALIDATE [Nace]" },
88 {EAP_TYPE_TLS, "EAP-TLS [RFC2716] [Aboba]" },
89 { 14, "Defender Token (AXENT) [Rosselli]" },
90 { 15, "RSA Security SecurID EAP [Asnes, Liberman]" },
91 { 16, "Arcot Systems EAP [Jerdonek]" },
92 {EAP_TYPE_LEAP,"EAP-Cisco Wireless (LEAP) [Norman]" },
93 { 18, "Nokia IP smart card authentication [Haverinen]" },
94 { 19, "SRP-SHA1 Part 1 [Carlson]" },
95 { 20, "SRP-SHA1 Part 2 [Carlson]" },
96 {EAP_TYPE_TTLS,"EAP-TTLS [Funk]" },
97 { 22, "Remote Access Service [Fields]" },
98 { 23, "UMTS Authentication and Key Agreement [Haverinen]" },
99 { 24, "EAP-3Com Wireless [Young]" },
100 { 25, "PEAP [Palekar]" },
101 { 26, "MS-EAP-Authentication [Palekar]" },
102 { 27, "Mutual Authentication w/Key Exchange (MAKE)[Berrendonner]" },
103 { 28, "CRYPTOCard [Webb]" },
104 { 29, "EAP-MSCHAP-V2 [Potter]" },
105 { 30, "DynamID [Merlin]" },
106 { 31, "Rob EAP [Ullah]" },
107 { 32, "SecurID EAP [Josefsson]" },
108 { 33, "MS-Authentication-TLV [Palekar]" },
109 { 34, "SentriNET [Kelleher]" },
110 { 35, "EAP-Actiontec Wireless [Chang]" },
111 { 36, "Cogent Systems Biometrics Authentication EAP [Xiong]" },
112 { 37, "AirFortress EAP [Hibbard]" },
113 { 38, "EAP-HTTP Digest [Tavakoli]" },
114 { 39, "SecureSuite EAP [Clements]" },
115 { 40, "DeviceConnect EAP [Pitard]" },
116 { 41, "EAP-SPEKE [Zick]" },
117 { 255, "Vendor-specific [draft-ietf-pppext-rfc2284bis-02.txt]" },
123 * State information for EAP-TLS (RFC2716) and Lightweight EAP:
125 * http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
127 * Attach to all conversations:
129 * a sequence number to be handed to "fragment_add_seq()" as
130 * the fragment sequence number - if it's -1, no reassembly
131 * is in progress, but if it's not, it's the sequence number
132 * to use for the current fragment;
134 * a value to be handed to "fragment_add_seq()" as the
135 * reassembly ID - when a reassembly is started, it's set to
136 * the frame number of the current frame, i.e. the frame
137 * that starts the reassembly;
139 * an indication of the current state of LEAP negotiation,
140 * with -1 meaning no LEAP negotiation is in progress.
142 * Attach to frames containing fragments of EAP-TLS messages the
143 * reassembly ID for those fragments, so we can find the reassembled
144 * data after the first pass through the packets.
146 * Attach to LEAP frames the state of the LEAP negotiation when the
147 * frame was processed, so we can properly dissect
148 * the LEAP message after the first pass through the packets.
150 * Attach to all conversations both pieces of information, to keep
151 * track of EAP-TLS reassembly and the LEAP state machine.
153 static GMemChunk *conv_state_chunk = NULL;
157 guint32 eap_reass_cookie;
161 static GMemChunk *frame_state_chunk = NULL;
164 int info; /* interpretation depends on EAP message type */
167 /*********************************************************************
170 **********************************************************************/
188 #define EAP_TLS_FLAG_L 0x80 /* Length included */
189 #define EAP_TLS_FLAG_M 0x40 /* More fragments */
190 #define EAP_TLS_FLAG_S 0x20 /* EAP-TLS start */
193 * reassembly of EAP-TLS
195 static GHashTable *eaptls_fragment_table = NULL;
197 static int hf_eaptls_fragment = -1;
198 static int hf_eaptls_fragments = -1;
199 static int hf_eaptls_fragment_overlap = -1;
200 static int hf_eaptls_fragment_overlap_conflict = -1;
201 static int hf_eaptls_fragment_multiple_tails = -1;
202 static int hf_eaptls_fragment_too_long_fragment = -1;
203 static int hf_eaptls_fragment_error = -1;
204 static gint ett_eaptls_fragment = -1;
205 static gint ett_eaptls_fragments = -1;
207 static const fragment_items eaptls_frag_items = {
208 &ett_eaptls_fragment,
209 &ett_eaptls_fragments,
210 &hf_eaptls_fragments,
212 &hf_eaptls_fragment_overlap,
213 &hf_eaptls_fragment_overlap_conflict,
214 &hf_eaptls_fragment_multiple_tails,
215 &hf_eaptls_fragment_too_long_fragment,
216 &hf_eaptls_fragment_error,
221 /*********************************************************************
222 **********************************************************************/
225 test_flag(unsigned char flag, unsigned char mask)
227 return ( ( flag & mask ) != 0 );
231 eaptls_defragment_init(void)
233 fragment_table_init(&eaptls_fragment_table);
237 eap_init_protocol(void)
239 if (conv_state_chunk != NULL)
240 g_mem_chunk_destroy(conv_state_chunk);
241 if (frame_state_chunk != NULL)
242 g_mem_chunk_destroy(frame_state_chunk);
244 conv_state_chunk = g_mem_chunk_new("conv_state_chunk",
245 sizeof (conv_state_t),
246 10 * sizeof (conv_state_t),
249 frame_state_chunk = g_mem_chunk_new("frame_state_chunk",
250 sizeof (frame_state_t),
251 100 * sizeof (frame_state_t),
256 dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
264 conversation_t *conversation;
265 conv_state_t *conversation_state;
266 frame_state_t *packet_state;
269 proto_tree *eap_tree = NULL;
271 if (check_col(pinfo->cinfo, COL_PROTOCOL))
272 col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAP");
273 if (check_col(pinfo->cinfo, COL_INFO))
274 col_clear(pinfo->cinfo, COL_INFO);
276 eap_code = tvb_get_guint8(tvb, 0);
278 if (check_col(pinfo->cinfo, COL_INFO))
279 col_add_str(pinfo->cinfo, COL_INFO,
280 val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)"));
283 * Find a conversation to which we belong; create one if we don't find
286 * We use the source and destination addresses, and the *matched* port
287 * number, because if this is running over RADIUS, there's no guarantee
288 * that the source port number for request and the destination port
289 * number for replies will be the same in all messages - the client
290 * may use different port numbers for each request.
292 * We have to pair up the matched port number with the corresponding
293 * address; we determine which that is by comparing it with the
294 * destination port - if it matches, we matched on the destination
295 * port (this is a request), otherwise we matched on the source port
298 * XXX - what if we're running over a TCP or UDP protocol with a
299 * heuristic dissector, meaning the matched port number won't be set?
301 * XXX - what if we have a capture file with captures on multiple
302 * PPP interfaces, with LEAP traffic on all of them? How can we
303 * keep them separate? (Or is that not going to happen?)
305 if (pinfo->destport == pinfo->match_port) {
306 conversation = find_conversation(&pinfo->dst, &pinfo->src,
307 pinfo->ptype, pinfo->destport,
310 conversation = find_conversation(&pinfo->src, &pinfo->dst,
311 pinfo->ptype, pinfo->srcport,
314 if (conversation == NULL) {
315 if (pinfo->destport == pinfo->match_port) {
316 conversation = conversation_new(&pinfo->dst, &pinfo->src,
317 pinfo->ptype, pinfo->destport,
320 conversation = conversation_new(&pinfo->src, &pinfo->dst,
321 pinfo->ptype, pinfo->srcport,
327 * Get the state information for the conversation; attach some if
330 conversation_state = conversation_get_proto_data(conversation, proto_eap);
331 if (conversation_state == NULL) {
333 * Attach state information to the conversation.
335 conversation_state = g_mem_chunk_alloc(conv_state_chunk);
336 conversation_state->eap_tls_seq = -1;
337 conversation_state->eap_reass_cookie = 0;
338 conversation_state->leap_state = -1;
339 conversation_add_proto_data(conversation, proto_eap, conversation_state);
343 * Set this now, so that it gets remembered even if we throw an exception
346 if (eap_code == EAP_FAILURE)
347 conversation_state->leap_state = -1;
349 eap_id = tvb_get_guint8(tvb, 1);
351 eap_len = tvb_get_ntohs(tvb, 2);
356 * This is an EAP fragment inside, for example, RADIUS. If we don't
357 * have all of the packet data, return the negative of the amount of
358 * additional data we need.
360 int reported_len = tvb_reported_length_remaining(tvb, 0);
362 if (reported_len < len)
363 return -(len - reported_len);
367 ti = proto_tree_add_item(tree, proto_eap, tvb, 0, len, FALSE);
368 eap_tree = proto_item_add_subtree(ti, ett_eap);
370 proto_tree_add_uint(eap_tree, hf_eap_code, tvb, 0, 1, eap_code);
374 proto_tree_add_item(eap_tree, hf_eap_identifier, tvb, 1, 1, FALSE);
377 proto_tree_add_uint(eap_tree, hf_eap_len, tvb, 2, 2, eap_len);
387 eap_type = tvb_get_guint8(tvb, 4);
389 if (check_col(pinfo->cinfo, COL_INFO))
390 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
391 val_to_str(eap_type, eap_type_vals,
392 "Unknown type (0x%02X)"));
394 proto_tree_add_uint(eap_tree, hf_eap_type, tvb, 4, 1, eap_type);
398 gint size = len - offset;
401 /*********************************************************************
402 **********************************************************************/
405 proto_tree_add_text(eap_tree, tvb, offset, size,
406 "Identity (%d byte%s): %s",
407 size, plurality(size, "", "s"),
408 tvb_format_text(tvb, offset, size));
410 if(!pinfo->fd->flags.visited)
411 conversation_state->leap_state = 0;
414 /*********************************************************************
415 **********************************************************************/
416 case EAP_TYPE_NOTIFY:
418 proto_tree_add_text(eap_tree, tvb, offset, size,
419 "Notification (%d byte%s): %s",
420 size, plurality(size, "", "s"),
421 tvb_format_text(tvb, offset, size));
424 /*********************************************************************
425 **********************************************************************/
428 proto_tree_add_item(eap_tree, hf_eap_type_nak, tvb,
432 /*********************************************************************
434 **********************************************************************/
438 guint8 flags = tvb_get_guint8(tvb, offset);
439 gboolean more_fragments;
442 int eap_tls_seq = -1;
443 guint32 eap_reass_cookie = 0;
444 gboolean needs_reassembly = FALSE;
446 more_fragments = test_flag(flags,EAP_TLS_FLAG_M);
447 has_length = test_flag(flags,EAP_TLS_FLAG_L);
449 /* Flags field, 1 byte */
451 proto_tree_add_text(eap_tree, tvb, offset, 1, "Flags(0x%X): %s%s%s",
453 has_length ? "Length ":"",
454 more_fragments ? "More " :"",
455 test_flag(flags,EAP_TLS_FLAG_S) ? "Start " :"");
459 /* Length field, 4 bytes, OPTIONAL. */
461 length = tvb_get_ntohl(tvb, offset);
463 proto_tree_add_text(eap_tree, tvb, offset, 4, "Length: %i",length);
472 gboolean save_fragmented;
474 tvb_len = tvb_length_remaining(tvb, offset);
479 EAP/TLS is weird protocol (it comes from
480 Microsoft after all).
482 If we have series of fragmented packets,
483 then there's no way of knowing that from
484 the packet itself, if it is the last packet
485 in series, that is that the packet part of
486 bigger fragmented set of data.
488 The only way to know is, by knowing
489 that we are already in defragmentation
490 "mode" and we are expecing packet
491 carrying fragment of data. (either
492 because we have not received expected
493 amount of data, or because the packet before
494 had "F"ragment flag set.)
496 The situation is alleviated by fact that it
497 is simple ack/nack protcol so there's no
498 place for out-of-order packets like it is
501 Anyway, point of this lengthy essay is that
502 we have to keep state information in the
503 conversation, so that we can put ourselves in
504 defragmenting mode and wait for the last packet,
505 and have to attach state to frames as well, so
506 that we can handle defragmentation after the
507 first pass through the capture.
509 /* See if we have a remembered defragmentation EAP ID. */
510 packet_state = p_get_proto_data(pinfo->fd, proto_eap);
511 if (packet_state == NULL) {
513 * We haven't - does this message require reassembly?
515 if (!pinfo->fd->flags.visited) {
517 * This is the first time we've looked at this frame,
518 * so it wouldn't have any remembered information.
520 * Therefore, we check whether this conversation has
521 * a reassembly operation in progress, or whether
522 * this frame has the Fragment flag set.
524 if (conversation_state->eap_tls_seq != -1) {
526 * There's a reassembly in progress; the sequence number
527 * of the previous fragment is
528 * "conversation_state->eap_tls_seq", and the reassembly
529 * ID is "conversation_state->eap_reass_cookie".
531 * We must include this frame in the reassembly.
532 * We advance the sequence number, giving us the
533 * sequence number for this fragment.
535 needs_reassembly = TRUE;
536 conversation_state->eap_tls_seq++;
538 eap_reass_cookie = conversation_state->eap_reass_cookie;
539 eap_tls_seq = conversation_state->eap_tls_seq;
540 } else if (more_fragments && has_length) {
542 * This message has the Fragment flag set, so it requires
543 * reassembly. It's the message containing the first
544 * fragment (if it's a later fragment, the sequence
545 * number in the conversation state would not be -1).
547 * If it doesn't include a length, however, we can't
548 * do reassembly (either the message is in error, as
549 * the first fragment *must* contain a length, or we
550 * didn't capture the first fragment, and this just
551 * happens to be the first fragment we saw), so we
552 * also check that we have a length;
554 needs_reassembly = TRUE;
555 conversation_state->eap_reass_cookie = pinfo->fd->num;
558 * Start the reassembly sequence number at 0.
560 conversation_state->eap_tls_seq = 0;
562 eap_tls_seq = conversation_state->eap_tls_seq;
563 eap_reass_cookie = conversation_state->eap_reass_cookie;
566 if (needs_reassembly) {
568 * This frame requires reassembly; remember the reassembly
569 * ID for subsequent accesses to it.
571 packet_state = g_mem_chunk_alloc(frame_state_chunk);
572 packet_state->info = eap_reass_cookie;
573 p_add_proto_data(pinfo->fd, proto_eap, packet_state);
578 * This frame has a reassembly cookie associated with it, so
579 * it requires reassembly. We've already done the
580 * reassembly in the first pass, so "fragment_add_seq()"
581 * won't look at the sequence number; set it to 0.
583 * XXX - a frame isn't supposed to have more than one
584 * EAP message in it, but if it includes both an EAP-TLS
585 * message and a LEAP message, we might be mistakenly
586 * concluding it requires reassembly because the "info"
587 * field isn't -1. We could, I guess, pack both EAP-TLS
588 * ID and LEAP state into the structure, but that doesn't
589 * work if you have multiple EAP-TLS or LEAP messages in
592 * But it's not clear how much work we should do to handle
593 * a bogus message such as that; as long as we don't crash
594 * or do something else equally horrible, we may not
595 * have to worry about this at all.
597 needs_reassembly = TRUE;
598 eap_reass_cookie = packet_state->info;
603 We test here to see whether EAP-TLS packet
604 carry fragmented of TLS data.
606 If this is the case, we do reasembly below,
607 otherwise we just call dissector.
609 if (needs_reassembly) {
610 fragment_data *fd_head = NULL;
613 * Yes, this frame contains a fragment that requires
616 save_fragmented = pinfo->fragmented;
617 pinfo->fragmented = TRUE;
618 fd_head = fragment_add_seq(tvb, offset, pinfo,
620 eaptls_fragment_table,
625 if (fd_head != NULL) /* Reassembled */
628 next_tvb = tvb_new_real_data(fd_head->data,
631 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
632 add_new_data_source(pinfo, next_tvb, "Reassembled EAP-TLS");
634 show_fragment_seq_tree(fd_head, &eaptls_frag_items,
635 eap_tree, pinfo, next_tvb);
637 call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
640 * We're finished reassembing this frame.
641 * Reinitialize the reassembly state.
643 if (!pinfo->fd->flags.visited)
644 conversation_state->eap_tls_seq = -1;
647 pinfo->fragmented = save_fragmented;
649 } else { /* this data is NOT fragmented */
650 next_tvb = tvb_new_subset(tvb, offset, tvb_len, size);
651 call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
655 break; /* EAP_TYPE_TLS */
656 /*********************************************************************
657 Cisco's Lightweight EAP (LEAP)
658 http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
659 **********************************************************************/
662 guint8 field,count,namesize;
666 field = tvb_get_guint8(tvb, offset);
667 proto_tree_add_text(eap_tree, tvb, offset, 1,
668 "Version: %i",field);
675 field = tvb_get_guint8(tvb, offset);
676 proto_tree_add_text(eap_tree, tvb, offset, 1,
677 "Reserved: %i",field);
683 count = tvb_get_guint8(tvb, offset);
685 proto_tree_add_text(eap_tree, tvb, offset, 1,
691 /* Data (byte*Count) */
692 /* This part is state-dependent. */
694 /* See if we've already remembered the state. */
695 packet_state = p_get_proto_data(pinfo->fd, proto_eap);
696 if (packet_state == NULL) {
698 * We haven't - compute the state based on the current
699 * state in the conversation.
701 leap_state = conversation_state->leap_state;
703 /* Advance the state machine. */
704 if (leap_state==0) leap_state = 1; else
705 if (leap_state==1) leap_state = 2; else
706 if (leap_state==2) leap_state = 3; else
707 if (leap_state==3) leap_state = 4; else
708 if (leap_state==4) leap_state = -1;
711 * Remember the state for subsequent accesses to this
714 packet_state = g_mem_chunk_alloc(frame_state_chunk);
715 packet_state->info = leap_state;
716 p_add_proto_data(pinfo->fd, proto_eap, packet_state);
719 * Update the conversation's state.
721 conversation_state->leap_state = leap_state;
724 /* Get the remembered state. */
725 leap_state = packet_state->info;
730 proto_tree_add_text(eap_tree, tvb, offset, count,
731 "Peer Challenge [8] Random Value:\"%s\"",
732 tvb_bytes_to_str(tvb, offset, count));
733 } else if (leap_state==2) {
734 proto_tree_add_text(eap_tree, tvb, offset, count,
735 "Peer Response [24] NtChallengeResponse(%s)",
736 tvb_bytes_to_str(tvb, offset, count));
737 } else if (leap_state==3) {
738 proto_tree_add_text(eap_tree, tvb, offset, count,
739 "AP Challenge [8] Random Value:\"%s\"",
740 tvb_bytes_to_str(tvb, offset, count));
741 } else if (leap_state==4) {
742 proto_tree_add_text(eap_tree, tvb, offset, count,
743 "AP Response [24] ChallengeResponse(%s)",
744 tvb_bytes_to_str(tvb, offset, count));
746 proto_tree_add_text(eap_tree, tvb, offset, count,
747 "Data (%d byte%s): \"%s\"",
748 count, plurality(count, "", "s"),
749 tvb_bytes_to_str(tvb, offset, count));
752 } /* END: if (tree) */
758 /* Name (Length-(8+Count)) */
759 namesize = eap_len - (8+count);
761 proto_tree_add_text(eap_tree, tvb, offset, namesize,
762 "Name (%d byte%s): %s",
763 namesize, plurality(count, "", "s"),
764 tvb_format_text(tvb, offset, namesize));
770 break; /* EAP_TYPE_LEAP */
771 /*********************************************************************
772 **********************************************************************/
775 proto_tree_add_text(eap_tree, tvb, offset, size,
776 "Type-Data (%d byte%s) Value: %s",
777 size, plurality(size, "", "s"),
778 tvb_bytes_to_str(tvb, offset, size));
781 /*********************************************************************
782 **********************************************************************/
783 } /* switch (eap_type) */
787 } /* switch (eap_code) */
789 return tvb_length(tvb);
793 dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
795 return dissect_eap_data(tvb, pinfo, tree, FALSE);
799 dissect_eap_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
801 return dissect_eap_data(tvb, pinfo, tree, TRUE);
805 proto_register_eap(void)
807 static hf_register_info hf[] = {
809 "Code", "eap.code", FT_UINT8, BASE_DEC,
810 VALS(eap_code_vals), 0x0, "", HFILL }},
811 { &hf_eap_identifier, {
812 "Id", "eap.id", FT_UINT8, BASE_DEC,
813 NULL, 0x0, "", HFILL }},
815 "Length", "eap.len", FT_UINT16, BASE_DEC,
816 NULL, 0x0, "", HFILL }},
818 "Type", "eap.type", FT_UINT8, BASE_DEC,
819 VALS(eap_type_vals), 0x0, "", HFILL }},
820 { &hf_eap_type_nak, {
821 "Desired Auth Type", "eap.desired_type", FT_UINT8, BASE_DEC,
822 VALS(eap_type_vals), 0x0, "", HFILL }},
823 { &hf_eaptls_fragment,
824 { "EAP-TLS Fragment", "eaptls.fragment",
825 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
826 "EAP-TLS Fragment", HFILL }},
827 { &hf_eaptls_fragments,
828 { "EAP-TLS Fragments", "eaptls.fragments",
829 FT_NONE, BASE_NONE, NULL, 0x0,
830 "EAP-TLS Fragments", HFILL }},
831 { &hf_eaptls_fragment_overlap,
832 { "Fragment overlap", "eaptls.fragment.overlap",
833 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
834 "Fragment overlaps with other fragments", HFILL }},
835 { &hf_eaptls_fragment_overlap_conflict,
836 { "Conflicting data in fragment overlap", "eaptls.fragment.overlap.conflict",
837 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
838 "Overlapping fragments contained conflicting data", HFILL }},
839 { &hf_eaptls_fragment_multiple_tails,
840 { "Multiple tail fragments found", "eaptls.fragment.multipletails",
841 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
842 "Several tails were found when defragmenting the packet", HFILL }},
843 { &hf_eaptls_fragment_too_long_fragment,
844 { "Fragment too long", "eaptls.fragment.toolongfragment",
845 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
846 "Fragment contained data past end of packet", HFILL }},
847 { &hf_eaptls_fragment_error,
848 { "Defragmentation error", "eaptls.fragment.error",
849 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
850 "Defragmentation error due to illegal fragments", HFILL }},
852 static gint *ett[] = {
854 &ett_eaptls_fragment,
855 &ett_eaptls_fragments,
858 proto_eap = proto_register_protocol("Extensible Authentication Protocol",
860 proto_register_field_array(proto_eap, hf, array_length(hf));
861 proto_register_subtree_array(ett, array_length(ett));
862 register_init_routine(&eap_init_protocol);
864 new_register_dissector("eap", dissect_eap, proto_eap);
865 new_register_dissector("eap_fragment", dissect_eap_fragment, proto_eap);
866 register_init_routine(eaptls_defragment_init);
870 proto_reg_handoff_eap(void)
872 dissector_handle_t eap_handle;
875 * Get a handle for the SSL/TLS dissector.
877 ssl_handle = find_dissector("ssl");
879 eap_handle = find_dissector("eap");
880 dissector_add("ppp.protocol", PPP_EAP, eap_handle);