void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) { fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1); fs_add_string(fs, "daddr", make_ip_str(ip->daddr), 1); fs_add_uint64(fs, "ipid", ntohl(ip->id)); fs_add_uint64(fs, "ttl", ntohl(ip->ttl)); }
void fs_add_ip_fields(fieldset_t *fs, struct ip *ip) { // WARNING: you must update fs_ip_fields_len as well // as the definitions set (ip_fiels) if you // change the fields added below: fs_add_string(fs, "saddr", make_ip_str(ip->ip_src.s_addr), 1); fs_add_uint64(fs, "saddr_raw", (uint64_t) ip->ip_src.s_addr); fs_add_string(fs, "daddr", make_ip_str(ip->ip_dst.s_addr), 1); fs_add_uint64(fs, "daddr_raw", (uint64_t) ip->ip_dst.s_addr); fs_add_uint64(fs, "ipid", ntohs(ip->ip_id)); fs_add_uint64(fs, "ttl", ip->ip_ttl); }
void dns_process_packet(const u_char *packet, uint32_t len, fieldset_t *fs, uint32_t *validation) { struct ip *ip_hdr = (struct ip *) &packet[sizeof(struct ether_header)]; if (ip_hdr->ip_p == IPPROTO_UDP) { struct udphdr *udp_hdr = (struct udphdr *) ((char *) ip_hdr + ip_hdr->ip_hl * 4); uint16_t udp_len = ntohs(udp_hdr->uh_ulen); assert(udp_len >= dns_packet_len); char* qname_p = NULL; dns_question_tail* tail_p = NULL; bool is_valid = 0; dns_header* dns_header_p = (dns_header*) &udp_hdr[1]; // verify our dns transaction id if (dns_header_p->id == (validation[2] & 0xFFFF)) { // Verify our question qname_p = (char*) dns_header_p + sizeof(dns_header); tail_p = (dns_question_tail*)(dns_packet + sizeof(dns_header) + qname_len); // Verify our qname if (strcmp(qname, qname_p) == 0) { // Verify the qtype and qclass. if (tail_p->qtype == htons(qtype) && tail_p->qclass \ == htons(0x01)) { is_valid = 1; } } } dns_header* dns_hdr = (dns_header*) &udp_hdr[1]; uint16_t qr = dns_hdr->qr; uint16_t rcode = dns_hdr->rcode; // Success: Has the right validation bits and the right Q // App success: has qr and rcode bits right // Any app level parsing issues: dns_parse_err // High level info fs_add_string(fs, "classification", (char*) "dns", 0); fs_add_uint64(fs, "success", is_valid); fs_add_uint64(fs, "app_success", is_valid && (qr == DNS_QR_ANSWER) && (rcode == DNS_RCODE_NOERR)); // UDP info fs_add_uint64(fs, "sport", ntohs(udp_hdr->uh_sport)); fs_add_uint64(fs, "dport", ntohs(udp_hdr->uh_dport)); fs_add_uint64(fs, "udp_len", udp_len); // ICMP info fs_add_null(fs, "icmp_responder"); fs_add_null(fs, "icmp_type"); fs_add_null(fs, "icmp_code"); fs_add_null(fs, "icmp_unreach_str"); // DNS data if (!is_valid) { // DNS header fs_add_null(fs, "dns_id"); fs_add_null(fs, "dns_rd"); fs_add_null(fs, "dns_tc"); fs_add_null(fs, "dns_aa"); fs_add_null(fs, "dns_opcode"); fs_add_null(fs, "dns_qr"); fs_add_null(fs, "dns_rcode"); fs_add_null(fs, "dns_cd"); fs_add_null(fs, "dns_ad"); fs_add_null(fs, "dns_z"); fs_add_null(fs, "dns_ra"); fs_add_null(fs, "dns_qdcount"); fs_add_null(fs, "dns_ancount"); fs_add_null(fs, "dns_nscount"); fs_add_null(fs, "dns_arcount"); fs_add_repeated(fs, "dns_questions", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_answers", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_authorities", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_additionals", fs_new_repeated_fieldset()); fs_add_uint64(fs, "dns_unconsumed_bytes", 0); fs_add_uint64(fs, "dns_parse_err", 1); } else { // DNS header fs_add_uint64(fs, "dns_id", ntohs(dns_hdr->id)); fs_add_uint64(fs, "dns_rd", dns_hdr->rd); fs_add_uint64(fs, "dns_tc", dns_hdr->tc); fs_add_uint64(fs, "dns_aa", dns_hdr->aa); fs_add_uint64(fs, "dns_opcode", dns_hdr->opcode); fs_add_uint64(fs, "dns_qr", qr); fs_add_uint64(fs, "dns_rcode", rcode); fs_add_uint64(fs, "dns_cd", dns_hdr->cd); fs_add_uint64(fs, "dns_ad", dns_hdr->ad); fs_add_uint64(fs, "dns_z", dns_hdr->z); fs_add_uint64(fs, "dns_ra", dns_hdr->ra); fs_add_uint64(fs, "dns_qdcount", ntohs(dns_hdr->qdcount)); fs_add_uint64(fs, "dns_ancount", ntohs(dns_hdr->ancount)); fs_add_uint64(fs, "dns_nscount", ntohs(dns_hdr->nscount)); fs_add_uint64(fs, "dns_arcount", ntohs(dns_hdr->arcount)); // And now for the complicated part. Hierarchical data. char* data = ((char*)dns_hdr) + sizeof(dns_header); uint16_t data_len = udp_len - sizeof(udp_hdr) - sizeof(dns_header); bool err = 0; // Questions fieldset_t *list = fs_new_repeated_fieldset(); for (int i = 0; i < ntohs(dns_hdr->qdcount) && !err; i++) { err = process_response_question(&data, &data_len, (char*)dns_hdr, udp_len, list); } fs_add_repeated(fs, "dns_questions", list); // Answers list = fs_new_repeated_fieldset(); for (int i = 0; i < ntohs(dns_hdr->ancount) && !err; i++) { err = process_response_answer(&data, &data_len, (char*)dns_hdr, udp_len, list); } fs_add_repeated(fs, "dns_answers", list); // Authorities list = fs_new_repeated_fieldset(); for (int i = 0; i < ntohs(dns_hdr->nscount) && !err; i++) { err = process_response_answer(&data, &data_len, (char*)dns_hdr, udp_len, list); } fs_add_repeated(fs, "dns_authorities", list); // Additionals list = fs_new_repeated_fieldset(); for (int i = 0; i < ntohs(dns_hdr->arcount) && !err; i++) { err = process_response_answer(&data, &data_len, (char*)dns_hdr, udp_len, list); } fs_add_repeated(fs, "dns_additionals", list); // Do we have unconsumed data? fs_add_uint64(fs, "dns_unconsumed_bytes", data_len); if (data_len != 0) { err = 1; } // Did we parse OK? fs_add_uint64(fs, "dns_parse_err", err); } // Now the raw stuff. fs_add_binary(fs, "raw_data", (udp_len - sizeof(struct udphdr)), (void*) &udp_hdr[1], 0); return; } else if (ip_hdr->ip_p == IPPROTO_ICMP) { struct icmp *icmp = (struct icmp*) ((char *) ip_hdr + 4*ip_hdr->ip_hl); struct ip *ip_inner = (struct ip*) ((char *) icmp + ICMP_UNREACH_HEADER_SIZE); // This is the packet we sent struct udphdr *udp_hdr = (struct udphdr *) ((char*) ip_inner + 4*ip_inner->ip_hl); uint16_t udp_len = ntohs(udp_hdr->uh_ulen); // High level info fs_add_string(fs, "classification", (char*) "icmp-unreach", 0); fs_add_uint64(fs, "success", 0); fs_add_uint64(fs, "app_success", 0); // UDP info fs_add_uint64(fs, "sport", ntohs(udp_hdr->uh_sport)); fs_add_uint64(fs, "dport", ntohs(udp_hdr->uh_dport)); fs_add_uint64(fs, "udp_len", udp_len); // ICMP info // XXX This is legacy. not well tested. fs_add_string(fs, "icmp_responder", make_ip_str(ip_hdr->ip_src.s_addr), 1); fs_add_uint64(fs, "icmp_type", icmp->icmp_type); fs_add_uint64(fs, "icmp_code", icmp->icmp_code); if (icmp->icmp_code <= ICMP_UNREACH_PRECEDENCE_CUTOFF) { fs_add_string(fs, "icmp_unreach_str", (char *) udp_unreach_strings[icmp->icmp_code], 0); } else { fs_add_string(fs, "icmp_unreach_str", (char *) "unknown", 0); } // DNS header fs_add_null(fs, "dns_id"); fs_add_null(fs, "dns_rd"); fs_add_null(fs, "dns_tc"); fs_add_null(fs, "dns_aa"); fs_add_null(fs, "dns_opcode"); fs_add_null(fs, "dns_qr"); fs_add_null(fs, "dns_rcode"); fs_add_null(fs, "dns_cd"); fs_add_null(fs, "dns_ad"); fs_add_null(fs, "dns_z"); fs_add_null(fs, "dns_ra"); fs_add_null(fs, "dns_qdcount"); fs_add_null(fs, "dns_ancount"); fs_add_null(fs, "dns_nscount"); fs_add_null(fs, "dns_arcount"); fs_add_repeated(fs, "dns_questions", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_answers", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_authorities", fs_new_repeated_fieldset()); fs_add_repeated(fs, "dns_additionals", fs_new_repeated_fieldset()); fs_add_uint64(fs, "dns_unconsumed_bytes", 0); fs_add_uint64(fs, "dns_parse_err", 1); fs_add_binary(fs, "raw_data", len, (char*)packet, 0); return; } else { // This should not happen. Both the pcap filter and validate // packet prevent this. log_fatal("dns", "Die. This can only happen if you " "change the pcap filter and don't update the " "process function."); return; } }