2 * Routines for LISP Data Message dissection
3 * Copyright 2010, Lorand Jakab <lj@lispmon.net>
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,
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 */
86 dissect_lisp_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
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
)
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
);
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
);
148 if (flags
&LISP_DATA_FLAG_V
) {
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
);
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
);
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
);
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
);
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);
189 call_dissector(ipv4_handle
, next_tvb
, pinfo
, tree
);
190 return tvb_reported_length(tvb
);
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 */
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
}},
247 { "Instance ID", "lisp-data.iid",
248 FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
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.
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
,
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
305 * indent-tabs-mode: nil
308 * vi: set shiftwidth=4 tabstop=8 expandtab:
309 * :indentSize=4:tabSize=8:noTabs=true: