Example #1
0
void
plog_response(int level, struct sockaddr *to, char sockchar, dns_msg_question_t *q, dns_header_t *h)
{
    int rcode;
    char buf[256];

    if (LogFlags & DNS_LOG_FLAG_QUERY) {
        dns_util_sa2str(buf, sizeof(buf), to);
        rcode = DNS_RCODE(ntohs(h->hdr_flags));

        plog(level, "response to %s %c: %s %s %s %s",
             buf, sockchar,
             dns_proto_rcode_string(rcode),
             q->mq_name,
             dns_proto_class_string(q->mq_class),
             dns_proto_type_string(q->mq_type));
    }
}
Example #2
0
struct dns_packet *
get_next_packet(struct dns_packet *decoded, pcap_parser_file * input)
{
    /* Misc. variables */
    char            fqdn[MAX_NAME + 1];
    unsigned int    fqdn_length;

    /* pcap-related variables */
    const uint8_t  *packet;     /* The actual packet */
    struct pcap_pkthdr header;  /* The header that pcap gives us */
    const struct sniff_ethernet *ethernet;      /* The ethernet header */
    unsigned short ethertype;
    const struct sniff_ipv4 *ipv4;      /* The IP header */
    const struct sniff_ipv6 *ipv6;
    const struct sniff_udp *udp;        /* The UDP header */
    const struct sniff_dns *dns;
    u_int           size_ip;
    u_int           size_layer2;
    unsigned short  ip_version;
    uint32_t        family;
    const uint8_t  *qsection;
    uint8_t         labelsize;
    uint16_t        add_type;
    uint16_t        edns_size;
    uint16_t        extended_rcode_and_version;
    uint16_t        zpart;
    const uint8_t  *sectionptr;
    const uint8_t  *where_am_i; /* Cursor in packet */
    bool            end_of_name;
    unsigned int    size_header;
    bool            end_of_headers, fragmented;
    uint8_t         next_v6_header;
    const struct sniff_eh *eh;  /* The IPv6 extension header, if present */
    const struct sniff_frag *frag;

    assert(decoded->qname != NULL);
    /* Grab next packet */
    decoded->rank = input->packetnum;
  next_packet:
    packet = (uint8_t *) pcap_next(input->handle, &header);
    if (packet == NULL) {       /* End of file */
        return NULL;
    }
    input->packetnum++;
    decoded->length = header.len;
    decoded->captured_length = header.caplen;
    decoded->date = header.ts;
    if (input->firstpacket.tv_sec == 0 && input->firstpacket.tv_usec == 0) {
        input->firstpacket = header.ts;
    }
    input->lastpacket = header.ts;
    if (input->datalink == DLT_EN10MB) {
        size_layer2 = SIZE_ETHERNET;
        ethernet = (struct sniff_ethernet *) (packet);
	ethertype = ntohs(ethernet->ether_type);
	if (ethertype == VLAN_ETHERTYPE) {
	    packet += 4;
	    ethernet = (struct sniff_ethernet *) (packet);
	    ethertype = ntohs(ethernet->ether_type);
	}
        if (ethertype == IPv6_ETHERTYPE) {
            ip_version = 6;
        } else if (ethertype == IPv4_ETHERTYPE) {
            ip_version = 4;
        } else {                /* Ignore other Ethernet types */
            goto next_packet;
        }
    } else if (input->datalink == DLT_LOOP) {
        size_layer2 = SIZE_LOOP;
        family = (ntohl(*((uint32_t *) packet)));
        if (family == PF_INET6) {
            ip_version = 6;
        } else if (family == PF_INET) {
            ip_version = 4;
        } else {                /* Ignore other packet types */
            goto next_packet;
        }
    } else {
        fatal("Unsupported data link type %s (%i)\n",
              pcap_datalink_val_to_description(input->datalink), input->datalink);
    }
    if (ip_version == 6) {
        ipv6 = (struct sniff_ipv6 *) (packet + size_layer2);
        size_ip = SIZE_IPv6;
        assert(IPV6_VERSION(ipv6) == 6);
        next_v6_header = ipv6->ip_nxt;
        size_header = 0;
        where_am_i = where_am_i + SIZE_IPv6;
        end_of_headers = false;
        fragmented = false;
        while (!end_of_headers) {
            /* Extension headers defined in RFC 2460, section 4 */
            if (next_v6_header == 0 ||
                next_v6_header == 43 || next_v6_header == 50
                || next_v6_header == 51 || next_v6_header == 60) {
                eh = (struct sniff_eh *) (where_am_i);
                next_v6_header = eh->eh_next;
                size_header = eh->eh_length;
            }
            /* Fragment */
            else if (next_v6_header == 44) {
                fragmented = 1;
                frag = (struct sniff_frag *) (where_am_i);
                next_v6_header = frag->frag_next;
                size_header = SIZE_FRAGMENT_HDR;
            } else {
                end_of_headers = true;
            }
            where_am_i = where_am_i + size_header;
            size_ip += size_header;
            if ((size_layer2 + size_ip) > decoded->captured_length) {
                if (verbose) {
                    fprintf(stdout,
                            "Warning: ignoring packet #%li because IPv6 headers too large\n",
                            input->packetnum);
                }
                goto next_packet;
            }
        }
        if (fragmented && FRAG_OFFSET(frag) == 0) {
            goto next_packet;
        }
    } else if (ip_version == 4) {
        ipv4 = (struct sniff_ipv4 *) (packet + size_layer2);
        size_ip = IP_HL(ipv4) * 4;
        assert(IPV4_VERSION(ipv4) == 4);
    } else {
        /* Should never happen */
        assert(0);
    }
    if ((ip_version == 6 && next_v6_header == UDP)
        || (ip_version == 4 && ipv4->ip_p == UDP)) {
        if (ip_version == 6) {
            assert(decoded->src != NULL);
            assert(decoded->dst != NULL);
            inet_ntop(AF_INET6, &ipv6->ip_src, decoded->src, INET6_ADDRSTRLEN);
            inet_ntop(AF_INET6, &ipv6->ip_dst, decoded->dst, INET6_ADDRSTRLEN);
        } else if (ip_version == 4) {
            assert(decoded->src != NULL);
            assert(decoded->dst != NULL);
            inet_ntop(AF_INET, &ipv4->ip_src, decoded->src, INET_ADDRSTRLEN);
            inet_ntop(AF_INET, &ipv4->ip_dst, decoded->dst, INET_ADDRSTRLEN);
        } else {
            goto next_packet;
        }
        udp = (struct sniff_udp *) (packet + size_layer2 + size_ip);
        decoded->src_port = (u_short) ntohs(udp->sport);
        decoded->dst_port = (u_short) ntohs(udp->dport);
        if (decoded->src_port == DNS_PORT || decoded->dst_port == DNS_PORT) {
            if (maxpackets > 0 && input->dnspacketnum >= maxpackets) {
                return NULL;
            }
            dns = (struct sniff_dns *) (packet + size_layer2 + size_ip + SIZE_UDP);
            decoded->query = DNS_QR(dns) == 0 ? true : false;
            decoded->query_id = dns->query_id;
            decoded->opcode = DNS_OPCODE(dns);
            decoded->returncode = DNS_RCODE(dns);
            decoded->aa = DNS_AA(dns) ? true : false;
            decoded->tc = DNS_TC(dns) ? true : false;
            decoded->rd = DNS_RD(dns) ? true : false;
            decoded->ra = DNS_RA(dns) ? true : false;
            decoded->ancount = ntohs(dns->ancount);
            decoded->nscount = ntohs(dns->nscount);
            decoded->arcount = ntohs(dns->arcount);
            qsection = (uint8_t *) (packet +
                                    size_layer2 + size_ip + SIZE_UDP + SIZE_DNS);
            fqdn[0] = '\0';
            end_of_name = false;
            for (sectionptr = qsection; !end_of_name;) {
                CHECK_SECTIONPTR(1);
                labelsize = (uint8_t) * sectionptr;
                if (labelsize == 0) {
                    sectionptr++;
                    end_of_name = true;
                } else if (labelsize > 63) {
                    /* It can be an error/attack or it can be compression (RFC 1035, 
                     * section 4.1.4). Today, we ignore packets with compression (we 
                     * just parse the question section, anyway). * * * * * * * *
                     * TODO */
                    if (verbose) {
                        fprintf(stdout,
                                "Warning: ignoring packet #%li because labelsize > 63\n",
                                input->packetnum);
                    }
                    goto next_packet;
                } else {
                    CHECK_SECTIONPTR(labelsize);
                    if (strlen(fqdn) == 0) {
                        strncpy(fqdn, (char *)
                                sectionptr + 1, labelsize);
                        fqdn_length = labelsize;
                    } else {
                        fqdn_length = strlen(fqdn);
                        if (fqdn_length + labelsize > MAX_NAME) {
                            if (verbose) {
                                fprintf(stdout,
                                        "Warning: ignoring packet #%li because malformed (FQDN length is already %i and label size is %i bytes)\n",
                                        input->packetnum, fqdn_length, labelsize);
                            };
                            goto next_packet;
                        }
                        strncat(fqdn, ".", 1);
                        strncat(fqdn, (char *)
                                sectionptr + 1, labelsize);
                        fqdn_length += (labelsize + 1);
                    }
                    if (fqdn_length > MAX_NAME) {
                        if (verbose) {
                            fprintf(stdout,
                                    "Warning: ignoring packet #%li because FQDN length > %i\n",
                                    input->packetnum, MAX_NAME);
                        }
                        goto next_packet;
                    }
                    fqdn[fqdn_length] = '\0';
                    sectionptr = sectionptr + labelsize + 1;
                    CHECK_SECTIONPTR(0);
                }
            }
            CHECK_SECTIONPTR(2);
            strcpy(decoded->qname, fqdn);
#ifdef PICKY_WITH_ALIGNMENT
            decoded->qtype = unaligned_uint16(sectionptr);
#else
            decoded->qtype = ntohs(*((uint16_t *) sectionptr));
#endif
            sectionptr += 2;
            CHECK_SECTIONPTR(2);
#ifdef PICKY_WITH_ALIGNMENT
            decoded->qclass = unaligned_uint16(sectionptr);
#else
            decoded->qclass = ntohs(*((uint16_t *) sectionptr));
#endif
            sectionptr += 2;
            decoded->edns0 = false;
            if (decoded->query) {
                edns_size = 0;
                if (dns->ancount == 0 && dns->nscount == 0) {
                    /* Probably by far the most common case in queries... */
                    if (dns->arcount != 0) {    /* There is an additional section.
                                                 * Probably the OPT * * * * * * * *
                                                 * * * * * of EDNS */
                        CHECK_SECTIONPTR(1);
                        labelsize = (uint8_t) * sectionptr;
                        if (labelsize == 0) {   /* Yes, EDNS0 */
                            sectionptr += 1;
                            CHECK_SECTIONPTR(2);
#ifdef PICKY_WITH_ALIGNMENT
                            add_type = unaligned_uint16(sectionptr);
#else
                            add_type = ntohs(*((uint16_t *) sectionptr));
#endif
                            sectionptr += 2;
                            CHECK_SECTIONPTR(2);
                            if (add_type == OPT) {
#ifdef PICKY_WITH_ALIGNMENT
                                edns_size = unaligned_uint16(sectionptr);
#else
                                edns_size = ntohs(*((uint16_t *) sectionptr));
#endif
                                decoded->edns0 = true;
                                /* RFC 2671 */
                                sectionptr += 2;
                                CHECK_SECTIONPTR(2);
#ifdef PICKY_WITH_ALIGNMENT
                                extended_rcode_and_version =
                                    unaligned_uint16(sectionptr);
#else
                                extended_rcode_and_version =
                                    ntohs(*((uint16_t *) sectionptr));
#endif
                                sectionptr += 2;
                                CHECK_SECTIONPTR(2);
#ifdef PICKY_WITH_ALIGNMENT
                                zpart = unaligned_uint16(sectionptr);
#else
                                zpart = ntohs(*((uint16_t *) sectionptr));
#endif
                                /* RFC 3225 */
                                decoded->do_dnssec =
                                    DNS_DO_DNSSEC(zpart) ? true : false;
                            }
                            sectionptr += 2;
			    /* TODO: dissect the RDATA to find things
			       like the option code (such as 3 for
			       NSID)
			       http://www.iana.org/assignments/dns-parameters */
                        }
                    }
                }
            }
            if (decoded->edns0) {
                decoded->edns0_size = (unsigned int) edns_size;
            }
            input->dnspacketnum++;
            return decoded;
        }
    }
    goto next_packet;
}