1
|
/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */
|
2
|
|
3
|
/*
|
4
|
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
5
|
* The Regents of the University of California. All rights reserved.
|
6
|
*
|
7
|
* Copyright (c) 1999-2004 The tcpdump.org project
|
8
|
*
|
9
|
* Redistribution and use in source and binary forms, with or without
|
10
|
* modification, are permitted provided that: (1) source code distributions
|
11
|
* retain the above copyright notice and this paragraph in its entirety, (2)
|
12
|
* distributions including binary code include the above copyright notice and
|
13
|
* this paragraph in its entirety in the documentation or other materials
|
14
|
* provided with the distribution, and (3) all advertising materials mentioning
|
15
|
* features or use of this software display the following acknowledgement:
|
16
|
* ``This product includes software developed by the University of California,
|
17
|
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
18
|
* the University nor the names of its contributors may be used to endorse
|
19
|
* or promote products derived from this software without specific prior
|
20
|
* written permission.
|
21
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
22
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
23
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
24
|
*/
|
25
|
|
26
|
#include <sys/types.h>
|
27
|
#include <sys/socket.h>
|
28
|
#include <sys/sbuf.h>
|
29
|
#include <netinet/in.h>
|
30
|
#include <netinet/ip.h>
|
31
|
#include <netinet/tcp.h>
|
32
|
|
33
|
#include <stdio.h>
|
34
|
#include <stdlib.h>
|
35
|
#include <string.h>
|
36
|
|
37
|
#include "common.h"
|
38
|
|
39
|
const struct tok ipproto_values[] = {
|
40
|
{ IPPROTO_HOPOPTS, "Options" },
|
41
|
{ IPPROTO_ICMP, "ICMP" },
|
42
|
{ IPPROTO_IGMP, "IGMP" },
|
43
|
{ IPPROTO_IPV4, "IPIP" },
|
44
|
{ IPPROTO_TCP, "TCP" },
|
45
|
{ IPPROTO_EGP, "EGP" },
|
46
|
{ IPPROTO_PIGP, "IGRP" },
|
47
|
{ IPPROTO_UDP, "UDP" },
|
48
|
{ IPPROTO_DCCP, "DCCP" },
|
49
|
{ IPPROTO_IPV6, "IPv6" },
|
50
|
{ IPPROTO_ROUTING, "Routing" },
|
51
|
{ IPPROTO_FRAGMENT, "Fragment" },
|
52
|
{ IPPROTO_RSVP, "RSVP" },
|
53
|
{ IPPROTO_GRE, "GRE" },
|
54
|
{ IPPROTO_ESP, "ESP" },
|
55
|
{ IPPROTO_AH, "AH" },
|
56
|
{ IPPROTO_MOBILE, "Mobile IP" },
|
57
|
{ IPPROTO_ICMPV6, "ICMPv6" },
|
58
|
{ IPPROTO_MOBILITY_OLD, "Mobile IP (old)" },
|
59
|
{ IPPROTO_EIGRP, "EIGRP" },
|
60
|
{ IPPROTO_OSPF, "OSPF" },
|
61
|
{ IPPROTO_PIM, "PIM" },
|
62
|
{ IPPROTO_IPCOMP, "Compressed IP" },
|
63
|
{ IPPROTO_VRRP, "VRRP" },
|
64
|
{ IPPROTO_PGM, "PGM" },
|
65
|
{ IPPROTO_SCTP, "SCTP" },
|
66
|
{ IPPROTO_MOBILITY, "Mobility" },
|
67
|
{ IPPROTO_CARP, "CARP" },
|
68
|
{ IPPROTO_PFSYNC, "pfsync" },
|
69
|
{ 0, NULL }
|
70
|
};
|
71
|
|
72
|
/* These tcp optinos do not have the size octet */
|
73
|
#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
|
74
|
#define TCP_SIGLEN 16
|
75
|
|
76
|
#define TCPOPT_WSCALE 3 /* window scale factor (rfc1323) */
|
77
|
#define TCPOPT_SACKOK 4 /* selective ack ok (rfc2018) */
|
78
|
#define TCPOPT_SACK 5 /* selective ack (rfc2018) */
|
79
|
#define TCPOPT_ECHO 6 /* echo (rfc1072) */
|
80
|
#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */
|
81
|
#define TCPOPT_TIMESTAMP 8 /* timestamp (rfc1323) */
|
82
|
#define TCPOLEN_TIMESTAMP 10
|
83
|
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
|
84
|
#define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */
|
85
|
#define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */
|
86
|
#define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */
|
87
|
#define TCPOPT_SIGNATURE 19 /* Keyed MD5 (rfc2385) */
|
88
|
#define TCPOLEN_SIGNATURE 18
|
89
|
#define TCPOPT_AUTH 20 /* Enhanced AUTH option */
|
90
|
#define TCPOPT_UTO 28 /* tcp user timeout (rfc5482) */
|
91
|
|
92
|
struct tok tcp_option_values[] = {
|
93
|
{ TCPOPT_EOL, "eol" },
|
94
|
{ TCPOPT_NOP, "nop" },
|
95
|
{ TCPOPT_MAXSEG, "mss" },
|
96
|
{ TCPOPT_WSCALE, "wscale" },
|
97
|
{ TCPOPT_SACKOK, "sackOK" },
|
98
|
{ TCPOPT_SACK, "sack" },
|
99
|
{ TCPOPT_ECHO, "echo" },
|
100
|
{ TCPOPT_ECHOREPLY, "echoreply" },
|
101
|
{ TCPOPT_TIMESTAMP, "TS" },
|
102
|
{ TCPOPT_CC, "cc" },
|
103
|
{ TCPOPT_CCNEW, "ccnew" },
|
104
|
{ TCPOPT_CCECHO, "" },
|
105
|
{ TCPOPT_SIGNATURE, "md5" },
|
106
|
{ TCPOPT_AUTH, "enhanced auth" },
|
107
|
{ TCPOPT_UTO, "uto" },
|
108
|
{ 0, NULL }
|
109
|
};
|
110
|
|
111
|
void
|
112
|
tcp_print(struct sbuf *sbuf, register const u_char *bp, register u_int length,
|
113
|
register const u_char *bp2)
|
114
|
{
|
115
|
register const struct tcphdr *tp;
|
116
|
register const struct ip *ip;
|
117
|
register u_char flags;
|
118
|
register u_int hlen;
|
119
|
register char ch;
|
120
|
u_int16_t sport, dport, win, urp;
|
121
|
u_int32_t seq, ack;
|
122
|
register const struct ip6_hdr *ip6;
|
123
|
|
124
|
tp = (const struct tcphdr *)bp;
|
125
|
|
126
|
hlen = (tp->th_off & 0x0f) * 4;
|
127
|
if (hlen < sizeof(*tp)) {
|
128
|
sbuf_printf(sbuf, "errormsg='tcp %d [bad hdr length %u - too short < %lu]',",
|
129
|
length - hlen, hlen, (unsigned long)sizeof(*tp));
|
130
|
return;
|
131
|
}
|
132
|
|
133
|
ip = (const struct ip *)bp2;
|
134
|
if (IP_V(ip) == 6)
|
135
|
ip6 = (const struct ip6_hdr *)bp2;
|
136
|
else
|
137
|
ip6 = NULL;
|
138
|
ch = '\0';
|
139
|
sport = EXTRACT_16BITS(&tp->th_sport);
|
140
|
dport = EXTRACT_16BITS(&tp->th_dport);
|
141
|
|
142
|
sbuf_printf(sbuf, "%u,%u,%d,", sport, dport, length - hlen);
|
143
|
|
144
|
seq = EXTRACT_32BITS(&tp->th_seq);
|
145
|
ack = EXTRACT_32BITS(&tp->th_ack);
|
146
|
win = EXTRACT_16BITS(&tp->th_win);
|
147
|
urp = EXTRACT_16BITS(&tp->th_urp);
|
148
|
|
149
|
flags = tp->th_flags;
|
150
|
sbuf_printf(sbuf, "%s%s%s", flags & TH_FIN ? "F" : "", flags & TH_SYN ? "S" : "", flags & TH_RST ? "R" : "");
|
151
|
sbuf_printf(sbuf, "%s%s%s", flags & TH_PUSH ? "P" : "", flags & TH_ACK ? "A" : "", flags & TH_URG ? "U" : "");
|
152
|
sbuf_printf(sbuf, "%s%s,", flags & TH_ECE ? "E" : "", flags & TH_CWR ? "C" : "");
|
153
|
|
154
|
if (hlen > length) {
|
155
|
sbuf_printf(sbuf, "errormsg='[bad hdr length %u - too long, > %u]',",
|
156
|
hlen, length);
|
157
|
return;
|
158
|
}
|
159
|
|
160
|
length -= hlen;
|
161
|
if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
|
162
|
if (length > 0)
|
163
|
sbuf_printf(sbuf, "%u:%u,", seq, seq + length);
|
164
|
else
|
165
|
sbuf_printf(sbuf, "%u,", seq);
|
166
|
} else
|
167
|
sbuf_printf(sbuf, ",");
|
168
|
|
169
|
if (flags & TH_ACK)
|
170
|
sbuf_printf(sbuf, "%u,", ack);
|
171
|
else
|
172
|
sbuf_printf(sbuf, ",");
|
173
|
|
174
|
sbuf_printf(sbuf, "%d,", win);
|
175
|
|
176
|
if (flags & TH_URG)
|
177
|
sbuf_printf(sbuf, "%d,", urp);
|
178
|
else
|
179
|
sbuf_printf(sbuf, ",");
|
180
|
|
181
|
/*
|
182
|
* Handle any options.
|
183
|
*/
|
184
|
if (hlen > sizeof(*tp)) {
|
185
|
register const u_char *cp;
|
186
|
register u_int opt, datalen;
|
187
|
register u_int len;
|
188
|
|
189
|
hlen -= sizeof(*tp);
|
190
|
cp = (const u_char *)tp + sizeof(*tp);
|
191
|
while (hlen > 0) {
|
192
|
if (ch != '\0')
|
193
|
sbuf_printf(sbuf, "%c", ch);
|
194
|
opt = *cp++;
|
195
|
if (ZEROLENOPT(opt))
|
196
|
len = 1;
|
197
|
else {
|
198
|
len = *cp++; /* total including type, len */
|
199
|
if (len < 2 || len > hlen)
|
200
|
goto bad;
|
201
|
--hlen; /* account for length byte */
|
202
|
}
|
203
|
--hlen; /* account for type byte */
|
204
|
datalen = 0;
|
205
|
|
206
|
sbuf_printf(sbuf, "%s", code2str(tcp_option_values, "Unknown Option %u", opt));
|
207
|
|
208
|
switch (opt) {
|
209
|
case TCPOPT_MAXSEG:
|
210
|
datalen = 2;
|
211
|
break;
|
212
|
case TCPOPT_WSCALE:
|
213
|
datalen = 1;
|
214
|
break;
|
215
|
case TCPOPT_SACK:
|
216
|
datalen = len - 2;
|
217
|
break;
|
218
|
case TCPOPT_CC:
|
219
|
case TCPOPT_CCNEW:
|
220
|
case TCPOPT_CCECHO:
|
221
|
case TCPOPT_ECHO:
|
222
|
case TCPOPT_ECHOREPLY:
|
223
|
datalen = 4;
|
224
|
break;
|
225
|
case TCPOPT_TIMESTAMP:
|
226
|
datalen = 8;
|
227
|
break;
|
228
|
case TCPOPT_SIGNATURE:
|
229
|
datalen = TCP_SIGLEN;
|
230
|
break;
|
231
|
case TCPOPT_AUTH:
|
232
|
datalen = len - 3;
|
233
|
break;
|
234
|
case TCPOPT_EOL:
|
235
|
case TCPOPT_NOP:
|
236
|
case TCPOPT_SACKOK:
|
237
|
/*
|
238
|
* Nothing interesting.
|
239
|
* fall through
|
240
|
*/
|
241
|
break;
|
242
|
case TCPOPT_UTO:
|
243
|
datalen = 2;
|
244
|
break;
|
245
|
default:
|
246
|
datalen = len - 2;
|
247
|
break;
|
248
|
}
|
249
|
|
250
|
/* Account for data printed */
|
251
|
cp += datalen;
|
252
|
hlen -= datalen;
|
253
|
|
254
|
/* Check specification against observed length */
|
255
|
++datalen; /* option octet */
|
256
|
if (!ZEROLENOPT(opt))
|
257
|
++datalen; /* size octet */
|
258
|
ch = ';';
|
259
|
if (opt == TCPOPT_EOL)
|
260
|
break;
|
261
|
}
|
262
|
}
|
263
|
|
264
|
if (length <= 0)
|
265
|
return;
|
266
|
|
267
|
return;
|
268
|
bad:
|
269
|
sbuf_printf(sbuf, "[bad opt],");
|
270
|
if (ch != '\0')
|
271
|
sbuf_printf(sbuf, ">,");
|
272
|
return;
|
273
|
}
|