Get rid of get_ber_last_reated_item() and fix dissection of wIN-TriggerList.
[obnox/wireshark/wip.git] / epan / dissectors / packet-enc.c
1 /*
2  * Copyright (c) 2003 Markus Friedl.  All rights reserved.
3  *
4  * $Id$
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/etypes.h>
34 #include <epan/addr_resolv.h>
35 #include "packet-enc.h"
36 #include "packet-ip.h"
37 #include "packet-ipv6.h"
38
39 #ifndef offsetof
40 /* Can't trust stddef.h to be there for us */
41 # define offsetof(type, member) ((size_t)(&((type *)0)->member))
42 #endif
43
44 /* The header in OpenBSD Encapsulating Interface files. */
45
46 struct enchdr {
47   guint32 af;
48   guint32 spi;
49   guint32 flags;
50 };
51 #define ENC_HDRLEN    sizeof(struct enchdr)
52
53 # define BSD_ENC_INET    2
54 # define BSD_ENC_INET6   24
55
56 # define BSD_ENC_M_CONF          0x0400  /* payload encrypted */
57 # define BSD_ENC_M_AUTH          0x0800  /* payload authenticated */
58 # define BSD_ENC_M_COMP          0x1000  /* payload compressed */
59 # define BSD_ENC_M_AUTH_AH       0x2000  /* header authenticated */
60
61 static dissector_handle_t  data_handle, ip_handle, ipv6_handle;
62
63 /* header fields */
64 static int proto_enc = -1;
65 static int hf_enc_af = -1;
66 static int hf_enc_spi = -1;
67 static int hf_enc_flags = -1;
68
69 static gint ett_enc = -1;
70
71 void
72 capture_enc(const guchar *pd, int len, packet_counts *ld)
73 {
74   guint32 af;
75
76   if (!BYTES_ARE_IN_FRAME(0, len, (int)ENC_HDRLEN)) {
77     ld->other++;
78     return;
79   }
80
81   af = pntohl(pd + offsetof(struct enchdr, af));
82   switch (af) {
83
84   case BSD_ENC_INET:
85     capture_ip(pd, ENC_HDRLEN, len, ld);
86     break;
87
88   case BSD_ENC_INET6:
89     capture_ipv6(pd, ENC_HDRLEN, len, ld);
90     break;
91
92   default:
93     ld->other++;
94     break;
95   }
96 }
97
98 static const value_string af_vals[] = {
99   { BSD_ENC_INET,  "IPv4" },
100   { BSD_ENC_INET6, "IPv6" },
101   { 0,            NULL }
102 };
103
104 static void
105 dissect_enc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
106 {
107   struct enchdr ench;
108   tvbuff_t *next_tvb;
109   proto_tree *enc_tree;
110   proto_item *ti;
111
112   if (check_col(pinfo->cinfo, COL_PROTOCOL))
113     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENC");
114
115   /* Copy out the enc header to insure alignment */
116   tvb_memcpy(tvb, (guint8 *)&ench, 0, sizeof(ench));
117
118   /* Byteswap the header now */
119   ench.spi = g_ntohl(ench.spi);
120   /* ench.af = g_ntohl(ench.af); */
121   /* ench.flags = g_ntohl(ench.flags); */
122
123   if (tree) {
124     ti = proto_tree_add_protocol_format(tree, proto_enc, tvb, 0,
125              ENC_HDRLEN,
126              "Enc %s, SPI 0x%8.8x, %s%s%s%s",
127              val_to_str(ench.af, af_vals, "unknown (%u)"),
128              ench.spi,
129              ench.flags ? "" : "unprotected",
130              ench.flags & BSD_ENC_M_AUTH ? "authentic" : "",
131              (ench.flags & (BSD_ENC_M_AUTH|BSD_ENC_M_CONF)) ==
132                 (BSD_ENC_M_AUTH|BSD_ENC_M_CONF) ? ", " : "",
133              ench.flags & BSD_ENC_M_CONF ? "confidential" : ""
134              );
135     enc_tree = proto_item_add_subtree(ti, ett_enc);
136
137     proto_tree_add_uint(enc_tree, hf_enc_af, tvb,
138              offsetof(struct enchdr, af), sizeof(ench.af),
139              ench.af);
140     proto_tree_add_uint(enc_tree, hf_enc_spi, tvb,
141              offsetof(struct enchdr, spi), sizeof(ench.spi),
142              ench.spi);
143     proto_tree_add_uint(enc_tree, hf_enc_flags, tvb,
144              offsetof(struct enchdr, flags), sizeof(ench.flags),
145              ench.flags);
146   }
147
148   /* Set the tvbuff for the payload after the header */
149   next_tvb = tvb_new_subset(tvb, ENC_HDRLEN, -1, -1);
150
151   switch (ench.af) {
152
153   case BSD_ENC_INET:
154     call_dissector(ip_handle, next_tvb, pinfo, tree);
155     break;
156
157   case BSD_ENC_INET6:
158     call_dissector(ipv6_handle, next_tvb, pinfo, tree);
159     break;
160
161   default:
162     call_dissector(data_handle, next_tvb, pinfo, tree);
163     break;
164   }
165 }
166
167 void
168 proto_register_enc(void)
169 {
170   static hf_register_info hf[] = {
171     { &hf_enc_af,
172       { "Address Family", "enc.af", FT_UINT32, BASE_DEC, VALS(af_vals), 0x0,
173         "Protocol (IPv4 vs IPv6)", HFILL }},
174     { &hf_enc_spi,
175       { "SPI", "enc.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
176         "Security Parameter Index", HFILL }},
177     { &hf_enc_flags,
178       { "Flags", "enc.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
179         "ENC flags", HFILL }},
180   };
181   static gint *ett[] = { &ett_enc };
182
183   proto_enc = proto_register_protocol("OpenBSD Encapsulating device",
184                                       "ENC", "enc");
185   proto_register_field_array(proto_enc, hf, array_length(hf));
186   proto_register_subtree_array(ett, array_length(ett));
187 }
188
189 void
190 proto_reg_handoff_enc(void)
191 {
192   dissector_handle_t enc_handle;
193
194   ip_handle = find_dissector("ip");
195   ipv6_handle = find_dissector("ipv6");
196   data_handle = find_dissector("data");
197
198   enc_handle = create_dissector_handle(dissect_enc, proto_enc);
199   dissector_add("wtap_encap", WTAP_ENCAP_ENC, enc_handle);
200 }