Add wtap-int.h. Move definitions relevant to the internal workins of wiretap
[metze/wireshark/wip.git] / packet-vtp.c
1 /* packet-vtp.c
2  * Routines for the disassembly of Cisco's Virtual Trunking Protocol
3  *
4  * $Id: packet-vtp.c,v 1.4 2000/05/14 07:19:49 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  * 
10  * 
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.
15  * 
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.
20  * 
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25  
26 #include "config.h"
27
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <glib.h>
36 #include "packet.h"
37
38 /*
39  * See
40  *
41  *      http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
42  *
43  * for some information on VTP.
44  *
45  * It's incomplete, and it appears to be inaccurate in a number of places,
46  * but it's all I could find....
47  */
48
49 static int proto_vtp = -1;
50 static int hf_vtp_version = -1;
51 static int hf_vtp_code = -1;
52 static int hf_vtp_followers = -1;
53 static int hf_vtp_md_len = -1;
54 static int hf_vtp_md = -1;
55 static int hf_vtp_conf_rev_num = -1;
56 static int hf_vtp_upd_id = -1;
57 static int hf_vtp_upd_ts = -1;
58 static int hf_vtp_md5_digest = -1;
59 static int hf_vtp_seq_num = -1;
60 static int hf_vtp_start_value = -1;
61 static int hf_vtp_vlan_info_len = -1;
62 static int hf_vtp_vlan_status_vlan_susp = -1;
63 static int hf_vtp_vlan_type = -1;
64 static int hf_vtp_vlan_name_len = -1;
65 static int hf_vtp_isl_vlan_id = -1;
66 static int hf_vtp_mtu_size = -1;
67 static int hf_vtp_802_10_index = -1;
68 static int hf_vtp_vlan_name = -1;
69 static int hf_vtp_vlan_tlvtype = -1;
70 static int hf_vtp_vlan_tlvlength = -1;
71
72 static gint ett_vtp = -1;
73 static gint ett_vtp_vlan_info = -1;
74 static gint ett_vtp_vlan_status = -1;
75 static gint ett_vtp_tlv = -1;
76
77 static int
78 dissect_vlan_info(const u_char *pd, int offset, proto_tree *tree);
79 static void
80 dissect_vlan_info_tlv(const u_char *pd, int offset, int length,
81     proto_tree *tree, proto_item *ti, guint8 type);
82
83 #define SUMMARY_ADVERT          0x01
84 #define SUBSET_ADVERT           0x02
85 #define ADVERT_REQUEST          0x03
86
87 static const value_string type_vals[] = {
88         { SUMMARY_ADVERT, "Summary-Advert" },
89         { SUBSET_ADVERT,  "Subset-Advert" },
90         { ADVERT_REQUEST, "Advert-Request" },
91         { 0,              NULL },
92 };
93         
94 void 
95 dissect_vtp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
96 {
97         proto_item *ti; 
98         proto_tree *vtp_tree = NULL;
99         guint8 code;
100         guint8 md_len;
101         int vlan_info_len;
102         guint32 upd_id;
103
104         if (check_col(fd, COL_PROTOCOL))
105                 col_add_str(fd, COL_PROTOCOL, "VTP");
106         if (check_col(fd, COL_INFO))
107                 col_add_str(fd, COL_INFO, "Virtual Trunking Protocol"); 
108
109         if (tree) {
110                 ti = proto_tree_add_item(tree, proto_vtp, NullTVB, offset, END_OF_FRAME,
111                     NULL);
112                 vtp_tree = proto_item_add_subtree(ti, ett_vtp);
113
114                 proto_tree_add_item(vtp_tree, hf_vtp_version, NullTVB, offset, 1,
115                     pd[offset]);
116                 offset += 1;
117
118                 code = pd[offset];
119                 proto_tree_add_item(vtp_tree, hf_vtp_code, NullTVB, offset, 1,
120                     code);
121                 offset += 1;
122                 
123                 switch (code) {
124
125                 case SUMMARY_ADVERT:
126                         proto_tree_add_item(vtp_tree, hf_vtp_followers, NullTVB, offset,
127                             1, pd[offset]);
128                         offset += 1;
129
130                         md_len = pd[offset];
131                         proto_tree_add_item(vtp_tree, hf_vtp_md_len, NullTVB, offset,
132                             1, md_len);
133                         offset += 1;
134
135                         proto_tree_add_string_format(vtp_tree, hf_vtp_md, NullTVB, offset,
136                             32, &pd[offset], "Management Domain: %.32s",
137                             &pd[offset]);
138                         offset += 32;
139
140                         proto_tree_add_item(vtp_tree, hf_vtp_conf_rev_num, NullTVB,
141                             offset, 4, pntohl(&pd[offset]));
142                         offset += 4;
143
144                         memcpy(&upd_id, &pd[offset], sizeof upd_id);
145                         proto_tree_add_item(vtp_tree, hf_vtp_upd_id, NullTVB,
146                             offset, 4, upd_id);
147                         offset += 4;
148
149                         proto_tree_add_string_format(vtp_tree, hf_vtp_upd_ts, NullTVB,
150                             offset, 12, &pd[offset],
151                             "Update Timestamp: %.2s-%.2s-%.2s %.2s:%.2s:%.2s",
152                             &pd[offset], &pd[offset+2], &pd[offset+4],
153                             &pd[offset+6], &pd[offset+8], &pd[offset+10]);
154                         offset += 12;
155
156                         proto_tree_add_item(vtp_tree, hf_vtp_md5_digest, NullTVB,
157                             offset, 16, &pd[offset]);
158                         break;
159
160                 case SUBSET_ADVERT:
161                         proto_tree_add_item(vtp_tree, hf_vtp_seq_num, NullTVB, offset,
162                             1, pd[offset]);
163                         offset += 1;
164
165                         md_len = pd[offset];
166                         proto_tree_add_item(vtp_tree, hf_vtp_md_len, NullTVB, offset,
167                             1, md_len);
168                         offset += 1;
169
170                         proto_tree_add_string_format(vtp_tree, hf_vtp_md, NullTVB, offset,
171                             32, &pd[offset], "Management Domain: %.32s",
172                             &pd[offset]);
173                         offset += 32;
174
175                         proto_tree_add_item(vtp_tree, hf_vtp_conf_rev_num, NullTVB,
176                             offset, 4, pntohl(&pd[offset]));
177                         offset += 4;
178
179                         for (;;) {
180                                 vlan_info_len = 
181                                     dissect_vlan_info(pd, offset, vtp_tree);
182                                 if (vlan_info_len < 0)
183                                         break;
184                                 offset += vlan_info_len;
185                         }
186                         break;
187
188                 case ADVERT_REQUEST:
189                         offset += 1;    /* skip reserved field */
190
191                         md_len = pd[offset];
192                         proto_tree_add_item(vtp_tree, hf_vtp_md_len, NullTVB, offset,
193                             1, md_len);
194                         offset += 1;
195
196                         proto_tree_add_item(vtp_tree, hf_vtp_start_value, NullTVB,
197                             offset, 2, pntohs(&pd[offset]));
198                         break;
199
200                 case 0x04:
201                         /*
202                          * Mysterious type, seen a lot.
203                          * Is this some mutant variant of Advert-Request?
204                          */
205                         offset += 1;    /* skip unknown field */
206
207                         md_len = pd[offset];
208                         proto_tree_add_item(vtp_tree, hf_vtp_md_len, NullTVB, offset,
209                             1, md_len);
210                         offset += 1;
211
212                         proto_tree_add_string_format(vtp_tree, hf_vtp_md, NullTVB, offset,
213                             32, &pd[offset], "Management Domain: %.32s",
214                             &pd[offset]);
215                         offset += 32;
216
217                         offset += 2;    /* skip unknown field */
218
219                         proto_tree_add_text(vtp_tree, NullTVB, offset, 2,
220                             "VLAN ID of some sort: 0x%04x",
221                             pntohs(&pd[offset]));
222                         offset += 2;
223                         break;
224                 }
225         }
226 }
227
228 #define VLAN_SUSPENDED  0x01
229
230 static const value_string vlan_type_vals[] = {
231         { 0x01, "Ethernet" },
232         { 0x02, "FDDI" },
233         { 0x03, "TrCRF" },
234         { 0x04, "FDDI-net" },
235         { 0x05, "TrBRF" },
236         { 0,    NULL },
237 };
238
239 #define SR_RING_NUM             0x01
240 #define SR_BRIDGE_NUM           0x02
241 #define STP_TYPE                0x03
242 #define PARENT_VLAN             0x04
243 #define TR_BRIDGED_VLANS        0x05
244 #define PRUNING                 0x06
245 #define BRIDGE_TYPE             0x07
246 #define MAX_ARE_HOP_CNT         0x08
247 #define MAX_STE_HOP_CNT         0x09
248 #define BACKUP_CRF_MODE         0x0A
249
250 static const value_string vlan_tlv_type_vals[] = {
251         { SR_RING_NUM,      "Source-Routing Ring Number" },
252         { SR_BRIDGE_NUM,    "Source-Routing Bridge Number" },
253         { STP_TYPE,         "Spanning-Tree Protocol Type" },
254         { PARENT_VLAN,      "Parent VLAN" },
255         { TR_BRIDGED_VLANS, "Translationally Bridged VLANs" },
256         { PRUNING,          "Pruning" },
257         { BRIDGE_TYPE,      "Bridge Type" },
258         { MAX_ARE_HOP_CNT,  "Max ARE Hop Count" },
259         { MAX_STE_HOP_CNT,  "Max STE Hop Count" },
260         { BACKUP_CRF_MODE,  "Backup CRF Mode" },
261         { 0,                NULL },
262 };
263
264 static int
265 dissect_vlan_info(const u_char *pd, int offset, proto_tree *tree)
266 {
267         proto_item *ti; 
268         proto_tree *vlan_info_tree;
269         proto_tree *status_tree;
270         guint8 vlan_info_len;
271         int vlan_info_left;
272         guint8 status;
273         guint8 vlan_name_len;
274         guint16 type;
275         int length;
276         char *type_str;
277         proto_tree *tlv_tree;
278
279         if (!BYTES_ARE_IN_FRAME(offset, 1))
280                 return -1;
281         vlan_info_len = pd[offset];
282         ti = proto_tree_add_text(tree, NullTVB, offset, vlan_info_len,
283             "VLAN Information");
284         vlan_info_tree = proto_item_add_subtree(ti, ett_vtp_vlan_info);
285         vlan_info_left = vlan_info_len;
286
287         proto_tree_add_item(vlan_info_tree, hf_vtp_vlan_info_len, NullTVB, offset, 1,
288             vlan_info_len);
289         offset += 1;
290         vlan_info_left -= 1;
291
292         if (!BYTES_ARE_IN_FRAME(offset, 1) || vlan_info_left < 1)
293                 return -1;
294         status = pd[offset];
295         ti = proto_tree_add_text(vlan_info_tree, NullTVB, offset, 1,
296             "Status: 0x%02x%s", status,
297             (status & VLAN_SUSPENDED) ? "(VLAN suspended)" : "");
298         status_tree = proto_item_add_subtree(ti, ett_vtp_vlan_status);
299         proto_tree_add_item(status_tree, hf_vtp_vlan_status_vlan_susp, NullTVB, offset, 1,
300             status);
301         offset += 1;
302         vlan_info_left -= 1;
303
304         if (!BYTES_ARE_IN_FRAME(offset, 1) || vlan_info_left < 1)
305                 return -1;
306         proto_tree_add_item(vlan_info_tree, hf_vtp_vlan_type, NullTVB, offset, 1,
307             pd[offset]);
308         offset += 1;
309         vlan_info_left -= 1;
310
311         if (!BYTES_ARE_IN_FRAME(offset, 1) || vlan_info_left < 1)
312                 return -1;
313         vlan_name_len = pd[offset];
314         proto_tree_add_item(vlan_info_tree, hf_vtp_vlan_name_len, NullTVB, offset, 1,
315             vlan_name_len);
316         offset += 1;
317         vlan_info_left -= 1;
318
319         if (!BYTES_ARE_IN_FRAME(offset, 2) || vlan_info_left < 2)
320                 return -1;
321         proto_tree_add_item(vlan_info_tree, hf_vtp_isl_vlan_id, NullTVB, offset, 2,
322             pntohs(&pd[offset]));
323         offset += 2;
324         vlan_info_left -= 2;
325
326         if (!BYTES_ARE_IN_FRAME(offset, 2) || vlan_info_left < 2)
327                 return -1;
328         proto_tree_add_item(vlan_info_tree, hf_vtp_mtu_size, NullTVB, offset, 2,
329             pntohs(&pd[offset]));
330         offset += 2;
331         vlan_info_left -= 2;
332
333         if (!BYTES_ARE_IN_FRAME(offset, 4) || vlan_info_left < 4)
334                 return -1;
335         proto_tree_add_item(vlan_info_tree, hf_vtp_802_10_index, NullTVB, offset, 4,
336             pntohl(&pd[offset]));
337         offset += 4;
338         vlan_info_left -= 4;
339
340         /* VLAN name length appears to be rounded up to a multiple of
341            4. */
342         vlan_name_len = 4*((vlan_name_len + 3)/4);
343         if (!BYTES_ARE_IN_FRAME(offset, vlan_name_len)
344             || vlan_info_left < vlan_name_len)
345                 return -1;
346         proto_tree_add_string_format(vlan_info_tree, hf_vtp_vlan_name, NullTVB, offset,
347             vlan_name_len, &pd[offset], "VLAN Name: %.*s", vlan_name_len,
348             &pd[offset]);
349         offset += vlan_name_len;
350         vlan_info_left -= vlan_name_len;
351
352         while (IS_DATA_IN_FRAME(offset) && vlan_info_left > 0) {
353                 type = pd[offset + 0];
354                 length = pd[offset + 1];
355                 type_str = val_to_str(type, vlan_tlv_type_vals,
356                     "Unknown (0x%04x)");
357
358                 ti = proto_tree_add_notext(vlan_info_tree, NullTVB, offset,
359                     2 + length*2);
360                 tlv_tree = proto_item_add_subtree(ti, ett_vtp_tlv);
361                 proto_tree_add_item(tlv_tree, hf_vtp_vlan_tlvtype, NullTVB, offset,
362                     1, type);
363                 proto_tree_add_item(tlv_tree, hf_vtp_vlan_tlvlength, NullTVB, offset+1,
364                     1, length);
365                 offset += 2;
366                 vlan_info_left -= 2;
367                 if (length > 0) {
368                         dissect_vlan_info_tlv(pd, offset, length*2, tlv_tree,
369                             ti, type);
370                 }
371                 offset += length*2;
372                 vlan_info_left -= length*2;
373         }
374
375         return vlan_info_len;
376 }
377
378 static const value_string stp_type_vals[] = {
379         { 1, "SRT" },
380         { 2, "SRB" },
381         { 3, "Auto" },
382         { 0, NULL },
383 };
384
385 static const value_string pruning_vals[] = {
386         { 1, "Enabled" },
387         { 2, "Disabled" },
388         { 0, NULL },
389 };
390
391 static const value_string bridge_type_vals[] = {
392         { 1, "SRT" },
393         { 2, "SRB" },
394         { 0, NULL },
395 };
396
397 static const value_string backup_crf_mode_vals[] = {
398         { 1, "TrCRF is configured as a backup" },
399         { 2, "TrCRF is not configured as a backup" },
400         { 0, NULL },
401 };
402
403 static void
404 dissect_vlan_info_tlv(const u_char *pd, int offset, int length,
405     proto_tree *tree, proto_item *ti, guint8 type)
406 {
407         switch (type) {
408
409         case SR_RING_NUM:
410                 if (length == 2) {
411                         proto_item_set_text(ti,
412                             "Source-Routing Ring Number: 0x%04x",
413                             pntohs(&pd[offset]));
414                         proto_tree_add_text(tree, NullTVB, offset, 2,
415                             "Source-Routing Ring Number: 0x%04x",
416                             pntohs(&pd[offset]));
417                 } else {
418                         proto_item_set_text(ti,
419                             "Source-Routing Ring Number: Bad length %u",
420                             length);
421                         proto_tree_add_text(tree, NullTVB, offset, length,
422                             "Source-Routing Ring Number: Bad length %u",
423                             length);
424                 }
425                 break;
426
427         case SR_BRIDGE_NUM:
428                 if (length == 2) {
429                         proto_item_set_text(ti,
430                             "Source-Routing Bridge Number: 0x%04x",
431                             pntohs(&pd[offset]));
432                         proto_tree_add_text(tree, NullTVB, offset, 2,
433                             "Source-Routing Bridge Number: 0x%04x",
434                             pntohs(&pd[offset]));
435                 } else {
436                         proto_item_set_text(ti,
437                             "Source-Routing Bridge Number: Bad length %u",
438                             length);
439                         proto_tree_add_text(tree, NullTVB, offset, length,
440                             "Source-Routing Bridge Number: Bad length %u",
441                             length);
442                 }
443                 break;
444
445         case STP_TYPE:
446                 if (length == 2) {
447                         proto_item_set_text(ti,
448                             "Spanning-Tree Protocol Type: %s",
449                             val_to_str(pntohs(&pd[offset]), stp_type_vals,
450                               "Unknown (0x%04x)"));
451                         proto_tree_add_text(tree, NullTVB, offset, 2,
452                             "Spanning-Tree Protocol Type: %s",
453                             val_to_str(pntohs(&pd[offset]), stp_type_vals,
454                               "Unknown (0x%04x)"));
455                 } else {
456                         proto_item_set_text(ti,
457                             "Spanning-Tree Protocol Type: Bad length %u",
458                             length);
459                         proto_tree_add_text(tree, NullTVB, offset, length,
460                             "Spanning-Tree Protocol Type: Bad length %u",
461                             length);
462                 }
463                 break;
464
465         case PARENT_VLAN:
466                 if (length == 2) {
467                         proto_item_set_text(ti,
468                             "Parent VLAN: 0x%04x",
469                             pntohs(&pd[offset]));
470                         proto_tree_add_text(tree, NullTVB, offset, 2,
471                             "Parent VLAN: 0x%04x",
472                             pntohs(&pd[offset]));
473                 } else {
474                         proto_item_set_text(ti,
475                             "Parent VLAN: Bad length %u",
476                             length);
477                         proto_tree_add_text(tree, NullTVB, offset, length,
478                             "Parent VLAN: Bad length %u",
479                             length);
480                 }
481                 break;
482
483         case TR_BRIDGED_VLANS:
484                 if (length == 2) {
485                         proto_item_set_text(ti,
486                             "Translationally Bridged VLANs: 0x%04x",
487                             pntohs(&pd[offset]));
488                         proto_tree_add_text(tree, NullTVB, offset, 2,
489                             "Translationally Bridged VLANs: 0x%04x",
490                             pntohs(&pd[offset]));
491                 } else {
492                         proto_item_set_text(ti,
493                             "Translationally Bridged VLANs: Bad length %u",
494                             length);
495                         proto_tree_add_text(tree, NullTVB, offset, length,
496                             "Translationally Bridged VLANs: Bad length %u",
497                             length);
498                 }
499                 break;
500
501         case PRUNING:
502                 if (length == 2) {
503                         proto_item_set_text(ti,
504                             "Pruning: %s",
505                             val_to_str(pntohs(&pd[offset]), pruning_vals,
506                               "Unknown (0x%04x)"));
507                         proto_tree_add_text(tree, NullTVB, offset, 2,
508                             "Pruning: %s",
509                             val_to_str(pntohs(&pd[offset]), pruning_vals,
510                               "Unknown (0x%04x)"));
511                 } else {
512                         proto_item_set_text(ti,
513                             "Pruning: Bad length %u",
514                             length);
515                         proto_tree_add_text(tree, NullTVB, offset, length,
516                             "Pruning: Bad length %u",
517                             length);
518                 }
519                 break;
520
521         case BRIDGE_TYPE:
522                 if (length == 2) {
523                         proto_item_set_text(ti,
524                             "Bridge Type: %s",
525                             val_to_str(pntohs(&pd[offset]), bridge_type_vals,
526                               "Unknown (0x%04x)"));
527                         proto_tree_add_text(tree, NullTVB, offset, 2,
528                             "Bridge Type: %s",
529                             val_to_str(pntohs(&pd[offset]), bridge_type_vals,
530                               "Unknown (0x%04x)"));
531                 } else {
532                         proto_item_set_text(ti,
533                             "Bridge Type: Bad length %u",
534                             length);
535                         proto_tree_add_text(tree, NullTVB, offset, length,
536                             "Bridge Type: Bad length %u",
537                             length);
538                 }
539                 break;
540
541         case MAX_ARE_HOP_CNT:
542                 if (length == 2) {
543                         proto_item_set_text(ti,
544                             "Max ARE Hop Count: %u",
545                             pntohs(&pd[offset]));
546                         proto_tree_add_text(tree, NullTVB, offset, 2,
547                             "Max ARE Hop Count: %u",
548                             pntohs(&pd[offset]));
549                 } else {
550                         proto_item_set_text(ti,
551                             "Max ARE Hop Count: Bad length %u",
552                             length);
553                         proto_tree_add_text(tree, NullTVB, offset, length,
554                             "Max ARE Hop Count: Bad length %u",
555                             length);
556                 }
557                 break;
558
559         case MAX_STE_HOP_CNT:
560                 if (length == 2) {
561                         proto_item_set_text(ti,
562                             "Max STE Hop Count: %u",
563                             pntohs(&pd[offset]));
564                         proto_tree_add_text(tree, NullTVB, offset, 2,
565                             "Max STE Hop Count: %u",
566                             pntohs(&pd[offset]));
567                 } else {
568                         proto_item_set_text(ti,
569                             "Max STE Hop Count: Bad length %u",
570                             length);
571                         proto_tree_add_text(tree, NullTVB, offset, length,
572                             "Max STE Hop Count: Bad length %u",
573                             length);
574                 }
575                 break;
576
577         case BACKUP_CRF_MODE:
578                 if (length == 2) {
579                         proto_item_set_text(ti,
580                             "Backup CRF Mode: %s",
581                             val_to_str(pntohs(&pd[offset]), backup_crf_mode_vals,
582                               "Unknown (0x%04x)"));
583                         proto_tree_add_text(tree, NullTVB, offset, 2,
584                             "Backup CRF Mode: %s",
585                             val_to_str(pntohs(&pd[offset]), backup_crf_mode_vals,
586                               "Unknown (0x%04x)"));
587                 } else {
588                         proto_item_set_text(ti,
589                             "Backup CRF Mode: Bad length %u",
590                             length);
591                         proto_tree_add_text(tree, NullTVB, offset, length,
592                             "Backup CRF Mode: Bad length %u",
593                             length);
594                 }
595                 break;
596
597         default:
598                 proto_item_set_text(ti, "Unknown TLV type: 0x%02x", type);
599                 proto_tree_add_text(tree, NullTVB, offset, length, "Data");
600                 break;
601         }
602 }
603
604 void
605 proto_register_vtp(void)
606 {
607         static hf_register_info hf[] = {
608                 { &hf_vtp_version,
609                 { "Version",    "vtp.version", FT_UINT8, BASE_HEX, NULL, 0x0,
610                         "" }},
611
612                 { &hf_vtp_code,
613                 { "Code",       "vtp.code", FT_UINT8, BASE_HEX, VALS(type_vals), 0x0,
614                         "" }},
615
616                 { &hf_vtp_followers,
617                 { "Followers",  "vtp.followers", FT_UINT8, BASE_DEC, NULL, 0x0,
618                         "Number of following Subset-Advert messages" }},
619
620                 { &hf_vtp_md_len,
621                 { "Management Domain Length", "vtp.md_len", FT_UINT8, BASE_DEC, NULL, 0x0,
622                         "Length of management domain string" }},
623
624                 { &hf_vtp_md,
625                 { "Management Domain", "vtp.md", FT_STRING, BASE_DEC, NULL, 0,
626                         "Management domain" }},
627
628                 { &hf_vtp_conf_rev_num,
629                 { "Configuration Revision Number", "vtp.conf_rev_num", FT_UINT32, BASE_DEC, NULL, 0x0,
630                         "Revision number of the configuration information" }},
631
632                 { &hf_vtp_upd_id,
633                 { "Updater Identity", "vtp.upd_id", FT_IPv4, BASE_NONE, NULL, 0x0,
634                         "IP address of the updater" }},
635
636                 { &hf_vtp_upd_ts,
637                 { "Update Timestamp", "vtp.upd_ts", FT_STRING, BASE_DEC, NULL, 0,
638                         "Time stamp of the current configuration revision" }},
639
640                 { &hf_vtp_md5_digest,
641                 { "MD5 Digest", "vtp.md5_digest", FT_BYTES, BASE_HEX, NULL, 0x0,
642                         "" }},
643
644                 { &hf_vtp_seq_num,
645                 { "Sequence Number",    "vtp.seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
646                         "Order of this frame in the sequence of Subset-Advert frames" }},
647
648                 { &hf_vtp_start_value,
649                 { "Start Value",        "vtp.start_value", FT_UINT16, BASE_HEX, NULL, 0x0,
650                         "Virtual LAN ID of first VLAN for which information is requested" }},
651
652                 { &hf_vtp_vlan_info_len,
653                 { "VLAN Information Length",    "vtp.vlan_info.len", FT_UINT8, BASE_DEC, NULL, 0x0,
654                         "Length of the VLAN information field" }},
655
656                 { &hf_vtp_vlan_status_vlan_susp,
657                 { "VLAN suspended",     "vtp.vlan_info.status.vlan_susp", FT_BOOLEAN, 8, NULL, VLAN_SUSPENDED,
658                         "VLAN suspended" }},
659
660                 { &hf_vtp_vlan_type,
661                 { "VLAN Type",  "vtp.vlan_info.vlan_type", FT_UINT8, BASE_HEX, VALS(vlan_type_vals), 0x0,
662                         "Type of VLAN" }},
663
664                 { &hf_vtp_vlan_name_len,
665                 { "VLAN Name Length", "vtp.vlan_info.vlan_name_len", FT_UINT8, BASE_DEC, NULL, 0x0,
666                         "Length of VLAN name string" }},
667
668                 { &hf_vtp_isl_vlan_id,
669                 { "ISL VLAN ID",        "vtp.vlan_info.isl_vlan_id", FT_UINT16, BASE_HEX, NULL, 0x0,
670                         "ID of this VLAN on ISL trunks" }},
671
672                 { &hf_vtp_mtu_size,
673                 { "MTU Size",   "vtp.vlan_info.mtu_size", FT_UINT16, BASE_DEC, NULL, 0x0,
674                         "MTU for this VLAN" }},
675
676                 { &hf_vtp_802_10_index,
677                 { "802.10 Index", "vtp.vlan_info.802_10_index", FT_UINT32, BASE_HEX, NULL, 0x0,
678                         "IEEE 802.10 security association identifier for this VLAN" }},
679
680                 { &hf_vtp_vlan_name,
681                 { "VLAN Name", "vtp.vlan_info.vlan_name", FT_STRING, BASE_DEC, NULL, 0,
682                         "VLAN name" }},
683
684                 { &hf_vtp_vlan_tlvtype,
685                 { "Type",       "vtp.vlan_info.tlv_type", FT_UINT8, BASE_HEX, VALS(vlan_tlv_type_vals), 0x0,
686                         "" }},
687
688                 { &hf_vtp_vlan_tlvlength,
689                 { "Length",     "vtp.vlan_info.tlv_len", FT_UINT8, BASE_DEC, NULL, 0x0,
690                         "" }},
691         };
692         static gint *ett[] = {
693                 &ett_vtp,
694                 &ett_vtp_vlan_info,
695                 &ett_vtp_vlan_status,
696                 &ett_vtp_tlv,
697         };
698
699         proto_vtp = proto_register_protocol("Virtual Trunking Protocol", "vtp");
700         proto_register_field_array(proto_vtp, hf, array_length(hf));
701         proto_register_subtree_array(ett, array_length(ett));
702 }