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