Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-socks.c
index 702b3acb4890cb63be78ee30dbd5fd8f023f52d8..a623c06b1a581d1a34985d5911c03f854ece674b 100644 (file)
@@ -2,12 +2,11 @@
  * Routines for socks versions 4 &5  packet dissection
  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
  *
- * $Id: packet-socks.c,v 1.4 2000/05/11 08:15:49 gram Exp $
+ * $Id: packet-socks.c,v 1.42 2002/08/02 23:36:03 jmayer Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- *
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  *
  * See http://www.socks.nec.com/socksprot.html for these and other documents
  *
+ * Revisions:
+ *
+ * 2001-01-08 JCFoster Fixed problem with NULL pointer for hash data.
+ *                     Now test and exit if hash_info is null.
  */
 
 /* Possible enhancements -
 #endif
 
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include <stdio.h>
 #include <string.h>
 #include <glib.h>
-#include "packet.h"
-#include "resolv.h"
-#include "globals.h"
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
 #include "alignment.h"
-#include "conversation.h"
+#include <epan/conversation.h>
 
 #include "packet-tcp.h"
 #include "packet-udp.h"
-
-#ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-#  include <stdarg.h>
-# else
-#  include <varargs.h>
-# endif
-# include "snprintf.h"
-#endif
-
+#include <epan/strutil.h>
 
 
-#define CHECK_PACKET_LENGTH(X) if ((offset+X) > fd->cap_len){  \
-        proto_tree_add_text(tree, NullTVB, offset, 0, "*** FRAME TOO SHORT ***"); \
-        return; }
-
-#define compare_packet(X) (X == (fd->num))
-#define get_packet_ptr (fd->num)
+#define compare_packet(X) (X == (pinfo->fd->num))
+#define get_packet_ptr (pinfo->fd->num)
 #define row_pointer_type guint32
 
 #define TCP_PORT_SOCKS 1080
@@ -125,8 +107,16 @@ static int hf_socks_ip_dst = -1;
 static int hf_socks_ip6_dst = -1;
 static int hf_user_name = -1;
 static int hf_socks_dstport = -1;
-static int hf_socks_command = -1;
+static int hf_socks_cmd = -1;
+static int hf_socks_results = -1;
+static int hf_socks_results_4 = -1;
+static int hf_socks_results_5 = -1;
+
 
+/************* Dissector handles ***********/
+
+static dissector_handle_t socks_handle;
+static dissector_handle_t socks_udp_handle;
 
 /************* State Machine names ***********/
 
@@ -147,15 +137,15 @@ enum SockState {
 
 
 typedef struct {
-       int     state;
-       int     version;
-       int     command;
-       int     grant;
-       gint32  port;
-       gint32  udp_port;
-       gint32  udp_remote_port;
+       int             state;
+       int             version;
+       int             command;
+       int             grant;
+       guint32         port;
+       guint32         udp_port;
+       guint32         udp_remote_port;
        
-       int     connect_offset;
+       int             connect_offset;
        row_pointer_type        v4_name_row;
        row_pointer_type        v4_user_name_row;
        row_pointer_type        connect_row;
@@ -184,6 +174,7 @@ static char *address_type_table[] = {
 
 /* String table for the V4 reply status messages */
 
+#ifdef __JUNK__
 static char *reply_table_v4[] = {
        "Granted",
        "Rejected or Failed",
@@ -191,10 +182,19 @@ static char *reply_table_v4[] = {
        "Rejected because the client program and identd report different user-ids",
        "Unknown"
 };
+#endif
 
+static const value_string reply_table_v4[] = {
+       {90, "Granted"},
+       {91, "Rejected or Failed"},
+       {92, "Rejected because SOCKS server cannot connect to identd on the client"},
+       {93, "Rejected because the client program and identd report different user-ids"},
+       {0, NULL}
+};
 
 /* String table for the V5 reply status messages */
 
+#ifdef __JUNK__
 static char *reply_table_v5[] = {
        "Succeeded",
        "General SOCKS server failure",
@@ -207,7 +207,29 @@ static char *reply_table_v5[] = {
        "Address type not supported",
        "Unknown"
 };
+#endif 
+
+static const value_string reply_table_v5[] = {
+       {0, "Succeeded"},
+       {1, "General SOCKS server failure"},
+       {2, "Connection not allowed by ruleset"},
+       {3, "Network unreachable"},
+       {4, "Host unreachable"},
+       {5, "Connection refused"},
+       {6, "TTL expired"},
+       {7, "Command not supported"},
+       {8, "Address type not supported"}
+};
 
+static const value_string cmd_strings[] = {
+       {0, "Unknow"},
+       {1, "Connect"},
+       {2, "Bind"}, 
+       {3, "UdpAssociate"},
+       {0x80, "Ping"},
+       {0x81, "Traceroute"},
+       {0, NULL}
+};
 
 #define socks_hash_init_count 20
 #define socks_hash_val_length (sizeof(socks_hash_entry_t))
@@ -218,7 +240,7 @@ static GMemChunk *socks_vals = NULL;
 /************************* Support routines ***************************/
 
 
-static int display_string( const u_char *pd, int offset, frame_data *fd,
+static int display_string(tvbuff_t *tvb, int offset,
        proto_tree *tree, char *label){
 
 /* display a string with a length, characters encoding */
@@ -229,29 +251,23 @@ static int display_string( const u_char *pd, int offset, frame_data *fd,
        proto_tree      *name_tree;
        proto_item      *ti;
 
-
        char temp[ 256];
-       int length = GBYTE( pd, offset);
-
-       if ((offset + 8) > fd->cap_len){  
-                       proto_tree_add_text(tree, NullTVB, offset, 0, "*** FRAME TOO SHORT ***");
-               return 0;
-       }
+       int length = tvb_get_guint8(tvb, offset);
 
-       strncpy( temp, &pd[ offset + 1], length);
+       tvb_memcpy(tvb, (guint8 *)temp, offset+1, length);
        temp[ length ] = 0;
   
-       ti = proto_tree_add_text(tree, NullTVB, offset, length + 1,
+       ti = proto_tree_add_text(tree, tvb, offset, length + 1,
                "%s: %s" , label, temp);
 
 
        name_tree = proto_item_add_subtree(ti, ett_socks_name);
 
-       proto_tree_add_text( name_tree, NullTVB, offset, 1, "Length: %d", length);
+       proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %u", length);
 
        ++offset;
 
-       proto_tree_add_text( name_tree, NullTVB, offset, length, "String: %s", temp);
+       proto_tree_add_text( name_tree, tvb, offset, length, "String: %s", temp);
 
        return length + 1;
 }      
@@ -290,39 +306,32 @@ static char *get_command_name( guint Number){
 }
 
 
-static int display_address( const u_char *pd, int offset,
-               frame_data *fd, proto_tree *tree) {
+static int display_address(tvbuff_t *tvb, int offset, proto_tree *tree) {
 
 /* decode and display the v5 address, return offset of next byte */
 
-       int a_type = GBYTE( pd, offset);
+       int a_type = tvb_get_guint8(tvb, offset);
 
-       proto_tree_add_text( tree, NullTVB, offset, 1,
+       proto_tree_add_text( tree, tvb, offset, 1,
                        "Address Type: %d (%s)", a_type, 
-                       address_type_table[ MAX( 0, MIN( a_type,
-                               array_length( address_type_table)-1))]);
+                       address_type_table[ MIN( (guint) a_type,
+                               array_length( address_type_table)-1) ]);
 
        ++offset;
 
        if ( a_type == 1){              /* IPv4 address */
-               if ( (offset + 4) > fd->cap_len) 
-                               proto_tree_add_text(tree, NullTVB, offset, 0, "*** FRAME TOO SHORT ***");
-
-               proto_tree_add_item( tree, hf_socks_ip_dst, NullTVB, offset,
-                                       4, GWORD( pd, offset));
+               proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset,
+                                       4, FALSE);
                offset += 4;
        }       
        else if ( a_type == 3){ /* domain name address */
 
-               offset += display_string( pd, offset, fd, tree,
+               offset += display_string(tvb, offset, tree,
                        "Remote name");
        }
        else if ( a_type == 4){ /* IPv6 address */
-               if ((offset + 16) > fd->cap_len) 
-                               proto_tree_add_text(tree, NullTVB, offset, 0, "*** FRAME TOO SHORT ***");
-
-               proto_tree_add_item( tree, hf_socks_ip6_dst, NullTVB, offset,
-                               4, GWORD( pd, offset));
+               proto_tree_add_item( tree, hf_socks_ip6_dst, tvb, offset,
+                               16, FALSE);
                offset += 16;
        }
 
@@ -330,19 +339,20 @@ static int display_address( const u_char *pd, int offset,
 }
 
 
-static int get_address_v5( const u_char *pd, int offset, 
+static int get_address_v5(tvbuff_t *tvb, int offset, 
        socks_hash_entry_t *hash_info) {
 
 /* decode the v5 address and return offset of next byte */
-/*$$$ this needs to handle IPV6 and domain name addresses */
+/*XXX this needs to handle IPV6 and domain name addresses */
  
 
-       int a_type = GBYTE( pd, offset++);
+       int a_type = tvb_get_guint8(tvb, offset++);
 
        if ( a_type == 1){              /* IPv4 address */
           
                if ( hash_info)
-                       hash_info->dst_addr = GWORD( pd, offset);
+                       tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr,
+                           offset, 4);
                offset += 4;
        }
                
@@ -350,95 +360,93 @@ static int get_address_v5( const u_char *pd, int offset,
                offset += 16;
        
        else if ( a_type == 3)  /* domain name address */
-               offset += GBYTE( pd, offset) + 1;
-       
+               offset += tvb_get_guint8(tvb, offset) + 1;
        return offset;
 }      
 
 
 /********************* V5 UDP Associate handlers ***********************/
 
-static void socks_udp_dissector( const u_char *pd, int offset, frame_data *fd,
-               proto_tree *tree) {
+static void
+socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
 
 /* Conversation dissector called from UDP dissector. Decode and display */
 /* the socks header, the pass the rest of the data to the udp port     */
 /* decode routine to  handle the payload.                              */
 
+       int offset = 0;
        guint32 *ptr;
        socks_hash_entry_t *hash_info;
        conversation_t *conversation;
        proto_tree      *socks_tree;
        proto_item      *ti;
        
-       conversation = find_conversation( &pi.src, &pi.dst, pi.ptype,
-               pi.srcport, pi.destport);
+       conversation = find_conversation( &pinfo->src, &pinfo->dst, pinfo->ptype,
+               pinfo->srcport, pinfo->destport, 0);
 
        g_assert( conversation);        /* should always find a conversation */
 
-       hash_info = (socks_hash_entry_t*)conversation->data;
+       hash_info = conversation_get_proto_data(conversation, proto_socks);
 
-       if (check_col(fd, COL_PROTOCOL))
-               col_add_str(fd, COL_PROTOCOL, "Socks");
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
 
-       if (check_col(fd, COL_INFO))
-               col_add_fstr(fd, COL_INFO, "Version: 5, UDP Associated packet");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_add_fstr(pinfo->cinfo, COL_INFO, "Version: 5, UDP Associated packet");
                        
        if ( tree) {
-               ti = proto_tree_add_item( tree, proto_socks, NullTVB, offset,
-                       END_OF_FRAME, NULL, "Socks:" );
+               ti = proto_tree_add_protocol_format( tree, proto_socks, tvb,
+                       offset, -1, "Socks" );
 
                socks_tree = proto_item_add_subtree(ti, ett_socks);
 
-               CHECK_PACKET_LENGTH( 3);
-
-                       proto_tree_add_text( socks_tree, NullTVB, offset, 2, "Reserved");
+                       proto_tree_add_text( socks_tree, tvb, offset, 2, "Reserved");
                offset += 2;
                
-                       proto_tree_add_text( socks_tree, NullTVB, offset, 1, "Fragment Number: %d", GBYTE( pd,offset));
+                       proto_tree_add_text( socks_tree, tvb, offset, 1, "Fragment Number: %d", tvb_get_guint8(tvb, offset));
                ++offset;
        
 
-               offset = display_address( pd, offset, fd, socks_tree);
-               hash_info->udp_remote_port = pntohs( &pd[ offset]);
+               offset = display_address( tvb, offset, socks_tree);
+               hash_info->udp_remote_port = tvb_get_ntohs(tvb, offset);
                
-               CHECK_PACKET_LENGTH( 2);
-               proto_tree_add_item( socks_tree, hf_socks_dstport, NullTVB,
+               proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb,
                        offset, 2, hash_info->udp_remote_port);
                        
                offset += 2;
        }
        else {          /* no tree, skip past the socks header */
-               CHECK_PACKET_LENGTH( 3);
                offset += 3;
-               offset = get_address_v5( pd,offset, 0) + 2;
+               offset = get_address_v5( tvb, offset, 0) + 2;
        }       
 
 
 /* set pi src/dst port and call the udp sub-dissector lookup */
 
-       if ( pi.srcport == hash_info->port)             
-                       ptr = &pi.destport;
+       if ( pinfo->srcport == hash_info->port)                 
+                       ptr = &pinfo->destport;
        else
-               ptr = &pi.srcport;
+               ptr = &pinfo->srcport;
 
         *ptr = hash_info->udp_remote_port;
        
-       decode_udp_ports( pd, offset, fd, tree, pi.srcport, pi.destport);
+       decode_udp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport);
  
         *ptr = hash_info->udp_port;
 
 }
 
                        
-void new_udp_conversation( socks_hash_entry_t *hash_info){
+static void 
+new_udp_conversation( socks_hash_entry_t *hash_info, packet_info *pinfo){
+
+       conversation_t *conversation = conversation_new( &pinfo->src, &pinfo->dst,  PT_UDP,
+                       hash_info->udp_port, hash_info->port, 0);
 
-       conversation_t *conversation = conversation_new( &pi.src, &pi.dst,  PT_UDP,
-                       hash_info->udp_port, hash_info->port, hash_info);
-                       
        g_assert( conversation);
        
-       conversation->dissector = socks_udp_dissector;
+       conversation_add_proto_data(conversation, proto_socks, hash_info);
+       conversation_set_dissector(conversation, socks_udp_handle);
 }
 
 
@@ -446,87 +454,92 @@ void new_udp_conversation( socks_hash_entry_t *hash_info){
 
 /**************** Protocol Tree Display routines  ******************/
 
-
-void display_socks_v4( const u_char *pd, int offset, frame_data *fd,
-       proto_tree *parent, proto_tree *tree, socks_hash_entry_t *hash_info) {
+static void
+display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree, socks_hash_entry_t *hash_info) {
 
 
-/* Display the protocol tree for the V5 version. This routine uses the */
+/* Display the protocol tree for the V4 version. This routine uses the */
 /* stored conversation information to decide what to do with the row.  */
 /* Per packet information would have been better to do this, but we    */
 /* didn't have that when I wrote this. And I didn't expect this to get */
 /* so messy.                                                           */
 
 
-       int command;
+       guint command;
 
                                        /* Display command from client */
        if (compare_packet( hash_info->connect_row)){
 
-               CHECK_PACKET_LENGTH( 8);
-               proto_tree_add_text( tree, NullTVB, offset, 1,
+               proto_tree_add_text( tree, tvb, offset, 1,
                                "Version: %u ", hash_info->version);
                ++offset;
-               command = GBYTE( pd, offset);
+               command = tvb_get_guint8(tvb, offset);
 
-               proto_tree_add_text( tree, NullTVB, offset, 1,
+               proto_tree_add_text( tree, tvb, offset, 1,
                        "Command: %u (%s)", command, 
                                get_command_name( command));
                ++offset;
 
                                                /* Do remote port       */
-               proto_tree_add_item( tree, hf_socks_dstport, NullTVB, offset, 2,
-                               pntohs( &pd[ offset]));
+               proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
+                               FALSE);
                offset += 2;
 
                                                /* Do destination address */
-               proto_tree_add_item( tree, hf_socks_ip_dst, NullTVB, offset,
-                               4, GWORD( pd, offset));
+               proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset,
+                               4, FALSE);
 
                offset += 4;
 
-/*$$ check this, needs to do length checking    */             
+/*XXX check this, needs to do length checking   */             
+/* Should perhaps do TCP reassembly as well */
+               if ( tvb_offset_exists(tvb, offset)) {
                                                /* display user name    */
-                       proto_tree_add_item( tree, hf_user_name, NullTVB, offset, 
-                               strlen( &pd[offset]) + 1,
-                               &pd[offset]);
+                       proto_tree_add_string( tree, hf_user_name, tvb, offset, 
+                               tvb_strsize(tvb, offset),
+                               tvb_get_ptr(tvb, offset, -1));
+               }
 
        }
                                /*Display command response from server*/
        
        else if ( compare_packet( hash_info->cmd_reply_row)){
                                 
-               CHECK_PACKET_LENGTH( 8);
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                       "Version: %u (should be 0) ", GBYTE( pd, offset));
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
+                               FALSE);
                ++offset;
                                                /* Do results code      */
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                       "Result Code: %u (%s)", GBYTE( pd, offset) ,
-                       reply_table_v4[ MAX(0, MIN( GBYTE( pd, offset) - 90, 4))]);
+               proto_tree_add_item( tree, hf_socks_results_4, tvb, offset, 1, FALSE);
+               proto_tree_add_item_hidden(tree, hf_socks_results, tvb, offset, 1, FALSE);
+
                ++offset;
 
                                                /* Do remote port       */
-               proto_tree_add_item( tree, hf_socks_dstport, NullTVB, offset, 2,
-                               pntohs( &pd[ offset]));
-               offset += 2;;
+               proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
+                               FALSE);
+               offset += 2;
                                                /* Do remote address    */
-               proto_tree_add_item( tree, hf_socks_ip_dst, NullTVB, offset, 4,
-                       GWORD( pd, offset));
+               proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4,
+                       FALSE);
        }
        
        else if ( compare_packet( hash_info->v4_user_name_row)){
                         
-/*$$ check this, needs to do length checking    */             
-               proto_tree_add_text( tree, NullTVB, offset, strlen( &pd[offset]),
-                               "User Name: %s", &pd[offset]);
+/*XXX check this, needs to do length checking   */
+/* Should perhaps do TCP reassembly as well */
+               if ( tvb_offset_exists(tvb, offset)) {
+                       proto_tree_add_text( tree, tvb, offset,
+                               tvb_strsize(tvb, offset),
+                               "User Name: %s", tvb_get_ptr(tvb, offset, -1));
+               }
        }
 }                      
 
 
-
-void display_socks_v5( const u_char *pd, int offset, frame_data *fd,
-       proto_tree *parent, proto_tree *tree, socks_hash_entry_t *hash_info) {
+static void 
+display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree, socks_hash_entry_t *hash_info) {
        
 /* Display the protocol tree for the version. This routine uses the    */
 /* stored conversation information to decide what to do with the row.  */
@@ -534,7 +547,7 @@ void display_socks_v5( const u_char *pd, int offset, frame_data *fd,
 /* didn't have that when I wrote this. And I didn't expect this to get */
 /* so messy.                                                           */
 
-       int i, command;
+       unsigned int i, command;
        guint temp;
        char *AuthMethodStr;
 
@@ -544,56 +557,51 @@ void display_socks_v5( const u_char *pd, int offset, frame_data *fd,
                proto_tree      *AuthTree;
                proto_item      *ti;
 
-               CHECK_PACKET_LENGTH( 2);
                                                /* Do version   */
-               proto_tree_add_item( tree, hf_socks_ver, NullTVB, offset, 1,
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
                                hash_info->version);
                ++offset;
 
-               temp = GBYTE( pd, offset);      /* Get Auth method count */
+               temp = tvb_get_guint8(tvb, offset);     /* Get Auth method count */
                                                        /* build auth tree */
-               ti = proto_tree_add_text( tree, NullTVB, offset, 1,
+               ti = proto_tree_add_text( tree, tvb, offset, 1,
                                "Client Authentication Methods");
                                
                AuthTree = proto_item_add_subtree(ti, ett_socks_auth);
 
-               proto_tree_add_text( AuthTree, NullTVB, offset, 1,
+               proto_tree_add_text( AuthTree, tvb, offset, 1,
                                "Count: %u ", temp);
                ++offset;
 
-               CHECK_PACKET_LENGTH( temp);
-
                for( i = 0; i  < temp; ++i) {
 
                        AuthMethodStr = get_auth_method_name(
-                               GBYTE( pd, offset + i));
-                       proto_tree_add_text( AuthTree, NullTVB, offset + i, 1,
+                               tvb_get_guint8( tvb, offset + i));
+                       proto_tree_add_text( AuthTree, tvb, offset + i, 1,
                                "Method[%d]: %u (%s)", i,
-                               GBYTE( pd, offset + i), AuthMethodStr); 
+                               tvb_get_guint8( tvb, offset + i), AuthMethodStr); 
                }
                return;
        }                                       /* Get accepted auth method */
        else if (compare_packet( hash_info->auth_method_row)) {
 
                ++offset;
-               CHECK_PACKET_LENGTH( 1);
 
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                       "Accepted Auth Method: 0x%0x (%s)", GBYTE( pd, offset),
-                               get_auth_method_name( GBYTE( pd, offset)));
+               proto_tree_add_text( tree, tvb, offset, 1,
+                       "Accepted Auth Method: 0x%0x (%s)", tvb_get_guint8( tvb, offset),
+                               get_auth_method_name( tvb_get_guint8( tvb, offset)));
 
                return;
        }                                       /* handle user/password auth */
        else if (compare_packet( hash_info->user_name_auth_row)) {
 
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                               "Version: %u ", hash_info->version);
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE);
                ++offset;
                                                /* process user name    */
-               offset += display_string( pd, offset, fd, tree,
+               offset += display_string( tvb, offset, tree,
                                "User name");
                                                /* process password     */
-               offset += display_string( pd, offset, fd, tree,
+               offset += display_string( tvb, offset, tree,
                                "Password");
        }                                       
                                        /* command to the server */     
@@ -602,37 +610,35 @@ void display_socks_v5( const u_char *pd, int offset, frame_data *fd,
                 (compare_packet( hash_info->cmd_reply_row)) ||
                 (compare_packet( hash_info->bind_reply_row))){
 
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                       "Version: %u ", hash_info->version);
-
-               CHECK_PACKET_LENGTH( 1);
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE);
 
                ++offset;
 
-               command = GBYTE( pd, offset);
+               command = tvb_get_guint8(tvb, offset);
                
                if (compare_packet( hash_info->command_row))
-                       proto_tree_add_text( tree, NullTVB, offset, 1, "Command: %u (%s)",
-                               command,  get_command_name( command));
-               else
-                       proto_tree_add_text( tree, NullTVB, offset, 1, "Status: %d (%s)",
-                               GBYTE( pd, offset), reply_table_v5[ MAX( 0,
-                               MIN(GBYTE( pd, offset) - 90, 9))]);
-               ++offset;
+                       proto_tree_add_uint( tree, hf_socks_cmd, tvb, offset, 1,
+                           command);
+
+               else {
+                       proto_tree_add_item( tree, hf_socks_results_5, tvb, offset, 1, FALSE);
+                       proto_tree_add_item_hidden(tree, hf_socks_results, tvb, offset, 1, FALSE);
+               }
 
-               proto_tree_add_text( tree, NullTVB, offset, 1,
-                       "Reserved: 0x%0x (should = 0x00)", GBYTE( pd, offset)); 
                ++offset;
 
-               offset = display_address( pd, offset, fd, tree);
+               proto_tree_add_text( tree, tvb, offset, 1,
+                       "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset)); 
+               ++offset;
 
-               CHECK_PACKET_LENGTH( 2);
+               offset = display_address(tvb, offset, tree);
+/*XXX Add remote port for search somehow */
                                                /* Do remote port       */
-               proto_tree_add_text( tree, NullTVB, offset, 2,
+               proto_tree_add_text( tree, tvb, offset, 2,
                                "%sPort: %d",
                                (compare_packet( hash_info->bind_reply_row) ?
                                        "Remote Host " : ""),
-                                pntohs( &pd[ offset]));
+                                tvb_get_ntohs(tvb, offset));
        }
 }
 
@@ -641,8 +647,9 @@ void display_socks_v5( const u_char *pd, int offset, frame_data *fd,
 /**************** Decoder State Machines ******************/
 
 
-static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
-       int offset, frame_data *fd) {
+static guint 
+state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
+       int offset, packet_info *pinfo) {
 
 /* Decode V4 protocol.  This is done on the first pass through the     */
 /* list.  Based upon the current state, decode the packet and determine        */
@@ -651,17 +658,18 @@ static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
 
        if ( hash_info->state == None) {                /* new connection */
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Connect to server request");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connect to server request");
 
                hash_info->state = Connecting;  /* change state         */
 
-               hash_info->command = GBYTE( pd, offset + 1);
+               hash_info->command = tvb_get_guint8(tvb, offset + 1);
                                                /* get remote port      */
                if ( hash_info->command == CONNECT_COMMAND)                                             
-                       hash_info->port =  pntohs( &pd[ offset + 2]);
+                       hash_info->port =  tvb_get_ntohs(tvb, offset + 2);
                                                /* get remote address   */
-               hash_info->dst_addr = GWORD( pd, offset + 4);
+
+               tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr, offset + 4, 4);
                
                                                /* save the packet pointer */
                hash_info->connect_row = get_packet_ptr;
@@ -671,17 +679,27 @@ static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
 
                offset += 8;
                
-               if ( offset == pi.len)          /* if no user name      */
-                                               /* change state         */
+               if ( !tvb_offset_exists(tvb, offset)) { /* if no user name */
+                                                       /* change state */
                        hash_info->state = V4UserNameWait;
-               
-                       
-               hash_info->connect_offset += strlen( &pd[ offset]) + 1;
+                       /*
+                        * XXX - add 1, or leave it alone?
+                        * We were adding "strlen(...) + 1".
+                        */
+                       hash_info->connect_offset += 1;
+               } else {
+                       /*
+                        * Add in the length of the user name.
+                        * XXX - what if the user name is split between
+                        * TCP segments?
+                        */
+                       hash_info->connect_offset += tvb_strsize(tvb, offset);
+               }
                
                if ( !hash_info->dst_addr){             /* if no dest address */
                                                        /* if more data */
-                       if ( hash_info->connect_offset < pi.len ) {
-/*$$$ copy remote name here ??? */
+                       if ( tvb_offset_exists(tvb, hash_info->connect_offset)) {
+/*XXX copy remote name here ??? */
                                hash_info->state = Connecting;
                        }
                        else
@@ -690,11 +708,11 @@ static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
                                                /* waiting for V4 user name */
        }else if ( hash_info->state == V4UserNameWait){ 
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Connect Request (User name)");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connect Request (User name)");
 
                hash_info->v4_user_name_row = get_packet_ptr;
-/*$$$ may need to check for domain name here */
+/*XXX may need to check for domain name here */
                hash_info->state = Connecting;
        }
                                        /* waiting for V4 domain name   */
@@ -706,8 +724,8 @@ static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
        }
        else if ( hash_info->state == Connecting){
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Connect Response");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connect Response");
 
                                                /* save packet pointer  */
                hash_info->cmd_reply_row = get_packet_ptr;
@@ -720,8 +738,9 @@ static guint state_machine_v4( socks_hash_entry_t *hash_info, const u_char *pd,
 
 
 
-static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd, 
-       int offset, frame_data *fd) {
+static void 
+state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
+       int offset, packet_info *pinfo) {
 
 /* Decode V5 protocol.  This is done on the first pass through the     */
 /* list.  Based upon the current state, decode the packet and determine        */
@@ -733,27 +752,22 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
 
        if ( hash_info->state == None) {
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Connect to server request");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connect to server request");
 
                hash_info->state = Connecting;  /* change state         */
                hash_info->connect_row = get_packet_ptr;        
 
-               if (( offset+ 1) > fd->cap_len){ 
-                       hash_info->state = Done;        /* change state         */
-                       return; 
-               }
-
-               temp = GBYTE( pd, offset + 1);
+               temp = tvb_get_guint8(tvb, offset + 1);
                                                /* skip past auth methods */
                offset = hash_info->connect_offset = offset + 1 + temp;
        }
        else if ( hash_info->state == Connecting){
 
-               guint AuthMethod = GBYTE( pd, offset + 1);
+               guint AuthMethod = tvb_get_guint8(tvb, offset + 1);
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Connect to server response");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connect to server response");
 
                hash_info->auth_method_row = get_packet_ptr;
 
@@ -764,7 +778,7 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
                        hash_info->state = UserNameAuth;
                        
                else if ( AuthMethod == GSS_API_AUTHENTICATION)
-/*$$$ should be this           hash_info->state = GssApiAuth; */
+/*XXX should be this           hash_info->state = GssApiAuth; */
                        hash_info->state = Done;        
                        
                else    hash_info->state = Done;        /*Auth failed or error*/
@@ -775,15 +789,10 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
 
                guint temp;
 
-               if (( offset+ 1) > fd->cap_len){ 
-                       hash_info->state = Done;        /* change state         */
-                       return; 
-               }
+               hash_info->command = tvb_get_guint8(tvb, offset + 1); /* get command */
 
-               hash_info->command = GBYTE( pd, offset + 1); /* get command */
-
-               if (check_col(fd, COL_INFO))
-                       col_append_fstr(fd, COL_INFO, " Command Request - %s",
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " Command Request - %s",
                                get_command_name(hash_info->command));
 
                hash_info->state = V5Reply;
@@ -791,25 +800,21 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
 
                offset += 3;                    /* skip to address type */
 
-               offset = get_address_v5( pd, offset, hash_info);
+               offset = get_address_v5(tvb, offset, hash_info);
 
-               if (( offset+ 1) > fd->cap_len){ 
-                       hash_info->state = Done;
-                       return; 
-               }
-               temp = GBYTE( pd, offset);
+               temp = tvb_get_guint8(tvb, offset);
 
                if (( hash_info->command == CONNECT_COMMAND) || 
                    ( hash_info->command == UDP_ASSOCIATE_COMMAND))
                                                /* get remote port      */
-                       hash_info->port =  pntohs( &pd[ offset]);
+                       hash_info->port =  tvb_get_ntohs(tvb, offset);
        }
 
        else if ( hash_info->state == V5Reply) {        /* V5 Command Reply */
 
 
-               if (check_col(fd, COL_INFO))
-                       col_append_fstr(fd, COL_INFO, " Command Response - %s",
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " Command Response - %s",
                                get_command_name(hash_info->command));
 
                hash_info->cmd_reply_row = get_packet_ptr;
@@ -824,32 +829,29 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
                        
                else if ( hash_info->command == UDP_ASSOCIATE_COMMAND){
                        offset += 3;            /* skip to address type */
-                       offset = get_address_v5( pd, offset, hash_info);
-
-       /* save server udp port and create upd conversation */
-                       if (( offset+ 2) > fd->cap_len){ 
-                               hash_info->state = Done;
-                               return; 
-                       }
-                       hash_info->udp_port =  pntohs( &pd[ offset]);
+                       offset = get_address_v5(tvb, offset, hash_info);
+
+       /* save server udp port and create udp conversation */
+                       hash_info->udp_port =  tvb_get_ntohs(tvb, offset);
                        
-                       new_udp_conversation( hash_info);
+                       if (!pinfo->fd->flags.visited)
+                               new_udp_conversation( hash_info, pinfo);
 
-/*$$ may need else statement to handle unknows and generate error message */
+/*XXX may need else statement to handle unknows and generate error message */
                        
                }               
        }
        else if ( hash_info->state == V5BindReply) {    /* V5 Bind Second Reply */
 
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " Command Response: Bind remote host info");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " Command Response: Bind remote host info");
 
                hash_info->bind_reply_row = get_packet_ptr;
                hash_info->state = Done;
        }
        else if ( hash_info->state == UserNameAuth) {   /* Handle V5 User Auth*/
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO,
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO,
                                " User authentication response");
 
                hash_info->user_name_auth_row = get_packet_ptr;
@@ -858,54 +860,54 @@ static void state_machine_v5( socks_hash_entry_t *hash_info, const u_char *pd,
        }
        else if ( hash_info->state == AuthReply){       /* V5 User Auth reply */
                hash_info->cmd_reply_row = get_packet_ptr;
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, " User authentication reply");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, " User authentication reply");
                hash_info->state = V5Command;
        }
 }
 
 
 
-static void display_ping_and_tracert( const u_char *pd, int offset,
-       frame_data *fd, proto_tree *tree, socks_hash_entry_t *hash_info) {
+static void 
+display_ping_and_tracert(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) {
 
 /* Display the ping/trace_route conversation */
 
 
-               const u_char    *data, *dataend;
-               const u_char   *lineend, *eol;
+               const guchar    *data, *dataend;
+               const guchar   *lineend, *eol;
                int             linelen;
 
                                        /* handle the end command */
-               if ( pi.destport == TCP_PORT_SOCKS){
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, ", Terminate Request");
+               if ( pinfo->destport == TCP_PORT_SOCKS){
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Terminate Request");
                
                if ( tree)
-                       proto_tree_add_text(tree, NullTVB, offset, 1,
+                       proto_tree_add_text(tree, tvb, offset, 1,
                                (hash_info->command  == PING_COMMAND) ?
                                "Ping: End command" :
                                "Traceroute: End command");
        }
                else{           /* display the PING or Traceroute results */
-               if (check_col(fd, COL_INFO))
-                       col_append_str(fd, COL_INFO, ", Results");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Results");
 
                if ( tree){
-                       proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME,
+                       proto_tree_add_text(tree, tvb, offset, -1,
                                (hash_info->command  == PING_COMMAND) ?
                                "Ping Results:" :
                                "Traceroute Results");
 
-                       data = &pd[offset];
-                       dataend = data + END_OF_FRAME;
+                       data = tvb_get_ptr(tvb, offset, -1);
+                       dataend = data + tvb_length_remaining(tvb, offset);
                
                                while (data < dataend) {
        
                                lineend = find_line_end(data, dataend, &eol);
                                linelen = lineend - data;
 
-                                       proto_tree_add_text( tree, NullTVB, offset, linelen,
+                                       proto_tree_add_text( tree, tvb, offset, linelen,
                                                format_text(data, linelen));
                                        offset += linelen;
                                        data = lineend;
@@ -916,34 +918,34 @@ static void display_ping_and_tracert( const u_char *pd, int offset,
 
 
 
-static void call_next_dissector( const u_char *pd, int offset, frame_data *fd,
+static void call_next_dissector(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree, socks_hash_entry_t *hash_info) {
 
 /* Display the results for PING and TRACERT extensions or              */
-/* Call TCP  dissector for the port that was passed during the         */
+/* Call TCP dissector for the port that was passed during the          */
 /* connect process                                                     */
-/* Load pointer to pi.XXXport depending upon the direction, change     */
-/* pi port to the remote port, call next dissecotr to decode the       */
-/* payload, and restore the pi port after that is done.                        */
+/* Load pointer to pinfo->XXXport depending upon the direction,                */
+/* change pinfo port to the remote port, call next dissecotr to decode */
+/* the payload, and restore the pinfo port after that is done.         */
 
        guint32 *ptr;
  
        if (( hash_info->command  == PING_COMMAND) ||
            ( hash_info->command  == TRACERT_COMMAND))
                 
-               display_ping_and_tracert( pd, offset, fd, tree, hash_info);
+               display_ping_and_tracert(tvb, offset, pinfo, tree, hash_info);
 
        else {          /* call the tcp port decoder to handle the payload */
        
-/*$$$ may want to load dest address here */
+/*XXX may want to load dest address here */
 
-               if ( pi.destport  == TCP_PORT_SOCKS)
-                       ptr = &pi.destport;
+               if ( pinfo->destport  == TCP_PORT_SOCKS)
+                       ptr = &pinfo->destport;
                else
-                       ptr = &pi.srcport;
+                       ptr = &pinfo->srcport;
 
                *ptr = hash_info->port;
-               decode_tcp_ports( pd, offset, fd, tree, pi.srcport, pi.destport);
+               decode_tcp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport);
                *ptr = TCP_PORT_SOCKS;
        }
 }                
@@ -951,107 +953,112 @@ static void call_next_dissector( const u_char *pd, int offset, frame_data *fd,
 
 
 static void
-dissect_socks(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
+dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
 
+       int             offset = 0;
        proto_tree      *socks_tree;
        proto_item      *ti;
        socks_hash_entry_t *hash_info;
        conversation_t *conversation;
        
+       conversation = find_conversation( &pinfo->src, &pinfo->dst, pinfo->ptype,
+               pinfo->srcport, pinfo->destport, 0);
 
-       conversation = find_conversation( &pi.src, &pi.dst, pi.ptype,
-               pi.srcport, pi.destport);
-
-       if ( conversation)                      /* conversation found */
-               hash_info = conversation->data;
-
-                       /* new conversation create local data structure */
-       else {                          
+       if ( !conversation){
+               conversation = conversation_new( &pinfo->src, &pinfo->dst, pinfo->ptype,
+                       pinfo->srcport, pinfo->destport, 0);
+       }
+       hash_info = conversation_get_proto_data(conversation,proto_socks);
+       if ( !hash_info){
                hash_info = g_mem_chunk_alloc(socks_vals);
                hash_info->start_done_row = G_MAXINT;
                hash_info->state = None;
-               hash_info->port = -1;
-               hash_info->version = GBYTE( pd, offset); /* get version*/
+               hash_info->port = 0;
+               hash_info->version = tvb_get_guint8(tvb, offset); /* get version*/
 
                if (( hash_info->version != 4) &&       /* error test version */
                   ( hash_info->version != 5))
                        hash_info->state = Done;
 
-               conversation_new( &pi.src, &pi.dst, pi.ptype,
-                       pi.srcport, pi.destport, hash_info);
+               conversation_add_proto_data(conversation, proto_socks,
+                       hash_info);
+
+                                               /* set dissector for now */
+               conversation_set_dissector(conversation, socks_handle);
        }
 
 /* display summary window information  */
 
-       if (check_col(fd, COL_PROTOCOL))
-               col_add_str(fd, COL_PROTOCOL, "Socks");
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
 
-       if (check_col(fd, COL_INFO)){
+       if (check_col(pinfo->cinfo, COL_INFO)){
                if (( hash_info->version == 4) || ( hash_info->version == 5)){
-                       col_add_fstr(fd, COL_INFO, "Version: %d",
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %d",
                                hash_info->version);
                }               
                else                    /* unknown version display error */
-                       col_add_str(fd, COL_INFO, "Unknown");
+                       col_set_str(pinfo->cinfo, COL_INFO, "Unknown");
                
 
                if ( hash_info->command == PING_COMMAND)
-                       col_append_str(fd, COL_INFO, ", Ping Req");
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Ping Req");
                if ( hash_info->command == TRACERT_COMMAND)
-                       col_append_str(fd, COL_INFO, ", Traceroute Req");
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Traceroute Req");
                
-               if ( hash_info->port != -1)
-                       col_append_fstr(fd, COL_INFO, ", Remote Port: %d",
+/*XXX          if ( hash_info->port != -1) */
+               if ( hash_info->port != 0)
+                       col_append_fstr(pinfo->cinfo, COL_INFO, ", Remote Port: %d",
                                hash_info->port);
        }
 
 
 /* run state machine if needed */
 
-       if ((hash_info->state != Done) && ( !fd->flags.visited)){
+       if ((hash_info->state != Done) && ( !pinfo->fd->flags.visited)){
 
                if ( hash_info->version == 4)
-                       state_machine_v4( hash_info, pd, offset, fd);
+                       state_machine_v4( hash_info, tvb, offset, pinfo);
 
                else if ( hash_info->version == 5)
-                       state_machine_v5( hash_info, pd, offset, fd);
+                       state_machine_v5( hash_info, tvb, offset, pinfo);
 
                if (hash_info->state == Done) {         /* if done now  */
-                       hash_info->start_done_row = fd->num;
+                       hash_info->start_done_row = pinfo->fd->num;
                }
        }
        
 /* if proto tree, decode and display */
 
        if (tree) {                     
-               ti = proto_tree_add_item( tree, proto_socks, NullTVB, offset,
-                       END_OF_FRAME, NULL, "Socks:" );
+               ti = proto_tree_add_item( tree, proto_socks, tvb, offset, -1,
+                       FALSE );
 
                socks_tree = proto_item_add_subtree(ti, ett_socks);
 
                if ( hash_info->version == 4)
-                       display_socks_v4( pd, offset, fd, tree, socks_tree,
+                       display_socks_v4(tvb, offset, pinfo, socks_tree,
                                hash_info);
                        
                else if ( hash_info->version == 5)
-                       display_socks_v5( pd, offset, fd, tree, socks_tree,
+                       display_socks_v5(tvb, offset, pinfo, socks_tree,
                                hash_info);
 
                                /* if past startup, add the faked stuff */
-               if ( fd->num >  hash_info->start_done_row){
+               if ( pinfo->fd->num >  hash_info->start_done_row){
                                                /*  add info to tree */
-                       proto_tree_add_text( socks_tree, NullTVB, offset, 0,
+                       proto_tree_add_text( socks_tree, tvb, offset, 0,
                                "Command: %d (%s)", hash_info->command,
                                get_command_name(hash_info->command));
 
-                       proto_tree_add_item( socks_tree, hf_socks_ip_dst, NullTVB,
+                       proto_tree_add_ipv4( socks_tree, hf_socks_ip_dst, tvb,
                                        offset, 0, hash_info->dst_addr);
 
                                /* no fake address for ping & traceroute */
                                
                        if (( hash_info->command != PING_COMMAND) &&
                            ( hash_info->command != TRACERT_COMMAND)){
-                               proto_tree_add_item( socks_tree, hf_socks_dstport, NullTVB,
+                               proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb,
                                        offset, 0, hash_info->port);
                        }
                }
@@ -1061,8 +1068,8 @@ dissect_socks(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
 /* call next dissector if ready */
 
-       if ( fd->num > hash_info->start_done_row){
-               call_next_dissector( pd, offset, fd, tree, hash_info);
+       if ( pinfo->fd->num > hash_info->start_done_row){
+               call_next_dissector(tvb, offset, pinfo, tree, hash_info);
        }
 }
 
@@ -1101,34 +1108,49 @@ proto_register_socks( void){
     
 
                { &hf_socks_ver,
-                       { "Version", "socks.ver", FT_UINT8, BASE_NONE, NULL,
-                               0x0, ""
+                       { "Version", "socks.version", FT_UINT8, BASE_DEC, NULL,
+                               0x0, "", HFILL
                        }
                },
                { &hf_socks_ip_dst,
                        { "Remote Address", "socks.dst", FT_IPv4, BASE_NONE, NULL,
-                               0x0, ""
+                               0x0, "", HFILL
                        }
                },
                { &hf_socks_ip6_dst,
-                       { "Remote Address", "socks.dstV6", FT_IPv6, BASE_NONE, NULL,
-                               0x0, ""
+                       { "Remote Address(ipv6)", "socks.dstV6", FT_IPv6, BASE_NONE, NULL,
+                               0x0, "", HFILL
                        }
                },
 
                 { &hf_user_name,
                        { "User Name", "socks.username", FT_STRING, BASE_NONE,
-                                NULL, 0x0, ""
+                                NULL, 0x0, "", HFILL
                        }
                 },
                { &hf_socks_dstport,
                        { "Remote Port", "socks.dstport", FT_UINT16,
-                               BASE_DEC, NULL, 0x0, ""
+                               BASE_DEC, NULL, 0x0, "", HFILL
+                       }
+               },
+               { &hf_socks_cmd,
+                       { "Command", "socks.command", FT_UINT8,
+                               BASE_DEC,  VALS(cmd_strings), 0x0, "", HFILL
+                       }
+               },
+               { &hf_socks_results_4,
+                       { "Results(V4)", "socks.results_v4", FT_UINT8,
+                               BASE_DEC, VALS(reply_table_v4), 0x0, "", HFILL
+                       }
+               },
+               { &hf_socks_results_5,
+                       { "Results(V5)", "socks.results_v5", FT_UINT8,
+                               BASE_DEC, VALS(reply_table_v5), 0x0, "", HFILL
                        }
                },
-               { &hf_socks_command,
-                       { "Command", "socks.command", FT_UINT16,
-                               BASE_DEC, NULL, 0x0, ""
+               { &hf_socks_results,
+                       { "Results(V5)", "socks.results", FT_UINT8,
+                               BASE_DEC, NULL, 0x0, "", HFILL
                        }
                }
 
@@ -1136,12 +1158,16 @@ proto_register_socks( void){
 
 
        proto_socks = proto_register_protocol (
-               "Socks Protocol", "socks");           
+               "Socks Protocol", "Socks", "socks");           
 
        proto_register_field_array(proto_socks, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));  
 
        register_init_routine( &socks_reinit);  /* register re-init routine */
+
+       socks_udp_handle = create_dissector_handle(socks_udp_dissector,
+           proto_socks);
+       socks_handle = create_dissector_handle(dissect_socks, proto_socks);
 }
 
 
@@ -1150,7 +1176,5 @@ proto_reg_handoff_socks(void) {
 
        /* dissector install routine */ 
  
-       dissector_add("tcp.port", TCP_PORT_SOCKS, dissect_socks);
+       dissector_add("tcp.port", TCP_PORT_SOCKS, socks_handle);
 }
-
-