Boolean fields are just like other fields - if you use the field name
[obnox/wireshark/wip.git] / packet-rx.c
1 /* packet-rx.c
2  * Routines for RX packet dissection
3  * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
4  * Based on routines from tcpdump patches by
5  *   Ken Hornstein <kenh@cmf.nrl.navy.mil>
6  *
7  * $Id: packet-rx.c,v 1.18 2001/01/09 06:31:41 guy Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@zing.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-tftp.c
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif
43
44 #include <string.h>
45 #include <glib.h>
46 #include "packet.h"
47 #include "packet-rx.h"
48 #include "packet-afs.h"
49 #include "resolv.h"
50
51 #define UDP_PORT_RX_LOW         7000
52 #define UDP_PORT_RX_HIGH        7009
53 #define UDP_PORT_RX_AFS_BACKUPS 7021
54
55 static const value_string rx_types[] = {
56         { RX_PACKET_TYPE_DATA,          "data" },
57         { RX_PACKET_TYPE_ACK,           "ack" },
58         { RX_PACKET_TYPE_BUSY,          "busy" },
59         { RX_PACKET_TYPE_ABORT,         "abort" },
60         { RX_PACKET_TYPE_ACKALL,        "ackall" },
61         { RX_PACKET_TYPE_CHALLENGE,     "challenge" },
62         { RX_PACKET_TYPE_RESPONSE,      "response" },
63         { RX_PACKET_TYPE_DEBUG,         "debug" },
64         { RX_PACKET_TYPE_PARAMS,        "params" },
65         { RX_PACKET_TYPE_VERSION,       "version" },
66         { 0,                            NULL },
67 };
68
69 static const value_string rx_flags[] = {
70         { RX_CLIENT_INITIATED,  "client-init" },
71         { RX_REQUEST_ACK,       "req-ack" },
72         { RX_LAST_PACKET,       "last-pckt" },
73         { RX_MORE_PACKETS,      "more-pckts" },
74         { RX_FREE_PACKET,       "free-pckt" },
75         { 0,                    NULL }
76 };
77
78 static int proto_rx = -1;
79
80 static int hf_rx_epoch = -1;
81 static int hf_rx_cid = -1;
82 static int hf_rx_seq = -1;
83 static int hf_rx_serial = -1;
84 static int hf_rx_callnumber = -1;
85 static int hf_rx_type = -1;
86 static int hf_rx_flags = -1;
87 static int hf_rx_flags_clientinit = -1;
88 static int hf_rx_flags_request_ack = -1;
89 static int hf_rx_flags_last_packet = -1;
90 static int hf_rx_flags_more_packets = -1;
91 static int hf_rx_flags_free_packet = -1;
92 static int hf_rx_userstatus = -1;
93 static int hf_rx_securityindex = -1;
94 static int hf_rx_spare = -1;
95 static int hf_rx_serviceid = -1;
96
97 static gint ett_rx = -1;
98 static gint ett_rx_flags = -1;
99
100 static void
101 dissect_rx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
102 {
103         proto_tree      *rx_tree, *rx_tree_flags, *rx_flags, *ti;
104         struct rx_header *rxh;
105         int reply;
106
107         OLD_CHECK_DISPLAY_AS_DATA(proto_rx, pd, offset, fd, tree);
108
109         rxh = (struct rx_header *) &pd[offset];
110
111         /* get at least a full packet structure */
112         if ( !BYTES_ARE_IN_FRAME(offset, sizeof(struct rx_header)) )
113                 return;
114
115         if (check_col(fd, COL_PROTOCOL))
116                 col_set_str(fd, COL_PROTOCOL, "RX");
117
118
119         if (tree) {
120                 ti = proto_tree_add_protocol_format(tree, proto_rx, NullTVB, offset,
121                         sizeof(struct rx_header), "RX Protocol (%s)", 
122                         val_to_str(rxh->type,rx_types,"unknown (%d)"));
123                 rx_tree = proto_item_add_subtree(ti, ett_rx);
124
125                 proto_tree_add_uint(rx_tree, hf_rx_epoch, NullTVB,
126                         offset, 4, pntohl(&rxh->epoch));
127                 proto_tree_add_uint(rx_tree, hf_rx_cid, NullTVB,
128                         offset+4, 4, pntohl(&rxh->cid));
129                 proto_tree_add_uint(rx_tree, hf_rx_callnumber, NullTVB,
130                         offset+8, 4, pntohl(&rxh->callNumber));
131                 proto_tree_add_uint(rx_tree, hf_rx_seq, NullTVB,
132                         offset+12, 4, pntohl(&rxh->seq));
133                 proto_tree_add_uint(rx_tree, hf_rx_serial, NullTVB,
134                         offset+16, 4, pntohl(&rxh->serial));
135
136                 proto_tree_add_uint(rx_tree, hf_rx_type, NullTVB,
137                         offset+20, 1, rxh->type);
138
139                 rx_flags = proto_tree_add_uint(rx_tree, hf_rx_flags, NullTVB,
140                         offset+21, 1, rxh->flags);
141                 rx_tree_flags = proto_item_add_subtree(rx_flags, ett_rx_flags);
142                 proto_tree_add_uint(rx_tree_flags, hf_rx_flags_free_packet, NullTVB,
143                         offset+21, 1, rxh->flags);
144                 proto_tree_add_uint(rx_tree_flags, hf_rx_flags_more_packets, NullTVB,
145                         offset+21, 1, rxh->flags);
146                 proto_tree_add_uint(rx_tree_flags, hf_rx_flags_last_packet, NullTVB,
147                         offset+21, 1, rxh->flags);
148                 proto_tree_add_uint(rx_tree_flags, hf_rx_flags_request_ack, NullTVB,
149                         offset+21, 1, rxh->flags);
150                 proto_tree_add_uint(rx_tree_flags, hf_rx_flags_clientinit, NullTVB,
151                         offset+21, 1, rxh->flags);
152
153                 proto_tree_add_uint(rx_tree, hf_rx_userstatus, NullTVB,
154                         offset+22, 1, rxh->userStatus);
155                 proto_tree_add_uint(rx_tree, hf_rx_securityindex, NullTVB,
156                         offset+23, 1, rxh->securityIndex);
157                 proto_tree_add_uint(rx_tree, hf_rx_spare, NullTVB,
158                         offset+24, 2, pntohs(&rxh->spare));
159                 proto_tree_add_uint(rx_tree, hf_rx_serviceid, NullTVB,
160                         offset+26, 2, pntohs(&rxh->serviceId));
161         }
162
163         if (check_col(fd, COL_INFO))
164                 col_add_fstr(fd, COL_INFO,
165                         "Type: %s  "
166                         "Seq: %lu  "
167                         "Call: %lu  "
168                         "Source Port: %s  "
169                         "Destination Port: %s  ",
170                         val_to_str(rxh->type, rx_types, "%d"),
171                         (unsigned long)pntohl(&rxh->seq),
172                         (unsigned long)pntohl(&rxh->callNumber),
173                         get_udp_port(pi.srcport),
174                         get_udp_port(pi.destport)
175                 );
176
177         reply = (rxh->flags & RX_CLIENT_INITIATED) == 0;
178         if ( (rxh->type == RX_PACKET_TYPE_ABORT && reply) ||
179                 rxh->type == RX_PACKET_TYPE_DATA )
180         {
181                 dissect_afs(pd,offset,fd,tree);
182         }
183 }
184
185 void
186 proto_register_rx(void)
187 {
188         static hf_register_info hf[] = {
189                 { &hf_rx_epoch, {
190                         "Epoch", "rx.epoch", FT_UINT32, BASE_DEC,
191                         NULL, 0, "Epoch" }},
192                 { &hf_rx_cid, {
193                         "CID", "rx.cid", FT_UINT32, BASE_DEC,
194                         NULL, 0, "CID" }},
195                 { &hf_rx_callnumber, {
196                         "Call Number", "rx.callnumber", FT_UINT32, BASE_DEC,
197                         NULL, 0, "Call Number" }},
198                 { &hf_rx_seq, {
199                         "Sequence Number", "rx.seq", FT_UINT32, BASE_DEC,
200                         NULL, 0, "Sequence Number" }},
201                 { &hf_rx_serial, {
202                         "Serial", "rx.serial", FT_UINT32, BASE_DEC,
203                         NULL, 0, "Serial" }},
204                 { &hf_rx_type, {
205                         "Type", "rx.type", FT_UINT8, BASE_DEC,
206                         VALS(rx_types), 0, "Type" }},
207                 { &hf_rx_flags, {
208                         "Flags", "rx.flags", FT_UINT8, BASE_HEX,
209                         NULL, 0, "Flags" }},
210                 { &hf_rx_flags_clientinit, {
211                         "Client Initiated", "rx.flags.client_init", FT_UINT8, BASE_BIN,
212                         NULL, RX_CLIENT_INITIATED, "Client Initiated" }},
213                 { &hf_rx_flags_request_ack, {
214                         "Request Ack", "rx.flags.request_ack", FT_UINT8, BASE_BIN,
215                         NULL, RX_REQUEST_ACK, "Request Ack" }},
216                 { &hf_rx_flags_last_packet, {
217                         "Last Packet", "rx.flags.last_packet", FT_UINT8, BASE_BIN,
218                         NULL, RX_LAST_PACKET, "Last Packet" }},
219                 { &hf_rx_flags_more_packets, {
220                         "More Packets", "rx.flags.more_packets", FT_UINT8, BASE_BIN,
221                         NULL, RX_MORE_PACKETS, "More Packets" }},
222                 { &hf_rx_flags_free_packet, {
223                         "Free Packet", "rx.flags.free_packet", FT_UINT8, BASE_BIN,
224                         NULL, RX_FREE_PACKET, "Free Packet" }},
225                 { &hf_rx_userstatus, {
226                         "User Status", "rx.userstatus", FT_UINT32, BASE_DEC,
227                         NULL, 0, "User Status" }},
228                 { &hf_rx_securityindex, {
229                         "Security Index", "rx.securityindex", FT_UINT32, BASE_DEC,
230                         NULL, 0, "Security Index" }},
231                 { &hf_rx_spare, {
232                         "Spare/Checksum", "rx.spare", FT_UINT16, BASE_DEC,
233                         NULL, 0, "Spare/Checksum" }},
234                 { &hf_rx_serviceid, {
235                         "Service ID", "rx.serviceid", FT_UINT16, BASE_DEC,
236                         NULL, 0, "Service ID" }},
237         };
238         static gint *ett[] = {
239                 &ett_rx,
240                 &ett_rx_flags,
241         };
242
243         proto_rx = proto_register_protocol("RX Protocol", "RX", "rx");
244         proto_register_field_array(proto_rx, hf, array_length(hf));
245         proto_register_subtree_array(ett, array_length(ett));
246 }
247
248 void
249 proto_reg_handoff_rx(void)
250 {
251         int port;
252
253         /* Ports in the range UDP_PORT_RX_LOW to UDP_PORT_RX_HIGH
254            are all used for various AFS services. */
255         for (port = UDP_PORT_RX_LOW; port <= UDP_PORT_RX_HIGH; port++)
256                 old_dissector_add("udp.port", port, dissect_rx, proto_rx);
257         old_dissector_add("udp.port", UDP_PORT_RX_AFS_BACKUPS, dissect_rx,
258             proto_rx);
259 }