/**************************************************************************** 
** File: ftpctrl.c
**
** Author: Mike Borella
**
** Comments: FTP control module.  
**
** $Id: ftpctrl.c,v 1.5 2006/11/21 07:47:34 farooq-i-azam Exp $
**
** 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 Library 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.
**
*****************************************************************************/

#include "ftpctrl.h"

extern struct arg_t * my_args;

/*----------------------------------------------------------------------------
**
** dump_ftpctrl()
**
** Parse and display FTP control packets
**
**----------------------------------------------------------------------------
*/

void dump_ftpctrl(packet_t *pkt)
{
  u_int8_t * payload;
  u_int32_t  size;
  u_int8_t * ptr;

  /* Set the layer */
  set_layer(LAYER_APPLICATION);

  /* find the payload size, then allocate memory and read the packet */
  size = get_packet_apparentbytesleft(pkt);
  if (size <= 0)
    return;
  payload = (u_int8_t *) my_malloc (size+1);
  payload[size] = '\0';
  if (get_packet_bytes(payload, pkt, size) == 0)
    {
      my_free(payload);
      return;
    }
  
  /* Get rid of carriage return and line feed at end of payload if it exists */
  ptr = payload + strlen(payload);
  while(1)
    {
      ptr --;
      if (*ptr == 0x0D || *ptr == 0x0A)
	*ptr = '\0';
      else
	break;
    }

  /* 
   * FTP control connections either have commands or response codes.  If there
   * is a response code, then this is a reply, otherwise it is a request. All
   * response codes are 3 digits long followed by a space.  Exception: Some
   * replies are split over multiple packets and do not have a numeric code
   * to begin with.  
   * 
   * We determine the direction by looking at the source port.  Replies
   * should always come from the FTP control port.
   */

  if (state_get_srcport() == PORT_FTPCTRL)
    {
      if (isdigit(payload[0]) && isdigit(payload[1]) && isdigit(payload[2]) &&
	  isspace(payload[3]))
	{
	  /* process a reply with a reply code */
	  char replycode_str[4];
	  int replycode;

	  strncpy(replycode_str, payload, 3);
	  replycode_str[3] = '\0';
	  replycode = atoi(replycode_str);
	  
	  if (my_args->m)
	    {
	      display_minimal_string("FTP control ");
	      display_minimal_string(replycode_str);
              display_minimal_string(payload+3);
	    }
	  else
	    {
	      display_header_banner("FTP control");
	      display_string("Reply code", replycode_str);
	      display_string("Reply", payload+4);
	    }
	}
      else
	{
	  /* process a reply without a reply code */
	  if (my_args->m)
	    {
	      display_minimal_string("FTP control ");
              display_minimal_string(payload+3);
	    }
	  else
	    {
	      display_header_banner("FTP control");
	      display_string("Reply", payload);
	    }	  
	}
    }
  else
    {
      /* process a request */
      u_int8_t * requestcode_str;
      u_int8_t * ptr;

      /* find the first space, which separates the request code from request */
      ptr = strchr(payload, ' ');
      if (!ptr)
	{
	  /* This is the case where there is nothing following the code */
	  ptr = payload + strlen(payload);
	  requestcode_str = payload;
	  payload = NULL;
	}
      else
	{
	  requestcode_str = my_malloc((ptr - payload) + 1);
	  strncpy(requestcode_str, payload, ptr - payload);
	  requestcode_str[ptr - payload] = '\0';
	}

      if (my_args->m)
	{
	  display_minimal_string("FTP control ");
	  display_minimal_string(requestcode_str);
          display_minimal_string(" ");
          display_minimal_string(ptr+1);
	}
      else
	{
          display_header_banner("FTP control");
          display_string("Request code", requestcode_str);
	  if (payload && ptr)
	    display_string("Request", ptr+1);
	}

      /* free memory */
      my_free(requestcode_str);
    }

  /* free memory */
  my_free(payload);
       
  /* dump the hex buffer */
  hexbuffer_flush();

}
