The function pointer in a "per_choice_t" or a "per_sequence_t" is to a
[obnox/wireshark/wip.git] / packet-tzsp.c
1 /* packet-tzsp.c
2  *
3  * $Id: packet-tzsp.c,v 1.6 2004/01/29 10:58:28 guy Exp $
4  *
5  * Copyright 2002, Tazmen Technologies Inc
6  *
7  * Tazmen Sniffer Protocol for encapsulating the packets across a network
8  * from a remote packet sniffer. TZSP can encapsulate any other protocol.
9  *
10  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #include <glib.h>
38
39 #include <epan/packet.h>
40
41 #define UDP_PORT_TZSP   0x9090
42
43 static int proto_tzsp = -1;
44 static int hf_tzsp_version = -1;
45 static int hf_tzsp_type = -1;
46 static int hf_tzsp_encap = -1;
47
48 static const value_string tzsp_type[] = {
49         {0,     "Received tag list"},
50         {1,     "Packet for transmit"},
51         {2,     "Reserved"},
52         {3,     "Configuration"},
53         {4,     "Keepalive"},
54         {5,     "Port opener"},
55         {0,     NULL}
56 };
57
58 static gint ett_tzsp = -1;
59
60 static dissector_handle_t data_handle;
61 static dissector_table_t encap_dissector_table;
62
63 /* ************************************************************************* */
64 /*                WLAN radio header felds                                    */
65 /* ************************************************************************* */
66
67 static int hf_status_field = -1;
68 static int hf_status_msg_type = -1;
69 static int hf_status_pcf = -1;
70 static int hf_status_mac_port = -1;
71 static int hf_status_undecrypted = -1;
72 static int hf_status_fcs_error = -1;
73
74 static int hf_time = -1;
75 static int hf_silence = -1;
76 static int hf_signal = -1;
77 static int hf_rate = -1;
78 static int hf_channel = -1;
79 static int hf_unknown = -1;
80 static int hf_original_length = -1;
81 static int hf_sensormac = -1;
82
83 /* ************************************************************************* */
84 /*                        Encapsulation type values                          */
85 /*               Note that these are not all the same as DLT_ values         */
86 /* ************************************************************************* */
87
88 #define TZSP_ENCAP_ETHERNET                     1
89 #define TZSP_ENCAP_IEEE_802_11                  18
90 #define TZSP_ENCAP_PRISM_HEADER                 119
91 #define TZSP_ENCAP_WLAN_AVS                     127
92
93 /* ************************************************************************* */
94 /*                          Generic header options                           */
95 /* ************************************************************************* */
96
97 #define TZSP_HDR_PAD 0 /* Pad. */
98 #define TZSP_HDR_END 1 /* End of the list. */
99 #define TZSP_HDR_ORIGINAL_LENGTH 41 /* Length of the packet before slicing. 2 bytes. */
100 #define TZSP_HDR_SENSOR 60 /* Sensor MAC address packet was received on, 6 byte ethernet address.*/
101
102 /* ************************************************************************* */
103 /*                          Options for 802.11 radios                        */
104 /* ************************************************************************* */
105
106 #define WLAN_RADIO_HDR_SIGNAL 10 /* Signal strength in dBm, signed byte. */
107 #define WLAN_RADIO_HDR_NOISE 11 /* Noise level in dBm, signed byte. */
108 #define WLAN_RADIO_HDR_RATE 12 /* Data rate, unsigned byte. */
109 #define WLAN_RADIO_HDR_TIMESTAMP 13 /* Timestamp in us, unsigned 32-bits network byte order. */
110 #define WLAN_RADIO_HDR_MSG_TYPE 14 /* Packet type, unsigned byte. */
111 #define WLAN_RADIO_HDR_CF 15 /* Whether packet arrived during CF period, unsigned byte. */
112 #define WLAN_RADIO_HDR_UN_DECR 16 /* Whether packet could not be decrypted by MAC, unsigned byte. */
113 #define WLAN_RADIO_HDR_FCS_ERR 17 /* Whether packet contains an FCS error, unsigned byte. */
114 #define WLAN_RADIO_HDR_CHANNEL 18 /* Channel number packet was received on, unsigned byte.*/
115
116 /* ************************************************************************* */
117 /*                Add option information to the display                      */
118 /* ************************************************************************* */
119
120 static int 
121 add_option_info(tvbuff_t *tvb, int pos, proto_tree *tree, proto_item *ti)
122 {
123         guint8 tag, length, fcs_err = 0, encr = 0, seen_fcs_err = 0;
124         
125         /*
126          * Read all option tags in an endless loop. If the packet is malformed this
127          * loop might be a problem.
128          */
129         while (TRUE) {
130                 tag = tvb_get_guint8(tvb, pos++);
131
132                 switch (tag) {
133                 case TZSP_HDR_PAD:
134                         length = 0;
135                         break;
136
137                 case TZSP_HDR_END:
138                         /* Fill in header with information from other tags. */
139                         if (seen_fcs_err) {
140                                 if (tree)
141                                         proto_item_append_text(ti,"%s", fcs_err?"FCS Error":(encr?"Encrypted":"Good"));
142                         }
143                         return pos;
144
145                 case TZSP_HDR_ORIGINAL_LENGTH:
146                         length = tvb_get_guint8(tvb, pos++);
147                         if (tree)
148                                 proto_tree_add_int (tree, hf_original_length, tvb, pos-2, 4,
149                                                 tvb_get_ntohs(tvb, pos));
150                         pos += length;
151                         break;
152
153                 case WLAN_RADIO_HDR_SIGNAL:
154                         length = tvb_get_guint8(tvb, pos++);
155                         if (tree)
156                                 proto_tree_add_int (tree, hf_signal, tvb, pos-2, 3,
157                                                 tvb_get_ntohs(tvb, pos));
158                         pos += length;
159                         break;
160
161                 case WLAN_RADIO_HDR_NOISE:
162                         length = tvb_get_guint8(tvb, pos++);
163                         if (tree)
164                                 proto_tree_add_int (tree, hf_silence, tvb, pos-2, 3,
165                                                 tvb_get_ntohs(tvb, pos));
166                         pos += length;
167                         break;
168
169                 case WLAN_RADIO_HDR_RATE:
170                         length = tvb_get_guint8(tvb, pos++);
171                         if (tree)
172                                 proto_tree_add_uint (tree, hf_rate, tvb, pos-2, 3,
173                                                         tvb_get_guint8(tvb, pos));
174                         pos += length;
175                         break;
176
177                 case WLAN_RADIO_HDR_TIMESTAMP:
178                         length = tvb_get_guint8(tvb, pos++);
179                         if (tree)
180                                 proto_tree_add_uint (tree, hf_time, tvb, pos-2, 6,
181                                                         tvb_get_ntohl(tvb, pos));
182                         pos += length;
183                         break;
184
185                 case WLAN_RADIO_HDR_MSG_TYPE:
186                         length = tvb_get_guint8(tvb, pos++);
187                         if (tree)
188                                 proto_tree_add_uint (tree, hf_status_msg_type, tvb, pos-2, 3,
189                                                 tvb_get_guint8(tvb, pos));
190                         pos += length;
191                         break;
192
193                 case WLAN_RADIO_HDR_CF:
194                         length = tvb_get_guint8(tvb, pos++);
195                         if (tree)
196                                 proto_tree_add_boolean (tree, hf_status_pcf, tvb, pos-2, 3,
197                                                 tvb_get_guint8(tvb, pos));
198                         pos += length;
199                         break;
200
201                 case WLAN_RADIO_HDR_UN_DECR:
202                         length = tvb_get_guint8(tvb, pos++);
203                         if (tree)
204                                 proto_tree_add_boolean (tree, hf_status_undecrypted, tvb, pos-2, 3,
205                                                 tvb_get_guint8(tvb, pos));
206                         encr = tvb_get_guint8(tvb, pos);
207                         pos += length;
208                         break;
209
210                 case WLAN_RADIO_HDR_FCS_ERR:
211                         seen_fcs_err = 1;
212                         length = tvb_get_guint8(tvb, pos++);
213                         if (tree)
214                                 proto_tree_add_boolean (tree, hf_status_fcs_error, tvb, pos-2, 3,
215                                                 tvb_get_guint8(tvb, pos));
216                         fcs_err = tvb_get_guint8(tvb, pos);
217                         pos += length;
218                         break;
219
220                 case WLAN_RADIO_HDR_CHANNEL:
221                         length = tvb_get_guint8(tvb, pos++);
222                         if (tree)
223                                 proto_tree_add_uint (tree, hf_channel, tvb, pos-2, 3,
224                                                         tvb_get_guint8(tvb, pos));
225                         pos += length;
226                         break;
227
228                 case TZSP_HDR_SENSOR:
229                         length = tvb_get_guint8(tvb, pos++);
230                         if (tree)
231                                 proto_tree_add_ether(tree, hf_sensormac, tvb, pos-2, 6,
232                                                         tvb_get_ptr (tvb, pos, 6));
233                         pos += length;
234                         break;
235
236                 default:
237                         length = tvb_get_guint8(tvb, pos++);
238                         if (tree)
239                                 proto_tree_add_bytes(tree, hf_unknown, tvb, pos-2, length+2,
240                                                         tvb_get_ptr(tvb, pos, length));
241                         pos += length;
242                         break;
243                 }
244         }
245 }
246
247 /* ************************************************************************* */
248 /*        Map TZSP encapsulation types to Wiretap encapsulation types        */
249 /* ************************************************************************* */
250 struct encap_map {
251         guint16 tzsp_encap;
252         int     wtap_encap;
253 };
254
255 static const struct encap_map map_table[] = {
256         { TZSP_ENCAP_ETHERNET,          WTAP_ENCAP_ETHERNET },
257         { TZSP_ENCAP_PRISM_HEADER,      WTAP_ENCAP_PRISM_HEADER },
258         { TZSP_ENCAP_WLAN_AVS,          WTAP_ENCAP_IEEE_802_11_WLAN_AVS },
259         { TZSP_ENCAP_IEEE_802_11,       WTAP_ENCAP_IEEE_802_11 },
260         { 0,                            -1 }
261 };
262
263 static int
264 tzsp_encap_to_wtap_encap(guint16 encap)
265 {
266         int i;
267
268         for (i = 0; map_table[i].wtap_encap != -1; i++) {
269                 if (map_table[i].tzsp_encap == encap)
270                         return map_table[i].wtap_encap;
271         }
272         return -1;
273 }
274
275 /* ************************************************************************* */
276 /*                Dissect a TZSP packet                                      */
277 /* ************************************************************************* */
278
279 static void
280 dissect_tzsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
281 {
282         proto_tree *tzsp_tree = NULL;
283         proto_item *ti = NULL;
284         int pos = 0;
285         tvbuff_t *next_tvb;
286         guint16 encapsulation = 0;
287         int wtap_encap;
288         dissector_handle_t encap_dissector;
289         char *encap_name, *info;
290         guint8 type;
291
292         if (check_col(pinfo->cinfo, COL_PROTOCOL))
293                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TZSP");
294         if (check_col(pinfo->cinfo, COL_INFO))
295                 col_clear(pinfo->cinfo, COL_INFO);
296
297         type = tvb_get_guint8(tvb, 1);
298
299         /* Find the dissector. */
300         encapsulation = tvb_get_ntohs(tvb, 2);
301         if (encapsulation != 0) {
302                 wtap_encap = tzsp_encap_to_wtap_encap(encapsulation);
303                 if (wtap_encap != -1 &&
304                     (encap_dissector = dissector_get_port_handle(encap_dissector_table, wtap_encap))) {
305                         encap_name = dissector_handle_get_short_name(encap_dissector);
306                 }
307                 else {
308                         encap_name = "Unknown";
309                 }
310                 info = encap_name;
311         }
312         else {
313                 wtap_encap = -1;
314                 encap_name = "Nothing";
315                 info = tzsp_type[type].strptr;
316         }
317
318         if (check_col(pinfo->cinfo, COL_INFO))
319                 col_set_str(pinfo->cinfo, COL_INFO, info);
320
321         if (tree) {
322                 /* Adding TZSP item and subtree */
323                 ti = proto_tree_add_protocol_format(tree, proto_tzsp, tvb, 0,
324                     -1, "TZSP: %s: ", info);
325                 tzsp_tree = proto_item_add_subtree(ti, ett_tzsp);
326
327                 proto_tree_add_item (tzsp_tree, hf_tzsp_version, tvb, 0, 1,
328                                         FALSE);
329                 proto_tree_add_uint (tzsp_tree, hf_tzsp_type, tvb, 1, 1,
330                                         type);
331                 proto_tree_add_uint_format (tzsp_tree, hf_tzsp_encap, tvb, 2, 2,
332                                         encapsulation, "Encapsulates: %s (%d)",
333                                         encap_name, encapsulation);
334         }
335
336         if (type != 4 && type != 5) {
337                 pos = add_option_info(tvb, 4, tzsp_tree, ti);
338
339                 if (tree)
340                         proto_item_set_end(ti, tvb, pos);
341                 next_tvb = tvb_new_subset(tvb, pos, -1, -1);
342                 if (encapsulation != 0
343                     && (wtap_encap == -1
344                         || !dissector_try_port(encap_dissector_table, wtap_encap,
345                                 next_tvb, pinfo, tree))) {
346
347                         if (check_col(pinfo->cinfo, COL_PROTOCOL))
348                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
349                         if (check_col(pinfo->cinfo, COL_INFO))
350                                 col_add_fstr(pinfo->cinfo, COL_INFO, "TZSP_ENCAP = %u",
351                                     encapsulation);
352                         call_dissector(data_handle, next_tvb, pinfo, tree);
353                 }
354         }
355 }
356
357 /* ************************************************************************* */
358 /*                Register the TZSP dissector                                */
359 /* ************************************************************************* */
360
361 void
362 proto_register_tzsp(void)
363 {
364         static const value_string msg_type[] = {
365                 {0,     "Normal"},
366                 {1,     "RFC1042 encoded"},
367                 {2,     "Bridge-tunnel encoded"},
368                 {4,     "802.11 management frame"},
369                 {0,     NULL}
370         };
371
372         static const true_false_string pcf_flag = {
373                 "CF: Frame received during CF period",
374                 "Not CF"
375         };
376
377         static const true_false_string undecr_flag = {
378                 "Encrypted frame could not be decrypted",
379                 "Unencrypted"
380         };
381
382         static const true_false_string fcs_err_flag = {
383                 "FCS error, frame is corrupted",
384                 "Frame is valid"
385         };
386
387         static const value_string channels[] = {
388                 /* 802.11b/g */
389                 {1, "1 (2.412 GHz)"},
390                 {2, "2 (2.417 GHz)"},
391                 {3, "3 (2.422 GHz)"},
392                 {4, "4 (2.427 GHz)"},
393                 {5, "5 (2.432 GHz)"},
394                 {6, "6 (2.437 GHz)"},
395                 {7, "7 (2.442 GHz)"},
396                 {8, "8 (2.447 GHz)"},
397                 {9, "9 (2.452 GHz)"},
398                 {10, "10 (2.457 GHz)"},
399                 {11, "11 (2.462 GHz)"},
400                 {12, "12 (2.467 GHz)"},
401                 {13, "13 (2.472 GHz)"},
402                 {14, "14 (2.484 GHz)"},
403                 /* 802.11a */
404                 {36, "36 (5.180 GHz)"},
405                 {40, "40 (5.200 GHz)"},
406                 {44, "44 (5.220 GHz)"},
407                 {48, "48 (5.240 GHz)"},
408                 {52, "52 (5.260 GHz)"},
409                 {56, "56 (5.280 GHz)"},
410                 {60, "60 (5.300 GHz)"},
411                 {64, "64 (5.320 GHz)"},
412                 {149, "149 (5.745 GHz)"},
413                 {153, "153 (5.765 GHz)"},
414                 {157, "157 (5.785 GHz)"},
415                 {161, "161 (5.805 GHz)"},
416                 {0, NULL}
417         };
418
419         static const value_string rates[] = {
420                 /* Old PRISM rates */
421                 {0x0A, "1 Mbit/s"},
422                 {0x14, "2 Mbit/s"},
423                 {0x37, "5.5 Mbit/s"},
424                 {0x6E, "11 Mbit/s"},
425                 /* MicroAP rates */
426                 {2, "1 Mbit/s"},
427                 {4, "2 Mbit/s"},
428                 {11, "5.5 Mbit/s"},
429                 {12, "6 Mbit/s"},
430                 {18, "9 Mbit/s"},
431                 {22, "11 Mbit/s"},
432                 {24, "12 Mbit/s"},
433                 {36, "18 Mbit/s"},
434                 {48, "24 Mbit/s"},
435                 {72, "36 Mbit/s"},
436                 {96, "48 Mbit/s"},
437                 {108, "54 Mbit/s"},
438                 {0, NULL}
439         };
440
441         static hf_register_info hf[] = {
442                 { &hf_tzsp_version, {
443                         "Version", "tzsp.version", FT_UINT8, BASE_DEC,
444                         NULL, 0, "Version", HFILL }},
445                 { &hf_tzsp_type, {
446                         "Type", "tzsp.type", FT_UINT8, BASE_DEC,
447                         VALS(tzsp_type), 0, "Type", HFILL }},
448                 { &hf_tzsp_encap, {
449                         "Encapsulation", "tzsp.encap", FT_UINT16, BASE_DEC,
450                         NULL, 0, "Encapsulation", HFILL }},
451                 { &hf_status_field, {
452                         "Status", "tzsp.wlan.status", FT_UINT16, BASE_HEX,
453                                 NULL, 0, "Status", HFILL }},
454                 { &hf_status_msg_type, {
455                         "Type", "tzsp.wlan.status.msg_type", FT_UINT8, BASE_HEX,
456                         VALS(msg_type), 0, "Message type", HFILL }},
457                 { &hf_status_mac_port, {
458                         "Port", "tzsp.wlan.status.mac_port", FT_UINT8, BASE_DEC,
459                         NULL, 0, "MAC port", HFILL }},
460                 { &hf_status_pcf, {
461                         "PCF", "tzsp.wlan.status.pcf", FT_BOOLEAN, BASE_HEX,
462                         TFS (&pcf_flag), 0, "Point Coordination Function", HFILL }},
463                 { &hf_status_undecrypted, {
464                         "Undecrypted", "tzsp.wlan.status.undecrypted", FT_BOOLEAN, BASE_HEX,
465                         TFS (&undecr_flag), 0, "Undecrypted", HFILL }},
466                 { &hf_status_fcs_error, {
467                         "FCS", "tzsp.wlan.status.fcs_err", FT_BOOLEAN, BASE_HEX,
468                         TFS (&fcs_err_flag), 0, "Frame check sequence", HFILL }},
469                 { &hf_time, {
470                         "Time", "tzsp.wlan.time", FT_UINT32, BASE_HEX,
471                         NULL, 0, "Time", HFILL }},
472                 { &hf_silence, {
473                         "Silence", "tzsp.wlan.silence", FT_INT8, BASE_HEX,
474                         NULL, 0, "Silence", HFILL }},
475                 { &hf_original_length, {
476                         "Original Length", "tzsp.original_length", FT_INT16, BASE_DEC,
477                         NULL, 0, "OrigLength", HFILL }},
478                 { &hf_signal, {
479                         "Signal", "tzsp.wlan.signal", FT_INT8, BASE_HEX,
480                         NULL, 0, "Signal", HFILL }},
481                 { &hf_rate, {
482                         "Rate", "tzsp.wlan.rate", FT_UINT8, BASE_HEX,
483                         VALS(rates), 0, "Rate", HFILL }},
484                 { &hf_channel, {
485                         "Channel", "tzsp.wlan.channel", FT_UINT8, BASE_DEC,
486                         VALS(channels), 0, "Channel", HFILL }},
487                 { &hf_unknown, {
488                         "Unknown tag", "tzsp.unknown", FT_BYTES, BASE_HEX,
489                         NULL, 0, "Unknown", HFILL }},
490                 { &hf_sensormac, {
491                         "Sensor Address", "tzsp.sensormac", FT_ETHER, BASE_HEX,
492                         NULL, 0, "Sensor MAC", HFILL }}
493         };
494
495         static gint *ett[] = {
496                 &ett_tzsp
497         };
498
499         proto_tzsp = proto_register_protocol("Tazmen Sniffer Protocol", "TZSP",
500             "tzsp");
501         proto_register_field_array(proto_tzsp, hf, array_length(hf));
502         proto_register_subtree_array(ett, array_length(ett));
503
504 }
505
506 void
507 proto_reg_handoff_tzsp(void)
508 {
509         dissector_handle_t tzsp_handle;
510
511         tzsp_handle = create_dissector_handle(dissect_tzsp, proto_tzsp);
512         dissector_add("udp.port", UDP_PORT_TZSP, tzsp_handle);
513
514         /* Get the data dissector for handling unknown encapsulation types. */
515         data_handle = find_dissector("data");
516
517         /* Register this protocol as an ecapsulation type. */
518         dissector_add("wtap_encap", WTAP_ENCAP_TZSP, tzsp_handle);
519
520         encap_dissector_table = find_dissector_table("wtap_encap");
521 }