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