/* @(#) $Header: ipdump.c,v 1.6 91/07/16 17:55:22 deyke Exp $ */

/* IP header tracing routines
 * Copyright 1991 Phil Karn, KA9Q
 */
#include <stdio.h>
#include "global.h"

#define	IPLEN		20

#define	DF		0x01
#define	MF		0x02
#define	CE		0x04

#define	IP_PTCL		94	
#define	TCP_PTCL	6
#define	UDP_PTCL	17
#define	ICMP_PTCL	1
#define	AX25_PTCL	93
#define RSPF_PTCL	73

void ip_dump(unsigned char *data, int length)
{
	int hdr_length;
	int tos;
	int ip_length;
	int id;
	int flags;
	int offset;
	int ttl;
	int protocol;
	unsigned char *source, *dest;

	fprintf(stdout, "IP:");

	/* Sneak peek at IP header and find length */
	hdr_length = (data[0] & 0xf) << 2;
	
	if (hdr_length < IPLEN)
	{
		fprintf(stdout, " bad header\n");
		return;
	}

	tos       = data[1];
	ip_length = get16(data + 2);
	id        = get16(data + 4);
	flags     = data[6] >> 5;
	offset    = get16(data + 6) & 0x1FFF;
	ttl       = data[8];
	protocol  = data[9];
	source    = data + 12;
	dest      = data + 16;

	fprintf(stdout, " len %d", ip_length);
	
	fprintf(stdout, " %d.%d.%d.%d",
			source[0], source[1],
			source[2], source[3]);
	
	fprintf(stdout, "->%d.%d.%d.%d ihl %d ttl %d",
			dest[0], dest[1], dest[2],
			dest[3], hdr_length, ttl);
		
	if (tos != 0) fprintf(stdout, " tos %d", tos);
		
	if (offset != 0 || (flags & MF))
		fprintf(stdout, " id %d offs %d", id, offset);
		
	if (flags & DF) fprintf(stdout, " DF");
	if (flags & MF) fprintf(stdout, " MF");
	if (flags & CE) fprintf(stdout, " CE");
	
	if (offset != 0)
	{
		putc('\n', stdout);
		return;
	}

	data   += hdr_length;
	length -= hdr_length;

	switch (protocol)
	{
	case IP_PTCL:
		fprintf(stdout, " prot IP\n");
		ip_dump(data, length);
		break;
	case TCP_PTCL:
		fprintf(stdout, " prot TCP\n");
		tcp_dump(data, length);
		break;
	case UDP_PTCL:
		fprintf(stdout, " prot UDP\n");
		udp_dump(data, length);
		break;
	case ICMP_PTCL:
		fprintf(stdout, " prot ICMP\n");
		icmp_dump(data, length);
		break;
	case AX25_PTCL:
		fprintf(stdout, " prot AX25\n");
		ax25_dump(data, length);
		break;
	case RSPF_PTCL:
		fprintf(stdout, " prot RSPF\n");
		rspf_dump(data, length);
		break;
	default:
		fprintf(stdout, " prot %d\n", protocol);
		data_dump(data, length);
		break;
	}
}
