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