From Laurent Rabret:
[obnox/wireshark/wip.git] / packet-socks.c
index 4a31977a9cb54be4f9549caa769867fc68e4efa0..21051676795add7b2f8274b4c9884dc32fd750a0 100644 (file)
@@ -2,22 +2,22 @@
  * Routines for socks versions 4 &5  packet dissection
  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
  *
- * $Id: packet-socks.c,v 1.29 2001/11/27 07:13:26 guy Exp $
+ * $Id: packet-socks.c,v 1.45 2003/04/23 10:20:29 sahlberg Exp $
  *
  * Ethereal - Network traffic analyzer
  * 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
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -40,8 +40,8 @@
  * Add GSS-API authentication per rfc-1961
  * Add CHAP authentication
  * Decode FLAG bits per
- *      http://www.socks.nec.com/draft/draft-ietf-aft-socks-pro-v-04.txt 
- * In call_next_dissector, could load the destination address into the 
+ *      http://www.socks.nec.com/draft/draft-ietf-aft-socks-pro-v-04.txt
+ * In call_next_dissector, could load the destination address into the
  *     pi structure before calling next dissector.
  * remove display_string or at least make it use protocol identifiers
  * socks_hash_entry_t needs to handle V5 address type and domain names
 #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>
 
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
-#include "packet.h"
-#include "resolv.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"
-#include "strutil.h"
+#include <epan/strutil.h>
 
 
 #define compare_packet(X) (X == (pinfo->fd->num))
@@ -99,7 +87,7 @@
 
 /********** V5 Authentication methods *************/
 
-#define NO_AUTHENTICATION      0               
+#define NO_AUTHENTICATION      0
 #define GSS_API_AUTHENTICATION         1
 #define USER_NAME_AUTHENTICATION       2
 #define CHAP_AUTHENTICATION    3
@@ -119,7 +107,10 @@ 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 ***********/
@@ -136,7 +127,7 @@ enum SockState {
        V4NameWait,
        V5Command,
        V5Reply,
-       V5BindReply,    
+       V5BindReply,
        UserNameAuth,
        GssApiAuth,
        AuthReply,
@@ -153,7 +144,7 @@ typedef struct {
        guint32         port;
        guint32         udp_port;
        guint32         udp_remote_port;
-       
+
        int             connect_offset;
        row_pointer_type        v4_name_row;
        row_pointer_type        v4_user_name_row;
@@ -164,7 +155,7 @@ typedef struct {
        row_pointer_type        auth_method_row;
        row_pointer_type        user_name_auth_row;
        guint32 start_done_row;
-       
+
        guint32 dst_addr;       /* this needs to handle IPv6 */
 }socks_hash_entry_t;
 
@@ -183,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",
@@ -190,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",
@@ -206,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))
@@ -217,7 +240,7 @@ static GMemChunk *socks_vals = NULL;
 /************************* Support routines ***************************/
 
 
-static int display_string(tvbuff_t *tvb, int offset, packet_info *pinfo,
+static int display_string(tvbuff_t *tvb, int offset,
        proto_tree *tree, char *label){
 
 /* display a string with a length, characters encoding */
@@ -228,28 +251,27 @@ static int display_string(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree      *name_tree;
        proto_item      *ti;
 
-
        char temp[ 256];
        int length = tvb_get_guint8(tvb, offset);
 
-       strncpy( temp, tvb_get_ptr(tvb, offset+1, -1), length);
+       tvb_memcpy(tvb, (guint8 *)temp, offset+1, length);
        temp[ length ] = 0;
-  
+
        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, tvb, offset, 1, "Length: %d", length);
+       proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %u", length);
 
        ++offset;
 
        proto_tree_add_text( name_tree, tvb, offset, length, "String: %s", temp);
 
        return length + 1;
-}      
+}
+
 
 
 static char *get_auth_method_name( guint Number){
@@ -284,15 +306,14 @@ static char *get_command_name( guint Number){
 }
 
 
-static int display_address(tvbuff_t *tvb, int offset,
-               packet_info *pinfo, 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 = tvb_get_guint8(tvb, offset);
 
        proto_tree_add_text( tree, tvb, offset, 1,
-                       "Address Type: %d (%s)", a_type, 
+                       "Address Type: %d (%s)", a_type,
                        address_type_table[ MIN( (guint) a_type,
                                array_length( address_type_table)-1) ]);
 
@@ -302,10 +323,10 @@ static int display_address(tvbuff_t *tvb, int 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(tvb, offset, pinfo, tree,
+               offset += display_string(tvb, offset, tree,
                        "Remote name");
        }
        else if ( a_type == 4){ /* IPv6 address */
@@ -318,30 +339,30 @@ static int display_address(tvbuff_t *tvb, int offset,
 }
 
 
-static int get_address_v5(tvbuff_t *tvb, 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 */
 /*XXX this needs to handle IPV6 and domain name addresses */
+
 
        int a_type = tvb_get_guint8(tvb, offset++);
 
        if ( a_type == 1){              /* IPv4 address */
-          
+
                if ( hash_info)
                        tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr,
                            offset, 4);
                offset += 4;
        }
-               
+
        else if ( a_type == 4)          /* IPv6 address */
                offset += 16;
-       
+
        else if ( a_type == 3)  /* domain name address */
                offset += tvb_get_guint8(tvb, offset) + 1;
        return offset;
-}      
+}
 
 
 /********************* V5 UDP Associate handlers ***********************/
@@ -359,7 +380,7 @@ socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
        conversation_t *conversation;
        proto_tree      *socks_tree;
        proto_item      *ti;
-       
+
        conversation = find_conversation( &pinfo->src, &pinfo->dst, pinfo->ptype,
                pinfo->srcport, pinfo->destport, 0);
 
@@ -367,63 +388,63 @@ socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
 
        hash_info = conversation_get_proto_data(conversation, proto_socks);
 
-       if (check_col(pinfo->fd, COL_PROTOCOL))
-               col_set_str(pinfo->fd, COL_PROTOCOL, "Socks");
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
+
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_add_fstr(pinfo->cinfo, COL_INFO, "Version: 5, UDP Associated packet");
 
-       if (check_col(pinfo->fd, COL_INFO))
-               col_add_fstr(pinfo->fd, COL_INFO, "Version: 5, UDP Associated packet");
-                       
        if ( tree) {
-               ti = proto_tree_add_protocol_format( tree, proto_socks, tvb, offset,
-                       tvb_length_remaining(tvb, offset), "Socks" );
+               ti = proto_tree_add_protocol_format( tree, proto_socks, tvb,
+                       offset, -1, "Socks" );
 
                socks_tree = proto_item_add_subtree(ti, ett_socks);
 
                        proto_tree_add_text( socks_tree, tvb, offset, 2, "Reserved");
                offset += 2;
-               
+
                        proto_tree_add_text( socks_tree, tvb, offset, 1, "Fragment Number: %d", tvb_get_guint8(tvb, offset));
                ++offset;
-       
 
-               offset = display_address( tvb, offset, pinfo, socks_tree);
+
+               offset = display_address( tvb, offset, socks_tree);
                hash_info->udp_remote_port = tvb_get_ntohs(tvb, offset);
-               
+
                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 */
                offset += 3;
                offset = get_address_v5( tvb, offset, 0) + 2;
-       }       
+       }
 
 
 /* set pi src/dst port and call the udp sub-dissector lookup */
 
-       if ( pinfo->srcport == hash_info->port)                 
+       if ( pinfo->srcport == hash_info->port)
                        ptr = &pinfo->destport;
        else
                ptr = &pinfo->srcport;
 
         *ptr = hash_info->udp_remote_port;
-       
+
        decode_udp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport);
+
         *ptr = hash_info->udp_port;
 
 }
 
-                       
-void 
+
+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);
 
        g_assert( conversation);
-       
+
        conversation_add_proto_data(conversation, proto_socks, hash_info);
        conversation_set_dissector(conversation, socks_udp_handle);
 }
@@ -433,19 +454,19 @@ new_udp_conversation( socks_hash_entry_t *hash_info, packet_info *pinfo){
 
 /**************** Protocol Tree Display routines  ******************/
 
-void
+static void
 display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
-       proto_tree *parent, proto_tree *tree, socks_hash_entry_t *hash_info) {
+       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)){
@@ -456,7 +477,7 @@ display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
                command = tvb_get_guint8(tvb, offset);
 
                proto_tree_add_text( tree, tvb, offset, 1,
-                       "Command: %u (%s)", command, 
+                       "Command: %u (%s)", command,
                                get_command_name( command));
                ++offset;
 
@@ -471,27 +492,27 @@ display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
                offset += 4;
 
-/*XXX 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_string( tree, hf_user_name, tvb, offset, 
-                               strlen( tvb_get_ptr(tvb, offset, -1)) + 1,
+                       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)){
-                                
-               proto_tree_add_text( tree, tvb, offset, 1,
-                       "Version: %u (should be 0) ", tvb_get_guint8(tvb, offset));
+
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
+                               FALSE);
                ++offset;
                                                /* Do results code      */
-               proto_tree_add_text( tree, tvb, offset, 1,
-                       "Result Code: %u (%s)", tvb_get_guint8(tvb, offset) ,
-                       reply_table_v4[ MAX(0, MIN( tvb_get_guint8(tvb, 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       */
@@ -502,24 +523,24 @@ display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
                proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4,
                        FALSE);
        }
-       
+
        else if ( compare_packet( hash_info->v4_user_name_row)){
-                        
+
 /*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,
-                               strlen( tvb_get_ptr(tvb, offset, -1)),
+                               tvb_strsize(tvb, offset),
                                "User Name: %s", tvb_get_ptr(tvb, offset, -1));
                }
        }
-}                      
+}
 
 
-void 
+static void
 display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
-       proto_tree *parent, proto_tree *tree, socks_hash_entry_t *hash_info) {
-       
+       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.  */
 /* Per packet information would have been better to do this, but we    */
@@ -537,7 +558,7 @@ display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
                proto_item      *ti;
 
                                                /* Do version   */
-               proto_tree_add_uint( tree, hf_socks_ver, tvb, offset, 1,
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
                                hash_info->version);
                ++offset;
 
@@ -545,7 +566,7 @@ display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
                                                        /* build auth tree */
                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, tvb, offset, 1,
@@ -558,7 +579,7 @@ display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
                                tvb_get_guint8( tvb, offset + i));
                        proto_tree_add_text( AuthTree, tvb, offset + i, 1,
                                "Method[%d]: %u (%s)", i,
-                               tvb_get_guint8( tvb, offset + i), AuthMethodStr); 
+                               tvb_get_guint8( tvb, offset + i), AuthMethodStr);
                }
                return;
        }                                       /* Get accepted auth method */
@@ -574,44 +595,44 @@ display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }                                       /* handle user/password auth */
        else if (compare_packet( hash_info->user_name_auth_row)) {
 
-               proto_tree_add_text( tree, tvb, 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( tvb, offset, pinfo, tree,
+               offset += display_string( tvb, offset, tree,
                                "User name");
                                                /* process password     */
-               offset += display_string( tvb, offset, pinfo, tree,
+               offset += display_string( tvb, offset, tree,
                                "Password");
-       }                                       
-                                       /* command to the server */     
+       }
+                                       /* command to the server */
                                        /* command response from server */
-       else if ((compare_packet( hash_info->command_row)) || 
+       else if ((compare_packet( hash_info->command_row)) ||
                 (compare_packet( hash_info->cmd_reply_row)) ||
                 (compare_packet( hash_info->bind_reply_row))){
 
-               proto_tree_add_text( tree, tvb, offset, 1,
-                       "Version: %u ", hash_info->version);
+               proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE);
 
                ++offset;
 
                command = tvb_get_guint8(tvb, offset);
-               
+
                if (compare_packet( hash_info->command_row))
-                       proto_tree_add_text( tree, tvb, offset, 1, "Command: %u (%s)",
-                               command,  get_command_name( command));
-               else
-                       proto_tree_add_text( tree, tvb, offset, 1, "Status: %d (%s)",
-                               tvb_get_guint8(tvb, offset), reply_table_v5[ MAX( 0,
-                               MIN(tvb_get_guint8(tvb, offset) - 90, 9))]);
+                       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);
+               }
+
                ++offset;
 
                proto_tree_add_text( tree, tvb, offset, 1,
-                       "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset)); 
+                       "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset));
                ++offset;
 
-               offset = display_address(tvb, offset, pinfo, tree);
-
+               offset = display_address(tvb, offset, tree);
+/*XXX Add remote port for search somehow */
                                                /* Do remote port       */
                proto_tree_add_text( tree, tvb, offset, 2,
                                "%sPort: %d",
@@ -622,11 +643,11 @@ display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 
-       
+
 /**************** Decoder State Machines ******************/
 
 
-static guint 
+static guint
 state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
        int offset, packet_info *pinfo) {
 
@@ -637,19 +658,19 @@ state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
 
        if ( hash_info->state == None) {                /* new connection */
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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 = tvb_get_guint8(tvb, offset + 1);
                                                /* get remote port      */
-               if ( hash_info->command == CONNECT_COMMAND)                                             
+               if ( hash_info->command == CONNECT_COMMAND)
                        hash_info->port =  tvb_get_ntohs(tvb, offset + 2);
                                                /* get remote address   */
 
                tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr, offset + 4, 4);
-               
+
                                                /* save the packet pointer */
                hash_info->connect_row = get_packet_ptr;
 
@@ -657,14 +678,24 @@ state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
                hash_info->connect_offset = offset + 8;
 
                offset += 8;
-               
-               if ( !tvb_offset_exists(tvb, offset))   /* if no user name */
+
+               if ( !tvb_offset_exists(tvb, offset)) { /* if no user name */
                                                        /* change state */
                        hash_info->state = V4UserNameWait;
-               
-                       
-               hash_info->connect_offset += strlen( tvb_get_ptr(tvb, offset, -1)) + 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 ( tvb_offset_exists(tvb, hash_info->connect_offset)) {
@@ -672,13 +703,13 @@ state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
                                hash_info->state = Connecting;
                        }
                        else
-                               hash_info->state = V4NameWait;  
+                               hash_info->state = V4NameWait;
                                                }
                                                /* waiting for V4 user name */
-       }else if ( hash_info->state == V4UserNameWait){ 
+       }else if ( hash_info->state == V4UserNameWait){
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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;
 /*XXX may need to check for domain name here */
@@ -693,8 +724,8 @@ state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
        }
        else if ( hash_info->state == Connecting){
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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;
@@ -707,7 +738,7 @@ state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
 
 
 
-static void 
+static void
 state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
        int offset, packet_info *pinfo) {
 
@@ -721,11 +752,11 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
 
        if ( hash_info->state == None) {
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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;        
+               hash_info->connect_row = get_packet_ptr;
 
                temp = tvb_get_guint8(tvb, offset + 1);
                                                /* skip past auth methods */
@@ -735,33 +766,33 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
 
                guint AuthMethod = tvb_get_guint8(tvb, offset + 1);
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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;
 
                if ( AuthMethod == NO_AUTHENTICATION)
                        hash_info->state = V5Command;
-                       
+
                else if ( AuthMethod == USER_NAME_AUTHENTICATION)
                        hash_info->state = UserNameAuth;
-                       
+
                else if ( AuthMethod == GSS_API_AUTHENTICATION)
 /*XXX should be this           hash_info->state = GssApiAuth; */
-                       hash_info->state = Done;        
-                       
+                       hash_info->state = Done;
+
                else    hash_info->state = Done;        /*Auth failed or error*/
 
        }
-       
+
        else if ( hash_info->state == V5Command) {      /* Handle V5 Command */
 
                guint temp;
 
                hash_info->command = tvb_get_guint8(tvb, offset + 1); /* get command */
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_fstr(pinfo->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;
@@ -773,7 +804,7 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
 
                temp = tvb_get_guint8(tvb, offset);
 
-               if (( hash_info->command == CONNECT_COMMAND) || 
+               if (( hash_info->command == CONNECT_COMMAND) ||
                    ( hash_info->command == UDP_ASSOCIATE_COMMAND))
                                                /* get remote port      */
                        hash_info->port =  tvb_get_ntohs(tvb, offset);
@@ -782,8 +813,8 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
        else if ( hash_info->state == V5Reply) {        /* V5 Command Reply */
 
 
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_fstr(pinfo->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;
@@ -792,35 +823,35 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
                    (hash_info->command == PING_COMMAND) ||
                    (hash_info->command == TRACERT_COMMAND))
                        hash_info->state = Done;
-                       
+
                else if ( hash_info->command == BIND_COMMAND)
                        hash_info->state = V5BindReply;
-                       
+
                else if ( hash_info->command == UDP_ASSOCIATE_COMMAND){
                        offset += 3;            /* skip to address type */
                        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);
-                       
+
                        if (!pinfo->fd->flags.visited)
                                new_udp_conversation( hash_info, pinfo);
 
 /*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(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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;
@@ -829,29 +860,29 @@ state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
        }
        else if ( hash_info->state == AuthReply){       /* V5 User Auth reply */
                hash_info->cmd_reply_row = get_packet_ptr;
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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 
+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 ( pinfo->destport == TCP_PORT_SOCKS){
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->fd, COL_INFO, ", Terminate Request");
-               
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Terminate Request");
+
                if ( tree)
                        proto_tree_add_text(tree, tvb, offset, 1,
                                (hash_info->command  == PING_COMMAND) ?
@@ -859,26 +890,25 @@ display_ping_and_tracert(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
                                "Traceroute: End command");
        }
                else{           /* display the PING or Traceroute results */
-               if (check_col(pinfo->fd, COL_INFO))
-                       col_append_str(pinfo->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, tvb, offset,
-                               tvb_length_remaining(tvb, offset),
+                       proto_tree_add_text(tree, tvb, offset, -1,
                                (hash_info->command  == PING_COMMAND) ?
                                "Ping Results:" :
                                "Traceroute Results");
 
                        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, tvb, offset, linelen,
-                                               format_text(data, linelen));
+                                               "%s", format_text(data, linelen));
                                        offset += linelen;
                                        data = lineend;
                                }
@@ -899,14 +929,14 @@ static void call_next_dissector(tvbuff_t *tvb, int offset, packet_info *pinfo,
 /* 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(tvb, offset, pinfo, tree, hash_info);
 
        else {          /* call the tcp port decoder to handle the payload */
-       
+
 /*XXX may want to load dest address here */
 
                if ( pinfo->destport  == TCP_PORT_SOCKS)
@@ -915,10 +945,10 @@ static void call_next_dissector(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        ptr = &pinfo->srcport;
 
                *ptr = hash_info->port;
-               decode_tcp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport);
+               decode_tcp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport, 0);
                *ptr = TCP_PORT_SOCKS;
        }
-}                
+}
 
 
 
@@ -930,7 +960,7 @@ dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *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);
 
@@ -943,7 +973,6 @@ dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
                hash_info = g_mem_chunk_alloc(socks_vals);
                hash_info->start_done_row = G_MAXINT;
                hash_info->state = None;
-//XX           hash_info->port = -1;
                hash_info->port = 0;
                hash_info->version = tvb_get_guint8(tvb, offset); /* get version*/
 
@@ -960,26 +989,26 @@ dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
 
 /* display summary window information  */
 
-       if (check_col(pinfo->fd, COL_PROTOCOL))
-               col_set_str(pinfo->fd, COL_PROTOCOL, "Socks");
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
 
-       if (check_col(pinfo->fd, COL_INFO)){
+       if (check_col(pinfo->cinfo, COL_INFO)){
                if (( hash_info->version == 4) || ( hash_info->version == 5)){
-                       col_add_fstr(pinfo->fd, COL_INFO, "Version: %d",
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %d",
                                hash_info->version);
-               }               
+               }
                else                    /* unknown version display error */
-                       col_set_str(pinfo->fd, COL_INFO, "Unknown");
-               
+                       col_set_str(pinfo->cinfo, COL_INFO, "Unknown");
+
 
                if ( hash_info->command == PING_COMMAND)
-                       col_append_str(pinfo->fd, COL_INFO, ", Ping Req");
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Ping Req");
                if ( hash_info->command == TRACERT_COMMAND)
-                       col_append_str(pinfo->fd, COL_INFO, ", Traceroute Req");
-               
-//XX           if ( hash_info->port != -1)
+                       col_append_str(pinfo->cinfo, COL_INFO, ", Traceroute Req");
+
+/*XXX          if ( hash_info->port != -1) */
                if ( hash_info->port != 0)
-                       col_append_fstr(pinfo->fd, COL_INFO, ", Remote Port: %d",
+                       col_append_fstr(pinfo->cinfo, COL_INFO, ", Remote Port: %d",
                                hash_info->port);
        }
 
@@ -998,21 +1027,21 @@ dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
                        hash_info->start_done_row = pinfo->fd->num;
                }
        }
-       
+
 /* if proto tree, decode and display */
 
-       if (tree) {                     
-               ti = proto_tree_add_item( tree, proto_socks, tvb, offset,
-                       tvb_length_remaining(tvb, offset), FALSE );
+       if (tree) {
+               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(tvb, offset, pinfo, tree, socks_tree,
+                       display_socks_v4(tvb, offset, pinfo, socks_tree,
                                hash_info);
-                       
+
                else if ( hash_info->version == 5)
-                       display_socks_v5(tvb, offset, pinfo, tree, socks_tree,
+                       display_socks_v5(tvb, offset, pinfo, socks_tree,
                                hash_info);
 
                                /* if past startup, add the faked stuff */
@@ -1026,7 +1055,7 @@ dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
                                        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_uint( socks_tree, hf_socks_dstport, tvb,
@@ -1072,14 +1101,14 @@ proto_register_socks( void){
                &ett_socks,
                &ett_socks_auth,
                &ett_socks_name
-               
+
        };
 
        static hf_register_info hf[] = {
-    
+
 
                { &hf_socks_ver,
-                       { "Version", "socks.ver", FT_UINT8, BASE_DEC, NULL,
+                       { "Version", "socks.version", FT_UINT8, BASE_DEC, NULL,
                                0x0, "", HFILL
                        }
                },
@@ -1089,7 +1118,7 @@ proto_register_socks( void){
                        }
                },
                { &hf_socks_ip6_dst,
-                       { "Remote Address", "socks.dstV6", FT_IPv6, BASE_NONE, NULL,
+                       { "Remote Address(ipv6)", "socks.dstV6", FT_IPv6, BASE_NONE, NULL,
                                0x0, "", HFILL
                        }
                },
@@ -1104,8 +1133,23 @@ proto_register_socks( void){
                                BASE_DEC, NULL, 0x0, "", HFILL
                        }
                },
-               { &hf_socks_command,
-                       { "Command", "socks.command", FT_UINT16,
+               { &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_results,
+                       { "Results(V5)", "socks.results", FT_UINT8,
                                BASE_DEC, NULL, 0x0, "", HFILL
                        }
                }
@@ -1114,10 +1158,10 @@ proto_register_socks( void){
 
 
        proto_socks = proto_register_protocol (
-               "Socks Protocol", "Socks", "socks");           
+               "Socks Protocol", "Socks", "socks");
 
        proto_register_field_array(proto_socks, hf, array_length(hf));
-       proto_register_subtree_array(ett, array_length(ett));  
+       proto_register_subtree_array(ett, array_length(ett));
 
        register_init_routine( &socks_reinit);  /* register re-init routine */
 
@@ -1130,8 +1174,7 @@ proto_register_socks( void){
 void
 proto_reg_handoff_socks(void) {
 
-       /* dissector install routine */ 
-       dissector_add("tcp.port", TCP_PORT_SOCKS, dissect_socks,
-           proto_socks);
+       /* dissector install routine */
+
+       dissector_add("tcp.port", TCP_PORT_SOCKS, socks_handle);
 }