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");
}
|