Removed two cases where protocol decoding assumed that the data in the
[obnox/wireshark/wip.git] / packet-trmac.c
1 /* packet-trmac.c
2  * Routines for Token-Ring Media Access Control
3  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4  *
5  * $Id: packet-trmac.c,v 1.14 1999/09/09 04:47:17 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <glib.h>
36 #include "packet.h"
37
38 static int proto_trmac = -1;
39
40 /* Major Vector */
41 static value_string major_vectors[] = {
42                 { 0x00, "Response" },
43                 { 0x02, "Beacon" },
44                 { 0x03, "Claim Token" },
45                 { 0x04, "Ring Purge" },
46                 { 0x05, "Active Monitor Present" },
47                 { 0x06, "Standby Monitor Present" },
48                 { 0x07, "Duplicate Address Test" },
49                 { 0x09, "Transmit Forward" },
50                 { 0x0B, "Remove Ring Station" },
51                 { 0x0C, "Change Parameters" },
52                 { 0x0D, "Initialize Ring Station" },
53                 { 0x0E, "Request Ring Station Address" },
54                 { 0x0F, "Request Ring Station Address" },
55                 { 0x10, "Request Ring Station Attachments" },
56                 { 0x20, "Request Initialization" },
57                 { 0x22, "Report Ring Station Address" },
58                 { 0x23, "Report Ring Station State" },
59                 { 0x24, "Report Ring Station Attachments" },
60                 { 0x25, "Report New Active Monitor" },
61                 { 0x26, "Report NAUN Change" },
62                 { 0x27, "Report Poll Error" },
63                 { 0x28, "Report Monitor Errors" },
64                 { 0x29, "Report Error" },
65                 { 0x2A, "Report Transmit Forward" },
66                 { 0x00, NULL }
67 };
68
69
70 /* Sub-vectors */
71 static int
72 sv_text(const u_char *pd, int pkt_offset, proto_tree *tree)
73 {
74         int     sv_length = pd[0];
75         guint16 beacon_type;
76
77         char *beacon[] = {"Recovery mode set", "Signal loss error",
78                 "Streaming signal not Claim Token MAC frame",
79                 "Streaming signal, Claim Token MAC frame"};
80
81         proto_tree      *sv_tree;
82         proto_item      *ti;
83
84         u_char          errors[6];      /* isolating or non-isolating */
85
86         /* this just adds to the clutter on the screen...
87         proto_tree_add_text(tree, pkt_offset, 1,
88                 "Subvector Length: %d bytes", sv_length);*/
89
90         switch(pd[1]) {
91                 case 0x01: /* Beacon Type */
92                         beacon_type = pntohs(&pd[2]);
93                         if (beacon_type < array_length(beacon)) {
94                                 proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
95                                         "Beacon Type: %s", beacon[beacon_type] );
96                         } else {
97                                 proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
98                                         "Beacon Type: Illegal value: %d", beacon_type );
99                         }
100                         break;
101
102                 case 0x02: /* NAUN */
103                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
104                                 "NAUN: %s", ether_to_str((guint8*)&pd[2]));
105                         break;
106
107                 case 0x03: /* Local Ring Number */
108                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
109                                 "Local Ring Number: 0x%04X (%d)",
110                                 pntohs( &pd[2] ), pntohs( &pd[2] ));
111                         break;
112
113                 case 0x04: /* Assign Physical Location */
114                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
115                                 "Assign Physical Location: 0x%08X", pntohl( &pd[2] ) );
116                         break;
117
118                 case 0x05: /* Soft Error Report Value */
119                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
120                                 "Soft Error Report Value: %d ms", 10 * pntohs( &pd[2] ) );
121                         break;
122
123                 case 0x06: /* Enabled Function Classes */
124                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
125                                 "Enabled Function Classes: %04X",  pntohs( &pd[2] ) );
126                         break;
127
128                 case 0x07: /* Allowed Access Priority */
129                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
130                                 "Allowed Access Priority: %04X",  pntohs( &pd[2] ) );
131                         break;
132
133                 case 0x09: /* Correlator */
134                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
135                                 "Correlator: %04X",  pntohs( &pd[2] ) );
136                         break;
137
138                 case 0x0A: /* Address of last neighbor notification */
139                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
140                                 "Address of Last Neighbor Notification: %s",
141                                 ether_to_str((guint8*)&pd[2]));
142                         break;
143
144                 case 0x0B: /* Physical Location */
145                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
146                                 "Physical Location: 0x%08X", pntohl( &pd[2] ) );
147                         break;
148
149                 case 0x20: /* Response Code */
150                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
151                                 "Response Code: 0x%04X 0x%04X", pntohl( &pd[2] ),
152                                 pntohl( &pd[4] ) );
153                         break;
154
155                 case 0x21: /* Reserved */
156                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
157                                 "Reserved: 0x%04X", pntohs( &pd[2] ) );
158                         break;
159
160                 case 0x22: /* Product Instance ID */
161                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
162                                 "Product Instance ID: ...");
163                         break;
164
165                 case 0x23: /* Ring Station Microcode Level */
166                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
167                                 "Ring Station Microcode Level: ...");
168                         break;
169
170                 case 0x26: /* Wrap data */
171                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
172                                 "Wrap Data: ... (%d bytes)", sv_length - 2);
173                         break;
174
175                 case 0x27: /* Frame Forward */
176                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
177                                 "Frame Forward: ... (%d bytes)", sv_length - 2);
178                         break;
179
180                 case 0x29: /* Ring Station Status Subvector */
181                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
182                                 "Ring Station Status Subvector: ...");
183                         break;
184
185                 case 0x2A: /* Transmit Status Code */
186                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
187                                 "Transmit Status Code: %04X", pntohs( &pd[2] ) );
188                         break;
189
190                 case 0x2B: /* Group Address */
191                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
192                                 "Group Address: %08X", pntohl( &pd[2] ) );
193                         break;
194
195                 case 0x2C: /* Functional Address */
196                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
197                                 "Functional Address: %08X", pntohl( &pd[2] ) );
198                         break;
199
200                 case 0x2D: /* Isolating Error Counts */
201                         memcpy(errors, &pd[2], 6);
202                         ti = proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
203                                 "Isolating Error Counts (%d total)",
204                                 errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
205                         sv_tree = proto_item_add_subtree(ti, ETT_TR_IERR_CNT);
206
207                         proto_tree_add_text(sv_tree, pkt_offset+2, 1,
208                                 "Line Errors: %d", errors[0]);
209                         proto_tree_add_text(sv_tree, pkt_offset+3, 1,
210                                 "Internal Errors: %d", errors[1]);
211                         proto_tree_add_text(sv_tree, pkt_offset+4, 1,
212                                 "Burst Errors: %d", errors[2]);
213                         proto_tree_add_text(sv_tree, pkt_offset+5, 1,
214                                 "A/C Errors: %d", errors[3]);
215                         proto_tree_add_text(sv_tree, pkt_offset+6, 1,
216                                 "Abort delimiter transmitted: %d", errors[4]);
217
218                         break;
219
220                 case 0x2E: /* Non-Isolating Error Counts */
221                         memcpy(errors, &pd[2], 6);
222                         ti = proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
223                                 "Non-Isolating Error Counts (%d total)",
224                                 errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
225                         sv_tree = proto_item_add_subtree(ti, ETT_TR_NERR_CNT);
226
227                         proto_tree_add_text(sv_tree, pkt_offset+2, 1,
228                                 "Lost Frame Errors: %d", errors[0]);
229                         proto_tree_add_text(sv_tree, pkt_offset+3, 1,
230                                 "Receiver Congestion: %d", errors[1]);
231                         proto_tree_add_text(sv_tree, pkt_offset+4, 1,
232                                 "Frame-Copied Congestion: %d", errors[2]);
233                         proto_tree_add_text(sv_tree, pkt_offset+5, 1,
234                                 "Frequency Errors: %d", errors[3]);
235                         proto_tree_add_text(sv_tree, pkt_offset+6, 1,
236                                 "Token Errors: %d", errors[4]);
237                         break;
238
239                 case 0x30: /* Error Code */
240                         proto_tree_add_text(tree, pkt_offset+1, sv_length-1,
241                                 "Error Code: %04X", pntohs( &pd[2] ) );
242                         break;
243
244                 default: /* Unknown */
245                         proto_tree_add_text(tree, pkt_offset+1, 1,
246                                 "Unknown Sub-Vector: 0x%02X", pd[1]);
247         }
248         return sv_length;
249 }
250
251 void
252 dissect_trmac(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
253
254         proto_tree      *mac_tree = NULL;
255         proto_item      *ti;
256         int                     mv_length, sv_length, sv_offset, sv_additional;
257         char            *class[] = { "Ring Station", "LLC Manager", "", "",
258                 "Configuration Report Server", "Ring Parameter Server",
259                 "Ring Error Monitor" };
260         char            *mv_text;
261
262         mv_length = pntohs(&pd[offset]);
263
264         /* Interpret the major vector */
265         mv_text = val_to_str(pd[offset+3], major_vectors, "Unknown Major Vector: %d\n");
266
267         /* Summary information */
268         if (check_col(fd, COL_PROTOCOL))
269                 col_add_str(fd, COL_PROTOCOL, "TR MAC");
270         if (check_col(fd, COL_INFO))
271                 col_add_str(fd, COL_INFO, mv_text);
272
273         if (tree) {
274
275                 ti = proto_tree_add_item(tree, proto_trmac, offset, mv_length, NULL);
276                 mac_tree = proto_item_add_subtree(ti, ETT_TR_MAC);
277
278                 if (mv_text)
279                         proto_tree_add_text(mac_tree, offset+3, 1, "Major Vector Command: %s",
280                                                         mv_text);
281                 else
282                         proto_tree_add_text(mac_tree, offset+3, 1, "Major Vector Command: %02X (Unknown)",
283                                                         pd[offset+3]);
284                 proto_tree_add_text(mac_tree, offset, 2, "Total Length: %d bytes",
285                         mv_length);
286                 proto_tree_add_text(mac_tree, offset+2, 1, "Source Class: %s",
287                         class[ pd[offset+2] & 0x0f ]);
288                 proto_tree_add_text(mac_tree, offset+2, 1, "Destination Class: %s",
289                         class[ pd[offset+2] >> 4 ]);
290
291                 /* interpret the subvectors */
292                 sv_offset = 0;
293                 offset += 4;
294                 sv_length = mv_length - 4;
295                 while (sv_offset < sv_length) {
296                         sv_additional = sv_text(&pd[offset + sv_offset], offset + sv_offset,
297                                                                 mac_tree);
298
299                         /* if this is a bad packet, we could get a 0-length added here,
300                          * looping forever */
301                         if (sv_additional)
302                                 sv_offset += sv_additional;
303                         else
304                                 break;
305                 }
306         }
307 }
308
309 void
310 proto_register_trmac(void)
311 {
312 /*        static hf_register_info hf[] = {
313                 { &variable,
314                 { "Name",           "trmac.abbreviation", TYPE, VALS_POINTER }},
315         };*/
316
317         proto_trmac = proto_register_protocol("Token-Ring Media Access Control", "trmac");
318  /*       proto_register_field_array(proto_trmac, hf, array_length(hf));*/
319 }