2 * Routines for IPsec/IPComp packet disassembly
4 * $Id: packet-ipsec.c,v 1.20 2000/08/13 14:08:17 deniel 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>
42 #include "packet-ipsec.h"
43 #include "packet-ip.h"
47 /* Place AH payload in sub tree */
48 gboolean g_ah_payload_in_subtree = FALSE;
50 static int proto_ah = -1;
51 static int hf_ah_spi = -1;
52 static int hf_ah_sequence = -1;
53 static int proto_esp = -1;
54 static int hf_esp_spi = -1;
55 static int hf_esp_sequence = -1;
56 static int proto_ipcomp = -1;
57 static int hf_ipcomp_flags = -1;
58 static int hf_ipcomp_cpi = -1;
60 static gint ett_ah = -1;
61 static gint ett_esp = -1;
62 static gint ett_ipcomp = -1;
65 guint8 ah_nxt; /* Next Header */
66 guint8 ah_len; /* Length of data + 1, in 32bit */
67 guint16 ah_reserve; /* Reserved for future use */
68 guint32 ah_spi; /* Security parameter index */
69 guint32 ah_seq; /* Sequence number field */
70 /* variable size, 32bit bound*/ /* Authentication data */
74 guint32 esp_spi; /* ESP */
75 guint32 esp_seq; /* Sequence number */
76 /*variable size*/ /* (IV and) Payload data */
77 /*variable size*/ /* padding */
78 /*8bit*/ /* pad size */
79 /*8bit*/ /* next header */
80 /*8bit*/ /* next header */
81 /*variable size, 32bit bound*/ /* Authentication data */
85 guint8 comp_nxt; /* Next Header */
86 guint8 comp_flags; /* Must be zero */
87 guint16 comp_cpi; /* Compression parameter index */
90 /* well-known algorithm number (in CPI), from RFC2409 */
91 #define IPCOMP_OUI 1 /* vendor specific */
92 #define IPCOMP_DEFLATE 2 /* RFC2394 */
93 #define IPCOMP_LZS 3 /* RFC2395 */
96 static const value_string cpi2val[] = {
97 { IPCOMP_OUI, "OUI" },
98 { IPCOMP_DEFLATE, "DEFLATE" },
99 { IPCOMP_LZS, "LZS" },
104 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
108 dissect_ah_old(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
115 memcpy(&ah, (void *) &pd[offset], sizeof(ah));
116 advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
118 if (check_col(fd, COL_PROTOCOL))
119 col_add_str(fd, COL_PROTOCOL, "AH");
120 if (check_col(fd, COL_INFO)) {
121 col_add_fstr(fd, COL_INFO, "AH (SPI=0x%08x)",
122 (guint32)ntohl(ah.ah_spi));
126 /* !!! specify length */
127 ti = proto_tree_add_item(tree, proto_ah, NullTVB, offset, advance, FALSE);
128 ah_tree = proto_item_add_subtree(ti, ett_ah);
130 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_nxt), 1,
131 "Next Header: %s (0x%02x)", ipprotostr(ah.ah_nxt), ah.ah_nxt);
132 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_len), 1,
133 "Length: %d", ah.ah_len << 2);
134 proto_tree_add_uint(ah_tree, hf_ah_spi, NullTVB,
135 offset + offsetof(struct newah, ah_spi), 4,
136 (guint32)ntohl(ah.ah_spi));
137 proto_tree_add_uint(ah_tree, hf_ah_sequence, NullTVB,
138 offset + offsetof(struct newah, ah_seq), 4,
139 (guint32)ntohl(ah.ah_seq));
140 proto_tree_add_text(ah_tree, NullTVB, offset + sizeof(ah), (ah.ah_len - 1) << 2,
144 /* start of the new header (could be a extension header) */
149 dissect_ah(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
151 proto_tree *ah_tree, *next_tree = NULL;
156 OLD_CHECK_DISPLAY_AS_DATA(proto_ah, pd, offset, fd, tree);
158 memcpy(&ah, (void *) &pd[offset], sizeof(ah));
159 advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
161 if (check_col(fd, COL_PROTOCOL))
162 col_add_str(fd, COL_PROTOCOL, "AH");
163 if (check_col(fd, COL_INFO)) {
164 col_add_fstr(fd, COL_INFO, "AH (SPI=0x%08x)",
165 (guint32)ntohl(ah.ah_spi));
169 /* !!! specify length */
170 ti = proto_tree_add_item(tree, proto_ah, NullTVB, offset, advance, FALSE);
171 ah_tree = proto_item_add_subtree(ti, ett_ah);
173 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_nxt), 1,
174 "Next Header: %s (0x%02x)", ipprotostr(ah.ah_nxt), ah.ah_nxt);
175 proto_tree_add_text(ah_tree, NullTVB, offset + offsetof(struct newah, ah_len), 1,
176 "Length: %d", ah.ah_len << 2);
177 proto_tree_add_uint(ah_tree, hf_ah_spi, NullTVB,
178 offset + offsetof(struct newah, ah_spi), 4,
179 (guint32)ntohl(ah.ah_spi));
180 proto_tree_add_uint(ah_tree, hf_ah_sequence, NullTVB,
181 offset + offsetof(struct newah, ah_seq), 4,
182 (guint32)ntohl(ah.ah_seq));
183 proto_tree_add_text(ah_tree, NullTVB, offset + sizeof(ah), (ah.ah_len - 1) << 2,
186 /* Decide where to place next protocol decode */
187 if (g_ah_payload_in_subtree) {
195 /* start of the new header (could be a extension header) */
198 if (g_ah_payload_in_subtree) {
199 col_set_writable(fd, FALSE);
202 /* do lookup with the subdissector table */
203 if (!old_dissector_try_port(ip_dissector_table, ah.ah_nxt, pd, offset, fd, next_tree)) {
204 old_dissect_data(pd, offset, fd, next_tree);
209 dissect_esp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
211 proto_tree *esp_tree;
215 OLD_CHECK_DISPLAY_AS_DATA(proto_esp, pd, offset, fd, tree);
217 memcpy(&esp, (void *) &pd[offset], sizeof(esp));
220 * load the top pane info. This should be overwritten by
221 * the next protocol in the stack
223 if (check_col(fd, COL_PROTOCOL))
224 col_add_str(fd, COL_PROTOCOL, "ESP");
225 if (check_col(fd, COL_INFO)) {
226 col_add_fstr(fd, COL_INFO, "ESP (SPI=0x%08x)",
227 (guint32)ntohl(esp.esp_spi));
231 * populate a tree in the second pane with the status of the link layer
235 ti = proto_tree_add_item(tree, proto_esp, NullTVB, offset, END_OF_FRAME, FALSE);
236 esp_tree = proto_item_add_subtree(ti, ett_esp);
237 proto_tree_add_uint(esp_tree, hf_esp_spi, NullTVB,
238 offset + offsetof(struct newesp, esp_spi), 4,
239 (guint32)ntohl(esp.esp_spi));
240 proto_tree_add_uint(esp_tree, hf_esp_sequence, NullTVB,
241 offset + offsetof(struct newesp, esp_seq), 4,
242 (guint32)ntohl(esp.esp_seq));
243 old_dissect_data(pd, offset + sizeof(struct newesp), fd, esp_tree);
248 dissect_ipcomp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
250 proto_tree *ipcomp_tree;
252 struct ipcomp ipcomp;
255 OLD_CHECK_DISPLAY_AS_DATA(proto_ipcomp, pd, offset, fd, tree);
257 memcpy(&ipcomp, (void *) &pd[offset], sizeof(ipcomp));
260 * load the top pane info. This should be overwritten by
261 * the next protocol in the stack
263 if (check_col(fd, COL_PROTOCOL))
264 col_add_str(fd, COL_PROTOCOL, "IPComp");
265 if (check_col(fd, COL_INFO)) {
266 p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
268 col_add_fstr(fd, COL_INFO, "IPComp (CPI=0x%04x)",
269 ntohs(ipcomp.comp_cpi));
271 col_add_fstr(fd, COL_INFO, "IPComp (CPI=%s)", p);
275 * populate a tree in the second pane with the status of the link layer
279 ti = proto_tree_add_item(tree, proto_ipcomp, NullTVB, offset, END_OF_FRAME,
281 ipcomp_tree = proto_item_add_subtree(ti, ett_ipcomp);
283 proto_tree_add_text(ipcomp_tree, NullTVB,
284 offset + offsetof(struct ipcomp, comp_nxt), 1,
285 "Next Header: %s (0x%02x)",
286 ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
287 proto_tree_add_uint(ipcomp_tree, hf_ipcomp_flags, NullTVB,
288 offset + offsetof(struct ipcomp, comp_flags), 1,
290 p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
292 proto_tree_add_uint(ipcomp_tree, hf_ipcomp_cpi, NullTVB,
293 offset + offsetof(struct ipcomp, comp_cpi), 2,
294 ntohs(ipcomp.comp_cpi));
296 proto_tree_add_uint_format(ipcomp_tree, hf_ipcomp_cpi, NullTVB,
297 offset + offsetof(struct ipcomp, comp_cpi), 2,
298 ntohs(ipcomp.comp_cpi),
300 p, ntohs(ipcomp.comp_cpi));
302 old_dissect_data(pd, offset + sizeof(struct ipcomp), fd, ipcomp_tree);
307 proto_register_ipsec(void)
310 static hf_register_info hf_ah[] = {
312 { "SPI", "ah.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
315 { "Sequence", "ah.sequence", FT_UINT32, BASE_HEX, NULL, 0x0,
319 static hf_register_info hf_esp[] = {
321 { "SPI", "esp.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
324 { "Sequence", "esp.sequence", FT_UINT32, BASE_HEX, NULL, 0x0,
328 static hf_register_info hf_ipcomp[] = {
330 { "Flags", "ipcomp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
333 { "CPI", "ipcomp.cpi", FT_UINT16, BASE_HEX, NULL, 0x0,
336 static gint *ett[] = {
344 proto_ah = proto_register_protocol("Authentication Header", "ah");
345 proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
347 proto_esp = proto_register_protocol("Encapsulated Security Payload", "esp");
348 proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
350 proto_ipcomp = proto_register_protocol("IP Payload Compression", "ipcomp");
351 proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
353 proto_register_subtree_array(ett, array_length(ett));
355 /* Register a configuration option for placement of AH payload dissection */
356 ah_module = prefs_register_module("ah", "AH", NULL);
357 prefs_register_bool_preference(ah_module, "place_ah_payload_in_subtree",
358 "Place AH payload in subtree",
359 "Whether the AH payload decode should be placed in a subtree",
360 &g_ah_payload_in_subtree);
364 proto_reg_handoff_ipsec(void)
366 old_dissector_add("ip.proto", IP_PROTO_AH, dissect_ah);
367 old_dissector_add("ip.proto", IP_PROTO_ESP, dissect_esp);
368 old_dissector_add("ip.proto", IP_PROTO_IPCOMP, dissect_ipcomp);