MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-lisp-data.c
blob23335a7c07db930d1c6bacd2211740cac9c74be3
1 /* packet-lisp-data.c
2 * Routines for LISP Data Message dissection
3 * Copyright 2010, Lorand Jakab <lj@lispmon.net>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
24 * USA.
27 #include "config.h"
29 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/expert.h>
34 /* See RFC 6830 "Locator/ID Separation Protocol (LISP)" */
36 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * |N|L|E|V|I|flags| Nonce/Map-Version |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Instance ID/Locator Status Bits |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 #define LISP_CONTROL_PORT 4342
44 #define LISP_DATA_PORT 4341
45 #define LISP_DATA_HEADER_LEN 8 /* Number of bytes in LISP data header */
47 #define LISP_DATA_FLAGS_WIDTH 8 /* Width (in bits) of the flags field */
48 #define LISP_DATA_FLAG_N 0x80 /* Nonce present */
49 #define LISP_DATA_FLAG_L 0x40 /* Locator-Status-Bits field enabled */
50 #define LISP_DATA_FLAG_E 0x20 /* Echo-Nonce-Request */
51 #define LISP_DATA_FLAG_V 0x10 /* Map-Version present */
52 #define LISP_DATA_FLAG_I 0x08 /* Instance ID present */
53 #define LISP_DATA_FLAG_RES 0x07 /* Reserved */
55 /* Initialize the protocol and registered fields */
56 static int proto_lisp_data = -1;
57 static int hf_lisp_data_flags = -1;
58 static int hf_lisp_data_flags_nonce = -1;
59 static int hf_lisp_data_flags_lsb = -1;
60 static int hf_lisp_data_flags_enr = -1;
61 static int hf_lisp_data_flags_mv = -1;
62 static int hf_lisp_data_flags_iid = -1;
63 static int hf_lisp_data_flags_res = -1;
64 static int hf_lisp_data_nonce = -1;
65 static int hf_lisp_data_mapver = -1;
66 static int hf_lisp_data_srcmapver = -1;
67 static int hf_lisp_data_dstmapver = -1;
68 static int hf_lisp_data_iid = -1;
69 static int hf_lisp_data_lsb = -1;
70 static int hf_lisp_data_lsb8 = -1;
72 /* Initialize the subtree pointers */
73 static gint ett_lisp_data = -1;
74 static gint ett_lisp_data_flags = -1;
75 static gint ett_lisp_data_mapver = -1;
77 static expert_field ei_lisp_data_flags_en_invalid = EI_INIT;
78 static expert_field ei_lisp_data_flags_nv_invalid = EI_INIT;
80 static dissector_handle_t ipv4_handle;
81 static dissector_handle_t ipv6_handle;
82 static dissector_handle_t lisp_handle;
84 /* Code to actually dissect the packets */
85 static int
86 dissect_lisp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
88 gint offset = 0;
89 guint8 flags;
90 guint8 ip_ver;
91 tvbuff_t *next_tvb;
92 proto_item *ti;
93 proto_item *tif;
94 proto_tree *lisp_data_tree;
95 proto_tree *lisp_data_flags_tree;
97 /* Check if we have a LISP control packet */
98 if (pinfo->destport == LISP_CONTROL_PORT)
99 return call_dissector(lisp_handle, tvb, pinfo, tree);
101 /* Check that there's enough data */
102 if (tvb_reported_length(tvb) < LISP_DATA_HEADER_LEN)
103 return 0;
105 /* Make entries in Protocol column and Info column on summary display */
106 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LISP");
108 col_set_str(pinfo->cinfo, COL_INFO, "LISP Encapsulation Header");
110 /* create display subtree for the protocol */
111 ti = proto_tree_add_item(tree, proto_lisp_data, tvb, 0,
112 LISP_DATA_HEADER_LEN, ENC_NA);
114 lisp_data_tree = proto_item_add_subtree(ti, ett_lisp_data);
116 tif = proto_tree_add_item(lisp_data_tree,
117 hf_lisp_data_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
119 lisp_data_flags_tree = proto_item_add_subtree(tif, ett_lisp_data_flags);
121 proto_tree_add_item(lisp_data_flags_tree,
122 hf_lisp_data_flags_nonce, tvb, offset, 1, ENC_BIG_ENDIAN);
123 proto_tree_add_item(lisp_data_flags_tree,
124 hf_lisp_data_flags_lsb, tvb, offset, 1, ENC_BIG_ENDIAN);
125 proto_tree_add_item(lisp_data_flags_tree,
126 hf_lisp_data_flags_enr, tvb, offset, 1, ENC_BIG_ENDIAN);
127 proto_tree_add_item(lisp_data_flags_tree,
128 hf_lisp_data_flags_mv, tvb, offset, 1, ENC_BIG_ENDIAN);
129 proto_tree_add_item(lisp_data_flags_tree,
130 hf_lisp_data_flags_iid, tvb, offset, 1, ENC_BIG_ENDIAN);
131 proto_tree_add_item(lisp_data_flags_tree,
132 hf_lisp_data_flags_res, tvb, offset, 1, ENC_BIG_ENDIAN);
134 flags = tvb_get_guint8(tvb, offset);
135 offset += 1;
137 if (flags&LISP_DATA_FLAG_E && !(flags&LISP_DATA_FLAG_N)) {
138 expert_add_info(pinfo, tif, &ei_lisp_data_flags_en_invalid);
141 if (flags&LISP_DATA_FLAG_N) {
142 if (flags&LISP_DATA_FLAG_V) {
143 expert_add_info(pinfo, tif, &ei_lisp_data_flags_nv_invalid);
145 proto_tree_add_item(lisp_data_tree,
146 hf_lisp_data_nonce, tvb, offset, 3, ENC_BIG_ENDIAN);
147 } else {
148 if (flags&LISP_DATA_FLAG_V) {
149 proto_item *tiv;
150 proto_tree *lisp_data_mapver_tree;
152 tiv = proto_tree_add_item(lisp_data_tree,
153 hf_lisp_data_mapver, tvb, offset, 3, ENC_BIG_ENDIAN);
155 lisp_data_mapver_tree = proto_item_add_subtree(tiv, ett_lisp_data_mapver);
157 proto_tree_add_item(lisp_data_mapver_tree,
158 hf_lisp_data_srcmapver, tvb, offset, 3, ENC_BIG_ENDIAN);
159 proto_tree_add_item(lisp_data_mapver_tree,
160 hf_lisp_data_dstmapver, tvb, offset, 3, ENC_BIG_ENDIAN);
163 offset += 3;
165 if (flags&LISP_DATA_FLAG_I) {
166 proto_tree_add_item(lisp_data_tree,
167 hf_lisp_data_iid, tvb, offset, 3, ENC_BIG_ENDIAN);
168 offset += 3;
169 if (flags&LISP_DATA_FLAG_L) {
170 proto_tree_add_item(lisp_data_tree,
171 hf_lisp_data_lsb8, tvb, offset, 1, ENC_BIG_ENDIAN);
173 /*offset +=1;*/
174 } else {
175 if (flags&LISP_DATA_FLAG_L) {
176 proto_tree_add_item(lisp_data_tree,
177 hf_lisp_data_lsb, tvb, offset, 4, ENC_BIG_ENDIAN);
178 /*offset += 4;*/
182 /* Check if there is stuff left in the buffer, and return if not */
184 /* Determine if encapsulated packet is IPv4 or IPv6, and call dissector */
185 next_tvb = tvb_new_subset_remaining(tvb, LISP_DATA_HEADER_LEN);
186 ip_ver = tvb_get_bits8(next_tvb, 0, 4);
187 switch (ip_ver) {
188 case 4:
189 call_dissector(ipv4_handle, next_tvb, pinfo, tree);
190 return tvb_reported_length(tvb);
191 case 6:
192 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
193 return tvb_reported_length(tvb);
196 /* Return the amount of data this dissector was able to dissect */
197 return LISP_DATA_HEADER_LEN;
201 /* Register the protocol with Wireshark */
202 void
203 proto_register_lisp_data(void)
205 /* Setup list of header fields */
206 static hf_register_info hf[] = {
207 { &hf_lisp_data_flags,
208 { "Flags", "lisp-data.flags",
209 FT_UINT8, BASE_HEX, NULL, 0x0, "LISP Data Header Flags", HFILL }},
210 { &hf_lisp_data_flags_nonce,
211 { "N bit (Nonce present)", "lisp-data.flags.nonce",
212 FT_BOOLEAN, LISP_DATA_FLAGS_WIDTH, TFS(&tfs_set_notset),
213 LISP_DATA_FLAG_N, NULL, HFILL }},
214 { &hf_lisp_data_flags_lsb,
215 { "L bit (Locator-Status-Bits field enabled)", "lisp-data.flags.lsb",
216 FT_BOOLEAN, LISP_DATA_FLAGS_WIDTH, TFS(&tfs_set_notset),
217 LISP_DATA_FLAG_L, NULL, HFILL }},
218 { &hf_lisp_data_flags_enr,
219 { "E bit (Echo-Nonce-Request)", "lisp-data.flags.enr",
220 FT_BOOLEAN, LISP_DATA_FLAGS_WIDTH, TFS(&tfs_set_notset),
221 LISP_DATA_FLAG_E, NULL, HFILL }},
222 { &hf_lisp_data_flags_mv,
223 { "V bit (Map-Version present)", "lisp-data.flags.mv",
224 FT_BOOLEAN, LISP_DATA_FLAGS_WIDTH, TFS(&tfs_set_notset),
225 LISP_DATA_FLAG_V, NULL, HFILL }},
226 { &hf_lisp_data_flags_iid,
227 { "I bit (Instance ID present)", "lisp-data.flags.iid",
228 FT_BOOLEAN, LISP_DATA_FLAGS_WIDTH, TFS(&tfs_set_notset),
229 LISP_DATA_FLAG_I, NULL, HFILL }},
230 { &hf_lisp_data_flags_res,
231 { "Reserved", "lisp-data.flags.res",
232 FT_UINT8, BASE_HEX, NULL,
233 LISP_DATA_FLAG_RES, "Must be zero", HFILL }},
234 { &hf_lisp_data_nonce,
235 { "Nonce", "lisp-data.nonce",
236 FT_UINT24, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }},
237 { &hf_lisp_data_mapver,
238 { "Map-Version", "lisp-data.mapver",
239 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
240 { &hf_lisp_data_srcmapver,
241 { "Source Map-Version", "lisp-data.srcmapver",
242 FT_UINT24, BASE_DEC, NULL, 0xFFF000, NULL, HFILL }},
243 { &hf_lisp_data_dstmapver,
244 { "Destination Map-Version", "lisp-data.dstmapver",
245 FT_UINT24, BASE_DEC, NULL, 0x000FFF, NULL, HFILL }},
246 { &hf_lisp_data_iid,
247 { "Instance ID", "lisp-data.iid",
248 FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
249 { &hf_lisp_data_lsb,
250 { "Locator-Status-Bits", "lisp-data.lsb",
251 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFF, NULL, HFILL }},
252 { &hf_lisp_data_lsb8,
253 { "Locator-Status-Bits", "lisp-data.lsb8",
254 FT_UINT8, BASE_HEX, NULL, 0xFF, NULL, HFILL }}
257 /* Setup protocol subtree array */
258 static gint *ett[] = {
259 &ett_lisp_data,
260 &ett_lisp_data_flags,
261 &ett_lisp_data_mapver
264 static ei_register_info ei[] = {
265 { &ei_lisp_data_flags_en_invalid, { "lisp-data.flags.en_invalid", PI_PROTOCOL, PI_WARN, "Invalid flag combination: if E is set, N MUST be set", EXPFILL }},
266 { &ei_lisp_data_flags_nv_invalid, { "lisp-data.flags.nv_invalid", PI_PROTOCOL, PI_WARN, "Invalid flag combination: N and V can't be set both", EXPFILL }},
269 expert_module_t* expert_lisp_data;
271 /* Register the protocol name and description */
272 proto_lisp_data = proto_register_protocol("Locator/ID Separation Protocol (Data)",
273 "LISP Data", "lisp-data");
275 /* Required function calls to register the header fields and subtrees used */
276 proto_register_field_array(proto_lisp_data, hf, array_length(hf));
277 proto_register_subtree_array(ett, array_length(ett));
278 expert_lisp_data = expert_register_protocol(proto_lisp_data);
279 expert_register_field_array(expert_lisp_data, ei, array_length(ei));
282 /* Simple form of proto_reg_handoff_lisp_data which can be used if there are
283 no prefs-dependent registration function calls.
286 void
287 proto_reg_handoff_lisp_data(void)
289 dissector_handle_t lisp_data_handle;
291 lisp_data_handle = new_create_dissector_handle(dissect_lisp_data,
292 proto_lisp_data);
293 dissector_add_uint("udp.port", LISP_DATA_PORT, lisp_data_handle);
294 ipv4_handle = find_dissector("ip");
295 ipv6_handle = find_dissector("ipv6");
296 lisp_handle = find_dissector("lisp");
300 * Editor modelines - http://www.wireshark.org/tools/modelines.html
302 * Local variables:
303 * c-basic-offset: 4
304 * tab-width: 8
305 * indent-tabs-mode: nil
306 * End:
308 * vi: set shiftwidth=4 tabstop=8 expandtab:
309 * :indentSize=4:tabSize=8:noTabs=true: