Don't guard col_set_str (COL_INFO/COL_PROTOCOL) with col_check
[obnox/wireshark/wip.git] / epan / dissectors / packet-rlogin.c
index 1a460fd69c8faf46587544dfdc4e03fb35534eb7..c3008116a4e4ced9b47f0c6524b479712ba8a295 100644 (file)
@@ -4,8 +4,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * Based upon RFC-1282 - BSD Rlogin
 
 #include <epan/packet.h>
 #include <epan/conversation.h>
+#include <epan/emem.h>
 
 #include "packet-tcp.h"
 
-#define TCP_PORT_RLOGIN 513
+#define RLOGIN_PORT 513
 
 static int proto_rlogin = -1;
 
@@ -51,143 +52,160 @@ static int ett_rlogin_window_x_pixels = -1;
 static int ett_rlogin_window_y_pixels = -1;
 
 static int hf_user_info = -1;
+static int hf_client_startup_flag = -1;
+static int hf_startup_info_received_flag = -1;
+static int hf_user_info_client_user_name = -1;
+static int hf_user_info_server_user_name = -1;
+static int hf_user_info_terminal_type = -1;
+static int hf_user_info_terminal_speed = -1;
+static int hf_control_message = -1;
 static int hf_window_info = -1;
+static int hf_window_info_ss = -1;
 static int hf_window_info_rows = -1;
 static int hf_window_info_cols = -1;
 static int hf_window_info_x_pixels = -1;
 static int hf_window_info_y_pixels = -1;
+static int hf_data = -1;
 
-#define RLOGIN_PORT 513
-
-#define NAME_LEN 32
-
-typedef struct {
-       int     state;
-       guint32 info_framenum;
-       char    name[ NAME_LEN];
-
-} rlogin_hash_entry_t;
-
-#define NONE           0
-#define USER_INFO_WAIT 1
-#define DONE           2
-#define BAD            2
-
-static GMemChunk *rlogin_vals = NULL;
-
-#define rlogin_hash_init_count 20
-
-static guint32 last_abs_sec = 0;
-static guint32 last_abs_usec= 0;
-
-static void
-rlogin_init(void)
+static const value_string control_message_vals[] =
 {
+    { 0x02,     "Clear buffer"        },
+    { 0x10,     "Raw mode"            },
+    { 0x20,     "Cooked mode"         },
+    { 0x80,     "Window size request" },
+    { 0, NULL }
+};
 
-/* Routine to initialize rlogin protocol before each capture or filter pass. */
-/* Release any memory if needed.  Then setup the memory chunks.                */
-
-       last_abs_sec = 0;
-       last_abs_usec= 0;
 
-       if (rlogin_vals)
-               g_mem_chunk_destroy(rlogin_vals);
+typedef enum  {
+       NONE=0,
+       USER_INFO_WAIT=1,
+       DONE=2
+} session_state_t;
 
-       rlogin_vals = g_mem_chunk_new("rlogin_vals",
-               sizeof( rlogin_hash_entry_t),
-               rlogin_hash_init_count * sizeof( rlogin_hash_entry_t),
-               G_ALLOC_AND_FREE);
-}
+#define NAME_LEN 32
+typedef struct {
+       session_state_t  state;
+       guint32          info_framenum;
+       char             user_name[NAME_LEN];
+} rlogin_hash_entry_t;
 
 
-/**************** Decoder State Machine ******************/
 
+/* Decoder State Machine.  Currently only used to snoop on
+   client-user-name as sent by the client up connection establishment.
+*/
 static void
-rlogin_state_machine( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
-       packet_info *pinfo)
+rlogin_state_machine(rlogin_hash_entry_t *hash_info, tvbuff_t *tvb, packet_info *pinfo)
 {
        guint length;
        gint stringlen;
 
-/* rlogin stream decoder */
-/* Just watched for second packet from client with the user name and   */
-/* terminal type information.                                          */
+       /* Won't change state if already seen this packet */
+       if (pinfo->fd->flags.visited)
+       {
+               return;
+       }
 
+       /* rlogin stream decoder */
+       /* Just watch for the second packet from client with the user name and */
+       /* terminal type information. */
 
-       if ( pinfo->destport != RLOGIN_PORT)   /* not from client */
+       if (pinfo->destport != RLOGIN_PORT)
+       {
                return;
-                                               /* exit if not needed */
-       if (( hash_info->state == DONE) || (  hash_info->state == BAD))
+       }
+       
+       /* exit if already passed username in conversation */
+       if (hash_info->state == DONE)
+       {
                return;
+       }
 
-                                               /* test timestamp */
-       if (( last_abs_sec > pinfo->fd->abs_secs) ||
-           (( last_abs_sec == pinfo->fd->abs_secs) &&
-            ( last_abs_usec >= pinfo->fd->abs_usecs)))
-               return;
-
-       last_abs_sec = pinfo->fd->abs_secs;             /* save timestamp */
-       last_abs_usec = pinfo->fd->abs_usecs;
-
+       /* exit if no data */
        length = tvb_length(tvb);
-       if ( length == 0)                               /* exit if no data */
+       if (length == 0)
+       {
                return;
+       }
 
-       if ( hash_info->state == NONE){                 /* new connection*/
-               if (tvb_get_guint8(tvb, 0) != '\0') {
-                       /*
-                        * We expected a NUL, but didn't get one; quit.
-                        */
+       if (hash_info->state == NONE)
+       {
+               /* new connection*/
+               if (tvb_get_guint8(tvb, 0) != '\0')
+               {
+                       /* We expected a null, but didn't get one; quit. */
                        hash_info->state = DONE;
                        return;
                }
-               else {
-                       if (length <= 1)                /* if no data   */
+               else 
+               {
+                       if (length <= 1)
+                       {
+                               /* Still waiting for data */
                                hash_info->state = USER_INFO_WAIT;
-                       else {
+                       }
+                       else
+                       {
+                               /* Have info, store frame number */
                                hash_info->state = DONE;
                                hash_info->info_framenum = pinfo->fd->num;
                        }
                }
-       }                                       /* expect user data here */
-/*$$$ may need to do more checking here */
-       else if ( hash_info->state == USER_INFO_WAIT) {
+       }
+       /* expect user data here */
+       /* TODO: may need to do more checking here? */
+       else
+       if (hash_info->state == USER_INFO_WAIT)
+       {
+               /* Store frame number here */
                hash_info->state = DONE;
                hash_info->info_framenum = pinfo->fd->num;
-                                                       /* save name for later*/
+
+               /* Work out length of string to copy */
                stringlen = tvb_strnlen(tvb, 0, NAME_LEN);
                if (stringlen == -1)
-                       stringlen = NAME_LEN - 1;       /* no '\0' found */
+                       stringlen = NAME_LEN - 1;   /* no '\0' found */
                else if (stringlen > NAME_LEN - 1)
-                       stringlen = NAME_LEN - 1;       /* name too long */
-               tvb_memcpy(tvb, (guint8 *)hash_info->name, 0, stringlen);
-               hash_info->name[stringlen] = '\0';
+                       stringlen = NAME_LEN - 1;   /* name too long */
 
-               if (check_col(pinfo->cinfo, COL_INFO))  /* update summary */
-                       col_append_str(pinfo->cinfo, COL_INFO,
-                           ", User information");
+               /* Copy and terminate string into hash name */
+               tvb_memcpy(tvb, (guint8 *)hash_info->user_name, 0, stringlen);
+               hash_info->user_name[stringlen] = '\0';
+
+               if (check_col(pinfo->cinfo, COL_INFO))
+               {
+                       col_append_str(pinfo->cinfo, COL_INFO, ", (User information)");
+               }
        }
 }
 
-static void rlogin_display( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
-       packet_info *pinfo, proto_tree *tree, struct tcpinfo *tcpinfo)
+/* Dissect details of packet */
+static void rlogin_display(rlogin_hash_entry_t *hash_info,
+                           tvbuff_t *tvb,
+                           packet_info *pinfo,
+                           proto_tree *tree,
+                           struct tcpinfo *tcpinfo)
 {
-/* Display the proto tree */
+       /* Display the proto tree */
        int             offset = 0;
        proto_tree      *rlogin_tree, *user_info_tree, *window_tree;
        proto_item      *ti;
        guint           length;
-       int             str_len;
-       gint            ti_offset;
-       proto_item      *user_info_item,  *window_info_item;
-
-       ti = proto_tree_add_item( tree, proto_rlogin, tvb, 0, -1, FALSE);
+       int             str_len;
+       gint            ti_offset;
+       proto_item      *user_info_item, *window_info_item;
 
+       /* Create rlogin subtree */
+       ti = proto_tree_add_item(tree, proto_rlogin, tvb, 0, -1, FALSE);
        rlogin_tree = proto_item_add_subtree(ti, ett_rlogin);
 
+       /* Return if data empty */
        length = tvb_length(tvb);
-       if ( length == 0)                       /* exit if no captured data */
+       if (length == 0)
+       {
                return;
+       }
 
        /*
         * XXX - this works only if the urgent pointer points to something
@@ -195,139 +213,180 @@ static void rlogin_display( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
         * to something past this segment, we'd have to remember the urgent
         * pointer setting for this conversation.
         */
-       if ( tcpinfo->urgent &&                 /* if urgent pointer set */
-            length >= tcpinfo->urgent_pointer) {       /* and it's in this frame */
-
+       if (tcpinfo->urgent &&                 /* if urgent pointer set */
+           length >= tcpinfo->urgent_pointer) /* and it's in this frame */
+       {
+               /* Get urgent byte into Temp */
                int urgent_offset = tcpinfo->urgent_pointer - 1;
-               guint8 Temp = tvb_get_guint8(tvb, urgent_offset);
-
-               if (urgent_offset > offset)     /* check for data in front */
-                       proto_tree_add_text( rlogin_tree, tvb, offset,
-                           urgent_offset, "Data");
-
-               proto_tree_add_text( rlogin_tree, tvb, urgent_offset, 1,
-                               "Control byte: %u (%s)",
-                               Temp,
-                               (Temp == 0x02) ? "Clear buffer" :
-                               (Temp == 0x10) ? "Raw mode" :
-                               (Temp == 0x20) ? "Cooked mode" :
-                               (Temp == 0x80) ? "Window size request" :
-                               "Unknown");
-               offset = urgent_offset + 1;     /* adjust offset */
-       }
-       else if ( tvb_get_guint8(tvb, offset) == '\0'){   /* startup */
-               if ( pinfo->srcport== RLOGIN_PORT)   /* from server */
-                       proto_tree_add_text(rlogin_tree, tvb, offset, 1,
-                                       "Startup info received flag (0x00)");
+               guint8 control_byte;
+
+               /* Check for text data in front */
+               if (urgent_offset > offset)
+               {
+                       proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, urgent_offset, FALSE);
+               }
 
+               /* Show control byte */
+               proto_tree_add_item(rlogin_tree, hf_control_message, tvb,
+                                   urgent_offset, 1, FALSE);
+               control_byte = tvb_get_guint8(tvb, urgent_offset);
+               if (check_col(pinfo->cinfo, COL_INFO))
+               {
+                       col_append_fstr(pinfo->cinfo, COL_INFO,
+                                      " (%s)", val_to_str(control_byte, control_message_vals, "Unknown"));
+               }
+
+               offset = urgent_offset + 1; /* adjust offset */
+       }
+       else
+       if (tvb_get_guint8(tvb, offset) == '\0')
+       {
+               /* Startup */
+               if (pinfo->srcport == RLOGIN_PORT)   /* from server */
+               {
+                       proto_tree_add_item(rlogin_tree, hf_startup_info_received_flag,
+                                           tvb, offset, 1, FALSE);
+               }
                else
-                       proto_tree_add_text(rlogin_tree, tvb, offset, 1,
-                                       "Client Startup Flag (0x00)");
+               {
+                       proto_tree_add_item(rlogin_tree, hf_client_startup_flag,
+                                           tvb, offset, 1, FALSE);
+               }
                ++offset;
        }
 
        if (!tvb_offset_exists(tvb, offset))
-               return; /* No more data to check */
-
-       if ( hash_info->info_framenum == pinfo->fd->num){
-               /*
-                * First frame of conversation, hence user info?
-                */
-               user_info_item = proto_tree_add_item( rlogin_tree, hf_user_info, tvb,
-                       offset, -1, FALSE);
-
-               /*
-                * Do server user name.
-                */
-               str_len = tvb_strsize(tvb, offset);
-               user_info_tree = proto_item_add_subtree( user_info_item,
-                       ett_rlogin_user_info);
-               proto_tree_add_text(user_info_tree, tvb, offset, str_len,
-                               "Server User Name: %.*s", str_len - 1,
-                               tvb_get_ptr(tvb, offset, str_len - 1));
-               offset += str_len;
+       {
+               /* No more data to check */
+               return;
+       }
+
+       if (hash_info->info_framenum == pinfo->fd->num)
+       {
+               gint info_len;
+               gint slash_offset;
+
+               /* First frame of conversation, assume user info... */
+               
+               info_len = tvb_length_remaining(tvb, offset);
 
-               /*
-                * Do client user name.
-                */
+               /* User info tree */
+               user_info_item = proto_tree_add_string_format(rlogin_tree, hf_user_info, tvb,
+                                                             offset, info_len, FALSE,
+                                                             "User info (%s)",
+                                                             tvb_format_text(tvb, offset, info_len));
+               user_info_tree = proto_item_add_subtree(user_info_item,
+                                                       ett_rlogin_user_info);
+
+               /* Client user name. */
                str_len = tvb_strsize(tvb, offset);
-               proto_tree_add_text(user_info_tree, tvb, offset, str_len,
-                               "Client User Name: %.*s", str_len - 1,
-                               tvb_get_ptr(tvb, offset, str_len - 1));
+               proto_tree_add_item(user_info_tree, hf_user_info_client_user_name,
+                                   tvb, offset, str_len, FALSE);
                offset += str_len;
 
-               /*
-                * Do terminal type/speed.
-                */
+               /* Server user name. */
                str_len = tvb_strsize(tvb, offset);
-               proto_tree_add_text(user_info_tree, tvb, offset, str_len,
-                               "Terminal Type/Speed: %.*s", str_len - 1,
-                               tvb_get_ptr(tvb, offset, str_len - 1));
+               proto_tree_add_item(user_info_tree, hf_user_info_server_user_name,
+                                   tvb, offset, str_len, FALSE);
                offset += str_len;
+
+               /* Terminal type/speed. */
+               slash_offset = tvb_find_guint8(tvb, offset, -1, '/');
+               if (slash_offset != -1)
+               {
+                       /* Terminal type */
+                       proto_tree_add_item(user_info_tree, hf_user_info_terminal_type,
+                                           tvb, offset, slash_offset-offset, FALSE);
+                       offset = slash_offset + 1;
+                       
+                       /* Terminal speed */
+                       str_len = tvb_strsize(tvb, offset);
+                       proto_tree_add_uint(user_info_tree, hf_user_info_terminal_speed,
+                                           tvb, offset, str_len,
+                                           atoi(tvb_format_text(tvb, offset, str_len)));
+                       offset += str_len;
+               }
        }
 
        if (!tvb_offset_exists(tvb, offset))
-               return; /* No more data to check */
-
-/* test for terminal information, the data will have 2 0xff bytes */
+       {
+               /* No more data to check */
+               return;
+       }
 
-                                               /* look for first 0xff byte */
+       /* Test for terminal information, the data will have 2 0xff bytes */
+       /* look for first 0xff byte */
        ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff);
 
+       /* Next byte must also be 0xff */
        if (ti_offset != -1 &&
            tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
-           tvb_get_guint8(tvb, ti_offset + 1) == 0xff) {
-               /*
-                * Found terminal info.
-                */
-               if (ti_offset > offset) {
-                       /*
-                        * There's data before the terminal info.
-                        */
-                       proto_tree_add_text( rlogin_tree, tvb, offset,
-                               (ti_offset - offset), "Data");
-                       offset = ti_offset;
-               }
-
-               window_info_item = proto_tree_add_item(rlogin_tree,
-                               hf_window_info, tvb, offset, 12, FALSE );
-
-               window_tree = proto_item_add_subtree(window_info_item,
-                                        ett_rlogin_window);
-
-               proto_tree_add_text(window_tree, tvb, offset, 2,
-                       "Magic Cookie: (0xff, 0xff)");
+           tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
+       {
+               guint16 rows, columns;
+               
+               /* Have found terminal info. */
+               if (ti_offset > offset)
+               {
+                       /* There's data before the terminal info. */
+                       proto_tree_add_item(rlogin_tree, hf_data, tvb,
+                                           offset, ti_offset - offset, FALSE);
+               }
+
+               /* Create window info tree */
+               window_info_item =
+                       proto_tree_add_item(rlogin_tree, hf_window_info, tvb, offset, 12, FALSE);
+               window_tree = proto_item_add_subtree(window_info_item, ett_rlogin_window);
+
+               /* Cookie */
+               proto_tree_add_text(window_tree, tvb, offset, 2, "Magic Cookie: (0xff, 0xff)");
                offset += 2;
 
-               proto_tree_add_text(window_tree, tvb, offset, 2,
-                       "Window size marker: 'ss'");
+               /* These bytes should be "ss" */
+               proto_tree_add_item(window_tree, hf_window_info_ss, tvb, offset, 2, FALSE);
                offset += 2;
 
-               proto_tree_add_item(window_tree, hf_window_info_rows, tvb,
-                       offset, 2, FALSE);
+               /* Character rows */
+               rows = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item(window_tree, hf_window_info_rows, tvb,
+                                   offset, 2, FALSE);
                offset += 2;
 
-               proto_tree_add_item(window_tree, hf_window_info_cols, tvb,
-                       offset, 2, FALSE);
+               /* Characters per row */
+               columns = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item(window_tree, hf_window_info_cols, tvb,
+                                   offset, 2, FALSE);
                offset += 2;
 
-               proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb,
-                       offset, 2, FALSE);
+               /* x pixels */
+               proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb,
+                                   offset, 2, FALSE);
                offset += 2;
 
+               /* y pixels */
                proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb,
-                       offset, 2, FALSE);
+                                   offset, 2, FALSE);
                offset += 2;
+               
+               /* Show setting highlights in info column */
+               if (check_col(pinfo->cinfo, COL_INFO))
+               {
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " (rows=%u, cols=%u)",
+                                       rows, columns);
+               }
        }
 
-       if (tvb_offset_exists(tvb, offset)) {
-               /*
-                * There's more data in the frame.
-                */
-               proto_tree_add_text(rlogin_tree, tvb, offset, -1, "Data");
+       if (tvb_offset_exists(tvb, offset))
+       {
+               /* There's more data in the frame. */
+               proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, -1, FALSE);
        }
 }
 
+
+/****************************************************************
+ * Main dissection function
+ ****************************************************************/
 static void
 dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -337,80 +396,108 @@ dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        guint length;
        gint ti_offset;
 
-                                               /* Lookup this connection*/
-       conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst,
-               pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
-
-       if ( !conversation) {
-               conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                       pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+       /* Get conversation */
+       conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+                                        pinfo->ptype, pinfo->srcport, pinfo->destport,
+                                     0);
+
+       /* Create if didn't previously exist */
+       if (!conversation)
+       {
+               conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+                                               pinfo->ptype, pinfo->srcport, pinfo->destport,
+                                               0);
        }
+
+       /* Get or create data associated with this conversation */
        hash_info = conversation_get_proto_data(conversation, proto_rlogin);
-       if ( !hash_info) {
-               hash_info = g_mem_chunk_alloc(rlogin_vals);
+       if (!hash_info)
+       {
+               /* Populate new data struct... */
+               hash_info = se_alloc(sizeof(rlogin_hash_entry_t));
                hash_info->state = NONE;
-               hash_info->info_framenum = 0;   /* no frame has the number 0 */
-               hash_info->name[ 0] = 0;
-               conversation_add_proto_data(conversation, proto_rlogin,
-                       hash_info);
+               hash_info->info_framenum = 0;  /* no frame has the number 0 */
+               hash_info->user_name[0] = '\0';
+
+               /* ... and store in conversation */
+               conversation_add_proto_data(conversation, proto_rlogin, hash_info);
        }
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))              /* update protocol  */
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");
+       /* Set protocol column text */
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");
 
-       if (check_col(pinfo->cinfo, COL_INFO)){         /* display packet info*/
-               if ( hash_info->name[0]) {
+       /* Set info column */
+       if (check_col(pinfo->cinfo, COL_INFO))
+       {
+               /* Show user-name if available */
+               if (hash_info->user_name[0])
+               {
                        col_add_fstr(pinfo->cinfo, COL_INFO,
-                           "User name: %s, ", hash_info->name);
+                                     "User name: %s, ", hash_info->user_name);
                }
                else
+               {
                        col_clear(pinfo->cinfo, COL_INFO);
+               }
 
+               /* Work out packet content summary for display */
                length = tvb_length(tvb);
-               if (length != 0) {
-                       if ( tvb_get_guint8(tvb, 0) == '\0') {
+               if (length != 0)
+               {
+                       /* Initial NULL byte represents part of connection handshake */
+                       if (tvb_get_guint8(tvb, 0) == '\0')
+                       {
                                col_append_str(pinfo->cinfo, COL_INFO,
-                                   "Start Handshake");
+                                              (pinfo->destport == RLOGIN_PORT) ?
+                                                  "Start Handshake" :
+                                                  "Startup info received");
                        }
-                       else if ( tcpinfo->urgent &&
-                                 length >= tcpinfo->urgent_pointer ) {
-                               col_append_str(pinfo->cinfo, COL_INFO,
-                                   "Control Message");
+                       else
+                       if (tcpinfo->urgent && length >= tcpinfo->urgent_pointer)
+                       {
+                               /* Urgent pointer inside current data represents a control message */
+                               col_append_str(pinfo->cinfo, COL_INFO, "Control Message");
                        }
-                       else {                  /* check for terminal info */
+                       else
+                       {
+                               /* Search for 2 consecutive ff bytes
+                                 (signifies window change control message) */
                                ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff);
                                if (ti_offset != -1 &&
                                    tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
-                                   tvb_get_guint8(tvb, ti_offset + 1) == 0xff) {
-                                       col_append_str(pinfo->cinfo, COL_INFO,
-                                           "Terminal Info");
+                                   tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
+                               {
+                                       col_append_str(pinfo->cinfo, COL_INFO, "Terminal Info");
                                }
-                               else {
-                                       int bytes_to_copy;
-
-                                       bytes_to_copy = tvb_length(tvb);
+                               else
+                               {
+                                       /* Show any text data in the frame */
+                                       int bytes_to_copy = tvb_length(tvb);
                                        if (bytes_to_copy > 128)
+                                       {
+                                               /* Truncate to 128 bytes for display */
                                                bytes_to_copy = 128;
+                                       }
+       
+                                       /* Add data into info column */
                                        col_append_fstr(pinfo->cinfo, COL_INFO,
-                                           "Data: %s",
-                                           tvb_format_text(tvb, 0, bytes_to_copy));
+                                                       "Data: %s",
+                                                        tvb_format_text(tvb, 0, bytes_to_copy));
                                }
                        }
                }
        }
 
-       rlogin_state_machine( hash_info, tvb, pinfo);
+       /* See if conversation state needs to be updated */
+       rlogin_state_machine(hash_info, tvb, pinfo);
 
-       if ( tree)                              /* if proto tree, decode data */
-               rlogin_display( hash_info, tvb, pinfo, tree, tcpinfo);
+       /* Dissect in detail */
+       rlogin_display(hash_info, tvb, pinfo, tree, tcpinfo);
 }
 
 
-void
-proto_register_rlogin( void){
-
-/* Prep the rlogin protocol, for now, just register it */
-
+void proto_register_rlogin(void)
+{
        static gint *ett[] = {
                &ett_rlogin,
                &ett_rlogin_window,
@@ -421,56 +508,94 @@ proto_register_rlogin( void){
                &ett_rlogin_user_info
        };
 
-       static hf_register_info hf[] = {
-
+       static hf_register_info hf[] =
+       {
                { &hf_user_info,
-                       { "User Info", "rlogin.user_info", FT_NONE, BASE_NONE,
-                                NULL, 0x0, "", HFILL
+                       { "User Info", "rlogin.user_info", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_client_startup_flag,
+                       { "Client startup flag", "rlogin.client_startup_flag", FT_UINT8, BASE_HEX,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_startup_info_received_flag,
+                       { "Startup info received flag", "rlogin.startup_info_received_flag", FT_UINT8, BASE_HEX,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_user_info_client_user_name,
+                       { "Client-user-name", "rlogin.client_user_name", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_user_info_server_user_name,
+                       { "Server-user-name", "rlogin.server_user_name", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_user_info_terminal_type,
+                       { "Terminal-type", "rlogin.terminal_type", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
                        }
                },
+               { &hf_user_info_terminal_speed,
+                       { "Terminal-speed", "rlogin.terminal_speed", FT_UINT32, BASE_DEC,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_control_message,
+                       { "Control message", "rlogin.control_message", FT_UINT8, BASE_HEX,
+                                VALS(control_message_vals), 0x0, NULL, HFILL
+                       }
+               },              
                { &hf_window_info,
                        { "Window Info", "rlogin.window_size", FT_NONE, BASE_NONE,
-                                NULL, 0x0, "", HFILL
+                                NULL, 0x0, NULL, HFILL
                        }
                },
+               { &hf_window_info_ss,
+                       { "Window size marker", "rlogin.window_size.ss", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },              
                { &hf_window_info_rows,
                        { "Rows", "rlogin.window_size.rows", FT_UINT16, BASE_DEC,
-                                NULL, 0x0, "", HFILL
+                                NULL, 0x0, NULL, HFILL
                        }
                },
                { &hf_window_info_cols,
                        { "Columns", "rlogin.window_size.cols", FT_UINT16, BASE_DEC,
-                                NULL, 0x0, "", HFILL
+                                NULL, 0x0, NULL, HFILL
                        }
                },
                { &hf_window_info_x_pixels,
                        { "X Pixels", "rlogin.window_size.x_pixels", FT_UINT16, BASE_DEC,
-                                NULL, 0x0, "", HFILL
+                                NULL, 0x0, NULL, HFILL
                        }
                },
                { &hf_window_info_y_pixels,
                        { "Y Pixels", "rlogin.window_size.y_pixels", FT_UINT16, BASE_DEC,
-                                NULL, 0x0, "", HFILL
+                                NULL, 0x0, NULL, HFILL
+                       }
+               },
+               { &hf_data,
+                       { "Data", "rlogin.data", FT_STRING, BASE_NONE,
+                                NULL, 0x0, NULL, HFILL
                        }
                }
        };
 
-       proto_rlogin = proto_register_protocol (
-               "Rlogin Protocol", "Rlogin", "rlogin");
+       proto_rlogin = proto_register_protocol("Rlogin Protocol", "Rlogin", "rlogin");
 
        proto_register_field_array(proto_rlogin, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
-
-       register_init_routine( &rlogin_init);   /* register re-init routine */
 }
 
-void
-proto_reg_handoff_rlogin(void) {
-
-       /* dissector install routine */
-
-       dissector_handle_t rlogin_handle;
-
-       rlogin_handle = create_dissector_handle(dissect_rlogin, proto_rlogin);
-       dissector_add("tcp.port", TCP_PORT_RLOGIN, rlogin_handle);
+void proto_reg_handoff_rlogin(void)
+{
+       /* Dissector install routine */
+       dissector_handle_t rlogin_handle = create_dissector_handle(dissect_rlogin,proto_rlogin);
+       dissector_add("tcp.port", RLOGIN_PORT, rlogin_handle);
 }