/**************************************************************************** 
** File: ipx.c
**
** Author: Mike Borella
**
** Comments: Dump IPX header information
**
** $Log: ipx.c,v $
** Revision 1.2  1998/06/12 21:01:08  mborella
** Added log tag
**
*****************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include "config.h"
#include "ipx.h"

extern struct arg_t *my_args;

/*----------------------------------------------------------------------------
**
** dump_ipx()
**
** Parse IPX header and dump fields
**
**----------------------------------------------------------------------------
*/

void dump_ipx(u_char *bp, int length)
{
  IPXhdr *ipx;
  u_int16_t len;
  u_char *cp;
  void dump_spx(u_char *, u_int16_t);
  void dump_ipxrip(u_char *, u_int16_t);
  static const char *ipxaddr_string(u_char *);
 
  /*
   * Dump header announcement
   */

  printf("-----------------------------------------------------------------\n");
  printf("                        IPX Header\n");
  printf("-----------------------------------------------------------------\n");

  /*
   * View the packet as an IPX header
   */

  ipx = (IPXhdr *) bp;

  /*
   * Check for truncated header and truncated packet
   */
  
  if (length < sizeof(IPXHDR_SIZE))
    {
      printf("Truncated header, length = %d bytes\n", length);
      return;
    }

  len = ntohs(ipx->len);
  if (length < len)
    {
      printf("Truncated packet: length field = %d, actual length = %d\n", 
	     len, length);
      return;
    }

  /*
   * Dump header fields
   */
  
  if (!my_args->n)
    {
      printf("Checksum:               %d\n", ntohs(ipx->csum));
      printf("Packet length:          %d\n", len);
      printf("Transport control:      %d\n", ipx->tc);
      printf("Packet type:            %d ", ipx->pt);

      switch(ipx->pt)
	{
	case 0: 
	  printf("(unknown)\n");
	  break;
	case 1:
	  printf("(RIP)\n");
	  break;
	case 2:
	  printf("(echo)\n");
	  break;
	case 3:
	  printf("(error)\n");
	  break;
	case 4:
	  printf("(PEP)\n");
	  break;
	case 5:
	  printf("(SPX)\n");
	  break;
	case 17:
	  printf("(NCP)\n");
	  break;
	case 20:
	  printf("(NetBIOS)\n");
	  break;
	default:
	  printf("(undefined)\n");
	  break;
	}

      printf("Destination network     %x\n", ntohl(ipx->dstnet));
      printf("Destination node        %s\n", ipxaddr_string(ipx->dstnode));
      printf("Destination port        %d\n", ntohs(ipx->dstport));
      printf("Source network          %x\n", ntohl(ipx->srcnet));
      printf("Source node             %s\n", ipxaddr_string(ipx->srcnode));
      printf("Source port             %d\n", ntohs(ipx->srcport));
    }


  /*
   * Hand it to the next higher level protocol.
   */

  len -= IPXHDR_SIZE;
  cp = (u_char *) bp + IPXHDR_SIZE;
 
  switch (ipx->pt) 
    {
    case 1: 
      dump_ipxrip(cp, len);
      break;

    case 5:
      dump_spx(cp, len);
      break; 
      
    default:
      break;
    }
  
}


/*----------------------------------------------------------------------------
**
** ipxaddr_string()
**
** Convert IPX address to hex format.  Stolen from tcpdump.
**
**----------------------------------------------------------------------------
*/

static const char *ipxaddr_string(u_char *node)
{
    static char line[256];

    sprintf(line, "%02x:%02x:%02x:%02x:%02x:%02x", node[0], node[1], 
	    node[2], node[3], node[4], node[5]);

    return line;
}
