Exemplo n.º 1
0
/* Extract src, dst addresses */
static inline void
extract_token_addrs(__capability const struct token_header *trp, char *fsrc, char *fdst)
{
	p_memcpy_from_packet(fdst, trp->token_dhost, 6);
	p_memcpy_from_packet(fsrc, trp->token_shost, 6);
}
Exemplo n.º 2
0
/*
 * Print a single PDU.
 */
static void
rpki_rtr_pdu_print (packetbody_t tptr, u_int indent)
{
    __capability const rpki_rtr_pdu *pdu_header;
    u_int pdu_type, pdu_len, hexdump;
    packetbody_t msg;

    pdu_header = (__capability const rpki_rtr_pdu *)tptr;
    pdu_type = pdu_header->pdu_type;
    pdu_len = EXTRACT_32BITS(pdu_header->length);
    hexdump = FALSE;

    printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u",
	   indent_string(8),
	   pdu_header->version,
	   tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type),
	   pdu_type, pdu_len);

    switch (pdu_type) {

	/*
	 * The following PDUs share the message format.
	 */
    case RPKI_RTR_SERIAL_NOTIFY_PDU:
    case RPKI_RTR_SERIAL_QUERY_PDU:
    case RPKI_RTR_END_OF_DATA_PDU:
        msg = (packetbody_t)(pdu_header + 1);
	printf("%sSession ID: 0x%04x, Serial: %u",
	       indent_string(indent+2),
	       EXTRACT_16BITS(pdu_header->u.session_id),
	       EXTRACT_32BITS(msg));
	break;

	/*
	 * The following PDUs share the message format.
	 */
    case RPKI_RTR_RESET_QUERY_PDU:
    case RPKI_RTR_CACHE_RESET_PDU:

	/*
	 * Zero payload PDUs.
	 */
	break;

    case RPKI_RTR_CACHE_RESPONSE_PDU:
	printf("%sSession ID: 0x%04x",
	       indent_string(indent+2),
	       EXTRACT_16BITS(pdu_header->u.session_id));
	break;

    case RPKI_RTR_IPV4_PREFIX_PDU:
	{
	    __capability const rpki_rtr_pdu_ipv4_prefix *pdu;

	    pdu = (__capability const rpki_rtr_pdu_ipv4_prefix *)tptr;
	    printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
		   indent_string(indent+2),
		   ipaddr_string(pdu->prefix),
		   pdu->prefix_length, pdu->max_length,
		   EXTRACT_32BITS(pdu->as), pdu->flags);
	}
	break;

#ifdef INET6
    case RPKI_RTR_IPV6_PREFIX_PDU:
	{
	    __capability const rpki_rtr_pdu_ipv6_prefix *pdu;

	    pdu = (__capability const rpki_rtr_pdu_ipv6_prefix *)tptr;
	    printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
		   indent_string(indent+2),
		   ip6addr_string(pdu->prefix),
		   pdu->prefix_length, pdu->max_length,
		   EXTRACT_32BITS(pdu->as), pdu->flags);
	}
	break;
#endif

    case RPKI_RTR_ERROR_REPORT_PDU:
	{
	    __capability const rpki_rtr_pdu_error_report *pdu;
	    u_int encapsulated_pdu_length, text_length, tlen, error_code;
	    u_char buf[80];

	    pdu = (__capability const rpki_rtr_pdu_error_report *)tptr;
	    encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length);
	    tlen = pdu_len;

	    error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code);
	    printf("%sError code: %s (%u), Encapsulated PDU length: %u",
		   indent_string(indent+2),
		   tok2str(rpki_rtr_error_codes, "Unknown", error_code),
		   error_code, encapsulated_pdu_length);

	    tptr += sizeof(*pdu);
	    tlen -= sizeof(*pdu);

	    /*
	     * Recurse if there is an encapsulated PDU.
	     */
	    if (encapsulated_pdu_length &&
		(encapsulated_pdu_length <= tlen)) {
		printf("%s-----encapsulated PDU-----", indent_string(indent+4));
		rpki_rtr_pdu_print(tptr, indent+2);
	    }

	    tptr += encapsulated_pdu_length;
	    tlen -= encapsulated_pdu_length;

	    /*
	     * Extract, trail-zero and print the Error message.
	     */ 
	    text_length = 0;
	    if (tlen > 4) {
		text_length = EXTRACT_32BITS(tptr);
		tptr += 4;
		tlen -= 4;
	    }
	    if (text_length && (text_length <= tlen )) {
		p_memcpy_from_packet(buf, tptr, MIN(sizeof(buf)-1, text_length));
		buf[text_length] = '\0';
		printf("%sError text: %s", indent_string(indent+2), buf);
	    }
	}
	break;

    default:

	/*
	 * Unknown data, please hexdump.
	 */ 
	hexdump = TRUE;
    }

    /* do we also want to see a hex dump ? */
    if (vflag > 1 || (vflag && hexdump)) {
	print_unknown_data(tptr,"\n\t  ", pdu_len);
    }
}
Exemplo n.º 3
0
void
tcp_print(packetbody_t bp, register u_int length,
	  packetbody_t bp2, int fragmented)
{
        __capability const struct tcphdr *tp;
        __capability 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;
        u_int utoval;
        int threv;
#ifdef INET6
        __capability const struct ip6_hdr *ip6;
#endif

        tp = (__capability const struct tcphdr *)bp;
        ip = (__capability const struct ip *)bp2;
#ifdef INET6
        if (IP_V(ip) == 6)
                ip6 = (__capability const struct ip6_hdr *)bp2;
        else
                ip6 = NULL;
#endif /*INET6*/
        ch = '\0';
        if (!PACKET_HAS_ELEMENT(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) {
		packetbody_t fraglenp;
		u_int32_t fraglen;
		__capability const struct sunrpc_msg *rp;
		enum sunrpc_msg_type direction;

		fraglenp = (packetbody_t)tp + hlen;
		if (PACKET_HAS_SPACE(fraglenp, 4)) {
			fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF;
			if (fraglen > (length - hlen) - 4)
				fraglen = (length - hlen) - 4;
			rp = (__capability const struct sunrpc_msg *)(fraglenp + 4);
			if (PACKET_HAS_ELEMENT(rp, rm_direction)) {
				direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction);
				if (dport == NFS_PORT &&
				    direction == SUNRPC_CALL) {
					nfsreq_print((packetbody_t)rp, fraglen,
					    (packetbody_t)ip);
					return;
				}
				if (sport == NFS_PORT &&
				    direction == SUNRPC_REPLY) {
					nfsreply_print((packetbody_t)rp,
					    fraglen, (packetbody_t)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;
        }

        PACKET_HAS_ONE_OR_TRUNC(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)) {
                struct tcp_seq_hash *th;
                packetbody_t 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
                rev = 0;
                if (ip6) {
                        src = (packetbody_t)&ip6->ip6_src;
                        dst = (packetbody_t)&ip6->ip6_dst;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (p_memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                p_memcpy_from_packet(&tha.src, dst, sizeof ip6->ip6_dst);
                                p_memcpy_from_packet(&tha.dst, src, sizeof ip6->ip6_src);
                                tha.port = dport << 16 | sport;
                        } else {
                                p_memcpy_from_packet(&tha.dst, dst, sizeof ip6->ip6_dst);
                                p_memcpy_from_packet(&tha.src, src, sizeof ip6->ip6_src);
                                tha.port = sport << 16 | dport;
                        }
                } else {
                        /*
                         * Zero out the tha structure; the src and dst
                         * fields are big enough to hold an IPv6
                         * address, but we only have IPv4 addresses
                         * and thus must clear out the remaining 124
                         * bits.
                         *
                         * XXX - should we just clear those bytes after
                         * copying the IPv4 addresses, rather than
                         * zeroing out the entire structure and then
                         * overwriting some of the zeroes?
                         *
                         * XXX - this could fail if we see TCP packets
                         * with an IPv6 address with the lower 124 bits
                         * all zero and also see TCP packes with an
                         * IPv4 address with the same 32 bits as the
                         * upper 32 bits of the IPv6 address in question.
                         * Can that happen?  Is it likely enough to be
                         * an issue?
                         */
                        memset(&tha, 0, sizeof(tha));
                        src = (packetbody_t)&ip->ip_src;
                        dst = (packetbody_t)&ip->ip_dst;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (p_memcmp(src, dst, sizeof ip->ip_dst) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                p_memcpy_from_packet(&tha.src, dst, sizeof ip->ip_dst);
                                p_memcpy_from_packet(&tha.dst, src, sizeof ip->ip_src);
                                tha.port = dport << 16 | sport;
                        } else {
                                p_memcpy_from_packet(&tha.dst, dst, sizeof ip->ip_dst);
                                p_memcpy_from_packet(&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 (p_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)
                                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 (vflag && !Kflag && !fragmented) {
                /* Check the checksum, if possible. */
                u_int16_t sum, tcp_sum;

                if (IP_V(ip) == 4) {
                        if (PACKET_HAS_SPACE(tp, length)) {
                                sum = tcp_cksum(ip, tp, length);
                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);

                                (void)printf(", cksum 0x%04x", tcp_sum);
                                if (sum != 0)
                                        (void)printf(" (incorrect -> 0x%04x)",
                                            in_cksum_shouldbe(tcp_sum, sum));
                                else
                                        (void)printf(" (correct)");
                        }
                }
#ifdef INET6
                else if (IP_V(ip) == 6 && ip6->ip6_plen) {
                        if (PACKET_HAS_SPACE(tp, length)) {
                                sum = nextproto6_cksum(ip6, (packetbody_t)tp, length, IPPROTO_TCP);
                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);

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

                        }
                }
#endif
        }

        length -= hlen;
        if (vflag > 1 || length > 0 || 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)) {
                packetbody_t cp;
                register u_int i, opt, datalen;
                register u_int len;

                hlen -= sizeof(*tp);
                cp = (packetbody_t)tp + sizeof(*tp);
                printf(", options [");
                while (hlen > 0) {
                        if (ch != '\0')
                                putchar(ch);
                        PACKET_HAS_ONE_OR_TRUNC(cp);
                        opt = *cp++;
                        if (ZEROLENOPT(opt))
                                len = 1;
                        else {
                                PACKET_HAS_ONE_OR_TRUNC(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; PACKET_HAS_SPACE_OR_TRUNC(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;

                        case TCPOPT_UTO:
                                datalen = 2;
                                LENCHECK(datalen);
                                utoval = EXTRACT_16BITS(cp);
                                (void)printf("0x%x", utoval);
                                if (utoval & 0x0001)
                                        utoval = (utoval >> 1) * 60;
                                else
                                        utoval >>= 1;
                                (void)printf(" %u", utoval);
                                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;
                }