/**************************************************************************** 
** File: udp.c
**
** Author: Mike Borella
**
** Comments: Dump UDP header information
**
** $Id: udp.c,v 1.19 2001/11/15 00:22:36 mborella 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 "global.h"
#include "ip_services.h"
#include "udp.h"
#include "payload.h"

extern struct arg_t *my_args;
extern strmap_t port_map[];

/*----------------------------------------------------------------------------
**
** dump_udp()
**
** Parse UDP header and dump fields
**
**----------------------------------------------------------------------------
*/

void dump_udp(packet_t *pkt)
{
  udp_header_t udp;
  service_func_t app_src;
  service_func_t app_dst;

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

  /* Stats accounting */
  stats_update(STATS_UDP);

  /*
   * Get the UDP header
   */

  if (get_packet_bytes((u_int8_t *) &udp, pkt, 8) == 0)
    return;

  /* 
   * Conversions
   */

  udp.src = ntohs(udp.src);
  udp.dst = ntohs(udp.dst);
  udp.length = ntohs(udp.length);
  udp.checksum = ntohs(udp.checksum);

  /*
   * Minimal mode
   */

  if (my_args->m && !my_args->t)
    {
      display_minimal_string("| UDP ");
      display_minimal((u_int8_t *) &udp.src, 2, DISP_DEC);
      display_minimal_string("->");
      display_minimal((u_int8_t *) &udp.dst, 2, DISP_DEC);
      display_minimal_string(" ");
    }
  else 
    if (!my_args->t)
      {  
	/* announcement */
	display_header_banner("UDP Header");
	
	/* dump fields */
	display_strmap("Source port", udp.src, port_map);
	display_strmap("Destination port", udp.dst, port_map);
	display("Length", (char *) &udp.length, 2, DISP_DEC);
	display("Checksum", (char *) &udp.checksum, 2, DISP_DEC);
      }

  /* Add state */
  state_set_srcport(udp.src);
  state_set_dstport(udp.dst);

  /* dump the hex buffer */
  if (!my_args->t)
    hexbuffer_flush();

  /* 
   * Let's try to decode the application from the port number.  If both 
   * match a decoder, we choose the lowest, assuming that the higher 
   * one is probably ephemeral.
   */
  
  app_src = port2func(udp.src);
  app_dst = port2func(udp.dst);
  if (app_src && app_dst)
    {
      if (udp.src < udp.dst)
	app_src(pkt);
      else
	app_dst(pkt);
    }
  else
    {
      if (app_src)
	app_src(pkt);
      else
	if (app_dst)
	  app_dst(pkt);
    }
  
  return;
}
