MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-rx.c
bloba9644fd1681e7e76436a368325abe48958258f82
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>
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * Copied from packet-tftp.c
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "config.h"
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-rx.h"
35 #include <epan/addr_resolv.h>
38 * See
40 * http://web.mit.edu/kolya/afs/rx/rx-spec
42 * XXX - is the "Epoch" really a UN*X time? The high-order bit, according
43 * to that spec, is a flag bit.
46 #define UDP_PORT_RX_LOW 7000
47 #define UDP_PORT_RX_HIGH 7009
48 #define UDP_PORT_RX_AFS_BACKUPS 7021
50 static const value_string rx_types[] = {
51 { RX_PACKET_TYPE_DATA, "data" },
52 { RX_PACKET_TYPE_ACK, "ack" },
53 { RX_PACKET_TYPE_BUSY, "busy" },
54 { RX_PACKET_TYPE_ABORT, "abort" },
55 { RX_PACKET_TYPE_ACKALL, "ackall" },
56 { RX_PACKET_TYPE_CHALLENGE, "challenge" },
57 { RX_PACKET_TYPE_RESPONSE, "response" },
58 { RX_PACKET_TYPE_DEBUG, "debug" },
59 { RX_PACKET_TYPE_PARAMS, "params" },
60 { RX_PACKET_TYPE_VERSION, "version" },
61 { 0, NULL },
64 static const value_string rx_reason[] = {
65 { RX_ACK_REQUESTED, "Ack Requested" },
66 { RX_ACK_DUPLICATE, "Duplicate Packet" },
67 { RX_ACK_OUT_OF_SEQUENCE, "Out Of Sequence" },
68 { RX_ACK_EXEEDS_WINDOW, "Exceeds Window" },
69 { RX_ACK_NOSPACE, "No Space" },
70 { RX_ACK_PING, "Ping" },
71 { RX_ACK_PING_RESPONSE, "Ping Response" },
72 { RX_ACK_DELAY, "Delay" },
73 { RX_ACK_IDLE, "Idle" },
74 { 0, NULL }
77 static const value_string rx_ack_type[] = {
78 { RX_ACK_TYPE_NACK, "NACK" },
79 { RX_ACK_TYPE_ACK, "ACK" },
80 { 0, NULL }
83 static int proto_rx = -1;
84 static int hf_rx_epoch = -1;
85 static int hf_rx_cid = -1;
86 static int hf_rx_seq = -1;
87 static int hf_rx_serial = -1;
88 static int hf_rx_callnumber = -1;
89 static int hf_rx_type = -1;
90 static int hf_rx_flags = -1;
91 static int hf_rx_flags_clientinit = -1;
92 static int hf_rx_flags_request_ack = -1;
93 static int hf_rx_flags_last_packet = -1;
94 static int hf_rx_flags_more_packets = -1;
95 static int hf_rx_flags_free_packet = -1;
96 static int hf_rx_userstatus = -1;
97 static int hf_rx_securityindex = -1;
98 static int hf_rx_spare = -1;
99 static int hf_rx_serviceid = -1;
100 static int hf_rx_bufferspace = -1;
101 static int hf_rx_maxskew = -1;
102 static int hf_rx_first_packet = -1;
103 static int hf_rx_prev_packet = -1;
104 static int hf_rx_reason = -1;
105 static int hf_rx_numacks = -1;
106 static int hf_rx_ack_type = -1;
107 static int hf_rx_ack = -1;
108 static int hf_rx_challenge = -1;
109 static int hf_rx_version = -1;
110 static int hf_rx_nonce = -1;
111 static int hf_rx_inc_nonce = -1;
112 static int hf_rx_min_level = -1;
113 static int hf_rx_level = -1;
114 static int hf_rx_response = -1;
115 static int hf_rx_encrypted = -1;
116 static int hf_rx_kvno = -1;
117 static int hf_rx_ticket_len = -1;
118 static int hf_rx_ticket = -1;
119 static int hf_rx_ifmtu = -1;
120 static int hf_rx_maxmtu = -1;
121 static int hf_rx_rwind = -1;
122 static int hf_rx_maxpackets = -1;
123 static int hf_rx_abort = -1;
124 static int hf_rx_abortcode = -1;
126 static gint ett_rx = -1;
127 static gint ett_rx_flags = -1;
128 static gint ett_rx_ack = -1;
129 static gint ett_rx_challenge = -1;
130 static gint ett_rx_response = -1;
131 static gint ett_rx_encrypted = -1;
132 static gint ett_rx_abort = -1;
134 static dissector_handle_t afs_handle;
136 static int
137 dissect_rx_response_encrypted(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
139 proto_tree *tree;
140 proto_item *item;
141 int old_offset=offset;
142 int i;
143 guint32 callnumber;
145 item = proto_tree_add_item(parent_tree, hf_rx_encrypted, tvb, offset, -1, ENC_NA);
146 tree = proto_item_add_subtree(item, ett_rx_encrypted);
148 /* epoch : 4 bytes */
150 nstime_t ts;
151 ts.secs = tvb_get_ntohl(tvb, offset);
152 ts.nsecs = 0;
154 proto_tree_add_time(tree, hf_rx_epoch, tvb,
155 offset, 4, &ts);
156 offset += 4;
159 /* cid : 4 bytes */
160 proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, ENC_BIG_ENDIAN);
161 offset += 4;
163 /*FIXME dont know how to handle this checksum, skipping it */
164 offset += 4;
166 /* sequrityindex : 1 byte */
167 proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, ENC_BIG_ENDIAN);
168 offset += 4;
170 for (i=0; i<RX_MAXCALLS; i++) {
171 /* callnumber : 4 bytes */
172 callnumber = tvb_get_ntohl(tvb, offset);
173 proto_tree_add_uint(tree, hf_rx_callnumber, tvb,
174 offset, 4, callnumber);
175 offset += 4;
178 /* inc nonce : 4 bytes */
179 proto_tree_add_item(tree, hf_rx_inc_nonce, tvb, offset, 4, ENC_BIG_ENDIAN);
180 offset += 4;
182 /* level : 4 bytes */
183 proto_tree_add_item(tree, hf_rx_level, tvb, offset, 4, ENC_BIG_ENDIAN);
184 offset += 4;
186 proto_item_set_len(item, offset-old_offset);
187 return offset;
191 static int
192 dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
194 proto_tree *tree;
195 proto_item *item;
196 guint32 version, tl;
197 int old_offset=offset;
199 col_add_fstr(pinfo->cinfo, COL_INFO,
200 "RESPONSE "
201 "Seq: %lu "
202 "Call: %lu "
203 "Source Port: %s "
204 "Destination Port: %s ",
205 (unsigned long)seq,
206 (unsigned long)callnumber,
207 get_udp_port(pinfo->srcport),
208 get_udp_port(pinfo->destport)
211 item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, ENC_NA);
212 tree = proto_item_add_subtree(item, ett_rx_response);
214 version = tvb_get_ntohl(tvb, offset);
215 proto_tree_add_uint(tree, hf_rx_version, tvb,
216 offset, 4, version);
217 offset += 4;
219 if (version==2) {
220 /* skip unused */
221 offset += 4;
223 /* encrypted : struct */
224 offset = dissect_rx_response_encrypted(tvb, tree, offset);
226 /* kvno */
227 proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, ENC_BIG_ENDIAN);
228 offset += 4;
230 /* ticket_len */
231 tl = tvb_get_ntohl(tvb, offset);
232 proto_tree_add_uint(tree, hf_rx_ticket_len, tvb,
233 offset, 4, tl);
234 offset += 4;
236 tvb_ensure_bytes_exist(tvb, offset, tl);
237 proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, ENC_NA);
238 offset += tl;
241 proto_item_set_len(item, offset-old_offset);
242 return offset;
245 static int
246 dissect_rx_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
248 proto_tree *tree;
249 proto_item *item;
250 int old_offset=offset;
252 col_add_fstr(pinfo->cinfo, COL_INFO,
253 "ABORT "
254 "Seq: %lu "
255 "Call: %lu "
256 "Source Port: %s "
257 "Destination Port: %s ",
258 (unsigned long)seq,
259 (unsigned long)callnumber,
260 get_udp_port(pinfo->srcport),
261 get_udp_port(pinfo->destport)
264 item = proto_tree_add_item(parent_tree, hf_rx_abort, tvb, offset, -1, ENC_NA);
265 tree = proto_item_add_subtree(item, ett_rx_abort);
267 /* kvno */
268 proto_tree_add_item(tree, hf_rx_abortcode, tvb, offset, 4, ENC_BIG_ENDIAN);
269 offset += 4;
271 proto_item_set_len(item, offset-old_offset);
272 return offset;
276 static int
277 dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
279 proto_tree *tree;
280 proto_item *item;
281 guint32 version;
282 int old_offset=offset;
284 col_add_fstr(pinfo->cinfo, COL_INFO,
285 "CHALLENGE "
286 "Seq: %lu "
287 "Call: %lu "
288 "Source Port: %s "
289 "Destination Port: %s ",
290 (unsigned long)seq,
291 (unsigned long)callnumber,
292 get_udp_port(pinfo->srcport),
293 get_udp_port(pinfo->destport)
296 item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, -1, ENC_NA);
297 tree = proto_item_add_subtree(item, ett_rx_challenge);
299 version = tvb_get_ntohl(tvb, offset);
300 proto_tree_add_uint(tree, hf_rx_version, tvb,
301 offset, 4, version);
302 offset += 4;
304 if (version==2) {
305 proto_tree_add_item(tree, hf_rx_nonce, tvb, offset, 4, ENC_BIG_ENDIAN);
306 offset += 4;
308 proto_tree_add_item(tree, hf_rx_min_level, tvb, offset, 4, ENC_BIG_ENDIAN);
309 offset += 4;
312 proto_item_set_len(item, offset-old_offset);
313 return offset;
316 static int
317 dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
319 proto_tree *tree;
320 proto_item *item;
321 guint8 num;
322 int old_offset = offset;
324 col_add_fstr(pinfo->cinfo, COL_INFO,
325 "ACK "
326 "Seq: %lu "
327 "Call: %lu "
328 "Source Port: %s "
329 "Destination Port: %s ",
330 (unsigned long)seq,
331 (unsigned long)callnumber,
332 get_udp_port(pinfo->srcport),
333 get_udp_port(pinfo->destport)
336 item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, -1, ENC_NA);
337 tree = proto_item_add_subtree(item, ett_rx_ack);
340 /* bufferspace: 2 bytes*/
341 proto_tree_add_item(tree, hf_rx_bufferspace, tvb, offset, 2, ENC_BIG_ENDIAN);
342 offset += 2;
344 /* maxskew: 2 bytes*/
345 proto_tree_add_item(tree, hf_rx_maxskew, tvb, offset, 2, ENC_BIG_ENDIAN);
346 offset += 2;
348 /* first packet: 4 bytes*/
349 proto_tree_add_item(tree, hf_rx_first_packet, tvb, offset, 4, ENC_BIG_ENDIAN);
350 offset += 4;
352 /* prev packet: 4 bytes*/
353 proto_tree_add_item(tree, hf_rx_prev_packet, tvb, offset, 4, ENC_BIG_ENDIAN);
354 offset += 4;
356 /* serial : 4 bytes */
357 proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
358 offset += 4;
360 /* reason : 1 byte */
361 proto_tree_add_item(tree, hf_rx_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
362 offset += 1;
364 /* nACKs */
365 num = tvb_get_guint8(tvb, offset);
366 proto_tree_add_uint(tree, hf_rx_numacks, tvb, offset, 1, num);
367 offset += 1;
369 while(num--){
370 proto_tree_add_item(tree, hf_rx_ack_type, tvb, offset, 1,
371 ENC_BIG_ENDIAN);
372 offset += 1;
375 /* Some implementations adds some extra fields.
376 * As far as I can see, these first add 3 padding bytes and then
377 * up to 4 32-bit values. (0,3,4 have been witnessed)
379 * RX as a protocol seems to be completely nondefined and seems to lack
380 * any sort of documentation other than "read the source of any of the
381 * (compatible?) implementations.
383 if (tvb_length_remaining(tvb, offset)>3) {
384 offset += 3; /* guess. some implementations adds 3 bytes */
386 if (tvb_reported_length_remaining(tvb, offset) >= 4){
387 proto_tree_add_item(tree, hf_rx_ifmtu, tvb, offset, 4,
388 ENC_BIG_ENDIAN);
389 offset += 4;
391 if (tvb_reported_length_remaining(tvb, offset) >= 4){
392 proto_tree_add_item(tree, hf_rx_maxmtu, tvb, offset, 4,
393 ENC_BIG_ENDIAN);
394 offset += 4;
396 if (tvb_reported_length_remaining(tvb, offset) >= 4){
397 proto_tree_add_item(tree, hf_rx_rwind, tvb, offset, 4,
398 ENC_BIG_ENDIAN);
399 offset += 4;
401 if (tvb_reported_length_remaining(tvb, offset) >= 4){
402 proto_tree_add_item(tree, hf_rx_maxpackets, tvb, offset, 4,
403 ENC_BIG_ENDIAN);
404 offset += 4;
408 proto_item_set_len(item, offset-old_offset);
409 return offset;
413 static int
414 dissect_rx_flags(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *parent_tree, int offset)
416 proto_tree *tree;
417 proto_item *item;
418 guint8 flags;
420 flags = tvb_get_guint8(tvb, offset);
421 rxinfo->flags = flags;
423 item = proto_tree_add_uint(parent_tree, hf_rx_flags, tvb,
424 offset, 1, flags);
425 tree = proto_item_add_subtree(item, ett_rx_flags);
427 proto_tree_add_boolean(tree, hf_rx_flags_free_packet, tvb,
428 offset, 1, flags);
429 proto_tree_add_boolean(tree, hf_rx_flags_more_packets, tvb,
430 offset, 1, flags);
431 proto_tree_add_boolean(tree, hf_rx_flags_last_packet, tvb,
432 offset, 1, flags);
433 proto_tree_add_boolean(tree, hf_rx_flags_request_ack, tvb,
434 offset, 1, flags);
435 proto_tree_add_boolean(tree, hf_rx_flags_clientinit, tvb,
436 offset, 1, flags);
438 offset += 1;
439 return offset;
442 static int
443 dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
445 proto_tree *tree;
446 proto_item *item;
447 int offset = 0;
448 struct rxinfo rxinfo;
449 guint8 type;
450 nstime_t ts;
451 guint32 seq, callnumber;
452 guint16 serviceid;
454 /* Ensure we have enough data */
455 if (tvb_length(tvb) < 28)
456 return 0;
458 /* Make sure it's a known type */
459 type = tvb_get_guint8(tvb, 20);
460 if (type == 0 || type == 10 || type == 11 || type == 12 || type > 13)
461 return 0;
463 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RX");
464 col_clear(pinfo->cinfo, COL_INFO);
466 item = proto_tree_add_protocol_format(parent_tree, proto_rx, tvb,
467 offset, 28, "RX Protocol");
468 tree = proto_item_add_subtree(item, ett_rx);
470 /* epoch : 4 bytes */
471 rxinfo.epoch = tvb_get_ntohl(tvb, offset);
472 ts.secs = rxinfo.epoch;
473 ts.nsecs = 0;
474 proto_tree_add_time(tree, hf_rx_epoch, tvb, offset, 4, &ts);
475 offset += 4;
477 /* cid : 4 bytes */
478 rxinfo.cid = tvb_get_ntohl(tvb, offset);
479 proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, ENC_BIG_ENDIAN);
480 offset += 4;
482 /* callnumber : 4 bytes */
483 callnumber = tvb_get_ntohl(tvb, offset);
484 proto_tree_add_uint(tree, hf_rx_callnumber, tvb,
485 offset, 4, callnumber);
486 offset += 4;
487 rxinfo.callnumber = callnumber;
489 /* seq : 4 bytes */
490 seq = tvb_get_ntohl(tvb, offset);
491 proto_tree_add_uint(tree, hf_rx_seq, tvb,
492 offset, 4, seq);
493 offset += 4;
494 rxinfo.seq = seq;
496 /* serial : 4 bytes */
497 proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
498 offset += 4;
500 /* type : 1 byte */
501 type = tvb_get_guint8(tvb, offset);
502 proto_tree_add_uint(tree, hf_rx_type, tvb,
503 offset, 1, type);
504 offset += 1;
505 rxinfo.type = type;
507 /* flags : 1 byte */
508 offset = dissect_rx_flags(tvb, &rxinfo, tree, offset);
510 /* userstatus : 1 byte */
511 proto_tree_add_item(tree, hf_rx_userstatus, tvb, offset, 1, ENC_BIG_ENDIAN);
512 offset += 1;
514 /* sequrityindex : 1 byte */
515 proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, ENC_BIG_ENDIAN);
516 offset += 1;
519 * How clever: even though the AFS header files indicate that the
520 * serviceId is first, it's really encoded _after_ the spare field.
521 * I wasted a day figuring that out!
524 /* spare */
525 proto_tree_add_item(tree, hf_rx_spare, tvb, offset, 2, ENC_BIG_ENDIAN);
526 offset += 2;
528 /* service id : 2 bytes */
529 serviceid = tvb_get_ntohs(tvb, offset);
530 proto_tree_add_uint(tree, hf_rx_serviceid, tvb,
531 offset, 2, serviceid);
532 offset += 2;
533 rxinfo.serviceid = serviceid;
535 switch (type) {
536 case RX_PACKET_TYPE_ACK:
537 /*dissect_rx_acks(tvb, pinfo, parent_tree, offset,
538 cant create it in a parallell tree, then ett seasrch
539 wont work */
540 dissect_rx_acks(tvb, pinfo, tree, offset,
541 seq, callnumber);
542 break;
543 case RX_PACKET_TYPE_ACKALL:
544 /* does not contain any payload */
545 col_add_fstr(pinfo->cinfo, COL_INFO,
546 "ACKALL "
547 "Seq: %lu "
548 "Call: %lu "
549 "Source Port: %s "
550 "Destination Port: %s ",
551 (unsigned long)seq,
552 (unsigned long)callnumber,
553 get_udp_port(pinfo->srcport),
554 get_udp_port(pinfo->destport)
556 break;
557 case RX_PACKET_TYPE_CHALLENGE:
558 dissect_rx_challenge(tvb, pinfo, tree, offset, seq, callnumber);
559 break;
560 case RX_PACKET_TYPE_RESPONSE:
561 dissect_rx_response(tvb, pinfo, tree, offset, seq, callnumber);
562 break;
563 case RX_PACKET_TYPE_DATA: {
564 tvbuff_t *next_tvb;
566 next_tvb = tvb_new_subset_remaining(tvb, offset);
567 call_dissector_with_data(afs_handle, next_tvb, pinfo, parent_tree, &rxinfo);
569 break;
570 case RX_PACKET_TYPE_ABORT:
571 dissect_rx_abort(tvb, pinfo, tree, offset, seq, callnumber);
572 break;
575 return(tvb_length(tvb));
578 void
579 proto_register_rx(void)
581 static hf_register_info hf[] = {
582 { &hf_rx_epoch, {
583 "Epoch", "rx.epoch", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
584 NULL, 0, NULL, HFILL }},
586 { &hf_rx_cid, {
587 "CID", "rx.cid", FT_UINT32, BASE_DEC,
588 NULL, 0, NULL, HFILL }},
590 { &hf_rx_callnumber, {
591 "Call Number", "rx.callnumber", FT_UINT32, BASE_DEC,
592 NULL, 0, NULL, HFILL }},
594 { &hf_rx_seq, {
595 "Sequence Number", "rx.seq", FT_UINT32, BASE_DEC,
596 NULL, 0, NULL, HFILL }},
598 { &hf_rx_serial, {
599 "Serial", "rx.serial", FT_UINT32, BASE_DEC,
600 NULL, 0, NULL, HFILL }},
602 { &hf_rx_type, {
603 "Type", "rx.type", FT_UINT8, BASE_DEC,
604 VALS(rx_types), 0, NULL, HFILL }},
606 { &hf_rx_flags, {
607 "Flags", "rx.flags", FT_UINT8, BASE_HEX,
608 NULL, 0, NULL, HFILL }},
610 { &hf_rx_flags_clientinit, {
611 "Client Initiated", "rx.flags.client_init", FT_BOOLEAN, 8,
612 NULL, RX_CLIENT_INITIATED, NULL, HFILL }},
614 { &hf_rx_flags_request_ack, {
615 "Request Ack", "rx.flags.request_ack", FT_BOOLEAN, 8,
616 NULL, RX_REQUEST_ACK, NULL, HFILL }},
618 { &hf_rx_flags_last_packet, {
619 "Last Packet", "rx.flags.last_packet", FT_BOOLEAN, 8,
620 NULL, RX_LAST_PACKET, NULL, HFILL }},
622 { &hf_rx_flags_more_packets, {
623 "More Packets", "rx.flags.more_packets", FT_BOOLEAN, 8,
624 NULL, RX_MORE_PACKETS, NULL, HFILL }},
626 { &hf_rx_flags_free_packet, {
627 "Free Packet", "rx.flags.free_packet", FT_BOOLEAN, 8,
628 NULL, RX_FREE_PACKET, NULL, HFILL }},
630 /* XXX - what about RX_SLOW_START_OR_JUMBO? */
632 { &hf_rx_userstatus, {
633 "User Status", "rx.userstatus", FT_UINT32, BASE_DEC,
634 NULL, 0, NULL, HFILL }},
636 { &hf_rx_securityindex, {
637 "Security Index", "rx.securityindex", FT_UINT32, BASE_DEC,
638 NULL, 0, NULL, HFILL }},
640 { &hf_rx_spare, {
641 "Spare/Checksum", "rx.spare", FT_UINT16, BASE_DEC,
642 NULL, 0, NULL, HFILL }},
644 { &hf_rx_serviceid, {
645 "Service ID", "rx.serviceid", FT_UINT16, BASE_DEC,
646 NULL, 0, NULL, HFILL }},
648 { &hf_rx_bufferspace, {
649 "Bufferspace", "rx.bufferspace", FT_UINT16, BASE_DEC,
650 NULL, 0, "Number Of Packets Available", HFILL }},
652 { &hf_rx_maxskew, {
653 "Max Skew", "rx.maxskew", FT_UINT16, BASE_DEC,
654 NULL, 0, NULL, HFILL }},
656 { &hf_rx_first_packet, {
657 "First Packet", "rx.first", FT_UINT32, BASE_DEC,
658 NULL, 0, NULL, HFILL }},
660 { &hf_rx_prev_packet, {
661 "Prev Packet", "rx.prev", FT_UINT32, BASE_DEC,
662 NULL, 0, "Previous Packet", HFILL }},
664 { &hf_rx_reason, {
665 "Reason", "rx.reason", FT_UINT8, BASE_DEC,
666 VALS(rx_reason), 0, "Reason For This ACK", HFILL }},
668 { &hf_rx_numacks, {
669 "Num ACKs", "rx.num_acks", FT_UINT8, BASE_DEC,
670 NULL, 0, "Number Of ACKs", HFILL }},
672 { &hf_rx_ack_type, {
673 "ACK Type", "rx.ack_type", FT_UINT8, BASE_DEC,
674 VALS(rx_ack_type), 0, "Type Of ACKs", HFILL }},
676 { &hf_rx_ack, {
677 "ACK Packet", "rx.ack", FT_NONE, BASE_NONE,
678 NULL, 0, NULL, HFILL }},
680 { &hf_rx_challenge, {
681 "CHALLENGE Packet", "rx.challenge", FT_NONE, BASE_NONE,
682 NULL, 0, NULL, HFILL }},
684 { &hf_rx_version, {
685 "Version", "rx.version", FT_UINT32, BASE_DEC,
686 NULL, 0, "Version Of Challenge/Response", HFILL }},
688 { &hf_rx_nonce, {
689 "Nonce", "rx.nonce", FT_UINT32, BASE_HEX,
690 NULL, 0, NULL, HFILL }},
692 { &hf_rx_inc_nonce, {
693 "Inc Nonce", "rx.inc_nonce", FT_UINT32, BASE_HEX,
694 NULL, 0, "Incremented Nonce", HFILL }},
696 { &hf_rx_min_level, {
697 "Min Level", "rx.min_level", FT_UINT32, BASE_DEC,
698 NULL, 0, NULL, HFILL }},
700 { &hf_rx_level, {
701 "Level", "rx.level", FT_UINT32, BASE_DEC,
702 NULL, 0, NULL, HFILL }},
704 { &hf_rx_response, {
705 "RESPONSE Packet", "rx.response", FT_NONE, BASE_NONE,
706 NULL, 0, NULL, HFILL }},
708 { &hf_rx_abort, {
709 "ABORT Packet", "rx.abort", FT_NONE, BASE_NONE,
710 NULL, 0, NULL, HFILL }},
712 { &hf_rx_encrypted, {
713 "Encrypted", "rx.encrypted", FT_NONE, BASE_NONE,
714 NULL, 0, "Encrypted part of response packet", HFILL }},
716 { &hf_rx_kvno, {
717 "kvno", "rx.kvno", FT_UINT32, BASE_DEC,
718 NULL, 0, NULL, HFILL }},
720 { &hf_rx_ticket_len, {
721 "Ticket len", "rx.ticket_len", FT_UINT32, BASE_DEC,
722 NULL, 0, "Ticket Length", HFILL }},
724 { &hf_rx_ticket, {
725 "ticket", "rx.ticket", FT_BYTES, BASE_NONE,
726 NULL, 0, NULL, HFILL }},
728 { &hf_rx_ifmtu, {
729 "Interface MTU", "rx.if_mtu", FT_UINT32, BASE_DEC,
730 NULL, 0, NULL, HFILL }},
732 { &hf_rx_maxmtu, {
733 "Max MTU", "rx.max_mtu", FT_UINT32, BASE_DEC,
734 NULL, 0, NULL, HFILL }},
736 { &hf_rx_rwind, {
737 "rwind", "rx.rwind", FT_UINT32, BASE_DEC,
738 NULL, 0, NULL, HFILL }},
740 { &hf_rx_maxpackets, {
741 "Max Packets", "rx.max_packets", FT_UINT32, BASE_DEC,
742 NULL, 0, NULL, HFILL }},
744 { &hf_rx_abortcode, {
745 "Abort Code", "rx.abort_code", FT_UINT32, BASE_DEC,
746 NULL, 0, NULL, HFILL }},
749 static gint *ett[] = {
750 &ett_rx,
751 &ett_rx_flags,
752 &ett_rx_ack,
753 &ett_rx_challenge,
754 &ett_rx_response,
755 &ett_rx_encrypted,
756 &ett_rx_abort
759 proto_rx = proto_register_protocol("RX Protocol", "RX", "rx");
760 proto_register_field_array(proto_rx, hf, array_length(hf));
761 proto_register_subtree_array(ett, array_length(ett));
764 void
765 proto_reg_handoff_rx(void)
767 dissector_handle_t rx_handle;
769 int port;
772 * Get handle for the AFS dissector.
774 afs_handle = find_dissector("afs");
776 /* Ports in the range UDP_PORT_RX_LOW to UDP_PORT_RX_HIGH
777 are all used for various AFS services. */
778 rx_handle = new_create_dissector_handle(dissect_rx, proto_rx);
779 for (port = UDP_PORT_RX_LOW; port <= UDP_PORT_RX_HIGH; port++)
780 dissector_add_uint("udp.port", port, rx_handle);
781 dissector_add_uint("udp.port", UDP_PORT_RX_AFS_BACKUPS, rx_handle);