예제 #1
0
파일: print-atalk.c 프로젝트: biot/tcpdump
/*
 * Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called
 * when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk
 * packets in them).
 */
void
atalk_print(netdissect_options *ndo,
            const u_char *bp, u_int length)
{
	const struct atDDP *dp;
	u_short snet;

	ndo->ndo_protocol = "atalk";
        if(!ndo->ndo_eflag)
            ND_PRINT("AT ");

	if (length < ddpSize) {
		ND_PRINT(" [|ddp %u]", length);
		return;
	}
	if (!ND_TTEST_LEN(bp, ddpSize)) {
		ND_PRINT(" [|ddp]");
		return;
	}
	dp = (const struct atDDP *)bp;
	snet = EXTRACT_BE_U_2(dp->srcNet);
	ND_PRINT("%s.%s", ataddr_string(ndo, snet, EXTRACT_U_1(dp->srcNode)),
	       ddpskt_string(ndo, EXTRACT_U_1(dp->srcSkt)));
	ND_PRINT(" > %s.%s: ",
	       ataddr_string(ndo, EXTRACT_BE_U_2(dp->dstNet), EXTRACT_U_1(dp->dstNode)),
	       ddpskt_string(ndo, EXTRACT_U_1(dp->dstSkt)));
	bp += ddpSize;
	length -= ddpSize;
	ddp_print(ndo, bp, length, EXTRACT_U_1(dp->type), snet, EXTRACT_U_1(dp->srcNode), EXTRACT_U_1(dp->srcSkt));
}
예제 #2
0
static int
l_strnstart(netdissect_options *ndo, const char *tstr1, u_int tl1,
    const char *str2, u_int l2)
{
	if (!ND_TTEST_LEN(str2, tl1)) {
		/*
		 * We don't have tl1 bytes worth of captured data
		 * for the string, so we can't check for this
		 * string.
		 */
		return 0;
	}
	if (tl1 > l2)
		return 0;

	return (strncmp(tstr1, str2, tl1) == 0 ? 1 : 0);
}
예제 #3
0
/*
 * Print out an NFS file handle and return a pointer to following word.
 * If packet was truncated, return 0.
 */
static const uint32_t *
parsefh(netdissect_options *ndo,
        const uint32_t *dp, int v3)
{
	u_int len;

	if (v3) {
		ND_TCHECK_4(dp);
		len = EXTRACT_BE_U_4(dp) / 4;
		dp++;
	} else
		len = NFSX_V2FH / 4;

	if (ND_TTEST_LEN(dp, len * sizeof(*dp))) {
		nfs_printfh(ndo, dp, len);
		return (dp + len);
	}
trunc:
	return (NULL);
}
예제 #4
0
파일: print-tcp.c 프로젝트: fenner/tcpdump
void
tcp_print(netdissect_options *ndo,
          const u_char *bp, u_int length,
          const u_char *bp2, int fragmented)
{
        const struct tcphdr *tp;
        const struct ip *ip;
        u_char flags;
        u_int hlen;
        char ch;
        uint16_t sport, dport, win, urp;
        uint32_t seq, ack, thseq, thack;
        u_int utoval;
        uint16_t magic;
        int rev;
        const struct ip6_hdr *ip6;

        ndo->ndo_protocol = "tcp";
        tp = (const struct tcphdr *)bp;
        ip = (const struct ip *)bp2;
        if (IP_V(ip) == 6)
                ip6 = (const struct ip6_hdr *)bp2;
        else
                ip6 = NULL;
        ch = '\0';
        if (!ND_TTEST_2(tp->th_dport)) {
                if (ip6) {
                        ND_PRINT("%s > %s:",
                                 ip6addr_string(ndo, ip6->ip6_src),
                                 ip6addr_string(ndo, ip6->ip6_dst));
                } else {
                        ND_PRINT("%s > %s:",
                                 ipaddr_string(ndo, ip->ip_src),
                                 ipaddr_string(ndo, ip->ip_dst));
                }
                nd_print_trunc(ndo);
                return;
        }

        sport = GET_BE_U_2(tp->th_sport);
        dport = GET_BE_U_2(tp->th_dport);

        if (ip6) {
                if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) {
                        ND_PRINT("%s.%s > %s.%s: ",
                                 ip6addr_string(ndo, ip6->ip6_src),
                                 tcpport_string(ndo, sport),
                                 ip6addr_string(ndo, ip6->ip6_dst),
                                 tcpport_string(ndo, dport));
                } else {
                        ND_PRINT("%s > %s: ",
                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
                }
        } else {
                if (GET_U_1(ip->ip_p) == IPPROTO_TCP) {
                        ND_PRINT("%s.%s > %s.%s: ",
                                 ipaddr_string(ndo, ip->ip_src),
                                 tcpport_string(ndo, sport),
                                 ipaddr_string(ndo, ip->ip_dst),
                                 tcpport_string(ndo, dport));
                } else {
                        ND_PRINT("%s > %s: ",
                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
                }
        }

        ND_TCHECK_SIZE(tp);

        hlen = TH_OFF(tp) * 4;

        if (hlen < sizeof(*tp)) {
                ND_PRINT(" tcp %u [bad hdr length %u - too short, < %lu]",
                         length - hlen, hlen, (unsigned long)sizeof(*tp));
                return;
        }

        seq = GET_BE_U_4(tp->th_seq);
        ack = GET_BE_U_4(tp->th_ack);
        win = GET_BE_U_2(tp->th_win);
        urp = GET_BE_U_2(tp->th_urp);

        if (ndo->ndo_qflag) {
                ND_PRINT("tcp %u", length - hlen);
                if (hlen > length) {
                        ND_PRINT(" [bad hdr length %u - too long, > %u]",
                                 hlen, length);
                }
                return;
        }

        flags = GET_U_1(tp->th_flags);
        ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));

        if (!ndo->ndo_Sflag && (flags & TH_ACK)) {
                /*
                 * 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).
                 */
                rev = 0;
                if (ip6) {
                        struct tcp_seq_hash6 *th;
                        struct tcp_seq_hash6 *tcp_seq_hash;
                        const void *src, *dst;
                        struct tha6 tha;

                        tcp_seq_hash = tcp_seq_hash6;
                        src = (const void *)ip6->ip6_src;
                        dst = (const void *)ip6->ip6_dst;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst));
                                UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src));
                                tha.port = ((u_int)dport) << 16 | sport;
                        } else {
                                UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst));
                                UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src));
                                tha.port = ((u_int)sport) << 16 | dport;
                        }

                        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 */
                                /* calloc() return used by the 'tcp_seq_hash6'
                                   hash table: do not free() */
                                if (th->nxt == NULL) {
                                        th->nxt = (struct tcp_seq_hash6 *)
                                                calloc(1, sizeof(*th));
                                        if (th->nxt == NULL)
                                                (*ndo->ndo_error)(ndo,
                                                        S_ERR_ND_MEM_ALLOC,
                                                        "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)
                                        seq -= th->ack, ack -= th->seq;
                                else
                                        seq -= th->seq, ack -= th->ack;
                        }

                        thseq = th->seq;
                        thack = th->ack;
                } else {
                        struct tcp_seq_hash *th;
                        struct tcp_seq_hash *tcp_seq_hash;
                        struct tha tha;

                        tcp_seq_hash = tcp_seq_hash4;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                UNALIGNED_MEMCPY(&tha.src, ip->ip_dst,
                                                 sizeof(ip->ip_dst));
                                UNALIGNED_MEMCPY(&tha.dst, ip->ip_src,
                                                 sizeof(ip->ip_src));
                                tha.port = ((u_int)dport) << 16 | sport;
                        } else {
                                UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst,
                                                 sizeof(ip->ip_dst));
                                UNALIGNED_MEMCPY(&tha.src, ip->ip_src,
                                                 sizeof(ip->ip_src));
                                tha.port = ((u_int)sport) << 16 | dport;
                        }

                        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 */
                                /* calloc() return used by the 'tcp_seq_hash4'
                                   hash table: do not free() */
                                if (th->nxt == NULL) {
                                        th->nxt = (struct tcp_seq_hash *)
                                                calloc(1, sizeof(*th));
                                        if (th->nxt == NULL)
                                                (*ndo->ndo_error)(ndo,
                                                        S_ERR_ND_MEM_ALLOC,
                                                        "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)
                                        seq -= th->ack, ack -= th->seq;
                                else
                                        seq -= th->seq, ack -= th->ack;
                        }

                        thseq = th->seq;
                        thack = th->ack;
                }
        } else {
                /*fool gcc*/
                thseq = thack = rev = 0;
        }
        if (hlen > length) {
                ND_PRINT(" [bad hdr length %u - too long, > %u]",
                         hlen, length);
                return;
        }

        if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) {
                /* Check the checksum, if possible. */
                uint16_t sum, tcp_sum;

                if (IP_V(ip) == 4) {
                        if (ND_TTEST_LEN(tp->th_sport, length)) {
                                sum = tcp_cksum(ndo, ip, tp, length);
                                tcp_sum = GET_BE_U_2(tp->th_sum);

                                ND_PRINT(", cksum 0x%04x", tcp_sum);
                                if (sum != 0)
                                        ND_PRINT(" (incorrect -> 0x%04x)",
                                            in_cksum_shouldbe(tcp_sum, sum));
                                else
                                        ND_PRINT(" (correct)");
                        }
                } else if (IP_V(ip) == 6 && ip6->ip6_plen) {
                        if (ND_TTEST_LEN(tp->th_sport, length)) {
                                sum = tcp6_cksum(ndo, ip6, tp, length);
                                tcp_sum = GET_BE_U_2(tp->th_sum);

                                ND_PRINT(", cksum 0x%04x", tcp_sum);
                                if (sum != 0)
                                        ND_PRINT(" (incorrect -> 0x%04x)",
                                            in_cksum_shouldbe(tcp_sum, sum));
                                else
                                        ND_PRINT(" (correct)");

                        }
                }
        }

        length -= hlen;
        if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
                ND_PRINT(", seq %u", seq);

                if (length > 0) {
                        ND_PRINT(":%u", seq + length);
                }
        }

        if (flags & TH_ACK) {
                ND_PRINT(", ack %u", ack);
        }

        ND_PRINT(", win %u", win);

        if (flags & TH_URG)
                ND_PRINT(", urg %u", urp);
        /*
         * Handle any options.
         */
        if (hlen > sizeof(*tp)) {
                const u_char *cp;
                u_int i, opt, datalen;
                u_int len;

                hlen -= sizeof(*tp);
                cp = (const u_char *)tp + sizeof(*tp);
                ND_PRINT(", options [");
                while (hlen > 0) {
                        if (ch != '\0')
                                ND_PRINT("%c", ch);
                        ND_TCHECK_1(cp);
                        opt = GET_U_1(cp);
                        cp++;
                        if (ZEROLENOPT(opt))
                                len = 1;
                        else {
                                ND_TCHECK_1(cp);
                                len = GET_U_1(cp);
                                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; ND_TCHECK_LEN(cp, l); }


                        ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt));

                        switch (opt) {

                        case TCPOPT_MAXSEG:
                                datalen = 2;
                                LENCHECK(datalen);
                                ND_PRINT(" %u", GET_BE_U_2(cp));
                                break;

                        case TCPOPT_WSCALE:
                                datalen = 1;
                                LENCHECK(datalen);
                                ND_PRINT(" %u", GET_U_1(cp));
                                break;

                        case TCPOPT_SACK:
                                datalen = len - 2;
                                if (datalen % 8 != 0) {
                                        ND_PRINT(" invalid sack");
                                } else {
                                        uint32_t s, e;

                                        ND_PRINT(" %u ", datalen / 8);
                                        for (i = 0; i < datalen; i += 8) {
                                                LENCHECK(i + 4);
                                                s = GET_BE_U_4(cp + i);
                                                LENCHECK(i + 8);
                                                e = GET_BE_U_4(cp + i + 4);
                                                if (rev) {
                                                        s -= thseq;
                                                        e -= thseq;
                                                } else {
                                                        s -= thack;
                                                        e -= thack;
                                                }
                                                ND_PRINT("{%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);
                                ND_PRINT(" %u", GET_BE_U_4(cp));
                                break;

                        case TCPOPT_TIMESTAMP:
                                datalen = 8;
                                LENCHECK(datalen);
                                ND_PRINT(" val %u ecr %u",
                                             GET_BE_U_4(cp),
                                             GET_BE_U_4(cp + 4));
                                break;

                        case TCPOPT_SIGNATURE:
                                datalen = TCP_SIGLEN;
                                LENCHECK(datalen);
                                ND_PRINT(" ");
#ifdef HAVE_LIBCRYPTO
                                switch (tcp_verify_signature(ndo, ip, tp,
                                                             bp + TH_OFF(tp) * 4, length, cp)) {

                                case SIGNATURE_VALID:
                                        ND_PRINT("valid");
                                        break;

                                case SIGNATURE_INVALID:
                                        nd_print_invalid(ndo);
                                        break;

                                case CANT_CHECK_SIGNATURE:
                                        ND_PRINT("can't check - ");
                                        for (i = 0; i < TCP_SIGLEN; ++i)
                                                ND_PRINT("%02x",
                                                         GET_U_1(cp + i));
                                        break;
                                }
#else
                                for (i = 0; i < TCP_SIGLEN; ++i)
                                        ND_PRINT("%02x", GET_U_1(cp + i));
#endif
                                break;

                        case TCPOPT_SCPS:
                                datalen = 2;
                                LENCHECK(datalen);
                                ND_PRINT(" cap %02x id %u", GET_U_1(cp),
                                         GET_U_1(cp + 1));
                                break;

                        case TCPOPT_TCPAO:
                                datalen = len - 2;
                                /* RFC 5925 Section 2.2:
                                 * "The Length value MUST be greater than or equal to 4."
                                 * (This includes the Kind and Length fields already processed
                                 * at this point.)
                                 */
                                if (datalen < 2) {
                                        nd_print_invalid(ndo);
                                } else {
                                        LENCHECK(1);
                                        ND_PRINT(" keyid %u", GET_U_1(cp));
                                        LENCHECK(2);
                                        ND_PRINT(" rnextkeyid %u",
                                                 GET_U_1(cp + 1));
                                        if (datalen > 2) {
                                                ND_PRINT(" mac 0x");
                                                for (i = 2; i < datalen; i++) {
                                                        LENCHECK(i + 1);
                                                        ND_PRINT("%02x",
                                                                 GET_U_1(cp + i));
                                                }
                                        }
                                }
                                break;

                        case TCPOPT_EOL:
                        case TCPOPT_NOP:
                        case TCPOPT_SACKOK:
                                /*
                                 * Nothing interesting.
                                 * fall through
                                 */
                                break;

                        case TCPOPT_UTO:
                                datalen = 2;
                                LENCHECK(datalen);
                                utoval = GET_BE_U_2(cp);
                                ND_PRINT(" 0x%x", utoval);
                                if (utoval & 0x0001)
                                        utoval = (utoval >> 1) * 60;
                                else
                                        utoval >>= 1;
                                ND_PRINT(" %u", utoval);
                                break;

                        case TCPOPT_MPTCP:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                if (!mptcp_print(ndo, cp-2, len, flags))
                                        goto bad;
                                break;

                        case TCPOPT_FASTOPEN:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                ND_PRINT(" ");
                                print_tcp_fastopen_option(ndo, cp, datalen, FALSE);
                                break;

                        case TCPOPT_EXPERIMENT2:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                if (datalen < 2)
                                        goto bad;
                                /* RFC6994 */
                                magic = GET_BE_U_2(cp);
                                ND_PRINT("-");

                                switch(magic) {

                                case 0xf989: /* TCP Fast Open RFC 7413 */
                                        print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE);
                                        break;

                                default:
                                        /* Unknown magic number */
                                        ND_PRINT("%04x", magic);
                                        break;
                                }
                                break;

                        default:
                                datalen = len - 2;
                                if (datalen)
                                        ND_PRINT(" 0x");
                                for (i = 0; i < datalen; ++i) {
                                        LENCHECK(i + 1);
                                        ND_PRINT("%02x", GET_U_1(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)
                                ND_PRINT("[len %u]", len);
                        ch = ',';
                        if (opt == TCPOPT_EOL)
                                break;
                }
                ND_PRINT("]");
        }
예제 #5
0
파일: print-atalk.c 프로젝트: biot/tcpdump
/*
 * Print AppleTalk LLAP packets.
 */
u_int
llap_print(netdissect_options *ndo,
           const u_char *bp, u_int length)
{
	const struct LAP *lp;
	const struct atDDP *dp;
	const struct atShortDDP *sdp;
	u_short snet;
	u_int hdrlen;

	ndo->ndo_protocol = "llap";
	if (length < sizeof(*lp)) {
		ND_PRINT(" [|llap %u]", length);
		return (length);
	}
	if (!ND_TTEST_LEN(bp, sizeof(*lp))) {
		nd_print_trunc(ndo);
		return (0);	/* cut short by the snapshot length */
	}
	lp = (const struct LAP *)bp;
	bp += sizeof(*lp);
	length -= sizeof(*lp);
	hdrlen = sizeof(*lp);
	switch (EXTRACT_U_1(lp->type)) {

	case lapShortDDP:
		if (length < ddpSSize) {
			ND_PRINT(" [|sddp %u]", length);
			return (length);
		}
		if (!ND_TTEST_LEN(bp, ddpSSize)) {
			ND_PRINT(" [|sddp]");
			return (0);	/* cut short by the snapshot length */
		}
		sdp = (const struct atShortDDP *)bp;
		ND_PRINT("%s.%s",
		    ataddr_string(ndo, 0, EXTRACT_U_1(lp->src)), ddpskt_string(ndo, EXTRACT_U_1(sdp->srcSkt)));
		ND_PRINT(" > %s.%s:",
		    ataddr_string(ndo, 0, EXTRACT_U_1(lp->dst)), ddpskt_string(ndo, EXTRACT_U_1(sdp->dstSkt)));
		bp += ddpSSize;
		length -= ddpSSize;
		hdrlen += ddpSSize;
		ddp_print(ndo, bp, length, EXTRACT_U_1(sdp->type), 0, EXTRACT_U_1(lp->src), EXTRACT_U_1(sdp->srcSkt));
		break;

	case lapDDP:
		if (length < ddpSize) {
			ND_PRINT(" [|ddp %u]", length);
			return (length);
		}
		if (!ND_TTEST_LEN(bp, ddpSize)) {
			ND_PRINT(" [|ddp]");
			return (0);	/* cut short by the snapshot length */
		}
		dp = (const struct atDDP *)bp;
		snet = EXTRACT_BE_U_2(dp->srcNet);
		ND_PRINT("%s.%s", ataddr_string(ndo, snet, EXTRACT_U_1(dp->srcNode)),
		    ddpskt_string(ndo, EXTRACT_U_1(dp->srcSkt)));
		ND_PRINT(" > %s.%s:",
		    ataddr_string(ndo, EXTRACT_BE_U_2(dp->dstNet), EXTRACT_U_1(dp->dstNode)),
		    ddpskt_string(ndo, EXTRACT_U_1(dp->dstSkt)));
		bp += ddpSize;
		length -= ddpSize;
		hdrlen += ddpSize;
		ddp_print(ndo, bp, length, EXTRACT_U_1(dp->type), snet, EXTRACT_U_1(dp->srcNode), EXTRACT_U_1(dp->srcSkt));
		break;

#ifdef notdef
	case lapKLAP:
		klap_print(bp, length);
		break;
#endif

	default:
		ND_PRINT("%u > %u at-lap#%u %u",
		    EXTRACT_U_1(lp->src), EXTRACT_U_1(lp->dst), EXTRACT_U_1(lp->type), length);
		break;
	}
	return (hdrlen);
}
예제 #6
0
파일: print-dccp.c 프로젝트: fenner/tcpdump
/**
 * dccp_print - show dccp packet
 * @bp - beginning of dccp packet
 * @data2 - beginning of enclosing
 * @len - length of ip packet
 */
void
dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2,
	   u_int len)
{
	const struct dccp_hdr *dh;
	const struct ip *ip;
	const struct ip6_hdr *ip6;
	const u_char *cp;
	u_short sport, dport;
	u_int hlen;
	u_int fixed_hdrlen;
	uint8_t	dccph_type;

	ndo->ndo_protocol = "dccp";
	dh = (const struct dccp_hdr *)bp;

	ip = (const struct ip *)data2;
	if (IP_V(ip) == 6)
		ip6 = (const struct ip6_hdr *)data2;
	else
		ip6 = NULL;

	/* make sure we have enough data to look at the X bit */
	cp = (const u_char *)(dh + 1);
	if (cp > ndo->ndo_snapend)
		goto trunc;
	if (len < sizeof(struct dccp_hdr)) {
		ND_PRINT("truncated-dccp - %u bytes missing!",
			 (u_int)sizeof(struct dccp_hdr) - len);
		return;
	}

	/* get the length of the generic header */
	fixed_hdrlen = dccp_basic_hdr_len(ndo, dh);
	if (len < fixed_hdrlen) {
		ND_PRINT("truncated-dccp - %u bytes missing!",
			  fixed_hdrlen - len);
		return;
	}
	ND_TCHECK_LEN(dh, fixed_hdrlen);

	sport = GET_BE_U_2(dh->dccph_sport);
	dport = GET_BE_U_2(dh->dccph_dport);
	hlen = GET_U_1(dh->dccph_doff) * 4;

	if (ip6) {
		ND_PRINT("%s.%u > %s.%u: ",
			  ip6addr_string(ndo, ip6->ip6_src), sport,
			  ip6addr_string(ndo, ip6->ip6_dst), dport);
	} else {
		ND_PRINT("%s.%u > %s.%u: ",
			  ipaddr_string(ndo, ip->ip_src), sport,
			  ipaddr_string(ndo, ip->ip_dst), dport);
	}

	ND_PRINT("DCCP");

	if (ndo->ndo_qflag) {
		ND_PRINT(" %u", len - hlen);
		if (hlen > len) {
			ND_PRINT(" [bad hdr length %u - too long, > %u]",
				  hlen, len);
		}
		return;
	}

	/* other variables in generic header */
	if (ndo->ndo_vflag) {
		ND_PRINT(" (CCVal %u, CsCov %u, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
	}

	/* checksum calculation */
	if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) {
		uint16_t sum = 0, dccp_sum;

		dccp_sum = GET_BE_U_2(dh->dccph_checksum);
		ND_PRINT("cksum 0x%04x ", dccp_sum);
		if (IP_V(ip) == 4)
			sum = dccp_cksum(ndo, ip, dh, len);
		else if (IP_V(ip) == 6)
			sum = dccp6_cksum(ndo, ip6, dh, len);
		if (sum != 0)
			ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum));
		else
			ND_PRINT("(correct)");
	}

	if (ndo->ndo_vflag)
		ND_PRINT(")");
	ND_PRINT(" ");

	dccph_type = DCCPH_TYPE(dh);
	switch (dccph_type) {
	case DCCP_PKT_REQUEST: {
		const struct dccp_hdr_request *dhr =
			(const struct dccp_hdr_request *)(bp + fixed_hdrlen);
		fixed_hdrlen += 4;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (service=%u) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  GET_BE_U_4(dhr->dccph_req_service));
		break;
	}
	case DCCP_PKT_RESPONSE: {
		const struct dccp_hdr_response *dhr =
			(const struct dccp_hdr_response *)(bp + fixed_hdrlen);
		fixed_hdrlen += 12;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (service=%u) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  GET_BE_U_4(dhr->dccph_resp_service));
		break;
	}
	case DCCP_PKT_DATA:
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_ACK: {
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	}
	case DCCP_PKT_DATAACK: {
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	}
	case DCCP_PKT_CLOSEREQ:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_CLOSE:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_RESET: {
		const struct dccp_hdr_reset *dhr =
			(const struct dccp_hdr_reset *)(bp + fixed_hdrlen);
		fixed_hdrlen += 12;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (code=%s) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  dccp_reset_code(GET_U_1(dhr->dccph_reset_code)));
		break;
	}
	case DCCP_PKT_SYNC:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_SYNCACK:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	default:
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type));
		break;
	}

	if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
			(DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
		dccp_print_ack_no(ndo, bp);

	if (ndo->ndo_vflag < 2)
		return;

	ND_PRINT("seq %" PRIu64, dccp_seqno(ndo, bp));

	/* process options */
	if (hlen > fixed_hdrlen){
		u_int optlen;
		cp = bp + fixed_hdrlen;
		ND_PRINT(" <");

		hlen -= fixed_hdrlen;
		while(1){
			optlen = dccp_print_option(ndo, cp, hlen);
			if (!optlen)
				break;
			if (hlen <= optlen)
				break;
			hlen -= optlen;
			cp += optlen;
			ND_PRINT(", ");
		}
		ND_PRINT(">");
	}
	return;
trunc:
	nd_print_trunc(ndo);
	return;
}
예제 #7
0
USES_APPLE_RST

/*
 * Verify a cryptographic signature of the packet.
 * Currently only MD5 is supported.
 */
int
signature_verify(netdissect_options *ndo, const u_char *pptr, u_int plen,
                 const u_char *sig_ptr, void (*clear_rtn)(void *),
                 const void *clear_arg)
{
    uint8_t *packet_copy, *sig_copy;
    uint8_t sig[16];
    unsigned int i;

    if (!ndo->ndo_sigsecret) {
        return (CANT_CHECK_SIGNATURE);
    }

    /*
     * Do we have all the packet data to be checked?
     */
    if (!ND_TTEST_LEN(pptr, plen)) {
        /* No. */
        return (CANT_CHECK_SIGNATURE);
    }

    /*
     * Do we have the entire signature to check?
     */
    if (!ND_TTEST_LEN(sig_ptr, sizeof(sig))) {
        /* No. */
        return (CANT_CHECK_SIGNATURE);
    }
    if (sig_ptr + sizeof(sig) > pptr + plen) {
        /* No. */
        return (CANT_CHECK_SIGNATURE);
    }

    /*
     * Make a copy of the packet, so we don't overwrite the original.
     */
    packet_copy = malloc(plen);
    if (packet_copy == NULL) {
        return (CANT_ALLOCATE_COPY);
    }

    memcpy(packet_copy, pptr, plen);

    /*
     * Clear the signature in the copy.
     */
    sig_copy = packet_copy + (sig_ptr - pptr);
    memset(sig_copy, 0, sizeof(sig));

    /*
     * Clear anything else that needs to be cleared in the copy.
     * Our caller is assumed to have vetted the clear_arg pointer.
     */
    (*clear_rtn)((void *)(packet_copy + ((const uint8_t *)clear_arg - pptr)));

    /*
     * Compute the signature.
     */
    signature_compute_hmac_md5(packet_copy, plen,
                               (unsigned char *)ndo->ndo_sigsecret,
                               strlen(ndo->ndo_sigsecret), sig);

    /*
     * Free the copy.
     */
    free(packet_copy);

    /*
     * Does the computed signature match the signature in the packet?
     */
    if (memcmp(sig_ptr, sig, sizeof(sig)) == 0) {
        /* Yes. */
        return (SIGNATURE_VALID);
    } else {
        /* No - print the computed signature. */
        for (i = 0; i < sizeof(sig); ++i) {
            ND_PRINT("%02x", sig[i]);
        }

        return (SIGNATURE_INVALID);
    }
}
예제 #8
0
static void
rfc1048_print(netdissect_options *ndo,
	      const u_char *bp)
{
	uint16_t tag;
	u_int len;
	const char *cp;
	char c;
	int first, idx;
	uint8_t subopt, suboptlen;

	ND_PRINT("\n\t  Vendor-rfc1048 Extensions");

	/* Step over magic cookie */
	ND_PRINT("\n\t    Magic Cookie 0x%08x", EXTRACT_BE_U_4(bp));
	bp += sizeof(int32_t);

	/* Loop while we there is a tag left in the buffer */
	while (ND_TTEST_1(bp)) {
		tag = EXTRACT_U_1(bp);
		bp++;
		if (tag == TAG_PAD && ndo->ndo_vflag < 3)
			continue;
		if (tag == TAG_END && ndo->ndo_vflag < 3)
			return;
		if (tag == TAG_EXTENDED_OPTION) {
			ND_TCHECK_2(bp + 1);
			tag = EXTRACT_BE_U_2(bp + 1);
			/* XXX we don't know yet if the IANA will
			 * preclude overlap of 1-byte and 2-byte spaces.
			 * If not, we need to offset tag after this step.
			 */
			cp = tok2str(xtag2str, "?xT%u", tag);
		} else
			cp = tok2str(tag2str, "?T%u", tag);
		c = *cp++;

		if (tag == TAG_PAD || tag == TAG_END)
			len = 0;
		else {
			/* Get the length; check for truncation */
			ND_TCHECK_1(bp);
			len = EXTRACT_U_1(bp);
			bp++;
		}

		ND_PRINT("\n\t    %s Option %u, length %u%s", cp, tag, len,
			  len > 0 ? ": " : "");

		if (tag == TAG_PAD && ndo->ndo_vflag > 2) {
			u_int ntag = 1;
			while (ND_TTEST_1(bp) &&
			       EXTRACT_U_1(bp) == TAG_PAD) {
				bp++;
				ntag++;
			}
			if (ntag > 1)
				ND_PRINT(", occurs %u", ntag);
		}

		if (!ND_TTEST_LEN(bp, len)) {
			ND_PRINT("[|rfc1048 %u]", len);
			return;
		}

		if (tag == TAG_DHCP_MESSAGE && len == 1) {
			ND_PRINT("%s", tok2str(dhcp_msg_values, "Unknown (%u)", EXTRACT_U_1(bp)));
			bp++;
			continue;
		}

		if (tag == TAG_PARM_REQUEST) {
			idx = 0;
			while (len > 0) {
				cp = tok2str(tag2str, "?Option %u", EXTRACT_U_1(bp));
				bp++;
				len--;
				if (idx % 4 == 0)
					ND_PRINT("\n\t      ");
				else
					ND_PRINT(", ");
				ND_PRINT("%s", cp + 1);
				idx++;
			}
			continue;
		}

		if (tag == TAG_EXTENDED_REQUEST) {
			first = 1;
			while (len > 1) {
				cp = tok2str(xtag2str, "?xT%u", EXTRACT_BE_U_2(bp));
				bp += 2;
				len -= 2;
				if (!first)
					ND_PRINT("+");
				ND_PRINT("%s", cp + 1);
				first = 0;
			}
			continue;
		}

		/* Print data */
		if (c == '?') {
			/* Base default formats for unknown tags on data size */
			if (len & 1)
				c = 'b';
			else if (len & 2)
				c = 's';
			else
				c = 'l';
		}
		first = 1;
		switch (c) {

		case 'a':
			/* ASCII strings */
			ND_PRINT("\"");
			if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) {
				ND_PRINT("\"");
				goto trunc;
			}
			ND_PRINT("\"");
			bp += len;
			len = 0;
			break;

		case 'i':
		case 'l':
		case 'L':
			/* ip addresses/32-bit words */
			while (len >= 4) {
				if (!first)
					ND_PRINT(",");
				if (c == 'i')
					ND_PRINT("%s", ipaddr_string(ndo, bp));
				else if (c == 'L')
					ND_PRINT("%d", EXTRACT_BE_S_4(bp));
				else
					ND_PRINT("%u", EXTRACT_BE_U_4(bp));
				bp += 4;
				len -= 4;
				first = 0;
			}
			break;

		case 'p':
			/* IP address pairs */
			while (len >= 2*4) {
				if (!first)
					ND_PRINT(",");
				ND_PRINT("(%s:", ipaddr_string(ndo, bp));
				bp += 4;
				len -= 4;
				ND_PRINT("%s)", ipaddr_string(ndo, bp));
				bp += 4;
				len -= 4;
				first = 0;
			}
			break;

		case 's':
			/* shorts */
			while (len >= 2) {
				if (!first)
					ND_PRINT(",");
				ND_PRINT("%u", EXTRACT_BE_U_2(bp));
				bp += 2;
				len -= 2;
				first = 0;
			}
			break;

		case 'B':
			/* boolean */
			while (len > 0) {
				uint8_t bool_value;
				if (!first)
					ND_PRINT(",");
				bool_value = EXTRACT_U_1(bp);
				switch (bool_value) {
				case 0:
					ND_PRINT("N");
					break;
				case 1:
					ND_PRINT("Y");
					break;
				default:
					ND_PRINT("%u?", bool_value);
					break;
				}
				++bp;
				--len;
				first = 0;
			}
			break;

		case 'b':
		case 'x':
		default:
			/* Bytes */
			while (len > 0) {
				uint8_t byte_value;
				if (!first)
					ND_PRINT(c == 'x' ? ":" : ".");
				byte_value = EXTRACT_U_1(bp);
				if (c == 'x')
					ND_PRINT("%02x", byte_value);
				else
					ND_PRINT("%u", byte_value);
				++bp;
				--len;
				first = 0;
			}
			break;

		case '$':
			/* Guys we can't handle with one of the usual cases */
			switch (tag) {

			case TAG_NETBIOS_NODE:
				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				tag = EXTRACT_U_1(bp);
				++bp;
				--len;
				ND_PRINT("%s", tok2str(nbo2str, NULL, tag));
				break;

			case TAG_OPT_OVERLOAD:
				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				tag = EXTRACT_U_1(bp);
				++bp;
				--len;
				ND_PRINT("%s", tok2str(oo2str, NULL, tag));
				break;

			case TAG_CLIENT_FQDN:
				/* this option should be at least 3 bytes long */
				if (len < 3) {
					ND_PRINT("ERROR: length < 3 bytes");
					bp += len;
					len = 0;
					break;
				}
				if (EXTRACT_U_1(bp))
					ND_PRINT("[%s] ", client_fqdn_flags(EXTRACT_U_1(bp)));
				bp++;
				if (EXTRACT_U_1(bp) || EXTRACT_U_1(bp + 1))
					ND_PRINT("%u/%u ", EXTRACT_U_1(bp), EXTRACT_U_1(bp + 1));
				bp += 2;
				ND_PRINT("\"");
				if (fn_printn(ndo, bp, len - 3, ndo->ndo_snapend)) {
					ND_PRINT("\"");
					goto trunc;
				}
				ND_PRINT("\"");
				bp += len - 3;
				len = 0;
				break;

			case TAG_CLIENT_ID:
			    {
				int type;

				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				type = EXTRACT_U_1(bp);
				bp++;
				len--;
				if (type == 0) {
					ND_PRINT("\"");
					if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) {
						ND_PRINT("\"");
						goto trunc;
					}
					ND_PRINT("\"");
					bp += len;
					len = 0;
					break;
				} else {
					ND_PRINT("%s ", tok2str(arp2str, "hardware-type %u,", type));
					while (len > 0) {
						if (!first)
							ND_PRINT(":");
						ND_PRINT("%02x", EXTRACT_U_1(bp));
						++bp;
						--len;
						first = 0;
					}
				}
				break;
			    }

			case TAG_AGENT_CIRCUIT:
				while (len >= 2) {
					subopt = EXTRACT_U_1(bp);
					suboptlen = EXTRACT_U_1(bp + 1);
					bp += 2;
					len -= 2;
					if (suboptlen > len) {
						ND_PRINT("\n\t      %s SubOption %u, length %u: length goes past end of option",
							  tok2str(agent_suboption_values, "Unknown", subopt),
							  subopt,
							  suboptlen);
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("\n\t      %s SubOption %u, length %u: ",
						  tok2str(agent_suboption_values, "Unknown", subopt),
						  subopt,
						  suboptlen);
					switch (subopt) {

					case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
					case AGENT_SUBOPTION_REMOTE_ID:
					case AGENT_SUBOPTION_SUBSCRIBER_ID:
						if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend))
							goto trunc;
						break;

					default:
						print_unknown_data(ndo, bp, "\n\t\t", suboptlen);
					}

					len -= suboptlen;
					bp += suboptlen;
				}
				break;

			case TAG_CLASSLESS_STATIC_RT:
			case TAG_CLASSLESS_STA_RT_MS:
			    {
				u_int mask_width, significant_octets, i;

				/* this option should be at least 5 bytes long */
				if (len < 5) {
					ND_PRINT("ERROR: length < 5 bytes");
					bp += len;
					len = 0;
					break;
				}
				while (len > 0) {
					if (!first)
						ND_PRINT(",");
					mask_width = EXTRACT_U_1(bp);
					bp++;
					len--;
					/* mask_width <= 32 */
					if (mask_width > 32) {
						ND_PRINT("[ERROR: Mask width (%u) > 32]", mask_width);
						bp += len;
						len = 0;
						break;
					}
					significant_octets = (mask_width + 7) / 8;
					/* significant octets + router(4) */
					if (len < significant_octets + 4) {
						ND_PRINT("[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4);
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("(");
					if (mask_width == 0)
						ND_PRINT("default");
					else {
						for (i = 0; i < significant_octets ; i++) {
							if (i > 0)
								ND_PRINT(".");
							ND_PRINT("%u", EXTRACT_U_1(bp));
							bp++;
						}
						for (i = significant_octets ; i < 4 ; i++)
							ND_PRINT(".0");
						ND_PRINT("/%u", mask_width);
					}
					ND_PRINT(":%s)", ipaddr_string(ndo, bp));
					bp += 4;
					len -= (significant_octets + 4);
					first = 0;
				}
				break;
			    }

			case TAG_USER_CLASS:
			    {
				u_int suboptnumber = 1;

				first = 1;
				if (len < 2) {
					ND_PRINT("ERROR: length < 2 bytes");
					bp += len;
					len = 0;
					break;
				}
				while (len > 0) {
					suboptlen = EXTRACT_U_1(bp);
					bp++;
					len--;
					ND_PRINT("\n\t      ");
					ND_PRINT("instance#%u: ", suboptnumber);
					if (suboptlen == 0) {
						ND_PRINT("ERROR: suboption length must be non-zero");
						bp += len;
						len = 0;
						break;
					}
					if (len < suboptlen) {
						ND_PRINT("ERROR: invalid option");
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("\"");
					if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) {
						ND_PRINT("\"");
						goto trunc;
					}
					ND_PRINT("\"");
					ND_PRINT(", length %u", suboptlen);
					suboptnumber++;
					len -= suboptlen;
					bp += suboptlen;
				}
				break;
			    }

			default:
				ND_PRINT("[unknown special tag %u, size %u]",
					  tag, len);
				bp += len;
				len = 0;
				break;
			}
			break;
		}
		/* Data left over? */
		if (len) {
			ND_PRINT("\n\t  trailing data length %u", len);
			bp += len;
		}
	}
	return;
trunc:
	ND_PRINT("|[rfc1048]");
}