📄 _tcp.c
字号:
}
else
{
*(struct in_addr *) &tha.dst = ip->ip_dst;
*(struct in_addr *) &tha.src = ip->ip_src;
tha.port = sport << 16 | dport;
}
}
#else
if (sport < dport || (sport == dport && ip->ip_src.s_addr < ip->ip_dst.s_addr))
{
tha.src = ip->ip_src, tha.dst = ip->ip_dst;
tha.port = sport << 16 | dport;
rev = 0;
}
else
{
tha.src = ip->ip_dst, tha.dst = ip->ip_src;
tha.port = dport << 16 | sport;
rev = 1;
}
#endif
threv = rev;
for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
th->nxt; th = th->nxt)
{
if (!memcmp(&tha,&th->addr,sizeof(th->addr)))
break;
}
if (!th->nxt || (flags & TH_SYN))
{
/* didn't find it or new conversation
*/
if (!th->nxt)
{
th->nxt = calloc (1, sizeof(*th));
if (!th->nxt)
PERROR (("tcp_print: calloc"));
}
th->addr = tha;
if (rev)
th->ack = seq, th->seq = ack - 1;
else th->seq = seq, th->ack = ack - 1;
}
else
{
thseq = th->seq;
thack = th->ack;
if (rev)
seq -= th->ack, ack -= th->seq;
else seq -= th->seq, ack -= th->ack;
}
}
else
{
/* fool gcc */
thseq = thack = threv = 0;
}
if (hlen > length)
{
PUTS (" [bad hdr length]");
return;
}
if (IP_V (ip) == 4 && vflag && !fragmented)
{
int sum;
if (TTEST2 (tp->th_sport, length))
{
sum = tcp_cksum (ip, tp, length);
if (sum != 0)
PRINTF (" [bad tcp cksum %x!]", sum);
else PUTS (" [tcp sum ok]");
}
}
#ifdef USE_INET6
if (IP_V (ip) == 6 && ip6->ip6_plen && vflag && !fragmented)
{
int sum;
if (TTEST2 (tp->th_sport, length))
{
sum = tcp6_cksum (ip6, tp, length);
if (sum != 0)
PRINTF (" [bad tcp cksum %x!]", sum);
else PUTS (" [tcp sum ok]");
}
}
#endif
length -= hlen;
if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
PRINTF (" %u:%u(%d)", seq, seq + length, length);
if (flags & TH_ACK)
PRINTF (" ack %u", ack);
PRINTF (" win %d", win);
if (flags & TH_URG)
PRINTF (" urg %d", urp);
/*
* Handle any options.
*/
hlen -= sizeof(*tp);
if (hlen > 0)
{
const u_char *cp;
int i, opt, len, datalen;
cp = (const u_char*)tp + sizeof(*tp);
PUTCHAR (' ');
ch = '<';
while (hlen > 0)
{
PUTCHAR (ch);
TCHECK (*cp);
opt = *cp++;
if (ZEROLENOPT (opt))
len = 1;
else
{
TCHECK (*cp);
len = *cp++;
if (len < 2 || len > hlen)
goto bad;
--hlen; /* account for length byte */
}
--hlen; /* account for type byte */
datalen = 0;
/*
* Bail if "l" bytes of data are not left or were not captured
*/
#define LENCHECK(l) { if ((l) > hlen) \
goto bad; \
TCHECK2(*cp, l); \
}
switch (opt)
{
case TCPOPT_MAXSEG:
PUTS ("mss");
datalen = 2;
LENCHECK (datalen);
PRINTF (" %u", EXTRACT_16BITS (cp));
break;
case TCPOPT_EOL:
PUTS ("eol");
break;
case TCPOPT_NOP:
PUTS ("nop");
break;
case TCPOPT_WSCALE:
PUTS ("wscale");
datalen = 1;
LENCHECK (datalen);
PRINTF (" %u", *cp);
break;
case TCPOPT_SACKOK:
PUTS ("sackOK");
break;
case TCPOPT_SACK:
{
u_int32_t s, e;
datalen = len - 2;
if (datalen % 8)
PUTS (" malformed sack ");
else
{
PRINTF (" sack %d ", datalen / 8);
for (i = 0; i < datalen; i += 8)
{
LENCHECK(i + 4);
s = EXTRACT_32BITS(cp + i);
LENCHECK(i + 8);
e = EXTRACT_32BITS(cp + i + 4);
if (threv)
{
s -= thseq;
e -= thseq;
}
else
{
s -= thack;
e -= thack;
}
PRINTF ("{%u:%u}", s, e);
}
PUTCHAR (' ');
}
break;
}
case TCPOPT_ECHO:
PUTS ("echo");
datalen = 4;
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp));
break;
case TCPOPT_ECHOREPLY:
PUTS ("echoreply");
datalen = 4;
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp));
break;
case TCPOPT_TIMESTAMP:
PUTS ("timestamp");
datalen = 8;
LENCHECK (4);
PRINTF (" %lu", EXTRACT_32BITS (cp));
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp + 4));
break;
case TCPOPT_CC:
PUTS ("cc");
datalen = 4;
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp));
break;
case TCPOPT_CCNEW:
PUTS ("ccnew");
datalen = 4;
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp));
break;
case TCPOPT_CCECHO:
PUTS ("ccecho");
datalen = 4;
LENCHECK (datalen);
PRINTF (" %lu", EXTRACT_32BITS (cp));
break;
default:
PRINTF ("opt-%d:", opt);
datalen = len - 2;
for (i = 0; i < datalen; ++i)
{
LENCHECK (i);
PRINTF ("%02x", cp[i]);
}
break;
}
/* Account for data printed */
cp += datalen;
hlen -= datalen;
/* Check specification against observed length */
++datalen; /* option octet */
if (!ZEROLENOPT (opt))
++datalen; /* size octet */
if (datalen != len)
PRINTF ("[len %d]", len);
ch = ',';
if (opt == TCPOPT_EOL)
break;
}
PUTCHAR ('>');
}
/* check for specific tcp-based protocols. This will never be
* perfect because of the stream nature of tcp but in practice
* it does pretty well
*/
if (!qflag)
{
#define ISPORT(p) (dport == (p) || sport == (p))
u_char *data = (u_char *)(tp + 1);
u_char *data_end;
if (length < snaplen - sizeof(*tp))
data_end = data + length;
else data_end = data + snaplen - sizeof(*tp);
#ifdef PRINT_NETBIOS_DETAILS
if (ISPORT(NETBIOS_SSN_PORT))
{
/* netbios-ssn packets, as used for file
* sharing by SMB (in for example, windows)
*/
nbt_tcp_print (data, data_end);
}
else
#endif
if (vflag && length > 0 && flags & TH_RST)
print_tcp_rst_data (bp, length);
}
return;
bad:
PUTS ("[bad opt]");
if (ch)
PUTCHAR ('>');
/* check for specific tcp-based protocols. This will never be
* perfect because of the stream nature of tcp but in practice
* it does pretty well
*/
if (!qflag)
{
#define ISPORT(p) (dport == (p) || sport == (p))
u_char *data = (u_char *)(tp + 1);
u_char *data_end;
if (length < snaplen - sizeof(*tp))
data_end = data + length;
else data_end = data + snaplen - sizeof(*tp);
#ifdef PRINT_NETBIOS_DETAILS
if (ISPORT(NETBIOS_SSN_PORT))
{
/* netbios-ssn packets, as used for file
* sharing by SMB (in for example, windows)
*/
nbt_tcp_print (data, data_end);
}
#endif
}
if (packettype)
{
switch (packettype)
{
case PT_SUNRPCRM:
sunrpcrm_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
break;
case PT_W3MUX:
w3mux_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
break;
case PT_IIOP:
iiop_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
break;
}
}
return;
trunc:
PUTS ("[|tcp]");
if (ch)
PUTCHAR ('>');
}
/*
*
* RFC1122 says the following on data in RST segments:
*
* 4.2.2.12 RST Segment: RFC-793 Section 3.4
*
* A TCP SHOULD allow a received RST segment to include data.
*
* DISCUSSION
* It has been suggested that a RST segment could contain
* ASCII text that encoded and explained the cause of the
* RST. No standard has yet been established for such
* data.
*
*/
static void print_tcp_rst_data (const u_char *sp, u_int length)
{
int c;
if (TTEST2(*sp, length))
PUTS (" [RST");
else PUTS (" [!RST");
if (length > MAX_RST_DATA_LEN)
{
length = MAX_RST_DATA_LEN; /* can use -X for longer */
PUTCHAR ('+'); /* indicate we truncate */
}
PUTCHAR (' ');
while (length-- && sp <= snapend)
{
c = *sp++;
if (isgraph(c) || c == ' ')
PUTCHAR (c);
else PUTCHAR ('.');
}
PUTCHAR (']');
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -