print-tcp.c

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

C
819
字号
                                seq -= th->ack, ack -= th->seq;                        else                                seq -= th->seq, ack -= th->ack;                }                thseq = th->seq;                thack = th->ack;        } else {                /*fool gcc*/                thseq = thack = threv = 0;        }        if (hlen > length) {                (void)printf(" [bad hdr length %u - too long, > %u]",                             hlen, length);                return;        }        if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) {                u_int16_t sum, tcp_sum;                if (TTEST2(tp->th_sport, length)) {                        sum = tcp_cksum(ip, tp, length);                        (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum));                        if (sum != 0) {                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);                                (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum));                        } else                                (void)printf(" (correct)");                }        }#ifdef INET6        if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) {                u_int16_t sum,tcp_sum;                if (TTEST2(tp->th_sport, length)) {                        sum = tcp6_cksum(ip6, tp, length);                        (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum));                        if (sum != 0) {                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);                                (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum));                        } else                                (void)printf(" (correct)");                }        }#endif        length -= hlen;        if (vflag > 1 || flags & (TH_SYN | TH_FIN | TH_RST)) {                (void)printf(", seq %u", seq);                if (length > 0) {                        (void)printf(":%u", seq + length);                }        }        if (flags & TH_ACK) {                (void)printf(", ack %u", ack);        }        (void)printf(", win %d", win);        if (flags & TH_URG)                (void)printf(", urg %d", urp);        /*         * Handle any options.         */        if (hlen > sizeof(*tp)) {                register const u_char *cp;                register u_int i, opt, datalen;                register u_int len;                hlen -= sizeof(*tp);                cp = (const u_char *)tp + sizeof(*tp);                printf(", options [");                while (hlen > 0) {                        if (ch != '\0')                                putchar(ch);                        TCHECK(*cp);                        opt = *cp++;                        if (ZEROLENOPT(opt))                                len = 1;                        else {                                TCHECK(*cp);                                len = *cp++;	/* total including type, len */                                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); }                        printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt));                        switch (opt) {                        case TCPOPT_MAXSEG:                                datalen = 2;                                LENCHECK(datalen);                                (void)printf(" %u", EXTRACT_16BITS(cp));                                break;                        case TCPOPT_WSCALE:                                datalen = 1;                                LENCHECK(datalen);                                (void)printf(" %u", *cp);                                break;                        case TCPOPT_SACK:                                datalen = len - 2;                                if (datalen % 8 != 0) {                                        (void)printf("malformed sack");                                } else {                                        u_int32_t s, e;                                        (void)printf(" %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;                                                }                                                (void)printf("{%u:%u}", s, e);                                        }                                }                                break;                        case TCPOPT_CC:                        case TCPOPT_CCNEW:                        case TCPOPT_CCECHO:                        case TCPOPT_ECHO:                        case TCPOPT_ECHOREPLY:                                /*                                 * those options share their semantics.                                 * fall through                                 */                                datalen = 4;                                LENCHECK(datalen);                                (void)printf(" %u", EXTRACT_32BITS(cp));                                break;                        case TCPOPT_TIMESTAMP:                                datalen = 8;                                LENCHECK(datalen);                                (void)printf(" val %u ecr %u",                                             EXTRACT_32BITS(cp),                                             EXTRACT_32BITS(cp + 4));                                break;                        case TCPOPT_SIGNATURE:                                datalen = TCP_SIGLEN;                                LENCHECK(datalen);#ifdef HAVE_LIBCRYPTO                                switch (tcp_verify_signature(ip, tp,                                                             bp + TH_OFF(tp) * 4, length, cp)) {                                case SIGNATURE_VALID:                                        (void)printf("valid");                                        break;                                case SIGNATURE_INVALID:                                        (void)printf("invalid");                                        break;                                case CANT_CHECK_SIGNATURE:                                        (void)printf("can't check - ");                                        for (i = 0; i < TCP_SIGLEN; ++i)                                                (void)printf("%02x", cp[i]);                                        break;                                }#else                                for (i = 0; i < TCP_SIGLEN; ++i)                                        (void)printf("%02x", cp[i]);#endif                                break;                        case TCPOPT_AUTH:                                (void)printf("keyid %d", *cp++);                                datalen = len - 3;                                for (i = 0; i < datalen; ++i) {                                        LENCHECK(i);                                        (void)printf("%02x", cp[i]);                                }                                break;                        case TCPOPT_EOL:                        case TCPOPT_NOP:                        case TCPOPT_SACKOK:                                /*                                 * Nothing interesting.                                 * fall through                                 */                                break;                        default:                                datalen = len - 2;                                for (i = 0; i < datalen; ++i) {                                        LENCHECK(i);                                        (void)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)                                (void)printf("[len %d]", len);                        ch = ',';                        if (opt == TCPOPT_EOL)                                break;                }                putchar(']');        }        /*         * Print length field before crawling down the stack.         */        printf(", length %u", length);        if (length <= 0)                return;        /*         * Decode payload if necessary.         */        bp += TH_OFF(tp) * 4;        if ((flags & TH_RST) && vflag) {                print_tcp_rst_data(bp, length);                return;        }         if (sport == TELNET_PORT || dport == TELNET_PORT) {                if (!qflag && vflag)                        telnet_print(bp, length);        } else if (sport == BGP_PORT || dport == BGP_PORT)                bgp_print(bp, length);        else if (sport == PPTP_PORT || dport == PPTP_PORT)                pptp_print(bp);#ifdef TCPDUMP_DO_SMB        else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)                nbt_tcp_print(bp, length);	else if (sport == SMB_PORT || dport == SMB_PORT)		smb_tcp_print(bp, length);#endif        else if (sport == BEEP_PORT || dport == BEEP_PORT)                beep_print(bp, length);        else if (length > 2 &&                 (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||                  sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {                /*                 * TCP DNS query has 2byte length at the head.                 * XXX packet could be unaligned, it can go strange                 */                ns_print(bp + 2, length - 2, 0);        } else if (sport == MSDP_PORT || dport == MSDP_PORT) {                msdp_print(bp, length);        }        else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {                ldp_print(bp, length);        }        return; bad:        fputs("[bad opt]", stdout);        if (ch != '\0')                putchar('>');        return; trunc:        fputs("[|tcp]", stdout);        if (ch != '\0')                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 voidprint_tcp_rst_data(register const u_char *sp, u_int length){        int c;        if (TTEST2(*sp, length))                printf(" [RST");        else                printf(" [!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++;                safeputchar(c);        }        putchar(']');}#ifdef HAVE_LIBCRYPTOstatic inttcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,                     const u_char *data, int length, const u_char *rcvsig){        struct tcphdr tp1;        u_char sig[TCP_SIGLEN];        char zero_proto = 0;        MD5_CTX ctx;        u_int16_t savecsum, tlen;#ifdef INET6        struct ip6_hdr *ip6;        u_int32_t len32;        u_int8_t nxt;#endif        tp1 = *tp;        if (tcpmd5secret == NULL)                return (CANT_CHECK_SIGNATURE);        MD5_Init(&ctx);        /*         * Step 1: Update MD5 hash with IP pseudo-header.         */        if (IP_V(ip) == 4) {                MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));                MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));                MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));                MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));                tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;                tlen = htons(tlen);                MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));#ifdef INET6        } else if (IP_V(ip) == 6) {                ip6 = (struct ip6_hdr *)ip;                MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src));                MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));                len32 = htonl(ntohs(ip6->ip6_plen));                MD5_Update(&ctx, (char *)&len32, sizeof(len32));                nxt = 0;                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));                nxt = IPPROTO_TCP;                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));#endif        } else                return (CANT_CHECK_SIGNATURE);        /*         * Step 2: Update MD5 hash with TCP header, excluding options.         * The TCP checksum must be set to zero.         */        savecsum = tp1.th_sum;        tp1.th_sum = 0;        MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr));        tp1.th_sum = savecsum;        /*         * Step 3: Update MD5 hash with TCP segment data, if present.         */        if (length > 0)                MD5_Update(&ctx, data, length);        /*         * Step 4: Update MD5 hash with shared secret.         */        MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret));        MD5_Final(sig, &ctx);        if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)                return (SIGNATURE_VALID);        else                return (SIGNATURE_INVALID);}#endif /* HAVE_LIBCRYPTO *//* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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