/src/wireshark/epan/dissectors/packet-fip.c
Line | Count | Source |
1 | | /* |
2 | | * packet-fip.c |
3 | | * Routines for FIP dissection - FCoE Initialization Protocol |
4 | | * Copyright (c) 2008 Cisco Systems, Inc. (jeykholt@cisco.com) |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * Based on packet-fcoe.c, Copyright 2006, Nuova Systems, (jre@nuovasystems.com) |
11 | | * Based on packet-fcp.c, Copyright 2001, Dinesh G Dutt (ddutt@cisco.com) |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | /* |
17 | | * For FIP protocol details, see http://t11.org. |
18 | | * This version uses preliminary details not yet standardized. |
19 | | * Based on http://www.t11.org/ftp/t11/pub/fc/bb-5/08-543v1.pdf |
20 | | * and http://www.t11.org/ftp/t11/pub/fc/bb-5/08-545v1.pdf |
21 | | */ |
22 | | |
23 | | #include "config.h" |
24 | | |
25 | | #include <epan/packet.h> |
26 | | #include <epan/to_str.h> |
27 | | #include <epan/expert.h> |
28 | | #include "packet-fc.h" |
29 | | |
30 | | void proto_register_fip(void); |
31 | | void proto_reg_handoff_fip(void); |
32 | | |
33 | | static dissector_handle_t fip_handle; |
34 | | |
35 | | /* |
36 | | * FIP protocol information. |
37 | | */ |
38 | 27 | #define FIP_HEADER_LEN 10 |
39 | 29 | #define FIP_BPW 4 /* bytes per descriptor length unit */ |
40 | | |
41 | | /* |
42 | | * FIP opcodes and subcodes. |
43 | | */ |
44 | | enum fip_opcode { |
45 | | FIP_OP_DISC = 1, /* discovery, advertisement, etc. */ |
46 | | FIP_OP_LS = 2, /* Link Service request or reply */ |
47 | | FIP_OP_CTRL = 3, /* control */ |
48 | | FIP_OP_VLAN = 4, /* VLAN request or reply */ |
49 | | FIP_OP_VN2VN = 5 /* VN_port to VN_port operation */ |
50 | | }; |
51 | | |
52 | | /* |
53 | | * Subcodes for FIP_OP_DISC. |
54 | | */ |
55 | | enum fip_disc_subcode { |
56 | | FIP_SC_SOL = 1, /* solicitation */ |
57 | | FIP_SC_ADV = 2 /* advertisement */ |
58 | | }; |
59 | | |
60 | | /* |
61 | | * Subcodes for FIP_OP_LS. |
62 | | */ |
63 | | enum fip_ls_subcode { |
64 | | FIP_SC_REQ = 1, /* request */ |
65 | | FIP_SC_REP = 2 /* reply */ |
66 | | }; |
67 | | |
68 | | enum fip_ctrl_subcode { |
69 | | FIP_SC_KA = 1, /* keep-alive */ |
70 | | FIP_SC_CVL = 2 /* clear virtual link */ |
71 | | }; |
72 | | |
73 | | enum fip_vlan_subcode { |
74 | | FIP_VL_REQ = 1, /* request */ |
75 | | FIP_VL_REP = 2 /* reply */ |
76 | | }; |
77 | | |
78 | | /* |
79 | | * Subcodes for FIP_OP_VN2VN. |
80 | | * XXX proposal |
81 | | */ |
82 | | enum fip_vn2vn_subcode { |
83 | | FIP_SC_VN_PROBE_REQ = 1, /* probe request */ |
84 | | FIP_SC_VN_PROBE_REP = 2, /* probe reply */ |
85 | | FIP_SC_VN_CLAIM_NOTIFY = 3, /* claim notification */ |
86 | | FIP_SC_VN_CLAIM_REP = 4, /* claim response */ |
87 | | FIP_SC_VN_BEACON = 5 /* beacon */ |
88 | | }; |
89 | | |
90 | | static const value_string fip_opcodes[] = { |
91 | | { FIP_OP_DISC, "Discovery" }, |
92 | | { FIP_OP_LS, "Link Service" }, |
93 | | { FIP_OP_CTRL, "Control" }, |
94 | | { FIP_OP_VLAN, "VLAN" }, |
95 | | { FIP_OP_VN2VN, "VN2VN" }, |
96 | | { 0, NULL } |
97 | | }; |
98 | | |
99 | | static const value_string fip_disc_subcodes[] = { |
100 | | { FIP_SC_SOL, "Solicitation" }, |
101 | | { FIP_SC_ADV, "Advertisement" }, |
102 | | { 0, NULL } |
103 | | }; |
104 | | |
105 | | static const value_string fip_ls_subcodes[] = { |
106 | | { FIP_SC_REQ, "ELS Request" }, |
107 | | { FIP_SC_REP, "ELS Response" }, |
108 | | { 0, NULL } |
109 | | }; |
110 | | |
111 | | static const value_string fip_ctrl_subcodes[] = { |
112 | | { FIP_SC_KA, "Keep-Alive" }, |
113 | | { FIP_SC_CVL, "Clear Virtual Link" }, |
114 | | { 0, NULL } |
115 | | }; |
116 | | |
117 | | static const value_string fip_vlan_subcodes[] = { |
118 | | { FIP_VL_REQ, "VLAN Request" }, |
119 | | { FIP_VL_REP, "VLAN Response" }, |
120 | | { 0, NULL } |
121 | | }; |
122 | | |
123 | | static const value_string fip_vn2vn_subcodes[] = { |
124 | | { FIP_SC_VN_PROBE_REQ, "Probe Request" }, |
125 | | { FIP_SC_VN_PROBE_REP, "Probe Reply" }, |
126 | | { FIP_SC_VN_CLAIM_NOTIFY, "Claim Notification" }, |
127 | | { FIP_SC_VN_CLAIM_REP, "Claim Response" }, |
128 | | { FIP_SC_VN_BEACON, "Beacon" }, |
129 | | { 0, NULL } |
130 | | }; |
131 | | |
132 | | /* |
133 | | * Descriptor types. |
134 | | */ |
135 | | enum fip_desc_type { |
136 | | FIP_DT_PRI = 1, /* priority for forwarder selection */ |
137 | | FIP_DT_MAC = 2, /* MAC address */ |
138 | | FIP_DT_MAP_OUI = 3, /* FC-MAP OUI */ |
139 | | FIP_DT_NAME = 4, /* switch name or node name */ |
140 | | FIP_DT_FAB = 5, /* fabric descriptor */ |
141 | | FIP_DT_FCOE_SIZE = 6, /* max FCoE frame size */ |
142 | | FIP_DT_FLOGI = 7, /* FLOGI request or response */ |
143 | | FIP_DT_FDISC = 8, /* FDISC request or response */ |
144 | | FIP_DT_LOGO = 9, /* LOGO request or response */ |
145 | | FIP_DT_ELP = 10, /* ELP request or response */ |
146 | | FIP_DT_VN = 11, /* VN_Port Info */ |
147 | | FIP_DT_FKA = 12, /* FIP keep-alive / advert. period */ |
148 | | FIP_DT_VEND = 13, /* Vendor-specific TLV */ |
149 | | FIP_DT_VLAN = 14, /* VLAN number */ |
150 | | FIP_DT_FC4F = 15 /* FC-4 features */ |
151 | | }; |
152 | | |
153 | | static const value_string fip_desc_types[] = { |
154 | | { FIP_DT_PRI, "Priority" }, |
155 | | { FIP_DT_MAC, "MAC Address" }, |
156 | | { FIP_DT_MAP_OUI, "FPMA MAP OUI" }, |
157 | | { FIP_DT_NAME, "Switch or Node Name" }, |
158 | | { FIP_DT_FAB, "Fabric Descriptor" }, |
159 | | { FIP_DT_FCOE_SIZE, "Max FCoE frame size" }, |
160 | | { FIP_DT_FLOGI, "FLOGI Encapsulation" }, |
161 | | { FIP_DT_FDISC, "FDISC Encapsulation" }, |
162 | | { FIP_DT_LOGO, "LOGO Encapsulation" }, |
163 | | { FIP_DT_ELP, "ELP Encapsulation" }, |
164 | | { FIP_DT_VN, "VN_Port Info" }, |
165 | | { FIP_DT_FKA, "FKA_ADV_Period" }, |
166 | | { FIP_DT_VEND, "Vendor_ID" }, |
167 | | { FIP_DT_VLAN, "VLAN" }, |
168 | | { FIP_DT_FC4F, "FC-4 features" }, |
169 | | { 0, NULL } |
170 | | }; |
171 | | static value_string_ext fip_desc_types_ext = VALUE_STRING_EXT_INIT(fip_desc_types); |
172 | | |
173 | | /* |
174 | | * flags in header fip_flags. |
175 | | */ |
176 | | enum fip_flag { |
177 | | FIP_FL_FPMA = 0x8000, /* supports FPMA fabric-provided MACs */ |
178 | | FIP_FL_SPMA = 0x4000, /* supports SPMA server-provided MACs */ |
179 | | FIP_FL_REC_P2P = 0x0008, /* recorded addr or point-to-point */ |
180 | | FIP_FL_AVAIL = 0x0004, /* available for FLOGI */ |
181 | | FIP_FL_SOL = 0x0002, /* this is a solicited message */ |
182 | | FIP_FL_FPORT = 0x0001 /* sent from an F port */ |
183 | | }; |
184 | | |
185 | | static int proto_fip; |
186 | | static int hf_fip_ver; |
187 | | static int hf_fip_reserved12; |
188 | | static int hf_fip_op; |
189 | | static int hf_fip_reserved8; |
190 | | static int hf_fip_disc_subcode; |
191 | | static int hf_fip_ls_subcode; |
192 | | static int hf_fip_ctrl_subcode; |
193 | | static int hf_fip_vlan_subcode; |
194 | | static int hf_fip_vn2vn_subcode; |
195 | | static int hf_fip_hex_subcode; |
196 | | static int hf_fip_dlen; |
197 | | static int hf_fip_flags; |
198 | | static int hf_fip_flag_fpma; |
199 | | static int hf_fip_flag_spma; |
200 | | static int hf_fip_flag_rec_p2p; |
201 | | static int hf_fip_flag_avail; |
202 | | static int hf_fip_flag_sol; |
203 | | static int hf_fip_flag_fport; |
204 | | static int hf_fip_descriptors; |
205 | | |
206 | | static int * const hf_fip_flags_fields[] = { |
207 | | &hf_fip_flag_fpma, |
208 | | &hf_fip_flag_spma, |
209 | | &hf_fip_flag_rec_p2p, |
210 | | &hf_fip_flag_avail, |
211 | | &hf_fip_flag_sol, |
212 | | &hf_fip_flag_fport, |
213 | | NULL |
214 | | }; |
215 | | |
216 | | static int hf_fip_desc_type; |
217 | | static int hf_fip_desc_len; |
218 | | static int hf_fip_desc_pri; |
219 | | static int hf_fip_desc_mac; |
220 | | static int hf_fip_desc_map; |
221 | | static int hf_fip_desc_name; |
222 | | static int hf_fip_desc_fab_vfid; |
223 | | static int hf_fip_desc_fab_map; |
224 | | static int hf_fip_desc_fab_name; |
225 | | static int hf_fip_desc_fcoe_size; |
226 | | static int hf_fip_desc_vn_mac; |
227 | | static int hf_fip_desc_vn_fid; |
228 | | static int hf_fip_desc_vn_wwpn; |
229 | | static int hf_fip_desc_fka; |
230 | | static int hf_fip_desc_vend; |
231 | | static int hf_fip_desc_vend_data; |
232 | | static int hf_fip_desc_vlan; |
233 | | static int hf_fip_desc_unk; |
234 | | static int hf_fip_desc_fc4f_types; |
235 | | static int hf_fip_desc_fcp_feat; |
236 | | static int hf_fip_type_ip; |
237 | | static int hf_fip_type_fcp; |
238 | | static int hf_fip_type_gs3; |
239 | | static int hf_fip_fcp_feat_i; |
240 | | static int hf_fip_fcp_feat_t; |
241 | | |
242 | | static int ett_fip; |
243 | | static int ett_fip_flags; |
244 | | static int ett_fip_dt_pri; |
245 | | static int ett_fip_dt_mac; |
246 | | static int ett_fip_dt_map; |
247 | | static int ett_fip_dt_name; |
248 | | static int ett_fip_dt_fab; |
249 | | static int ett_fip_dt_mdl; |
250 | | static int ett_fip_dt_caps; |
251 | | static int ett_fip_dt_vn; |
252 | | static int ett_fip_dt_fka; |
253 | | static int ett_fip_dt_vend; |
254 | | static int ett_fip_dt_vlan; |
255 | | static int ett_fip_dt_unk; |
256 | | static int ett_fip_dt_fc4f; |
257 | | static int ett_fip_dt_fc4f_types; |
258 | | static int ett_fip_dt_fcp_feat; |
259 | | |
260 | | static expert_field ei_fip_descriptors; |
261 | | |
262 | | static dissector_handle_t fc_handle; |
263 | | |
264 | | /* |
265 | | * Insert common descriptor type and length fields. |
266 | | */ |
267 | | static proto_tree* |
268 | | fip_desc_type_len(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, uint8_t dtype, int ett, proto_item** item) |
269 | 9 | { |
270 | 9 | proto_tree* ret_tree; |
271 | | |
272 | 9 | ret_tree = proto_tree_add_subtree_format(tree, tvb, 0, -1, ett, item, |
273 | 9 | "Descriptor: %s ", val_to_str_ext(pinfo->pool, dtype, &fip_desc_types_ext, "Unknown 0x%x")); |
274 | 9 | proto_tree_add_item(ret_tree, hf_fip_desc_type, tvb, 0, 1, ENC_BIG_ENDIAN); |
275 | 9 | proto_tree_add_item(ret_tree, hf_fip_desc_len, tvb, 1, 1, ENC_BIG_ENDIAN); |
276 | | |
277 | 9 | return ret_tree; |
278 | 9 | } |
279 | | |
280 | | /* |
281 | | * Dissect the FC-4 type features descriptor. |
282 | | */ |
283 | | static void |
284 | | fip_desc_fc4f(tvbuff_t *tvb, proto_tree *tree, proto_item *item) |
285 | 0 | { |
286 | 0 | unsigned mask; |
287 | 0 | unsigned offset; |
288 | |
|
289 | 0 | static int * const types_word0[] = { /* types 0 - 31 */ |
290 | 0 | &hf_fip_type_ip, |
291 | 0 | &hf_fip_type_fcp, |
292 | 0 | NULL |
293 | 0 | }; |
294 | 0 | static int * const types_word1[] = { /* types 32 - 63 */ |
295 | 0 | &hf_fip_type_gs3, |
296 | 0 | NULL |
297 | 0 | }; |
298 | 0 | static int * const fcp_feat[] = { |
299 | 0 | &hf_fip_fcp_feat_t, |
300 | 0 | &hf_fip_fcp_feat_i, |
301 | 0 | NULL |
302 | 0 | }; |
303 | | |
304 | | /* |
305 | | * First the 256-bit bitmask of types supported. |
306 | | */ |
307 | 0 | offset = 4; |
308 | 0 | proto_tree_add_bitmask(tree, tvb, offset, hf_fip_desc_fc4f_types, |
309 | 0 | ett_fip_dt_fc4f_types, types_word0, ENC_BIG_ENDIAN); |
310 | 0 | offset += 4; |
311 | 0 | proto_tree_add_bitmask(tree, tvb, offset, hf_fip_desc_fc4f_types, |
312 | 0 | ett_fip_dt_fc4f_types, types_word1, ENC_BIG_ENDIAN); |
313 | 0 | offset += 256 / 8 - 4; /* skip to end of bitmask (32 bytes) */ |
314 | | |
315 | | /* |
316 | | * Next the 4-bit capabilities per type. |
317 | | * Only decode FCP (type 8) for now. |
318 | | */ |
319 | 0 | offset += 8 / 2; /* skip first 8 types, 2 types per byte */ |
320 | 0 | proto_tree_add_bitmask(tree, tvb, offset, hf_fip_desc_fcp_feat, |
321 | 0 | ett_fip_dt_fcp_feat, fcp_feat, ENC_BIG_ENDIAN); |
322 | 0 | mask = tvb_get_ntohl(tvb, offset); |
323 | 0 | if (mask & 1) { |
324 | 0 | proto_item_append_text(item, "FCP Target "); |
325 | 0 | } |
326 | 0 | if (mask & 2) { |
327 | 0 | proto_item_append_text(item, "FCP Initiator "); |
328 | 0 | } |
329 | 0 | } |
330 | | |
331 | | static int |
332 | | dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
333 | 9 | { |
334 | 9 | unsigned op; |
335 | 9 | unsigned sub; |
336 | 9 | unsigned rlen; |
337 | 9 | proto_item *ti; |
338 | 9 | proto_item *item; |
339 | 9 | proto_tree *fip_tree; |
340 | 9 | proto_tree *subtree; |
341 | 9 | unsigned dtype; |
342 | 9 | unsigned dlen; |
343 | 9 | unsigned desc_offset; |
344 | 9 | unsigned val; |
345 | 9 | tvbuff_t *desc_tvb; |
346 | 9 | const char *info; |
347 | | |
348 | 9 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIP"); |
349 | 9 | col_clear(pinfo->cinfo, COL_INFO); |
350 | | |
351 | 9 | if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) { |
352 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]"); |
353 | 0 | proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, |
354 | 0 | -1, "FIP [packet too short]"); |
355 | 0 | return tvb_captured_length(tvb); |
356 | 0 | } |
357 | | |
358 | 9 | op = tvb_get_ntohs(tvb, 2); |
359 | 9 | sub = tvb_get_uint8(tvb, 5); |
360 | | |
361 | 9 | switch (op) { |
362 | 0 | case FIP_OP_DISC: |
363 | 0 | info = val_to_str(pinfo->pool, sub, fip_disc_subcodes, "Discovery 0x%x"); |
364 | 0 | break; |
365 | 0 | case FIP_OP_LS: |
366 | 0 | info = val_to_str(pinfo->pool, sub, fip_ls_subcodes, "Link Service 0x%x"); |
367 | 0 | break; |
368 | 0 | case FIP_OP_CTRL: |
369 | 0 | info = val_to_str(pinfo->pool, sub, fip_ctrl_subcodes, "Control 0x%x"); |
370 | 0 | break; |
371 | 0 | case FIP_OP_VLAN: |
372 | 0 | info = val_to_str(pinfo->pool, sub, fip_vlan_subcodes, "VLAN 0x%x"); |
373 | 0 | break; |
374 | 0 | case FIP_OP_VN2VN: |
375 | 0 | info = val_to_str(pinfo->pool, sub, fip_vn2vn_subcodes, "VN2VN 0x%x"); |
376 | 0 | break; |
377 | 9 | default: |
378 | 9 | info = val_to_str(pinfo->pool, op, fip_opcodes, "Unknown op 0x%x"); |
379 | 9 | break; |
380 | 9 | } |
381 | | |
382 | 9 | col_add_str(pinfo->cinfo, COL_INFO, info); |
383 | | |
384 | 9 | rlen = tvb_get_ntohs(tvb, 6); |
385 | | |
386 | 9 | ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, |
387 | 9 | FIP_HEADER_LEN + rlen * FIP_BPW, |
388 | 9 | "FIP %s", info); |
389 | 9 | fip_tree = proto_item_add_subtree(ti, ett_fip); |
390 | 9 | proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, ENC_BIG_ENDIAN); |
391 | 9 | proto_tree_add_item(fip_tree, hf_fip_reserved12, tvb, 0, 2, ENC_BIG_ENDIAN); |
392 | 9 | proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, ENC_BIG_ENDIAN); |
393 | 9 | proto_tree_add_item(fip_tree, hf_fip_reserved8, tvb, 4, 1, ENC_NA); |
394 | 9 | switch (op) { |
395 | 0 | case FIP_OP_DISC: |
396 | 0 | proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
397 | 0 | break; |
398 | 0 | case FIP_OP_LS: |
399 | 0 | proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
400 | 0 | break; |
401 | 0 | case FIP_OP_CTRL: |
402 | 0 | proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
403 | 0 | break; |
404 | 0 | case FIP_OP_VLAN: |
405 | 0 | proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
406 | 0 | break; |
407 | 0 | case FIP_OP_VN2VN: |
408 | 0 | proto_tree_add_item(fip_tree, hf_fip_vn2vn_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
409 | 0 | break; |
410 | 9 | default: |
411 | 9 | proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); |
412 | 9 | break; |
413 | 9 | } |
414 | 9 | proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, ENC_BIG_ENDIAN); |
415 | | |
416 | 9 | proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags, |
417 | 9 | ett_fip_flags, hf_fip_flags_fields, ENC_BIG_ENDIAN); |
418 | | |
419 | 9 | desc_offset = FIP_HEADER_LEN; |
420 | 9 | rlen *= FIP_BPW; |
421 | 9 | proto_tree_add_bytes_format(fip_tree, hf_fip_descriptors, tvb, desc_offset, rlen, NULL, "Descriptors"); |
422 | | |
423 | 18 | while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) { |
424 | 11 | dlen = tvb_get_uint8(tvb, desc_offset + 1) * FIP_BPW; |
425 | 11 | if (!dlen) { |
426 | 1 | proto_tree_add_expert_remaining(fip_tree, pinfo, &ei_fip_descriptors, tvb, desc_offset); |
427 | 1 | break; |
428 | 1 | } |
429 | 10 | if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) { |
430 | 1 | break; |
431 | 1 | } |
432 | 9 | desc_tvb = tvb_new_subset_length(tvb, desc_offset, dlen); |
433 | 9 | dtype = tvb_get_uint8(desc_tvb, 0); |
434 | 9 | desc_offset += dlen; |
435 | 9 | rlen -= dlen; |
436 | | |
437 | 9 | switch (dtype) { |
438 | 0 | case FIP_DT_PRI: |
439 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_pri, &item); |
440 | 0 | proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb, |
441 | 0 | 3, 1, ENC_BIG_ENDIAN); |
442 | 0 | proto_item_append_text(item, "%u", tvb_get_uint8(desc_tvb, 3)); |
443 | 0 | break; |
444 | 0 | case FIP_DT_MAC: |
445 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_mac, &item); |
446 | 0 | proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb, |
447 | 0 | 2, 6, ENC_NA); |
448 | 0 | proto_item_append_text(item, "%s", |
449 | 0 | tvb_bytes_to_str_punct(pinfo->pool, desc_tvb, 2, 6, ':')); |
450 | 0 | break; |
451 | 3 | case FIP_DT_MAP_OUI: |
452 | 3 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_map, &item); |
453 | 3 | proto_tree_add_item(subtree, hf_fip_desc_map, desc_tvb, |
454 | 3 | 5, 3, ENC_NA); |
455 | 3 | proto_item_append_text(item, "%s", tvb_fc_to_str(pinfo->pool, desc_tvb, 5)); |
456 | 3 | break; |
457 | 0 | case FIP_DT_NAME: |
458 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_name, &item); |
459 | 0 | proto_tree_add_item(subtree, hf_fip_desc_name, desc_tvb, 4, 8, ENC_NA); |
460 | 0 | proto_item_append_text(item, "%s", tvb_fcwwn_to_str(pinfo->pool, desc_tvb, 4)); |
461 | 0 | break; |
462 | 0 | case FIP_DT_FAB: |
463 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_fab, &item); |
464 | 0 | proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb, |
465 | 0 | 2, 2, ENC_BIG_ENDIAN); |
466 | 0 | proto_tree_add_item(subtree, hf_fip_desc_fab_map, desc_tvb, |
467 | 0 | 5, 3, ENC_NA); |
468 | 0 | proto_tree_add_item(subtree, hf_fip_desc_fab_name, desc_tvb, 8, 8, ENC_NA); |
469 | 0 | proto_item_append_text(item, "%s", tvb_fcwwn_to_str(pinfo->pool, desc_tvb, 8)); |
470 | 0 | break; |
471 | 0 | case FIP_DT_FCOE_SIZE: |
472 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_mdl, &item); |
473 | 0 | proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb, |
474 | 0 | 2, 2, ENC_BIG_ENDIAN); |
475 | 0 | proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); |
476 | 0 | break; |
477 | 0 | case FIP_DT_FLOGI: |
478 | 0 | case FIP_DT_FDISC: |
479 | 0 | case FIP_DT_LOGO: |
480 | 0 | case FIP_DT_ELP: { |
481 | 0 | tvbuff_t *ls_tvb; |
482 | 0 | fc_data_t fc_data = {ETHERTYPE_FIP, 0}; |
483 | |
|
484 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_caps, &item); |
485 | 0 | ls_tvb = tvb_new_subset_remaining(desc_tvb, 4); |
486 | 0 | call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data); |
487 | 0 | proto_item_append_text(item, "%u bytes", dlen - 4); |
488 | 0 | } |
489 | 0 | break; |
490 | 0 | case FIP_DT_VN: |
491 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_vn, &item); |
492 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb, |
493 | 0 | 2, 6, ENC_NA); |
494 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb, |
495 | 0 | 9, 3, ENC_BIG_ENDIAN); |
496 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vn_wwpn, |
497 | 0 | desc_tvb, 12, 8, ENC_NA); |
498 | 0 | proto_item_append_text(item, "MAC %s FC_ID %6.6x", |
499 | 0 | tvb_bytes_to_str_punct(pinfo->pool, desc_tvb, 2, 6, ':'), |
500 | 0 | tvb_get_ntoh24(desc_tvb, 9)); |
501 | 0 | break; |
502 | 0 | case FIP_DT_FKA: |
503 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_fka, &item); |
504 | 0 | val = tvb_get_ntohl(desc_tvb, 4); |
505 | 0 | proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka, |
506 | 0 | desc_tvb, 4, 4, val, "%u ms", val); |
507 | 0 | proto_item_append_text(item, "%u ms", val); |
508 | 0 | break; |
509 | 0 | case FIP_DT_VEND: |
510 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_vend, &item); |
511 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb, |
512 | 0 | 4, 8, ENC_NA); |
513 | 0 | if (tvb_reported_length_remaining(desc_tvb, 9)) { |
514 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vend_data, |
515 | 0 | desc_tvb, 9, -1, ENC_NA); |
516 | 0 | } |
517 | 0 | break; |
518 | 0 | case FIP_DT_VLAN: |
519 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_vlan, &item); |
520 | 0 | proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb, |
521 | 0 | 2, 2, ENC_BIG_ENDIAN); |
522 | 0 | proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); |
523 | 0 | break; |
524 | 0 | case FIP_DT_FC4F: |
525 | 0 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_fc4f, &item); |
526 | 0 | fip_desc_fc4f(desc_tvb, subtree, item); |
527 | 0 | break; |
528 | 6 | default: |
529 | 6 | subtree = fip_desc_type_len(fip_tree, pinfo, desc_tvb, dtype, ett_fip_dt_unk, &item); |
530 | 6 | proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb, |
531 | 6 | 2, -1, ENC_NA); |
532 | 6 | break; |
533 | 9 | } |
534 | 9 | } |
535 | 9 | return tvb_captured_length(tvb); |
536 | 9 | } |
537 | | |
538 | | void |
539 | | proto_register_fip(void) |
540 | 15 | { |
541 | | /* Setup list of header fields See Section 1.6.1 for details*/ |
542 | 15 | static hf_register_info hf[] = { |
543 | | /* |
544 | | * FIP header fields. |
545 | | */ |
546 | 15 | { &hf_fip_ver, |
547 | 15 | { "Version", "fip.ver", |
548 | 15 | FT_UINT8, BASE_DEC, NULL, 0xf0, |
549 | 15 | NULL, HFILL}}, |
550 | | |
551 | 15 | { &hf_fip_reserved12, |
552 | 15 | { "Reserved", "fip.reserved", |
553 | 15 | FT_UINT16, BASE_HEX, NULL, 0x0fff, |
554 | 15 | NULL, HFILL}}, |
555 | | |
556 | 15 | { &hf_fip_op, |
557 | 15 | { "Opcode", "fip.opcode", |
558 | 15 | FT_UINT16, BASE_HEX, VALS(fip_opcodes), 0, |
559 | 15 | NULL, HFILL}}, |
560 | | |
561 | 15 | { &hf_fip_reserved8, |
562 | 15 | { "Reserved", "fip.reserved", |
563 | 15 | FT_UINT8, BASE_HEX, NULL, 0x0, |
564 | 15 | NULL, HFILL}}, |
565 | | |
566 | 15 | { &hf_fip_disc_subcode, |
567 | 15 | { "Discovery Subcode", "fip.disc_subcode", |
568 | 15 | FT_UINT8, BASE_HEX, VALS(fip_disc_subcodes), 0, |
569 | 15 | NULL, HFILL}}, |
570 | | |
571 | 15 | { &hf_fip_ls_subcode, |
572 | 15 | { "Link Service Subcode", "fip.ls.subcode", |
573 | 15 | FT_UINT8, BASE_HEX, VALS(fip_ls_subcodes), 0, |
574 | 15 | NULL, HFILL}}, |
575 | | |
576 | 15 | { &hf_fip_ctrl_subcode, |
577 | 15 | { "Control Subcode", "fip.ctrl_subcode", |
578 | 15 | FT_UINT8, BASE_HEX, VALS(fip_ctrl_subcodes), 0, |
579 | 15 | NULL, HFILL}}, |
580 | | |
581 | 15 | { &hf_fip_vlan_subcode, |
582 | 15 | { "VLAN Subcode", "fip.vlan_subcode", |
583 | 15 | FT_UINT8, BASE_HEX, VALS(fip_vlan_subcodes), 0, |
584 | 15 | NULL, HFILL}}, |
585 | | |
586 | 15 | { &hf_fip_vn2vn_subcode, |
587 | 15 | { "VN2VN Subcode", "fip.vn2vn_subcode", |
588 | 15 | FT_UINT8, BASE_HEX, VALS(fip_vn2vn_subcodes), 0, |
589 | 15 | NULL, HFILL}}, |
590 | | |
591 | 15 | { &hf_fip_hex_subcode, |
592 | 15 | { "Unknown Subcode", "fip.subcode", |
593 | 15 | FT_UINT8, BASE_HEX, NULL, 0, |
594 | 15 | NULL, HFILL}}, |
595 | | |
596 | 15 | { &hf_fip_dlen, |
597 | 15 | { "Length of Descriptors (words)", "fip.dl_len", |
598 | 15 | FT_UINT16, BASE_DEC, NULL, 0, |
599 | 15 | NULL, HFILL}}, |
600 | | |
601 | 15 | { &hf_fip_flags, |
602 | 15 | { "Flags", "fip.flags", |
603 | 15 | FT_UINT16, BASE_HEX, NULL, 0, |
604 | 15 | NULL, HFILL}}, |
605 | | |
606 | 15 | { &hf_fip_flag_fpma, |
607 | 15 | { "Fabric Provided MAC addr", "fip.flags.fpma", |
608 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_FPMA, |
609 | 15 | NULL, HFILL}}, |
610 | | |
611 | 15 | { &hf_fip_flag_spma, |
612 | 15 | { "Server Provided MAC addr", "fip.flags.spma", |
613 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_SPMA, |
614 | 15 | NULL, HFILL}}, |
615 | | |
616 | 15 | { &hf_fip_flag_rec_p2p, |
617 | 15 | { "REC/P2P", "fip.flags.rec_p2p", |
618 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_REC_P2P, |
619 | 15 | NULL, HFILL}}, |
620 | | |
621 | 15 | { &hf_fip_flag_avail, |
622 | 15 | { "Available", "fip.flags.available", |
623 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_AVAIL, |
624 | 15 | NULL, HFILL}}, |
625 | | |
626 | 15 | { &hf_fip_flag_sol, |
627 | 15 | { "Solicited", "fip.flags.sol", |
628 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_SOL, |
629 | 15 | NULL, HFILL}}, |
630 | | |
631 | 15 | { &hf_fip_flag_fport, |
632 | 15 | { "F_Port", "fip.flags.fport", |
633 | 15 | FT_BOOLEAN, 16, NULL, FIP_FL_FPORT, |
634 | 15 | NULL, HFILL}}, |
635 | | |
636 | 15 | { &hf_fip_desc_type, |
637 | 15 | { "Descriptor Type", "fip.desc_type", |
638 | 15 | FT_UINT8, BASE_HEX | BASE_EXT_STRING, &fip_desc_types_ext, 0, |
639 | 15 | NULL, HFILL}}, |
640 | | |
641 | 15 | { &hf_fip_desc_len, |
642 | 15 | { "Descriptor Length (words)", "fip.desc_len", |
643 | 15 | FT_UINT8, BASE_DEC, NULL, 0, |
644 | 15 | NULL, HFILL}}, |
645 | | |
646 | | /* |
647 | | * Various descriptor fields. |
648 | | */ |
649 | 15 | { &hf_fip_desc_pri, |
650 | 15 | { "Priority", "fip.pri", |
651 | 15 | FT_UINT8, BASE_DEC, NULL, 0, |
652 | 15 | NULL, HFILL}}, |
653 | | |
654 | 15 | { &hf_fip_desc_mac, |
655 | 15 | { "MAC Address", "fip.mac", |
656 | 15 | FT_ETHER, BASE_NONE, NULL, 0, |
657 | 15 | NULL, HFILL}}, |
658 | | |
659 | 15 | { &hf_fip_desc_map, |
660 | 15 | { "FC-MAP-OUI", "fip.map", |
661 | 15 | FT_BYTES, SEP_DOT, NULL, 0, |
662 | 15 | NULL, HFILL}}, |
663 | | |
664 | 15 | { &hf_fip_desc_name, |
665 | 15 | { "Switch or Node Name", "fip.name", |
666 | 15 | FT_FCWWN, BASE_NONE, NULL, 0, |
667 | 15 | NULL, HFILL}}, |
668 | | |
669 | 15 | { &hf_fip_desc_fab_vfid, |
670 | 15 | { "VFID", "fip.fab.vfid", |
671 | 15 | FT_UINT16, BASE_DEC, NULL, 0, |
672 | 15 | NULL, HFILL}}, |
673 | | |
674 | 15 | { &hf_fip_desc_fab_map, |
675 | 15 | { "FC-MAP", "fip.fab.map", |
676 | 15 | FT_BYTES, SEP_DOT, NULL, 0, |
677 | 15 | NULL, HFILL}}, |
678 | | |
679 | 15 | { &hf_fip_desc_fab_name, |
680 | 15 | { "Fabric Name", "fip.fab.name", |
681 | 15 | FT_FCWWN, BASE_NONE, NULL, 0, |
682 | 15 | NULL, HFILL}}, |
683 | | |
684 | 15 | { &hf_fip_desc_fcoe_size, |
685 | 15 | { "Max FCoE frame size", "fip.fcoe_size", |
686 | 15 | FT_UINT16, BASE_DEC, NULL, 0, |
687 | 15 | NULL, HFILL}}, |
688 | | |
689 | 15 | { &hf_fip_desc_vn_mac, |
690 | 15 | { "VN_Port MAC Address", "fip.vn.mac", |
691 | 15 | FT_ETHER, BASE_NONE, NULL, 0, |
692 | 15 | NULL, HFILL}}, |
693 | | |
694 | 15 | { &hf_fip_desc_vn_fid, |
695 | 15 | { "VN_Port FC_ID", "fip.vn.fc_id", |
696 | 15 | FT_UINT32, BASE_HEX, NULL, 0, |
697 | 15 | NULL, HFILL}}, |
698 | | |
699 | 15 | { &hf_fip_desc_vn_wwpn, |
700 | 15 | { "Port Name", "fip.vn.pwwn", |
701 | 15 | FT_FCWWN, BASE_NONE, NULL, 0, |
702 | 15 | NULL, HFILL}}, |
703 | | |
704 | 15 | { &hf_fip_desc_fka, |
705 | 15 | { "FKA_ADV_Period", "fip.fka", |
706 | 15 | FT_UINT32, BASE_DEC, NULL, 0, |
707 | 15 | NULL, HFILL}}, |
708 | | |
709 | 15 | { &hf_fip_desc_vend, |
710 | 15 | { "Vendor-ID", "fip.vendor", |
711 | 15 | FT_BYTES, BASE_NONE, NULL, 0, |
712 | 15 | NULL, HFILL}}, |
713 | | |
714 | 15 | { &hf_fip_desc_vend_data, |
715 | 15 | { "Vendor-specific data", "fip.vendor.data", |
716 | 15 | FT_BYTES, BASE_NONE, NULL, 0, |
717 | 15 | NULL, HFILL}}, |
718 | | |
719 | 15 | { &hf_fip_desc_vlan, |
720 | 15 | { "VLAN", "fip.vlan", |
721 | 15 | FT_UINT16, BASE_DEC, NULL, 0, |
722 | 15 | NULL, HFILL}}, |
723 | | |
724 | 15 | { &hf_fip_desc_fc4f_types, |
725 | 15 | { "FC4 Types", "fip.fc4f.types", |
726 | 15 | FT_UINT32, BASE_HEX, NULL, 0, |
727 | 15 | NULL, HFILL}}, |
728 | | |
729 | 15 | { &hf_fip_desc_fcp_feat, |
730 | 15 | { "FCP Features", "fip.fc4f.feat.fcp", |
731 | 15 | FT_UINT32, BASE_HEX, NULL, 0xf, |
732 | 15 | NULL, HFILL}}, |
733 | | |
734 | 15 | { &hf_fip_type_ip, |
735 | 15 | { "IP", "fip.fc4f.ip", |
736 | 15 | FT_BOOLEAN, 32, NULL, 1 << 5, |
737 | 15 | NULL, HFILL}}, |
738 | | |
739 | 15 | { &hf_fip_type_fcp, |
740 | 15 | { "FCP", "fip.fc4f.fcp", |
741 | 15 | FT_BOOLEAN, 32, NULL, 1 << 8, |
742 | 15 | NULL, HFILL}}, |
743 | | |
744 | 15 | { &hf_fip_type_gs3, |
745 | 15 | { "GS3", "fip.fc4f.gs3", |
746 | 15 | FT_BOOLEAN, 32, NULL, 1 << 0, |
747 | 15 | NULL, HFILL}}, |
748 | | |
749 | 15 | { &hf_fip_fcp_feat_t, |
750 | 15 | { "FCP Target", "fip.fc4f.feat.fcp.target", |
751 | 15 | FT_BOOLEAN, 32, NULL, 1, |
752 | 15 | NULL, HFILL}}, |
753 | | |
754 | 15 | { &hf_fip_fcp_feat_i, |
755 | 15 | { "FCP Initiator", "fip.fc4f.feat.fcp.initiator", |
756 | 15 | FT_BOOLEAN, 32, NULL, 2, |
757 | 15 | NULL, HFILL}}, |
758 | | |
759 | 15 | { &hf_fip_desc_unk, |
760 | 15 | { "Unknown Descriptor", "fip.desc_unk", |
761 | 15 | FT_BYTES, BASE_NONE, NULL, 0, |
762 | 15 | NULL, HFILL}}, |
763 | | |
764 | 15 | { &hf_fip_descriptors, |
765 | 15 | { "Descriptors", "fip.descriptors", |
766 | 15 | FT_BYTES, BASE_NONE, NULL, 0, |
767 | 15 | NULL, HFILL}}, |
768 | | |
769 | 15 | }; |
770 | 15 | static int *ett[] = { |
771 | 15 | &ett_fip, |
772 | 15 | &ett_fip_flags, |
773 | 15 | &ett_fip_dt_pri, |
774 | 15 | &ett_fip_dt_mac, |
775 | 15 | &ett_fip_dt_map, |
776 | 15 | &ett_fip_dt_name, |
777 | 15 | &ett_fip_dt_fab, |
778 | 15 | &ett_fip_dt_mdl, |
779 | 15 | &ett_fip_dt_caps, |
780 | 15 | &ett_fip_dt_vn, |
781 | 15 | &ett_fip_dt_fka, |
782 | 15 | &ett_fip_dt_vend, |
783 | 15 | &ett_fip_dt_vlan, |
784 | 15 | &ett_fip_dt_fc4f, |
785 | 15 | &ett_fip_dt_fc4f_types, |
786 | 15 | &ett_fip_dt_fcp_feat, |
787 | 15 | &ett_fip_dt_unk |
788 | 15 | }; |
789 | | |
790 | 15 | static ei_register_info ei[] = { |
791 | 15 | { &ei_fip_descriptors, { "fip.descriptors.length_error", PI_MALFORMED, PI_ERROR, "Descriptor [length error]", EXPFILL }}, |
792 | 15 | }; |
793 | | |
794 | 15 | expert_module_t* expert_fip; |
795 | | |
796 | | /* Register the protocol name and description */ |
797 | 15 | proto_fip = proto_register_protocol("FCoE Initialization Protocol", |
798 | 15 | "FIP", "fip"); |
799 | 15 | fip_handle = register_dissector("fip", dissect_fip, proto_fip); |
800 | | |
801 | | /* Required function calls to register the header fields and |
802 | | * subtrees used */ |
803 | 15 | proto_register_field_array(proto_fip, hf, array_length(hf)); |
804 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
805 | 15 | expert_fip = expert_register_protocol(proto_fip); |
806 | 15 | expert_register_field_array(expert_fip, ei, array_length(ei)); |
807 | 15 | } |
808 | | |
809 | | /* |
810 | | * This function name is required because a script is used to find these |
811 | | * routines and create the code that calls these routines. |
812 | | */ |
813 | | void |
814 | | proto_reg_handoff_fip(void) |
815 | 15 | { |
816 | 15 | dissector_add_uint("ethertype", ETHERTYPE_FIP, fip_handle); |
817 | 15 | fc_handle = find_dissector_add_dependency("fc", proto_fip); |
818 | 15 | } |
819 | | |
820 | | /* |
821 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
822 | | * |
823 | | * Local variables: |
824 | | * c-basic-offset: 4 |
825 | | * tab-width: 8 |
826 | | * indent-tabs-mode: nil |
827 | | * End: |
828 | | * |
829 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
830 | | * :indentSize=4:tabSize=8:noTabs=true: |
831 | | */ |