summaryrefslogtreecommitdiffstats
path: root/listen/ipdump.c
blob: 8dfc43399d1ef80e3696fc693694a754787dd69d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* @(#) $Header: /home/ax25-cvs/ax25-apps/listen/ipdump.c,v 1.2 2001/09/12 13:18:44 terry Exp $ */

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

#define	IPLEN		20

#define	MF		0x2000
#define	DF		0x4000
#define	CE		0x8000

#define	IPIPNEW_PTCL	4
#define	IPIPOLD_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 hexdump)
{
	int hdr_length;
	int tos;
	int ip_length;
	int id;
	int fl_offs;
	int flags;
	int offset;
	int ttl;
	int protocol;
	unsigned char *source, *dest;

	lprintf(T_PROTOCOL, "IP:");

	/* Sneak peek at IP header and find length */
	hdr_length = (data[0] & 0xf) << 2;

	if (hdr_length < IPLEN) {
		lprintf(T_ERROR, " bad header\n");
		return;
	}

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

	lprintf(T_IPHDR, " len %d", ip_length);

	lprintf(T_ADDR, " %d.%d.%d.%d->%d.%d.%d.%d",
		source[0], source[1], source[2], source[3],
		dest[0], dest[1], dest[2], dest[3]);

	lprintf(T_IPHDR, " ihl %d ttl %d", hdr_length, ttl);

	if (tos != 0)
		lprintf(T_IPHDR, " tos %d", tos);

	if (offset != 0 || (flags & MF))
		lprintf(T_IPHDR, " id %d offs %d", id, offset);

	if (flags & DF)
		lprintf(T_IPHDR, " DF");
	if (flags & MF)
		lprintf(T_IPHDR, " MF");
	if (flags & CE)
		lprintf(T_IPHDR, " CE");

	data += hdr_length;
	length -= hdr_length;

	if (offset != 0) {
		lprintf(T_IPHDR, "\n");
		if (length > 0)
			data_dump(data, length, hexdump);
		return;
	}

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