2 * Routines for the disassembly of the proprietary Cisco IPSEC in
3 * TCP encapsulation protocol
7 * Copyright 2007 Joerg Mayer (see AUTHORS file)
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 * - Find out the meaning of the (unknown) trailer
30 * - UDP checksum is wrong
31 * - Currently doesn't handle AH (lack of sample trace)
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include "packet-ndmp.h"
43 static int hf_tcpencap_unknown = -1;
44 static int hf_tcpencap_zero = -1;
45 static int hf_tcpencap_seq = -1;
46 static int hf_tcpencap_ike_direction = -1;
47 static int hf_tcpencap_esp_zero = -1;
48 static int hf_tcpencap_magic = -1;
49 static int hf_tcpencap_proto = -1;
50 static int hf_tcpencap_magic2 = -1;
52 static int proto_tcpencap = -1;
53 static gint ett_tcpencap = -1;
54 static gint ett_tcpencap_unknown = -1;
56 static const value_string tcpencap_ikedir_vals[] = {
57 { 0x0000, "Server to client" },
58 { 0x4000, "Client to server" },
63 static const value_string tcpencap_proto_vals[] = {
70 #define TCP_CISCO_IPSEC 10000
71 static guint global_tcpencap_tcp_port = TCP_CISCO_IPSEC;
73 static dissector_handle_t esp_handle;
74 static dissector_handle_t udp_handle;
76 #define TCP_ENCAP_P_ESP 1
77 #define TCP_ENCAP_P_UDP 2
80 /* oh what a crap protocol.
81 there is nothing in the protocol that makes it easy to identify and then
82 worse is that by default it is using port 10000 which ndmp has been
85 assume it is tcpencap if it does not look like ndmp
88 packet_is_tcpencap(tvbuff_t *tvb, packet_info *pinfo)
90 if(check_if_ndmp(tvb, pinfo)){
98 * TCP Encapsulation of IPsec Packets
99 * as supported by the cisco vpn3000 concentrator series
102 dissect_tcpencap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
104 proto_tree *tcpencap_tree = NULL;
105 proto_tree *tcpencap_unknown_tree = NULL;
107 proto_item *tree_item = NULL;
108 proto_item *unknown_item = NULL;
110 guint32 reported_length = tvb_reported_length(tvb);
114 /* verify that this looks like a tcpencap packet */
115 if(!packet_is_tcpencap(tvb, pinfo)){
119 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPENCAP");
120 if (check_col(pinfo->cinfo, COL_INFO))
121 col_clear(pinfo->cinfo, COL_INFO);
123 /* If the first 4 bytes are 0x01f401f4 (udp src and dst port = 500)
124 we most likely have UDP (isakmp) traffic */
126 if (tvb_get_ntohl(tvb, 0) == 0x01f401f4) { /* UDP means ISAKMP */
127 protocol = TCP_ENCAP_P_UDP;
128 } else { /* Hopefully ESP */
129 protocol = TCP_ENCAP_P_ESP;
133 tree_item = proto_tree_add_item(tree, proto_tcpencap, tvb, 0, -1, FALSE);
134 tcpencap_tree = proto_item_add_subtree(tree_item, ett_tcpencap);
136 /* Dissect the trailer following the encapsulated IPSEC/ISAKMP packet */
137 offset = reported_length - 16;
138 unknown_item = proto_tree_add_item(tcpencap_tree, hf_tcpencap_unknown, tvb,
140 /* Try to guess the contents of the trailer */
141 tcpencap_unknown_tree = proto_item_add_subtree(unknown_item, ett_tcpencap_unknown);
142 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_zero, tvb, offset + 0, 4, FALSE);
143 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_seq, tvb, offset + 4, 2, FALSE);
144 if (protocol == TCP_ENCAP_P_UDP) {
145 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_ike_direction, tvb, offset + 6, 2, FALSE);
147 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_esp_zero, tvb, offset + 6, 2, FALSE);
149 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_magic, tvb, offset + 8, 5, FALSE);
150 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_proto, tvb, offset + 13, 1, FALSE);
151 proto_tree_add_item(tcpencap_unknown_tree, hf_tcpencap_magic2, tvb, offset + 14, 2, FALSE);
154 /* Create the tvbuffer for the next dissector */
155 next_tvb = tvb_new_subset(tvb, 0, reported_length - 16 , -1);
156 if (protocol == TCP_ENCAP_P_UDP) {
157 call_dissector(udp_handle, next_tvb, pinfo, tree);
158 } else { /* Hopefully ESP */
159 call_dissector(esp_handle, next_tvb, pinfo, tree);
162 return tvb_length(tvb);
166 proto_register_tcpencap(void)
168 static hf_register_info hf[] = {
170 { &hf_tcpencap_unknown,
171 { "Unknown trailer", "tcpencap.unknown", FT_BYTES, BASE_NONE, NULL,
175 { "All zero", "tcpencap.zero", FT_BYTES, BASE_NONE, NULL,
179 { "Sequence number", "tcpencap.seq", FT_UINT16, BASE_HEX, NULL,
182 { &hf_tcpencap_esp_zero,
183 { "ESP zero", "tcpencap.espzero", FT_UINT16, BASE_HEX, NULL,
186 { &hf_tcpencap_ike_direction,
187 { "ISAKMP traffic direction", "tcpencap.ikedirection", FT_UINT16, BASE_HEX, VALS(tcpencap_ikedir_vals),
190 { &hf_tcpencap_magic,
191 { "Magic number", "tcpencap.magic", FT_BYTES, BASE_NONE, NULL,
194 { &hf_tcpencap_proto,
195 { "Protocol", "tcpencap.proto", FT_UINT8, BASE_HEX, VALS(tcpencap_proto_vals),
198 { &hf_tcpencap_magic2,
199 { "Magic 2", "tcpencap.magic2", FT_BYTES, BASE_NONE, NULL,
204 static gint *ett[] = {
206 &ett_tcpencap_unknown,
209 module_t *tcpencap_module;
211 void proto_reg_handoff_tcpencap(void);
213 proto_tcpencap = proto_register_protocol(
214 "TCP Encapsulation of IPsec Packets", "TCPENCAP", "tcpencap");
215 proto_register_field_array(proto_tcpencap, hf, array_length(hf));
216 proto_register_subtree_array(ett, array_length(ett));
217 tcpencap_module = prefs_register_protocol(proto_tcpencap, proto_reg_handoff_tcpencap);
218 prefs_register_uint_preference(tcpencap_module, "tcp.port", "IPSEC TCP Port",
219 "Set the port for IPSEC/ISAKMP messages"
220 "If other than the default of 10000)",
221 10, &global_tcpencap_tcp_port);
225 proto_reg_handoff_tcpencap(void)
227 static dissector_handle_t tcpencap_handle;
228 static gboolean initialized = FALSE;
229 static guint tcpencap_tcp_port;
232 tcpencap_handle = new_create_dissector_handle(dissect_tcpencap, proto_tcpencap);
233 esp_handle = find_dissector("esp");
234 udp_handle = find_dissector("udp");
237 dissector_delete("tcp.port", tcpencap_tcp_port, tcpencap_handle);
240 tcpencap_tcp_port = global_tcpencap_tcp_port;
241 dissector_add("tcp.port", global_tcpencap_tcp_port, tcpencap_handle);