#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "timer.h"
#include "iface.h"
#include "ip.h"
#include "trace.h"
#include "netuser.h"

int
ip_dump(bpp,check)
struct mbuf **bpp;
int check;
{
	void tcp_dump(),udp_dump(),icmp_dump();
	struct ip ip;
	int16 ip_len;
	int16 offset;
	int16 length;
	int16 csum;

	if(bpp == NULLBUFP || *bpp == NULLBUF)
		return;	

	printf("IP: ");
	/* Sneak peek at IP header and find length */
	ip_len = ((*bpp)->data[0] & 0xf) << 2;
	if(ip_len < IPLEN){
		printf("bad header\n");
		return;
	}
	if(check)
		csum = cksum(NULLHEADER,*bpp,ip_len);
	else
		csum = 0;

	ntohip(&ip,bpp);	/* Can't fail, we've already checked ihl */

	/* Trim data segment if necessary. */
	length = ip.length - ip_len;	/* Length of data portion */
	trim_mbuf(bpp,length);	
	printf("%s",inet_ntoa(ip.source));
	printf("->%s len %u ihl %u ttl %u prot %u",
		inet_ntoa(ip.dest),ip.length,ip_len,ip.ttl & 0xff,
		ip.protocol & 0xff);
	if(ip.tos != 0)
		printf(" tos %u",ip.tos);
	offset = (ip.fl_offs & F_OFFSET) << 3;
	if(offset != 0 || (ip.fl_offs & MF))
		printf(" id %u offs %u",ip.id,offset);
	if(ip.fl_offs & DF)
		printf(" DF");
	if(ip.fl_offs & MF){
		printf(" MF");
		check = 0;	/* Bypass host-level checksum verify */
	}
	if(csum != 0)
		printf(" CHECKSUM ERROR (%u)",csum);
	printf("\n");
	if(offset == 0){
		switch(ip.protocol & 0xff){
		case TCP_PTCL:
			tcp_dump(bpp,ip.source,ip.dest,check);
			break;
		case UDP_PTCL:
			udp_dump(bpp,ip.source,ip.dest,check);
			break;
		case ICMP_PTCL:
			icmp_dump(bpp,ip.source,ip.dest,check);
			break;
		}
	}
}

