/*
 * TCPVIEW
 *
 * Author:	Martin Hunt
 *		Networks and Distributed Computing
 *		Computing & Communications
 *		University of Washington
 *		Administration Building, AG-44
 *		Seattle, WA  98195
 *		Internet: martinh@cac.washington.edu
 *
 *
 * Copyright 1992 by the University of Washington
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appears in all copies and that both the
 * above copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the University of Washington not be
 * used in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  This software is made
 * available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#ifndef lint
static char rcsid[] =
    "@(#) $Header: /usr/staff/martinh/tcpview/RCS/detail-tcp.c,v 1.1 1992/12/01 18:22:52 martinh Exp $ (UW)";
#endif

#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>

#include <X11/X.h>
#include <X11/Xproto.h>

#include "tcpview.h"
#include "addrtoname.h"

extern u_short D_Src_Port, D_Dst_Port;

void  detail_tcp( tp, length )
register struct tcphdr *tp;
u_short length;
{
  register u_char flags;
  register int hlen;
  u_short sport, dport, win, urp;
  u_long seq, ack;


  if ((Phdr->caplen-Offset) < sizeof(struct tcphdr)) {
    printf("***** TCP (truncated) *****\n");
    hex(0, Phdr->caplen - Offset - 1);
    return ;
  }

  hlen = tp->th_off * 4;

  printf("----- TCP Header -----\n\n");
  hex( 0, hlen - 1 );
  hex( -1, -1 );

  D_Src_Port = sport = ntohs(tp->th_sport);
  D_Dst_Port = dport = ntohs(tp->th_dport);
  printf("Source port = %d ( %s )\n",sport,tcpport_string(sport));
  hex( 0, 1 );
  printf("Destination port = %d ( %s )\n",dport,tcpport_string(dport));
  hex( 2, 3 );

  bcopy(&tp->th_seq,&seq,4);
  ntohl(seq);
  printf("Sequence number = %lu\n",seq);
  hex( 4, 7 );

  flags = tp->th_flags;

  if( flags & TH_ACK ) {
    bcopy(&tp->th_ack,&ack,4);
    ntohl(ack);
    printf("Acknowledgement number = %lu\n",ack);
    hex( 8, 11);
  }

  printf("Header length = %d\n",hlen);
  hex( 12, 12 );

  printf("Flags = %x ",flags );
  hex( 13, 13 );
  if ( flags ) {
    printf("( ");
    if (flags & TH_URG)
      printf("UGP ");
    if (flags & TH_ACK)
      printf("ACK ");
    if (flags & TH_SYN)
      printf("SYN ");
    if (flags & TH_FIN)
      printf("FIN ");
    if (flags & TH_RST)
      printf("RST ");
    if (flags & TH_PUSH)
      printf("PSH ");
    printf(")\n");
  } 

  printf("Window = %d\n",ntohs(tp->th_win));
  hex( 14, 15 );

  printf("Checksum = %x\n",ntohs(tp->th_sum));
  hex( 16, 17);

  if( flags & TH_URG ) {
    printf("Urgent pointer = %d\n",ntohs(tp->th_urp));
    hex( 18, 19);
  }

  /*
   * Handle any options.
   */
  if ((hlen -= sizeof(struct tcphdr)) > 0) {
    register u_char *cp = (u_char *)tp + sizeof(struct tcphdr);
    int i;

    printf("Options follow\n");
    hex( 20, hlen+sizeof(struct tcphdr)-1);
    while (--hlen >= 0) {
      switch (*cp++) {
      case TCPOPT_MAXSEG:
	{
	  u_short mss;
#ifdef TCPDUMP_ALIGN
	  bcopy((char *)cp + 1, (char *)&mss, 
		sizeof(mss));
#else
	  mss = *(u_short *)(cp + 1);
#endif				
	  printf("Maximum segment size = %d\n", ntohs(mss));
	  hex(((u_long)cp-(u_long)tp)-1,
	      ((u_long)cp-(u_long)tp)+2);
	  cp += 3;
	  hlen -= 3;
	  break;
	}
      case TCPOPT_EOL:
	printf("EOL\n");
	hex(((u_long)cp-(u_long)tp),((u_long)cp-(u_long)tp)+1);
	break;
      case TCPOPT_NOP:
	printf("NOP\n");
	hex(((u_long)cp-(u_long)tp),((u_long)cp-(u_long)tp)+1);
	break;
      default:
	printf("opt-%d:", cp[-1]);
	hex(((u_long)cp-(u_long)tp)-1,((u_long)cp-(u_long)tp)-1);
	for (i = *cp++ - 2, hlen -= i + 1; i > 0; --i)
	  printf("%02x", *cp++);
	break;
      }
    }
  } else {
    printf("No TCP Options\n");
    hex( -1, -1 );
  }

  hlen = tp->th_off * 4;
  length -= hlen;
  if( length ) {
    printf("[ %d bytes of data ]\n",length);
    hex( hlen, hlen+length-1 );
  }
}


syntax highlighted by Code2HTML, v. 0.9.1