add ipcomp.flags to filter notation.
[metze/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.8 1999/10/15 05:46:18 itojun 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_format(ah_tree, hf_ah_spi,
125                                    offset + offsetof(struct newah, ah_spi), 4,
126                                    (guint32)ntohl(ah.ah_spi),
127                                    "SPI: 0x%08x",
128                                    (guint32)ntohl(ah.ah_spi));
129         proto_tree_add_item_format(ah_tree, hf_ah_sequence,
130                                    offset + offsetof(struct newah, ah_seq), 4,
131                                    (guint32)ntohl(ah.ah_seq),
132                                    "Sequence?: 0x%08x",
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_format(esp_tree, hf_esp_spi, 
170                                    offset + offsetof(struct newesp, esp_spi), 4,
171                                    (guint32)ntohl(esp.esp_spi),
172                                    "SPI: 0x%08x", 
173                                    (guint32)ntohl(esp.esp_spi));
174         proto_tree_add_item_format(esp_tree, hf_esp_sequence,
175                                    offset + offsetof(struct newesp, esp_seq), 4,
176                                    (guint32)ntohl(esp.esp_seq),
177                                    "Sequence?: 0x%08x", 
178                                    (guint32)ntohl(esp.esp_seq));
179         dissect_data(pd, offset + sizeof(struct newesp), fd, esp_tree);
180     }
181 }
182
183 void
184 dissect_ipcomp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
185 {
186     proto_tree *ipcomp_tree;
187     proto_item *ti;
188     struct ipcomp ipcomp;
189     char *p;
190
191     memcpy(&ipcomp, (void *) &pd[offset], sizeof(ipcomp)); 
192
193     /*
194      * load the top pane info. This should be overwritten by
195      * the next protocol in the stack
196      */
197     if (check_col(fd, COL_PROTOCOL))
198         col_add_str(fd, COL_PROTOCOL, "IPComp");
199     if (check_col(fd, COL_INFO)) {
200         p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
201         if (p[0] == '\0') {
202             col_add_fstr(fd, COL_INFO, "IPComp (CPI=0x%04x)",
203                 ntohs(ipcomp.comp_cpi));
204         } else
205             col_add_fstr(fd, COL_INFO, "IPComp (CPI=%s)", p);
206     }
207
208     /*
209      * populate a tree in the second pane with the status of the link layer
210      * (ie none)
211      */
212     if (tree) {
213         ti = proto_tree_add_item(tree, proto_ipcomp, offset, END_OF_FRAME,
214             NULL);
215         ipcomp_tree = proto_item_add_subtree(ti, ETT_IPCOMP);
216
217         proto_tree_add_text(ipcomp_tree,
218             offset + offsetof(struct ipcomp, comp_nxt), 1,
219             "Next Header: %s (0x%02x)",
220             ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
221         proto_tree_add_item(ipcomp_tree, hf_ipcomp_flags,
222             offset + offsetof(struct ipcomp, comp_flags), 1,
223             ipcomp.comp_flags);
224         p = val_to_str(ntohs(ipcomp.comp_cpi), cpi2val, "");
225         if (p[0] == '\0') {
226             proto_tree_add_item(ipcomp_tree, hf_ipcomp_cpi, 
227                 offset + offsetof(struct ipcomp, comp_cpi), 2,
228                 ntohs(ipcomp.comp_cpi));
229         } else {
230             proto_tree_add_item_format(ipcomp_tree, hf_ipcomp_cpi, 
231                 offset + offsetof(struct ipcomp, comp_cpi), 2,
232                 ntohs(ipcomp.comp_cpi),
233                 "CPI: %s (0x%04x)",
234                 p, ntohs(ipcomp.comp_cpi));
235         }
236         dissect_data(pd, offset + sizeof(struct ipcomp), fd, ipcomp_tree);
237     }
238 }
239
240 void
241 proto_register_ipsec(void)
242 {
243
244   static hf_register_info hf_ah[] = {
245     { &hf_ah_spi,
246       { "SPI",          "ah.spi",       FT_UINT32,      BASE_HEX, NULL, 0x0,
247         "" }},
248     { &hf_ah_sequence,
249       { "Sequence",     "ah.sequence",  FT_UINT32,      BASE_HEX, NULL, 0x0,
250         "" }}
251   };
252
253   static hf_register_info hf_esp[] = {
254     { &hf_esp_spi,
255       { "SPI",          "esp.spi",      FT_UINT32,      BASE_HEX, NULL, 0x0,
256         "" }},
257     { &hf_esp_sequence,
258       { "Sequence",     "esp.sequence", FT_UINT32,      BASE_HEX, NULL, 0x0,
259         "" }}
260   };
261
262   static hf_register_info hf_ipcomp[] = {
263     { &hf_ipcomp_flags,
264       { "Flags",        "ipcomp.flags", FT_UINT8,       BASE_HEX, NULL, 0x0,
265         "" }},
266     { &hf_ipcomp_cpi,
267       { "CPI",          "ipcomp.cpi",   FT_UINT16,      BASE_HEX, NULL, 0x0,
268         "" }},
269   };
270
271   proto_ah = proto_register_protocol("Authentication Header", "ah");
272   proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
273
274   proto_esp = proto_register_protocol("Encapsulated Security Payload", "esp");
275   proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
276
277   proto_ipcomp = proto_register_protocol("IP Payload Compression", "ipcomp");
278   proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
279 }