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
120
121
122
123
124
125
126
127
128
129
130
131
|
/* TCP header tracing routines
* Copyright 1991 Phil Karn, KA9Q
*/
#include <stdio.h>
#include <string.h>
#include "listen.h"
#define FIN 0x01
#define SYN 0x02
#define RST 0x04
#define PSH 0x08
#define ACK 0x10
#define URG 0x20
#define CE 0x40
/* TCP options */
#define EOL_KIND 0
#define NOOP_KIND 1
#define MSS_KIND 2
#define MSS_LENGTH 4
#define TCPLEN 20
#define max(a,b) ((a) > (b) ? (a) : (b))
/* Dump a TCP segment header. Assumed to be in network byte order */
void tcp_dump(unsigned char *data, int length, int hexdump)
{
int source, dest;
int seq;
int ack;
int flags;
int wnd;
int up;
int hdrlen;
int mss = 0;
source = get16(data + 0);
dest = get16(data + 2);
seq = get32(data + 4);
ack = get32(data + 8);
hdrlen = (data[12] & 0xF0) >> 2;
flags = data[13];
wnd = get16(data + 14);
up = get16(data + 18);
lprintf(T_PROTOCOL, "TCP:");
lprintf(T_TCPHDR, " %s->", servname(source, "tcp"));
lprintf(T_TCPHDR, "%s Seq x%x", servname(dest, "tcp"), seq);
if (flags & ACK)
lprintf(T_TCPHDR, " Ack x%x", ack);
if (flags & CE)
lprintf(T_TCPHDR, " CE");
if (flags & URG)
lprintf(T_TCPHDR, " URG");
if (flags & ACK)
lprintf(T_TCPHDR, " ACK");
if (flags & PSH)
lprintf(T_TCPHDR, " PSH");
if (flags & RST)
lprintf(T_TCPHDR, " RST");
if (flags & SYN)
lprintf(T_TCPHDR, " SYN");
if (flags & FIN)
lprintf(T_TCPHDR, " FIN");
lprintf(T_TCPHDR, " Wnd %d", wnd);
if (flags & URG)
lprintf(T_TCPHDR, " UP x%x", up);
/* Process options, if any */
if (hdrlen > TCPLEN && length >= hdrlen) {
unsigned char *cp = data + TCPLEN;
int i = hdrlen - TCPLEN;
int kind, optlen;
while (i > 0) {
kind = *cp++;
/* Process single-byte options */
switch (kind) {
case EOL_KIND:
i--;
cp++;
break;
case NOOP_KIND:
i--;
cp++;
continue;
}
/* All other options have a length field */
optlen = *cp++;
/* Process valid multi-byte options */
switch (kind) {
case MSS_KIND:
if (optlen == MSS_LENGTH)
mss = get16(cp);
break;
}
optlen = max(2, optlen); /* Enforce legal minimum */
i -= optlen;
cp += optlen - 2;
}
}
if (mss != 0)
lprintf(T_TCPHDR, " MSS %d", mss);
length -= hdrlen;
data += hdrlen;
if (length > 0) {
lprintf(T_TCPHDR, " Data %d\n", length);
data_dump(data, length, hexdump);
return;
}
lprintf(T_TCPHDR, "\n");
}
|