print-tcp.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 819 行 · 第 1/2 页

C
819
字号
/*	$NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $	*//* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 *	The Regents of the University of California.  All rights reserved. * * Copyright (c) 1999-2004 The tcpdump.org project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic const char rcsid[] _U_ ="@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.130.2.3 2007-12-22 03:08:45 guy Exp $ (LBL)";  #else__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $");#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <tcpdump-stdinc.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "interface.h"#include "addrtoname.h"#include "extract.h"#include "tcp.h"#include "ip.h"#ifdef INET6#include "ip6.h"#endif#include "ipproto.h"#include "rpc_auth.h"#include "rpc_msg.h"#include "nameser.h"#ifdef HAVE_LIBCRYPTO#include <openssl/md5.h>#define SIGNATURE_VALID		0#define SIGNATURE_INVALID	1#define CANT_CHECK_SIGNATURE	2static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,                                const u_char *data, int length, const u_char *rcvsig);#endifstatic void print_tcp_rst_data(register const u_char *sp, u_int length);#define MAX_RST_DATA_LEN	30struct tha {#ifndef INET6        struct in_addr src;        struct in_addr dst;#else        struct in6_addr src;        struct in6_addr dst;#endif /*INET6*/        u_int port;};struct tcp_seq_hash {        struct tcp_seq_hash *nxt;        struct tha addr;        tcp_seq seq;        tcp_seq ack;};#define TSEQ_HASHSIZE 919/* These tcp optinos do not have the size octet */#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];struct tok tcp_flag_values[] = {        { TH_FIN, "F" },        { TH_SYN, "S" },        { TH_RST, "R" },        { TH_PUSH, "P" },        { TH_ACK, "." },        { TH_URG, "U" },        { TH_ECNECHO, "E" },        { TH_CWR, "W" },        { 0, NULL }};struct tok tcp_option_values[] = {        { TCPOPT_EOL, "eol" },        { TCPOPT_NOP, "nop" },        { TCPOPT_MAXSEG, "mss" },        { TCPOPT_WSCALE, "wscale" },        { TCPOPT_SACKOK, "sackOK" },        { TCPOPT_SACK, "sack" },        { TCPOPT_ECHO, "echo" },        { TCPOPT_ECHOREPLY, "echoreply" },        { TCPOPT_TIMESTAMP, "TS" },        { TCPOPT_CC, "cc" },        { TCPOPT_CCNEW, "ccnew" },        { TCPOPT_CCECHO, "" },        { TCPOPT_SIGNATURE, "md5" },        { TCPOPT_AUTH, "enhanced auth" },        { 0, NULL }};static int tcp_cksum(register const struct ip *ip,		     register const struct tcphdr *tp,		     register u_int len){        union phu {                struct phdr {                        u_int32_t src;                        u_int32_t dst;                        u_char mbz;                        u_char proto;                        u_int16_t len;                } ph;                u_int16_t pa[6];        } phu;        const u_int16_t *sp;        /* pseudo-header.. */        phu.ph.len = htons((u_int16_t)len);        phu.ph.mbz = 0;        phu.ph.proto = IPPROTO_TCP;        memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));        if (IP_HL(ip) == 5)                memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));        else                phu.ph.dst = ip_finddst(ip);        sp = &phu.pa[0];        return in_cksum((u_short *)tp, len,                        sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);}#ifdef INET6static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,                      u_int len){        size_t i;        u_int32_t sum = 0;        union {                struct {                        struct in6_addr ph_src;                        struct in6_addr ph_dst;                        u_int32_t	ph_len;                        u_int8_t	ph_zero[3];                        u_int8_t	ph_nxt;                } ph;                u_int16_t pa[20];        } phu;        /* pseudo-header */        memset(&phu, 0, sizeof(phu));        phu.ph.ph_src = ip6->ip6_src;        phu.ph.ph_dst = ip6->ip6_dst;        phu.ph.ph_len = htonl(len);        phu.ph.ph_nxt = IPPROTO_TCP;        for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)                sum += phu.pa[i];        return in_cksum((u_short *)tp, len, sum);}#endifvoidtcp_print(register const u_char *bp, register u_int length,	  register const u_char *bp2, int fragmented){        register const struct tcphdr *tp;        register const struct ip *ip;        register u_char flags;        register u_int hlen;        register char ch;        u_int16_t sport, dport, win, urp;        u_int32_t seq, ack, thseq, thack;        int threv;#ifdef INET6        register const struct ip6_hdr *ip6;#endif        tp = (struct tcphdr *)bp;        ip = (struct ip *)bp2;#ifdef INET6        if (IP_V(ip) == 6)                ip6 = (struct ip6_hdr *)bp2;        else                ip6 = NULL;#endif /*INET6*/        ch = '\0';        if (!TTEST(tp->th_dport)) {                (void)printf("%s > %s: [|tcp]",                             ipaddr_string(&ip->ip_src),                             ipaddr_string(&ip->ip_dst));                return;        }        sport = EXTRACT_16BITS(&tp->th_sport);        dport = EXTRACT_16BITS(&tp->th_dport);        hlen = TH_OFF(tp) * 4;        /*	 * If data present, header length valid, and NFS port used,	 * assume NFS.	 * Pass offset of data plus 4 bytes for RPC TCP msg length	 * to NFS print routines.	 */	if (!qflag && hlen >= sizeof(*tp) && hlen <= length &&	    (length - hlen) >= 4) {		u_char *fraglenp;		u_int32_t fraglen;		register struct sunrpc_msg *rp;		enum sunrpc_msg_type direction;		fraglenp = (u_char *)tp + hlen;		if (TTEST2(*fraglenp, 4)) {			fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF;			if (fraglen > (length - hlen) - 4)				fraglen = (length - hlen) - 4;			rp = (struct sunrpc_msg *)(fraglenp + 4);			if (TTEST(rp->rm_direction)) {				direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction);				if (dport == NFS_PORT &&				    direction == SUNRPC_CALL) {					nfsreq_print((u_char *)rp, fraglen,					    (u_char *)ip);					return;				}				if (sport == NFS_PORT &&				    direction == SUNRPC_REPLY) {					nfsreply_print((u_char *)rp, fraglen,					    (u_char *)ip);					return;				}			}                }        }#ifdef INET6        if (ip6) {                if (ip6->ip6_nxt == IPPROTO_TCP) {                        (void)printf("%s.%s > %s.%s: ",                                     ip6addr_string(&ip6->ip6_src),                                     tcpport_string(sport),                                     ip6addr_string(&ip6->ip6_dst),                                     tcpport_string(dport));                } else {                        (void)printf("%s > %s: ",                                     tcpport_string(sport), tcpport_string(dport));                }        } else#endif /*INET6*/        {                if (ip->ip_p == IPPROTO_TCP) {                        (void)printf("%s.%s > %s.%s: ",                                     ipaddr_string(&ip->ip_src),                                     tcpport_string(sport),                                     ipaddr_string(&ip->ip_dst),                                     tcpport_string(dport));                } else {                        (void)printf("%s > %s: ",                                     tcpport_string(sport), tcpport_string(dport));                }        }        if (hlen < sizeof(*tp)) {                (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]",                             length - hlen, hlen, (unsigned long)sizeof(*tp));                return;        }        TCHECK(*tp);        seq = EXTRACT_32BITS(&tp->th_seq);        ack = EXTRACT_32BITS(&tp->th_ack);        win = EXTRACT_16BITS(&tp->th_win);        urp = EXTRACT_16BITS(&tp->th_urp);        if (qflag) {                (void)printf("tcp %d", length - hlen);                if (hlen > length) {                        (void)printf(" [bad hdr length %u - too long, > %u]",                                     hlen, length);                }                return;        }        flags = tp->th_flags;        printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));        if (!Sflag && (flags & TH_ACK)) {                register struct tcp_seq_hash *th;                const void *src, *dst;                register int rev;                struct tha tha;                /*                 * Find (or record) the initial sequence numbers for                 * this conversation.  (we pick an arbitrary                 * collating order so there's only one entry for                 * both directions).                 */#ifdef INET6                memset(&tha, 0, sizeof(tha));                rev = 0;                if (ip6) {                        src = &ip6->ip6_src;                        dst = &ip6->ip6_dst;                        if (sport > dport)                                rev = 1;                        else if (sport == dport) {                                if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)                                        rev = 1;                        }                        if (rev) {                                memcpy(&tha.src, dst, sizeof ip6->ip6_dst);                                memcpy(&tha.dst, src, sizeof ip6->ip6_src);                                tha.port = dport << 16 | sport;                        } else {                                memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);                                memcpy(&tha.src, src, sizeof ip6->ip6_src);                                tha.port = sport << 16 | dport;                        }                } else {                        src = &ip->ip_src;                        dst = &ip->ip_dst;                        if (sport > dport)                                rev = 1;                        else if (sport == dport) {                                if (memcmp(src, dst, sizeof ip->ip_dst) > 0)                                        rev = 1;                        }                        if (rev) {                                memcpy(&tha.src, dst, sizeof ip->ip_dst);                                memcpy(&tha.dst, src, sizeof ip->ip_src);                                tha.port = dport << 16 | sport;                        } else {                                memcpy(&tha.dst, dst, sizeof ip->ip_dst);                                memcpy(&tha.src, src, sizeof ip->ip_src);                                tha.port = sport << 16 | dport;                        }                }#else                rev = 0;                src = &ip->ip_src;                dst = &ip->ip_dst;                if (sport > dport)                        rev = 1;                else if (sport == dport) {                        if (memcmp(src, dst, sizeof ip->ip_dst) > 0)                                rev = 1;                }                if (rev) {                        memcpy(&tha.src, dst, sizeof ip->ip_dst);                        memcpy(&tha.dst, src, sizeof ip->ip_src);                        tha.port = dport << 16 | sport;                } else {                        memcpy(&tha.dst, dst, sizeof ip->ip_dst);                        memcpy(&tha.src, src, sizeof ip->ip_src);                        tha.port = sport << 16 | dport;                }#endif                threv = rev;                for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];                     th->nxt; th = th->nxt)                        if (memcmp((char *)&tha, (char *)&th->addr,                                   sizeof(th->addr)) == 0)                                break;                if (!th->nxt || (flags & TH_SYN)) {                        /* didn't find it or new conversation */                        if (th->nxt == NULL) {                                th->nxt = (struct tcp_seq_hash *)                                        calloc(1, sizeof(*th));                                if (th->nxt == NULL)                                        error("tcp_print: calloc");                        }                        th->addr = tha;                        if (rev)                                th->ack = seq, th->seq = ack - 1;                        else                                th->seq = seq, th->ack = ack - 1;                } else {                        if (rev)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?