static bool process_response_question(char **data, uint16_t* data_len, const char* payload, uint16_t payload_len, fieldset_t* list) { // Payload is the start of the DNS packet, including header // data is handle to the start of this RR // data_len is a pointer to the how much total data we have to work with. // This is awful. I'm bad and should feel bad. uint16_t bytes_consumed = 0; char* question_name = get_name(*data, *data_len, payload, payload_len, &bytes_consumed); // Error. if (question_name == NULL) { return 1; } assert(bytes_consumed > 0); if ( (bytes_consumed + sizeof(dns_question_tail)) > *data_len) { free(question_name); return 1; } dns_question_tail* tail = (dns_question_tail*)(*data + bytes_consumed); uint16_t qtype = ntohs(tail->qtype); uint16_t qclass = ntohs(tail->qclass); // Build our new question fieldset fieldset_t *qfs = fs_new_fieldset(); fs_add_unsafe_string(qfs, "name", question_name, 1); fs_add_uint64(qfs, "qtype", qtype); if (qtype > MAX_QTYPE || qtype_qtype_to_strid[qtype] == BAD_QTYPE_VAL) { fs_add_string(qfs, "qtype_str", (char*) BAD_QTYPE_STR, 0); } else { // I've written worse things than this 3rd arg. But I want to be fast. fs_add_string(qfs, "qtype_str", (char*)qtype_strs[qtype_qtype_to_strid[qtype]], 0); } fs_add_uint64(qfs, "qclass", qclass); // Now we're adding the new fs to the list. fs_add_fieldset(list, NULL, qfs); // Now update the pointers. *data = *data + bytes_consumed + sizeof(dns_question_tail); *data_len = *data_len - bytes_consumed - sizeof(dns_question_tail); return 0; }
static bool process_response_answer(char **data, uint16_t* data_len, const char* payload, uint16_t payload_len, fieldset_t* list) { log_trace("dns", "call to process_response_answer, data_len: %d", *data_len); // Payload is the start of the DNS packet, including header // data is handle to the start of this RR // data_len is a pointer to the how much total data we have to work with. // This is awful. I'm bad and should feel bad. uint16_t bytes_consumed = 0; char* answer_name = get_name(*data, *data_len, payload, payload_len, &bytes_consumed); // Error. if (answer_name == NULL) { return 1; } assert(bytes_consumed > 0); if ( (bytes_consumed + sizeof(dns_answer_tail)) > *data_len) { free(answer_name); return 1; } dns_answer_tail* tail = (dns_answer_tail*)(*data + bytes_consumed); uint16_t type = ntohs(tail->type); uint16_t class = ntohs(tail->class); uint32_t ttl = ntohl(tail->ttl); uint16_t rdlength = ntohs(tail->rdlength); char* rdata = tail->rdata; if ((rdlength + bytes_consumed + sizeof(dns_answer_tail)) > *data_len) { free(answer_name); return 1; } // Build our new question fieldset fieldset_t *afs = fs_new_fieldset(); fs_add_unsafe_string(afs, "name", answer_name, 1); fs_add_uint64(afs, "type", type); if (type > MAX_QTYPE || qtype_qtype_to_strid[type] == BAD_QTYPE_VAL) { fs_add_string(afs, "type_str", (char*) BAD_QTYPE_STR, 0); } else { // I've written worse things than this 3rd arg. But I want to be fast. fs_add_string(afs, "type_str", (char*)qtype_strs[qtype_qtype_to_strid[type]], 0); } fs_add_uint64(afs, "class", class); fs_add_uint64(afs, "ttl", ttl); fs_add_uint64(afs, "rdlength", rdlength); // XXX Fill this out for the other types we care about. if (type == DNS_QTYPE_NS || type == DNS_QTYPE_CNAME) { uint16_t rdata_bytes_consumed = 0; char* rdata_name = get_name(rdata, rdlength, payload, payload_len, &rdata_bytes_consumed); if (rdata_name == NULL) { fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { fs_add_uint64(afs, "rdata_is_parsed", 1); fs_add_unsafe_string(afs, "rdata", rdata_name, 1); } } else if (type == DNS_QTYPE_MX) { uint16_t rdata_bytes_consumed = 0; if (rdlength <= 4) { fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { char* rdata_name = get_name(rdata + 2, rdlength-2, payload, payload_len, &rdata_bytes_consumed); if (rdata_name == NULL) { fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { // (largest value 16bit) + " " + answer + null char* rdata_with_pref = xmalloc(5 + 1 + strlen(rdata_name) + 1); uint8_t num_printed = snprintf(rdata_with_pref, 6, "%hu ", ntohs( *(uint16_t*)rdata)); memcpy(rdata_with_pref + num_printed, rdata_name, strlen(rdata_name)); fs_add_uint64(afs, "rdata_is_parsed", 1); fs_add_unsafe_string(afs, "rdata", rdata_with_pref, 1); } } } else if (type == DNS_QTYPE_TXT) { if (rdlength >= 1 && (rdlength - 1) != *(uint8_t*)rdata ) { log_warn("dns", "TXT record with wrong TXT len. Not processing."); fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { fs_add_uint64(afs, "rdata_is_parsed", 1); char* txt = xmalloc(rdlength); memcpy(txt, rdata + 1, rdlength-1); fs_add_unsafe_string(afs, "rdata", txt, 1); } } else if (type == DNS_QTYPE_A) { if (rdlength != 4) { log_warn("dns", "A record with IP of length %d. Not processing.", rdlength); fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { fs_add_uint64(afs, "rdata_is_parsed", 1); char* addr = strdup(inet_ntoa( *(struct in_addr*)rdata )); fs_add_unsafe_string(afs, "rdata", addr, 1); } } else if (type == DNS_QTYPE_AAAA) { if (rdlength != 16) { log_warn("dns", "AAAA record with IP of length %d. Not processing.", rdlength); fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } else { fs_add_uint64(afs, "rdata_is_parsed", 1); char* ipv6_str = xmalloc(INET6_ADDRSTRLEN); inet_ntop(AF_INET6, (struct sockaddr_in6*)rdata, ipv6_str,INET6_ADDRSTRLEN); fs_add_unsafe_string(afs, "rdata", ipv6_str, 1); } } else { fs_add_uint64(afs, "rdata_is_parsed", 0); fs_add_binary(afs, "rdata", rdlength, rdata, 0); } // Now we're adding the new fs to the list. fs_add_fieldset(list, NULL, afs); // Now update the pointers. *data = *data + bytes_consumed + sizeof(dns_answer_tail) + rdlength; *data_len = *data_len - bytes_consumed - sizeof(dns_answer_tail) - rdlength; log_trace("dns", "return success from process_response_answer, data_len: %d", *data_len); return 0; }
void handle_packet(uint32_t buflen, const u_char *bytes) { if ((sizeof(struct ip) + (zconf.send_ip_pkts ? 0 : sizeof(struct ether_header))) > buflen) { // buffer not large enough to contain ethernet // and ip headers. further action would overrun buf return; } struct ip *ip_hdr = (struct ip *) &bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct ether_header))]; uint32_t src_ip = ip_hdr->ip_src.s_addr; uint32_t validation[VALIDATE_BYTES/sizeof(uint8_t)]; // TODO: for TTL exceeded messages, ip_hdr->saddr is going to be different // and we must calculate off potential payload message instead validate_gen(ip_hdr->ip_dst.s_addr, ip_hdr->ip_src.s_addr, (uint8_t *) validation); if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct ether_header)), &src_ip, validation)) { return; } int is_repeat = pbm_check(seen, ntohl(src_ip)); //HACK vgiannin for multiple port is_repeat=0; fieldset_t *fs = fs_new_fieldset(); //struct tcphdr *tcp = (struct tcphdr*)((char *) ip_hdr + 4*ip_hdr->ip_hl); //uint16_t sport = ntohs(tcp->th_sport); //printf("port : %d\n",sport); // char line[50]; // struct in_addr t; // t.s_addr = ip_hdr->ip_src.s_addr; // const char *temp = inet_ntoa(t); // sprintf(line,"%s:%d",temp,sport); //printf("%s\n",line ); fs_add_ip_fields(fs, ip_hdr); // HACK: // probe modules (for whatever reason) expect the full ethernet frame // in process_packet. For VPN, we only get back an IP frame. // Here, we fake an ethernet frame (which is initialized to // have ETH_P_IP proto and 00s for dest/src). if (zconf.send_ip_pkts) { if (buflen > sizeof(fake_eth_hdr)) { buflen = sizeof(fake_eth_hdr); } memcpy(&fake_eth_hdr[sizeof(struct ether_header)], bytes, buflen); bytes = fake_eth_hdr; } zconf.probe_module->process_packet(bytes, buflen, fs); fs_add_system_fields(fs, is_repeat, zsend.complete); int success_index = zconf.fsconf.success_index; assert(success_index < fs->len); int is_success = fs_get_uint64_by_index(fs, success_index); if (is_success) { zrecv.success_total++; if (!is_repeat) { zrecv.success_unique++; pbm_set(seen, ntohl(src_ip)); } if (zsend.complete) { zrecv.cooldown_total++; if (!is_repeat) { zrecv.cooldown_unique++; } } } else { zrecv.failure_total++; } // probe module includes app_success field if (zconf.fsconf.app_success_index >= 0) { int is_app_success = fs_get_uint64_by_index(fs, zconf.fsconf.app_success_index); if (is_app_success) { zrecv.app_success_total++; if (!is_repeat) { zrecv.app_success_unique++; } } } fieldset_t *o = NULL; // we need to translate the data provided by the probe module // into a fieldset that can be used by the output module if (!is_success && zconf.filter_unsuccessful) { goto cleanup; } if (is_repeat && zconf.filter_duplicates) { goto cleanup; } if (!evaluate_expression(zconf.filter.expression, fs)) { goto cleanup; } o = translate_fieldset(fs, &zconf.fsconf.translation); if (zconf.output_module && zconf.output_module->process_ip) { zconf.output_module->process_ip(o); } cleanup: fs_free(fs); free(o); if (zconf.output_module && zconf.output_module->update && !(zrecv.success_unique % zconf.output_module->update_interval)) { zconf.output_module->update(&zconf, &zsend, &zrecv); } }