Handle ignored files more flexible. This also fixes the newest files
[metze/wireshark/wip.git] / packet-rx.c
index e63d504751661b2e65f8fd0535062fd11f79d99b..e9040b170cde4c06199e63d147d75bd4d4c7dff7 100644 (file)
@@ -4,10 +4,10 @@
  * Based on routines from tcpdump patches by
  *   Ken Hornstein <kenh@cmf.nrl.navy.mil>
  *
- * $Id: packet-rx.c,v 1.20 2001/05/27 01:48:24 guy Exp $
+ * $Id: packet-rx.c,v 1.37 2002/08/28 21:00:30 jmayer Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from packet-tftp.c
 
 #include <stdio.h>
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include <string.h>
 #include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
 #include "packet-rx.h"
-#include "packet-afs.h"
-#include "resolv.h"
+#include <epan/resolv.h>
 
 #define UDP_PORT_RX_LOW                7000
 #define UDP_PORT_RX_HIGH       7009
@@ -72,6 +63,7 @@ static const value_string rx_flags[] = {
        { RX_LAST_PACKET,       "last-pckt" },
        { RX_MORE_PACKETS,      "more-pckts" },
        { RX_FREE_PACKET,       "free-pckt" },
+       { RX_SLOW_START_OR_JUMBO, "slow-start/jumbogram" },
        { 0,                    NULL }
 };
 
@@ -79,11 +71,12 @@ static const value_string rx_reason[] = {
        { RX_ACK_REQUESTED,             "Ack Requested"         },
        { RX_ACK_DUPLICATE,             "Duplicate Packet"      },
        { RX_ACK_OUT_OF_SEQUENCE,       "Out Of Sequence"       },
-       { RX_ACK_EXEEDS_WINDOW,         "Exceeds Window"        },      
+       { RX_ACK_EXEEDS_WINDOW,         "Exceeds Window"        },
        { RX_ACK_NOSPACE,               "No Space"              },
        { RX_ACK_PING,                  "Ping"                  },
        { RX_ACK_PING_RESPONSE,         "Ping Response"         },
        { RX_ACK_DELAY,                 "Delay"                 },
+       { RX_ACK_IDLE,                  "Idle"                  },
        { 0,                            NULL                    }
 };
 
@@ -129,6 +122,12 @@ static int hf_rx_encrypted = -1;
 static int hf_rx_kvno = -1;
 static int hf_rx_ticket_len = -1;
 static int hf_rx_ticket = -1;
+static int hf_rx_ifmtu = -1;
+static int hf_rx_maxmtu = -1;
+static int hf_rx_rwind = -1;
+static int hf_rx_maxpackets = -1;
+static int hf_rx_abort = -1;
+static int hf_rx_abortcode = -1;
 
 static gint ett_rx = -1;
 static gint ett_rx_flags = -1;
@@ -136,9 +135,12 @@ static gint ett_rx_ack = -1;
 static gint ett_rx_challenge = -1;
 static gint ett_rx_response = -1;
 static gint ett_rx_encrypted = -1;
+static gint ett_rx_abort = -1;
+
+static dissector_handle_t afs_handle;
 
 static int
-dissect_rx_response_encrypted(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+dissect_rx_response_encrypted(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
 {
        proto_tree *tree;
        proto_item *item;
@@ -146,31 +148,29 @@ dissect_rx_response_encrypted(tvbuff_t *tvb, packet_info *pinfo, proto_tree *par
        int i;
        guint32 callnumber;
 
-       item = proto_tree_add_item(parent_tree, hf_rx_encrypted, tvb, offset, 0, FALSE);
+       item = proto_tree_add_item(parent_tree, hf_rx_encrypted, tvb, offset, -1, FALSE);
        tree = proto_item_add_subtree(item, ett_rx_encrypted);
 
        /* epoch : 4 bytes */
        {
-               struct timeval tv;
-               tv.tv_sec = tvb_get_ntohl(tvb, offset);
-               tv.tv_usec = 0;
-               
+               nstime_t ts;
+               ts.secs = tvb_get_ntohl(tvb, offset);
+               ts.nsecs = 0;
+
                proto_tree_add_time(tree, hf_rx_epoch, tvb,
-                       offset, 4, &tv);
+                       offset, 4, &ts);
                offset += 4;
        }
 
        /* cid : 4 bytes */
-       proto_tree_add_uint(tree, hf_rx_cid, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, FALSE);
        offset += 4;
 
        /*FIXME dont know how to handle this checksum, skipping it */
        offset += 4;
 
        /* sequrityindex : 1 byte */
-       proto_tree_add_uint(tree, hf_rx_securityindex, tvb,
-               offset, 1, tvb_get_guint8(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, FALSE);
        offset += 4;
 
        for (i=0; i<RX_MAXCALLS; i++) {
@@ -182,19 +182,17 @@ dissect_rx_response_encrypted(tvbuff_t *tvb, packet_info *pinfo, proto_tree *par
        }
 
        /* inc nonce : 4 bytes */
-       proto_tree_add_uint(tree, hf_rx_inc_nonce, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_inc_nonce, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* level : 4 bytes */
-       proto_tree_add_uint(tree, hf_rx_level, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_level, tvb, offset, 4, FALSE);
        offset += 4;
-       
-       proto_item_set_len(item, offset-old_offset);    
+
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
-       
+
 
 static int
 dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
@@ -204,8 +202,8 @@ dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
        guint32 version, tl;
        int old_offset=offset;
 
-       if (check_col(pinfo->fd, COL_INFO)) {
-               col_add_fstr(pinfo->fd, COL_INFO,
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_add_fstr(pinfo->cinfo, COL_INFO,
                        "RESPONSE  "
                        "Seq: %lu  "
                        "Call: %lu  "
@@ -218,7 +216,7 @@ dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
                );
        }
 
-       item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, 0, FALSE);
+       item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, FALSE);
        tree = proto_item_add_subtree(item, ett_rx_response);
 
        version = tvb_get_ntohl(tvb, offset);
@@ -231,27 +229,59 @@ dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
                offset += 4;
 
                /* encrypted : struct */
-               offset = dissect_rx_response_encrypted(tvb, pinfo, tree, offset);
+               offset = dissect_rx_response_encrypted(tvb, tree, offset);
 
                /* kvno */
-               proto_tree_add_uint(tree, hf_rx_kvno, tvb,
-                       offset, 4, tvb_get_ntohl(tvb, offset));
+               proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, FALSE);
                offset += 4;
-               
+
                /* ticket_len */
                tl = tvb_get_ntohl(tvb, offset);
                proto_tree_add_uint(tree, hf_rx_ticket_len, tvb,
                        offset, 4, tl);
                offset += 4;
-       
+
                proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, FALSE);
-               offset += tl;   
+               offset += tl;
+       }
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+dissect_rx_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
+{
+       proto_tree *tree;
+       proto_item *item;
+       int old_offset=offset;
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_add_fstr(pinfo->cinfo, COL_INFO,
+                       "ABORT  "
+                       "Seq: %lu  "
+                       "Call: %lu  "
+                       "Source Port: %s  "
+                       "Destination Port: %s  ",
+                       (unsigned long)seq,
+                       (unsigned long)callnumber,
+                       get_udp_port(pinfo->srcport),
+                       get_udp_port(pinfo->destport)
+               );
        }
 
-       proto_item_set_len(item, offset-old_offset);    
+       item = proto_tree_add_item(parent_tree, hf_rx_abort, tvb, offset, -1, FALSE);
+       tree = proto_item_add_subtree(item, ett_rx_abort);
+
+       /* kvno */
+       proto_tree_add_item(tree, hf_rx_abortcode, tvb, offset, 4, FALSE);
+       offset += 4;
+
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
+
 static int
 dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
 {
@@ -260,8 +290,8 @@ dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
        guint32 version;
        int old_offset=offset;
 
-       if (check_col(pinfo->fd, COL_INFO)) {
-               col_add_fstr(pinfo->fd, COL_INFO,
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_add_fstr(pinfo->cinfo, COL_INFO,
                        "CHALLENGE  "
                        "Seq: %lu  "
                        "Call: %lu  "
@@ -274,7 +304,7 @@ dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
                );
        }
 
-       item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, 0, FALSE);
+       item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, -1, FALSE);
        tree = proto_item_add_subtree(item, ett_rx_challenge);
 
        version = tvb_get_ntohl(tvb, offset);
@@ -283,16 +313,14 @@ dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
        offset += 4;
 
        if (version==2) {
-               proto_tree_add_uint(tree, hf_rx_nonce, tvb,
-                       offset, 4, tvb_get_ntohl(tvb, offset));
+               proto_tree_add_item(tree, hf_rx_nonce, tvb, offset, 4, FALSE);
                offset += 4;
 
-               proto_tree_add_uint(tree, hf_rx_min_level, tvb,
-                       offset, 4, tvb_get_ntohl(tvb, offset));
+               proto_tree_add_item(tree, hf_rx_min_level, tvb, offset, 4, FALSE);
                offset += 4;
        }
 
-       proto_item_set_len(item, offset-old_offset);    
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
@@ -304,8 +332,8 @@ dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int
        guint8 num;
        int old_offset = offset;
 
-       if (check_col(pinfo->fd, COL_INFO)) {
-               col_add_fstr(pinfo->fd, COL_INFO,
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_add_fstr(pinfo->cinfo, COL_INFO,
                        "ACK  "
                        "Seq: %lu  "
                        "Call: %lu  "
@@ -318,66 +346,92 @@ dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int
                );
        }
 
-       item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, 0, FALSE);
+       item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, -1, FALSE);
        tree = proto_item_add_subtree(item, ett_rx_ack);
 
 
        /* bufferspace: 2 bytes*/
-       proto_tree_add_uint(tree, hf_rx_bufferspace, tvb,
-               offset, 2, tvb_get_ntohs(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_bufferspace, tvb, offset, 2, FALSE);
        offset += 2;
-       
+
        /* maxskew: 2 bytes*/
-       proto_tree_add_uint(tree, hf_rx_maxskew, tvb,
-               offset, 2, tvb_get_ntohs(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_maxskew, tvb, offset, 2, FALSE);
        offset += 2;
-       
+
        /* first packet: 4 bytes*/
-       proto_tree_add_uint(tree, hf_rx_first_packet, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_first_packet, tvb, offset, 4, FALSE);
        offset += 4;
-       
+
        /* prev packet: 4 bytes*/
-       proto_tree_add_uint(tree, hf_rx_prev_packet, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_prev_packet, tvb, offset, 4, FALSE);
        offset += 4;
 
-       /* serial : 4 bytes */  
-       proto_tree_add_uint(tree, hf_rx_serial, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset) );
+       /* serial : 4 bytes */
+       proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* reason : 1 byte */
-       proto_tree_add_uint(tree, hf_rx_reason, tvb,
-               offset, 1, tvb_get_guint8(tvb, offset) );
+       proto_tree_add_item(tree, hf_rx_reason, tvb, offset, 1, FALSE);
        offset += 1;
 
        /* nACKs */
        num = tvb_get_guint8(tvb, offset);
-       proto_tree_add_uint(tree, hf_rx_numacks, tvb,
-               offset, 1, tvb_get_guint8(tvb, offset) );
+       proto_tree_add_uint(tree, hf_rx_numacks, tvb, offset, 1, num);
        offset += 1;
 
        while(num--){
-               proto_tree_add_uint(tree, hf_rx_ack_type, tvb,
-                       offset, 1, tvb_get_guint8(tvb, offset) );
+               proto_tree_add_item(tree, hf_rx_ack_type, tvb, offset, 1,
+                       FALSE);
                offset += 1;
        }
-       
-       proto_item_set_len(item, offset-old_offset);    
+
+       /* Some implementations adds some extra fields.
+        * As far as I can see, these first add 3 padding bytes and then
+         * up to 4 32-bit values. (0,3,4 have been witnessed)
+        *
+        * RX as a protocol seems to be completely nondefined and seems to lack
+        * any sort of documentation other than "read the source of any of the
+        * (compatible?) implementations.
+         */
+       if (tvb_length_remaining(tvb, offset)>3) {
+               offset += 3;    /* guess. some implementations adds 3 bytes */
+
+               if (tvb_reported_length_remaining(tvb, offset) >= 4){
+                       proto_tree_add_item(tree, hf_rx_ifmtu, tvb, offset, 4,
+                               FALSE);
+                       offset += 4;
+               }
+               if (tvb_reported_length_remaining(tvb, offset) >= 4){
+                       proto_tree_add_item(tree, hf_rx_maxmtu, tvb, offset, 4,
+                               FALSE);
+                       offset += 4;
+               }
+               if (tvb_reported_length_remaining(tvb, offset) >= 4){
+                       proto_tree_add_item(tree, hf_rx_rwind, tvb, offset, 4,
+                               FALSE);
+                       offset += 4;
+               }
+               if (tvb_reported_length_remaining(tvb, offset) >= 4){
+                       proto_tree_add_item(tree, hf_rx_maxpackets, tvb, offset, 4,
+                               FALSE);
+                       offset += 4;
+               }
+       }
+
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
 
 static int
-dissect_rx_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+dissect_rx_flags(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *parent_tree, int offset)
 {
        proto_tree *tree;
        proto_item *item;
        guint8 flags;
 
        flags = tvb_get_guint8(tvb, offset);
-       pinfo->ps.rx.flags = flags;
+       rxinfo->flags = flags;
 
        item = proto_tree_add_uint(parent_tree, hf_rx_flags, tvb,
                offset, 1, flags);
@@ -404,33 +458,33 @@ dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
        proto_tree *tree;
        proto_item *item;
        int offset = 0;
+       struct rxinfo rxinfo;
        guint8 type;
        guint32 seq, callnumber;
        guint16 serviceid;
 
-       if (check_col(pinfo->fd, COL_PROTOCOL))
-               col_set_str(pinfo->fd, COL_PROTOCOL, "RX");
-       if (check_col(pinfo->fd, COL_INFO))
-               col_clear(pinfo->fd, COL_INFO);
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RX");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
 
-       item = proto_tree_add_protocol_format(parent_tree, proto_rx, tvb, 
+       item = proto_tree_add_protocol_format(parent_tree, proto_rx, tvb,
                offset, 28, "RX Protocol");
        tree = proto_item_add_subtree(item, ett_rx);
 
        /* epoch : 4 bytes */
        {
-               struct timeval tv;
-               tv.tv_sec = tvb_get_ntohl(tvb, offset);
-               tv.tv_usec = 0;
-               
+               nstime_t ts;;
+               ts.secs = tvb_get_ntohl(tvb, offset);
+               ts.nsecs = 0;
+
                proto_tree_add_time(tree, hf_rx_epoch, tvb,
-                       offset, 4, &tv);
+                       offset, 4, &ts);
                offset += 4;
        }
 
        /* cid : 4 bytes */
-       proto_tree_add_uint(tree, hf_rx_cid, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* callnumber : 4 bytes */
@@ -438,18 +492,17 @@ dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
        proto_tree_add_uint(tree, hf_rx_callnumber, tvb,
                offset, 4, callnumber);
        offset += 4;
-       pinfo->ps.rx.callnumber = callnumber;
+       rxinfo.callnumber = callnumber;
 
        /* seq : 4 bytes */
        seq = tvb_get_ntohl(tvb, offset);
        proto_tree_add_uint(tree, hf_rx_seq, tvb,
                offset, 4, seq);
        offset += 4;
-       pinfo->ps.rx.seq = seq;
+       rxinfo.seq = seq;
 
        /* serial : 4 bytes */
-       proto_tree_add_uint(tree, hf_rx_serial, tvb,
-               offset, 4, tvb_get_ntohl(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* type : 1 byte */
@@ -457,24 +510,27 @@ dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
        proto_tree_add_uint(tree, hf_rx_type, tvb,
                offset, 1, type);
        offset += 1;
-       pinfo->ps.rx.type = type;
+       rxinfo.type = type;
 
        /* flags : 1 byte */
-       offset = dissect_rx_flags(tvb, pinfo, tree, offset);
+       offset = dissect_rx_flags(tvb, &rxinfo, tree, offset);
 
        /* userstatus : 1 byte */
-       proto_tree_add_uint(tree, hf_rx_userstatus, tvb,
-               offset, 1, tvb_get_guint8(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_userstatus, tvb, offset, 1, FALSE);
        offset += 1;
 
        /* sequrityindex : 1 byte */
-       proto_tree_add_uint(tree, hf_rx_securityindex, tvb,
-               offset, 1, tvb_get_guint8(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, FALSE);
        offset += 1;
 
+       /*
+        * How clever: even though the AFS header files indicate that the
+        * serviceId is first, it's really encoded _after_ the spare field.
+        * I wasted a day figuring that out!
+        */
+
        /* spare */
-       proto_tree_add_uint(tree, hf_rx_spare, tvb,
-               offset, 2, tvb_get_ntohs(tvb, offset));
+       proto_tree_add_item(tree, hf_rx_spare, tvb, offset, 2, FALSE);
        offset += 2;
 
        /* service id : 2 bytes */
@@ -482,20 +538,20 @@ dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
        proto_tree_add_uint(tree, hf_rx_serviceid, tvb,
                offset, 2, serviceid);
        offset += 2;
-       pinfo->ps.rx.serviceid = serviceid;
+       rxinfo.serviceid = serviceid;
 
        switch (type) {
        case RX_PACKET_TYPE_ACK:
-               /*dissect_rx_acks(tvb, pinfo, parent_tree, offset, 
+               /*dissect_rx_acks(tvb, pinfo, parent_tree, offset,
                        cant create it in a parallell tree, then ett seasrch
                        wont work */
-               dissect_rx_acks(tvb, pinfo, tree, offset, 
+               dissect_rx_acks(tvb, pinfo, tree, offset,
                        seq, callnumber);
                break;
        case RX_PACKET_TYPE_ACKALL:
                /* does not contain any payload */
-               if (check_col(pinfo->fd, COL_INFO)) {
-                       col_add_fstr(pinfo->fd, COL_INFO,
+               if (check_col(pinfo->cinfo, COL_INFO)) {
+                       col_add_fstr(pinfo->cinfo, COL_INFO,
                                "ACKALL  "
                                "Seq: %lu  "
                                "Call: %lu  "
@@ -516,10 +572,14 @@ dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
                break;
        case RX_PACKET_TYPE_DATA: {
                tvbuff_t *next_tvb;
+               pinfo->private_data = &rxinfo;
                next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-               dissect_afs(next_tvb, pinfo, parent_tree);
+               call_dissector(afs_handle, next_tvb, pinfo, parent_tree);
                };
                break;
+       case RX_PACKET_TYPE_ABORT:
+               dissect_rx_abort(tvb, pinfo, tree, offset, seq, callnumber);
+               break;
        }
 
 }
@@ -530,143 +590,167 @@ proto_register_rx(void)
        static hf_register_info hf[] = {
                { &hf_rx_epoch, {
                        "Epoch", "rx.epoch", FT_ABSOLUTE_TIME, BASE_DEC,
-                       NULL, 0, "Epoch" }},
+                       NULL, 0, "Epoch", HFILL }},
 
                { &hf_rx_cid, {
                        "CID", "rx.cid", FT_UINT32, BASE_DEC,
-                       NULL, 0, "CID" }},
+                       NULL, 0, "CID", HFILL }},
 
                { &hf_rx_callnumber, {
                        "Call Number", "rx.callnumber", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Call Number" }},
+                       NULL, 0, "Call Number", HFILL }},
 
                { &hf_rx_seq, {
                        "Sequence Number", "rx.seq", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Sequence Number" }},
+                       NULL, 0, "Sequence Number", HFILL }},
 
                { &hf_rx_serial, {
                        "Serial", "rx.serial", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Serial" }},
+                       NULL, 0, "Serial", HFILL }},
 
                { &hf_rx_type, {
                        "Type", "rx.type", FT_UINT8, BASE_DEC,
-                       VALS(rx_types), 0, "Type" }},
+                       VALS(rx_types), 0, "Type", HFILL }},
 
                { &hf_rx_flags, {
                        "Flags", "rx.flags", FT_UINT8, BASE_HEX,
-                       NULL, 0, "Flags" }},
+                       NULL, 0, "Flags", HFILL }},
 
                { &hf_rx_flags_clientinit, {
                        "Client Initiated", "rx.flags.client_init", FT_UINT8, BASE_BIN,
-                       NULL, RX_CLIENT_INITIATED, "Client Initiated" }},
+                       NULL, RX_CLIENT_INITIATED, "Client Initiated", HFILL }},
 
                { &hf_rx_flags_request_ack, {
                        "Request Ack", "rx.flags.request_ack", FT_UINT8, BASE_BIN,
-                       NULL, RX_REQUEST_ACK, "Request Ack" }},
+                       NULL, RX_REQUEST_ACK, "Request Ack", HFILL }},
 
                { &hf_rx_flags_last_packet, {
                        "Last Packet", "rx.flags.last_packet", FT_UINT8, BASE_BIN,
-                       NULL, RX_LAST_PACKET, "Last Packet" }},
+                       NULL, RX_LAST_PACKET, "Last Packet", HFILL }},
 
                { &hf_rx_flags_more_packets, {
                        "More Packets", "rx.flags.more_packets", FT_UINT8, BASE_BIN,
-                       NULL, RX_MORE_PACKETS, "More Packets" }},
+                       NULL, RX_MORE_PACKETS, "More Packets", HFILL }},
 
                { &hf_rx_flags_free_packet, {
                        "Free Packet", "rx.flags.free_packet", FT_UINT8, BASE_BIN,
-                       NULL, RX_FREE_PACKET, "Free Packet" }},
+                       NULL, RX_FREE_PACKET, "Free Packet", HFILL }},
 
                { &hf_rx_userstatus, {
                        "User Status", "rx.userstatus", FT_UINT32, BASE_DEC,
-                       NULL, 0, "User Status" }},
+                       NULL, 0, "User Status", HFILL }},
 
                { &hf_rx_securityindex, {
                        "Security Index", "rx.securityindex", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Security Index" }},
+                       NULL, 0, "Security Index", HFILL }},
 
                { &hf_rx_spare, {
                        "Spare/Checksum", "rx.spare", FT_UINT16, BASE_DEC,
-                       NULL, 0, "Spare/Checksum" }},
+                       NULL, 0, "Spare/Checksum", HFILL }},
 
                { &hf_rx_serviceid, {
                        "Service ID", "rx.serviceid", FT_UINT16, BASE_DEC,
-                       NULL, 0, "Service ID" }},
+                       NULL, 0, "Service ID", HFILL }},
 
                { &hf_rx_bufferspace, {
                        "Bufferspace", "rx.bufferspace", FT_UINT16, BASE_DEC,
-                       NULL, 0, "Number Of Packets Available" }},
+                       NULL, 0, "Number Of Packets Available", HFILL }},
 
                { &hf_rx_maxskew, {
                        "Max Skew", "rx.maxskew", FT_UINT16, BASE_DEC,
-                       NULL, 0, "Max Skew" }},
+                       NULL, 0, "Max Skew", HFILL }},
 
                { &hf_rx_first_packet, {
                        "First Packet", "rx.first", FT_UINT32, BASE_DEC,
-                       NULL, 0, "First Packet" }},
+                       NULL, 0, "First Packet", HFILL }},
 
                { &hf_rx_prev_packet, {
                        "Prev Packet", "rx.prev", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Previous Packet" }},
+                       NULL, 0, "Previous Packet", HFILL }},
 
                { &hf_rx_reason, {
                        "Reason", "rx.reason", FT_UINT8, BASE_DEC,
-                       VALS(rx_reason), 0, "Reason For This ACK" }},
+                       VALS(rx_reason), 0, "Reason For This ACK", HFILL }},
 
                { &hf_rx_numacks, {
                        "Num ACKs", "rx.num_acks", FT_UINT8, BASE_DEC,
-                       NULL, 0, "Number Of ACKs" }},
+                       NULL, 0, "Number Of ACKs", HFILL }},
 
                { &hf_rx_ack_type, {
                        "ACK Type", "rx.ack_type", FT_UINT8, BASE_DEC,
-                       VALS(rx_ack_type), 0, "Type Of ACKs" }},
+                       VALS(rx_ack_type), 0, "Type Of ACKs", HFILL }},
 
                { &hf_rx_ack, {
                        "ACK Packet", "rx.ack", FT_NONE, BASE_NONE,
-                       NULL, 0, "ACK Packet" }},
+                       NULL, 0, "ACK Packet", HFILL }},
 
                { &hf_rx_challenge, {
                        "CHALLENGE Packet", "rx.challenge", FT_NONE, BASE_NONE,
-                       NULL, 0, "CHALLENGE Packet" }},
+                       NULL, 0, "CHALLENGE Packet", HFILL }},
 
                { &hf_rx_version, {
                        "Version", "rx.version", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Version Of Challenge/Response" }},
+                       NULL, 0, "Version Of Challenge/Response", HFILL }},
 
                { &hf_rx_nonce, {
                        "Nonce", "rx.nonce", FT_UINT32, BASE_HEX,
-                       NULL, 0, "Nonce" }},
+                       NULL, 0, "Nonce", HFILL }},
 
                { &hf_rx_inc_nonce, {
                        "Inc Nonce", "rx.inc_nonce", FT_UINT32, BASE_HEX,
-                       NULL, 0, "Incremented Nonce" }},
+                       NULL, 0, "Incremented Nonce", HFILL }},
 
                { &hf_rx_min_level, {
                        "Min Level", "rx.min_level", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Min Level" }},
+                       NULL, 0, "Min Level", HFILL }},
 
                { &hf_rx_level, {
                        "Level", "rx.level", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Level" }},
+                       NULL, 0, "Level", HFILL }},
 
                { &hf_rx_response, {
                        "RESPONSE Packet", "rx.response", FT_NONE, BASE_NONE,
-                       NULL, 0, "RESPONSE Packet" }},
+                       NULL, 0, "RESPONSE Packet", HFILL }},
+
+               { &hf_rx_abort, {
+                       "ABORT Packet", "rx.abort", FT_NONE, BASE_NONE,
+                       NULL, 0, "ABORT Packet", HFILL }},
 
                { &hf_rx_encrypted, {
                        "Encrypted", "rx.encrypted", FT_NONE, BASE_NONE,
-                       NULL, 0, "Encrypted part of response packet" }},
+                       NULL, 0, "Encrypted part of response packet", HFILL }},
 
                { &hf_rx_kvno, {
                        "kvno", "rx.kvno", FT_UINT32, BASE_DEC,
-                       NULL, 0, "kvno" }},
+                       NULL, 0, "kvno", HFILL }},
 
                { &hf_rx_ticket_len, {
                        "Ticket len", "rx.ticket_len", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Ticket Length" }},
+                       NULL, 0, "Ticket Length", HFILL }},
 
                { &hf_rx_ticket, {
                        "ticket", "rx.ticket", FT_BYTES, BASE_HEX,
-                       NULL, 0, "Ticket" }},
+                       NULL, 0, "Ticket", HFILL }},
+
+               { &hf_rx_ifmtu, {
+                       "Interface MTU", "rx.if_mtu", FT_UINT32, BASE_DEC,
+                       NULL, 0, "Interface MTU", HFILL }},
+
+               { &hf_rx_maxmtu, {
+                       "Max MTU", "rx.max_mtu", FT_UINT32, BASE_DEC,
+                       NULL, 0, "Max MTU", HFILL }},
+
+               { &hf_rx_rwind, {
+                       "rwind", "rx.rwind", FT_UINT32, BASE_DEC,
+                       NULL, 0, "rwind", HFILL }},
+
+               { &hf_rx_maxpackets, {
+                       "Max Packets", "rx.max_packets", FT_UINT32, BASE_DEC,
+                       NULL, 0, "Max Packets", HFILL }},
+
+               { &hf_rx_abortcode, {
+                       "Abort Code", "rx.abort_code", FT_UINT32, BASE_DEC,
+                       NULL, 0, "Abort Code", HFILL }},
 
        };
        static gint *ett[] = {
@@ -676,6 +760,7 @@ proto_register_rx(void)
                &ett_rx_challenge,
                &ett_rx_response,
                &ett_rx_encrypted,
+               &ett_rx_abort
        };
 
        proto_rx = proto_register_protocol("RX Protocol", "RX", "rx");
@@ -686,12 +771,19 @@ proto_register_rx(void)
 void
 proto_reg_handoff_rx(void)
 {
+       dissector_handle_t rx_handle;
+
        int port;
 
+       /*
+        * Get handle for the AFS dissector.
+        */
+       afs_handle = find_dissector("afs");
+
        /* Ports in the range UDP_PORT_RX_LOW to UDP_PORT_RX_HIGH
           are all used for various AFS services. */
+       rx_handle = create_dissector_handle(dissect_rx, proto_rx);
        for (port = UDP_PORT_RX_LOW; port <= UDP_PORT_RX_HIGH; port++)
-               dissector_add("udp.port", port, dissect_rx, proto_rx);
-       dissector_add("udp.port", UDP_PORT_RX_AFS_BACKUPS, dissect_rx,
-           proto_rx);
+               dissector_add("udp.port", port, rx_handle);
+       dissector_add("udp.port", UDP_PORT_RX_AFS_BACKUPS, rx_handle);
 }