2 * Routines for IPsec/IPComp packet disassembly
4 * $Id: packet-ipsec.c,v 1.24 2001/01/03 07:53:43 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * 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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
43 #include "packet-ipsec.h"
44 #include "packet-ip.h"
48 /* Place AH payload in sub tree */
49 gboolean g_ah_payload_in_subtree = FALSE;
51 static int proto_ah = -1;
52 static int hf_ah_spi = -1;
53 static int hf_ah_sequence = -1;
54 static int proto_esp = -1;
55 static int hf_esp_spi = -1;
56 static int hf_esp_sequence = -1;
57 static int proto_ipcomp = -1;
58 static int hf_ipcomp_flags = -1;
59 static int hf_ipcomp_cpi = -1;
61 static gint ett_ah = -1;
62 static gint ett_esp = -1;
63 static gint ett_ipcomp = -1;
66 guint8 ah_nxt; /* Next Header */
67 guint8 ah_len; /* Length of data + 1, in 32bit */
68 guint16 ah_reserve; /* Reserved for future use */
69 guint32 ah_spi; /* Security parameter index */
70 guint32 ah_seq; /* Sequence number field */
71 /* variable size, 32bit bound*/ /* Authentication data */
75 guint32 esp_spi; /* ESP */
76 guint32 esp_seq; /* Sequence number */
77 /*variable size*/ /* (IV and) Payload data */
78 /*variable size*/ /* padding */
79 /*8bit*/ /* pad size */
80 /*8bit*/ /* next header */
81 /*8bit*/ /* next header */
82 /*variable size, 32bit bound*/ /* Authentication data */
86 guint8 comp_nxt; /* Next Header */
87 guint8 comp_flags; /* Must be zero */
88 guint16 comp_cpi; /* Compression parameter index */
91 /* well-known algorithm number (in CPI), from RFC2409 */
92 #define IPCOMP_OUI 1 /* vendor specific */
93 #define IPCOMP_DEFLATE 2 /* RFC2394 */
94 #define IPCOMP_LZS 3 /* RFC2395 */
97 static const value_string cpi2val[] = {
98 { IPCOMP_OUI, "OUI" },
99 { IPCOMP_DEFLATE, "DEFLATE" },
100 { IPCOMP_LZS, "LZS" },
105 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
109 dissect_ah_old(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
116 memcpy(&ah, (void *) &pd[offset], sizeof(ah));
117 advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
119 if (check_col(fd, COL_PROTOCOL))
120 col_set_str(fd, COL_PROTOCOL, "AH");
121 if (check_col(fd, COL_INFO)) {
122 col_add_fstr(fd, COL_INFO, "AH (SPI=0x%08x)",
123 (guint32)ntohl(ah.ah_spi));
127 /* !!! specify length */
128 ti = proto_tree_add_item(tree, proto_ah, NullTVB, offset, advance, FALSE);
129 ah_tree = proto_item_add_subtree(ti, ett_ah);
131 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_nxt), 1,
132 "Next Header: %s (0x%02x)", ipprotostr(ah.ah_nxt), ah.ah_nxt);
133 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_len), 1,
134 "Length: %d", ah.ah_len << 2);
135 proto_tree_add_uint(ah_tree, hf_ah_spi, NullTVB,
136 offset + offsetof(struct newah, ah_spi), 4,
137 (guint32)ntohl(ah.ah_spi));
138 proto_tree_add_uint(ah_tree, hf_ah_sequence, NullTVB,
139 offset + offsetof(struct newah, ah_seq), 4,
140 (guint32)ntohl(ah.ah_seq));
141 proto_tree_add_text(ah_tree, NullTVB, offset + sizeof(ah), (ah.ah_len - 1) << 2,
145 /* start of the new header (could be a extension header) */
150 dissect_ah(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
152 proto_tree *ah_tree, *next_tree = NULL;
157 OLD_CHECK_DISPLAY_AS_DATA(proto_ah, pd, offset, fd, tree);
159 memcpy(&ah, (void *) &pd[offset], sizeof(ah));
160 advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
162 if (check_col(fd, COL_PROTOCOL))
163 col_set_str(fd, COL_PROTOCOL, "AH");
164 if (check_col(fd, COL_INFO)) {
165 col_add_fstr(fd, COL_INFO, "AH (SPI=0x%08x)",
166 (guint32)ntohl(ah.ah_spi));
170 /* !!! specify length */
171 ti = proto_tree_add_item(tree, proto_ah, NullTVB, offset, advance, FALSE);
172 ah_tree = proto_item_add_subtree(ti, ett_ah);
174 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_nxt), 1,
175 "Next Header: %s (0x%02x)", ipprotostr(ah.ah_nxt), ah.ah_nxt);
176 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_len), 1,
177 "Length: %d", ah.ah_len << 2);
178 proto_tree_add_uint(ah_tree, hf_ah_spi, NullTVB,
179 offset + offsetof(struct newah, ah_spi), 4,
180 (guint32)ntohl(ah.ah_spi));
181 proto_tree_add_uint(ah_tree, hf_ah_sequence, NullTVB,
182 offset + offsetof(struct newah, ah_seq), 4,
183 (guint32)ntohl(ah.ah_seq));
184 proto_tree_add_text(ah_tree, NullTVB, offset + sizeof(ah), (ah.ah_len - 1) << 2,
187 /* Decide where to place next protocol decode */
188 if (g_ah_payload_in_subtree) {
196 /* start of the new header (could be a extension header) */
199 if (g_ah_payload_in_subtree) {
200 col_set_writable(fd, FALSE);
203 /* do lookup with the subdissector table */
204 if (!old_dissector_try_port(ip_dissector_table, ah.ah_nxt, pd, offset, fd, next_tree)) {
205 old_dissect_data(pd, offset, fd, next_tree);
210 dissect_esp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
212 proto_tree *esp_tree;
216 OLD_CHECK_DISPLAY_AS_DATA(proto_esp, pd, offset, fd, tree);
218 memcpy(&esp, (void *) &pd[offset], sizeof(esp));
221 * load the top pane info. This should be overwritten by
222 * the next protocol in the stack
224 if (check_col(fd, COL_PROTOCOL))
225 col_set_str(fd, COL_PROTOCOL, "ESP");
226 if (check_col(fd, COL_INFO)) {
227 col_add_fstr(fd, COL_INFO, "ESP (SPI=0x%08x)",
228 (guint32)ntohl(esp.esp_spi));
232 * populate a tree in the second pane with the status of the link layer
236 ti = proto_tree_add_item(tree, proto_esp, NullTVB, offset, END_OF_FRAME, FALSE);
237 esp_tree = proto_item_add_subtree(ti, ett_esp);
238 proto_tree_add_uint(esp_tree, hf_esp_spi, NullTVB,
239 offset + offsetof(struct newesp, esp_spi), 4,
240 (guint32)ntohl(esp.esp_spi));
241 proto_tree_add_uint(esp_tree, hf_esp_sequence, NullTVB,
242 offset + offsetof(struct newesp, esp_seq), 4,
243 (guint32)ntohl(esp.esp_seq));
244 old_dissect_data(pd, offset + sizeof(struct newesp), fd, esp_tree);
249 dissect_ipcomp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
251 proto_tree *ipcomp_tree;
253 struct ipcomp ipcomp;
256 OLD_CHECK_DISPLAY_AS_DATA(proto_ipcomp, pd, offset, fd, tree);
258 memcpy(&ipcomp, (void *) &pd[offset], sizeof(ipcomp));
261 * load the top pane info. This should be overwritten by
262 * the next protocol in the stack
264 if (check_col(fd, COL_PROTOCOL))
265 col_set_str(fd, COL_PROTOCOL, "IPComp");
266 if (check_col(fd, COL_INFO)) {
267 p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
269 col_add_fstr(fd, COL_INFO, "IPComp (CPI=0x%04x)",
270 ntohs(ipcomp.comp_cpi));
272 col_add_fstr(fd, COL_INFO, "IPComp (CPI=%s)", p);
276 * populate a tree in the second pane with the status of the link layer
280 ti = proto_tree_add_item(tree, proto_ipcomp, NullTVB, offset, END_OF_FRAME,
282 ipcomp_tree = proto_item_add_subtree(ti, ett_ipcomp);
284 proto_tree_add_text(ipcomp_tree, NullTVB,
285 offset + offsetof(struct ipcomp, comp_nxt), 1,
286 "Next Header: %s (0x%02x)",
287 ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
288 proto_tree_add_uint(ipcomp_tree, hf_ipcomp_flags, NullTVB,
289 offset + offsetof(struct ipcomp, comp_flags), 1,
291 p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
293 proto_tree_add_uint(ipcomp_tree, hf_ipcomp_cpi, NullTVB,
294 offset + offsetof(struct ipcomp, comp_cpi), 2,
295 ntohs(ipcomp.comp_cpi));
297 proto_tree_add_uint_format(ipcomp_tree, hf_ipcomp_cpi, NullTVB,
298 offset + offsetof(struct ipcomp, comp_cpi), 2,
299 ntohs(ipcomp.comp_cpi),
301 p, ntohs(ipcomp.comp_cpi));
303 old_dissect_data(pd, offset + sizeof(struct ipcomp), fd, ipcomp_tree);
308 proto_register_ipsec(void)
311 static hf_register_info hf_ah[] = {
313 { "SPI", "ah.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
316 { "Sequence", "ah.sequence", FT_UINT32, BASE_HEX, NULL, 0x0,
320 static hf_register_info hf_esp[] = {
322 { "SPI", "esp.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
325 { "Sequence", "esp.sequence", FT_UINT32, BASE_HEX, NULL, 0x0,
329 static hf_register_info hf_ipcomp[] = {
331 { "Flags", "ipcomp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
334 { "CPI", "ipcomp.cpi", FT_UINT16, BASE_HEX, NULL, 0x0,
337 static gint *ett[] = {
345 proto_ah = proto_register_protocol("Authentication Header", "AH", "ah");
346 proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
348 proto_esp = proto_register_protocol("Encapsulated Security Payload",
350 proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
352 proto_ipcomp = proto_register_protocol("IP Payload Compression",
354 proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
356 proto_register_subtree_array(ett, array_length(ett));
358 /* Register a configuration option for placement of AH payload dissection */
359 ah_module = prefs_register_protocol(proto_ah, NULL);
360 prefs_register_bool_preference(ah_module, "place_ah_payload_in_subtree",
361 "Place AH payload in subtree",
362 "Whether the AH payload decode should be placed in a subtree",
363 &g_ah_payload_in_subtree);
367 proto_reg_handoff_ipsec(void)
369 old_dissector_add("ip.proto", IP_PROTO_AH, dissect_ah);
370 old_dissector_add("ip.proto", IP_PROTO_ESP, dissect_esp);
371 old_dissector_add("ip.proto", IP_PROTO_IPCOMP, dissect_ipcomp);