Say "Tethereal", rather than "Ethereal", in messages from Tethereal.
[obnox/wireshark/wip.git] / packet-ipsec.c
1 /* packet-ipsec.c
2  * Routines for IPsec/IPComp packet disassembly 
3  *
4  * $Id: packet-ipsec.c,v 1.10 1999/11/16 11:42:35 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
38 #endif
39
40 #include <glib.h>
41 #include "packet.h"
42 #include "resolv.h"
43
44 static int proto_ah = -1;
45 static int hf_ah_spi = -1;
46 static int hf_ah_sequence = -1;
47 static int proto_esp = -1;
48 static int hf_esp_spi = -1;
49 static int hf_esp_sequence = -1;
50 static int proto_ipcomp = -1;
51 static int hf_ipcomp_flags = -1;
52 static int hf_ipcomp_cpi = -1;
53
54 static gint ett_ah = -1;
55 static gint ett_esp = -1;
56 static gint ett_ipcomp = -1;
57
58 struct newah {
59         guint8  ah_nxt;         /* Next Header */
60         guint8  ah_len;         /* Length of data + 1, in 32bit */
61         guint16 ah_reserve;     /* Reserved for future use */
62         guint32 ah_spi;         /* Security parameter index */
63         guint32 ah_seq;         /* Sequence number field */
64         /* variable size, 32bit bound*/ /* Authentication data */
65 };
66
67 struct newesp {
68         guint32 esp_spi;        /* ESP */
69         guint32 esp_seq;        /* Sequence number */
70         /*variable size*/               /* (IV and) Payload data */
71         /*variable size*/               /* padding */
72         /*8bit*/                        /* pad size */
73         /*8bit*/                        /* next header */
74         /*8bit*/                        /* next header */
75         /*variable size, 32bit bound*/  /* Authentication data */
76 };
77
78 struct ipcomp {
79         guint8 comp_nxt;        /* Next Header */
80         guint8 comp_flags;      /* Must be zero */
81         guint16 comp_cpi;       /* Compression parameter index */
82 };
83
84 /* well-known algorithm number (in CPI), from RFC2409 */
85 #define IPCOMP_OUI      1       /* vendor specific */
86 #define IPCOMP_DEFLATE  2       /* RFC2394 */
87 #define IPCOMP_LZS      3       /* RFC2395 */
88 #define IPCOMP_MAX      4
89
90 static const value_string cpi2val[] = {
91     { IPCOMP_OUI, "OUI" },
92     { IPCOMP_DEFLATE, "DEFLATE" },
93     { IPCOMP_LZS, "LZS" },
94     { 0, NULL },
95 };
96
97 #ifndef offsetof
98 #define offsetof(type, member)  ((size_t)(&((type *)0)->member))
99 #endif
100
101 int
102 dissect_ah(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
103 {
104     proto_tree *ah_tree;
105     proto_item *ti;
106     struct newah ah;
107     int advance;
108
109     memcpy(&ah, (void *) &pd[offset], sizeof(ah)); 
110     advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
111
112     if (check_col(fd, COL_PROTOCOL))
113         col_add_str(fd, COL_PROTOCOL, "AH");
114     if (check_col(fd, COL_INFO)) {
115         col_add_fstr(fd, COL_INFO, "AH (SPI=0x%08x)",
116             (guint32)ntohl(ah.ah_spi));
117     }
118
119     if (tree) {
120         /* !!! specify length */
121         ti = proto_tree_add_item(tree, proto_ah, offset, advance, NULL);
122         ah_tree = proto_item_add_subtree(ti, ett_ah);
123
124         proto_tree_add_text(ah_tree, offset + offsetof(struct newah, ah_nxt), 1,
125             "Next Header: %s (0x%02x)", ipprotostr(ah.ah_nxt), ah.ah_nxt);
126         proto_tree_add_text(ah_tree, offset + offsetof(struct newah, ah_len), 1,
127             "Length: %d", ah.ah_len << 2);
128         proto_tree_add_item(ah_tree, hf_ah_spi,
129                             offset + offsetof(struct newah, ah_spi), 4,
130                             (guint32)ntohl(ah.ah_spi));
131         proto_tree_add_item(ah_tree, hf_ah_sequence,
132                             offset + offsetof(struct newah, ah_seq), 4,
133                             (guint32)ntohl(ah.ah_seq));
134         proto_tree_add_text(ah_tree, offset + sizeof(ah), (ah.ah_len - 1) << 2,
135                             "ICV");
136     }
137
138     /* start of the new header (could be a extension header) */
139     return advance;
140 }
141
142 void
143 dissect_esp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
144 {
145     proto_tree *esp_tree;
146     proto_item *ti;
147     struct newesp esp;
148
149     memcpy(&esp, (void *) &pd[offset], sizeof(esp)); 
150
151     /*
152      * load the top pane info. This should be overwritten by
153      * the next protocol in the stack
154      */
155     if (check_col(fd, COL_PROTOCOL))
156         col_add_str(fd, COL_PROTOCOL, "ESP");
157     if (check_col(fd, COL_INFO)) {
158         col_add_fstr(fd, COL_INFO, "ESP (SPI=0x%08x)",
159             (guint32)ntohl(esp.esp_spi));
160     }
161
162     /*
163      * populate a tree in the second pane with the status of the link layer
164      * (ie none)
165      */
166     if(tree) {
167         ti = proto_tree_add_item(tree, proto_esp, offset, END_OF_FRAME, NULL);
168         esp_tree = proto_item_add_subtree(ti, ett_esp);
169         proto_tree_add_item(esp_tree, hf_esp_spi, 
170                             offset + offsetof(struct newesp, esp_spi), 4,
171                             (guint32)ntohl(esp.esp_spi));
172         proto_tree_add_item(esp_tree, hf_esp_sequence,
173                             offset + offsetof(struct newesp, esp_seq), 4,
174                             (guint32)ntohl(esp.esp_seq));
175         dissect_data(pd, offset + sizeof(struct newesp), fd, esp_tree);
176     }
177 }
178
179 void
180 dissect_ipcomp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
181 {
182     proto_tree *ipcomp_tree;
183     proto_item *ti;
184     struct ipcomp ipcomp;
185     char *p;
186
187     memcpy(&ipcomp, (void *) &pd[offset], sizeof(ipcomp)); 
188
189     /*
190      * load the top pane info. This should be overwritten by
191      * the next protocol in the stack
192      */
193     if (check_col(fd, COL_PROTOCOL))
194         col_add_str(fd, COL_PROTOCOL, "IPComp");
195     if (check_col(fd, COL_INFO)) {
196         p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
197         if (p[0] == '\0') {
198             col_add_fstr(fd, COL_INFO, "IPComp (CPI=0x%04x)",
199                 ntohs(ipcomp.comp_cpi));
200         } else
201             col_add_fstr(fd, COL_INFO, "IPComp (CPI=%s)", p);
202     }
203
204     /*
205      * populate a tree in the second pane with the status of the link layer
206      * (ie none)
207      */
208     if (tree) {
209         ti = proto_tree_add_item(tree, proto_ipcomp, offset, END_OF_FRAME,
210             NULL);
211         ipcomp_tree = proto_item_add_subtree(ti, ett_ipcomp);
212
213         proto_tree_add_text(ipcomp_tree,
214             offset + offsetof(struct ipcomp, comp_nxt), 1,
215             "Next Header: %s (0x%02x)",
216             ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
217         proto_tree_add_item(ipcomp_tree, hf_ipcomp_flags,
218             offset + offsetof(struct ipcomp, comp_flags), 1,
219             ipcomp.comp_flags);
220         p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
221         if (p[0] == '\0') {
222             proto_tree_add_item(ipcomp_tree, hf_ipcomp_cpi, 
223                 offset + offsetof(struct ipcomp, comp_cpi), 2,
224                 ntohs(ipcomp.comp_cpi));
225         } else {
226             proto_tree_add_item_format(ipcomp_tree, hf_ipcomp_cpi, 
227                 offset + offsetof(struct ipcomp, comp_cpi), 2,
228                 ntohs(ipcomp.comp_cpi),
229                 "CPI: %s (0x%04x)",
230                 p, ntohs(ipcomp.comp_cpi));
231         }
232         dissect_data(pd, offset + sizeof(struct ipcomp), fd, ipcomp_tree);
233     }
234 }
235
236 void
237 proto_register_ipsec(void)
238 {
239
240   static hf_register_info hf_ah[] = {
241     { &hf_ah_spi,
242       { "SPI",          "ah.spi",       FT_UINT32,      BASE_HEX, NULL, 0x0,
243         "" }},
244     { &hf_ah_sequence,
245       { "Sequence",     "ah.sequence",  FT_UINT32,      BASE_HEX, NULL, 0x0,
246         "" }}
247   };
248
249   static hf_register_info hf_esp[] = {
250     { &hf_esp_spi,
251       { "SPI",          "esp.spi",      FT_UINT32,      BASE_HEX, NULL, 0x0,
252         "" }},
253     { &hf_esp_sequence,
254       { "Sequence",     "esp.sequence", FT_UINT32,      BASE_HEX, NULL, 0x0,
255         "" }}
256   };
257
258   static hf_register_info hf_ipcomp[] = {
259     { &hf_ipcomp_flags,
260       { "Flags",        "ipcomp.flags", FT_UINT8,       BASE_HEX, NULL, 0x0,
261         "" }},
262     { &hf_ipcomp_cpi,
263       { "CPI",          "ipcomp.cpi",   FT_UINT16,      BASE_HEX, NULL, 0x0,
264         "" }},
265   };
266   static gint *ett[] = {
267     &ett_ah,
268     &ett_esp,
269     &ett_ipcomp,
270   };
271
272   proto_ah = proto_register_protocol("Authentication Header", "ah");
273   proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
274
275   proto_esp = proto_register_protocol("Encapsulated Security Payload", "esp");
276   proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
277
278   proto_ipcomp = proto_register_protocol("IP Payload Compression", "ipcomp");
279   proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
280
281   proto_register_subtree_array(ett, array_length(ett));
282 }