static SELECT_RESPONSE_t nb_recv_callback(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param) { settings_t *settings = (settings_t*) param; uint16_t i; dns_t *dns = dns_create_from_packet(data, length); printf("Received a query from %s:%d:\n", addr, port); for(i = 0; i < dns->question_count; i++) { if(dns->questions[i].type == DNS_TYPE_NB) { char decoded_name[16]; uint8_t type; NB_print_question(dns->questions[i], dns->flags); NB_decode_name(dns->questions[i].name, decoded_name, &type); if(should_poison(settings, dns->flags, decoded_name, addr)) send_poison_response(settings, s, addr, port, decoded_name, type, dns->trn_id); if(should_conflict(settings, dns->flags, decoded_name, addr)) send_conflict_response(settings, s, addr, port, decoded_name, type, dns->trn_id); } else if(dns->questions[i].type == DNS_TYPE_NBSTAT) { NBSTAT_print_question(dns->questions[i], dns->flags); } else { fprintf(stderr, "Unknown NetBIOS question: 0x%04x\n", dns->questions[i].type); } } printf("\n"); dns_destroy(dns); return SELECT_OK; }
static SELECT_RESPONSE_t dns_callback(void *group, int socket, uint8_t *packet, size_t packet_length, char *addr, uint16_t port, void *s) { settings_t *settings = (settings_t*) s; dns_t *response; uint8_t *response_packet; uint32_t response_packet_length; /* Parse the DNS packet. */ dns_t *request = dns_create_from_packet(packet, packet_length); /* Create the response packet. */ response = dns_create(); response->trn_id = request->trn_id; response->flags = 0x8000; if(request->question_count > 0) { int i; /* Display the questions. */ for(i = 0; i < request->question_count; i++) { /* Grab the question and display it. */ question_t this_question = request->questions[i]; fprintf(stderr, "Question %d: %s (0x%04x 0x%04x)\n", i, this_question.name, this_question.type, this_question.class); /* Add an answer, if appropriate. */ dns_add_question(response, this_question.name, this_question.type, this_question.class); if(settings->A && (this_question.type == DNS_TYPE_A || this_question.type == DNS_TYPE_ANY)) { fprintf(stderr, "(Responding with %s)\n", settings->A); dns_add_answer_A(response, this_question.name, 0x0001, settings->TTL, settings->A); } #ifndef WIN32 else if(settings->AAAA && this_question.type == DNS_TYPE_AAAA) { fprintf(stderr, "(Responding with %s)\n", settings->AAAA); dns_add_answer_AAAA(response, this_question.name, 0x0001, settings->TTL, settings->AAAA); } #endif } /* If we have any answers, send back our packet. */ if(response->answer_count > 0) { /* Send the packet. */ response_packet = dns_to_packet(response, &response_packet_length); udp_send(socket, addr, port, response_packet, response_packet_length); } else { /* Send back an error. */ response_packet = dns_create_error_string(request->trn_id, request->questions[0], &response_packet_length); udp_send(socket, addr, port, response_packet, response_packet_length); } /* Delete the response. */ safe_free(response_packet); dns_destroy(response); /* Delete the request. */ dns_destroy(request); }
static SELECT_RESPONSE_t recv_socket_callback(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param) { /*driver_dns_t *driver_dns = param;*/ dns_t *dns = dns_create_from_packet(data, length); driver_dns_t *driver = (driver_dns_t*) param; LOG_INFO("DNS response received (%d bytes)", length); /* TODO */ if(dns->rcode != _DNS_RCODE_SUCCESS) { /* TODO: Handle errors more gracefully */ switch(dns->rcode) { case _DNS_RCODE_FORMAT_ERROR: LOG_ERROR("DNS: RCODE_FORMAT_ERROR"); break; case _DNS_RCODE_SERVER_FAILURE: LOG_ERROR("DNS: RCODE_SERVER_FAILURE"); break; case _DNS_RCODE_NAME_ERROR: LOG_ERROR("DNS: RCODE_NAME_ERROR"); break; case _DNS_RCODE_NOT_IMPLEMENTED: LOG_ERROR("DNS: RCODE_NOT_IMPLEMENTED"); break; case _DNS_RCODE_REFUSED: LOG_ERROR("DNS: RCODE_REFUSED"); break; default: LOG_ERROR("DNS: Unknown error code (0x%04x)", dns->rcode); break; } } else if(dns->question_count != 1) { LOG_ERROR("DNS returned the wrong number of response fields (question_count should be 1, was instead %d).", dns->question_count); LOG_ERROR("This is probably due to a DNS error"); } else if(dns->answer_count < 1) { LOG_ERROR("DNS didn't return an answer"); LOG_ERROR("This is probably due to a DNS error"); } else { size_t i; uint8_t *answer = NULL; size_t answer_length = 0; dns_type_t type = dns->answers[0].type; if(type == _DNS_TYPE_TEXT) { /* Get the answer. */ answer = dns->answers[0].answer->TEXT.text; answer_length = dns->answers[0].answer->TEXT.length; LOG_INFO("Received a TXT response (%zu bytes)", answer_length); /* Decode it. */ answer = buffer_decode_hex(answer, &answer_length); } else if(type == _DNS_TYPE_CNAME) { /* Get the answer. */ answer = remove_domain((char*)dns->answers[0].answer->CNAME.name, driver->domain); answer_length = strlen((char*)answer); LOG_INFO("Received a CNAME response (%zu bytes)", answer_length); /* Decode it. */ answer = buffer_decode_hex(answer, &answer_length); } else if(type == _DNS_TYPE_MX) { /* Get the answer. */ answer = remove_domain((char*)dns->answers[0].answer->MX.name, driver->domain); answer_length = strlen((char*)answer); LOG_INFO("Received a MX response (%zu bytes)", answer_length); /* Decode it. */ answer = buffer_decode_hex(answer, &answer_length); } else if(type == _DNS_TYPE_A) { buffer_t *buf = buffer_create(BO_BIG_ENDIAN); qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_a); for(i = 0; i < dns->answer_count; i++) buffer_add_bytes(buf, dns->answers[i].answer->A.bytes + 1, 3); answer_length = buffer_read_next_int8(buf); LOG_INFO("Received an A response (%zu bytes)", answer_length); answer = safe_malloc(answer_length); buffer_read_bytes_at(buf, 1, answer, answer_length); } #ifndef WIN32 else if(type == _DNS_TYPE_AAAA) { buffer_t *buf = buffer_create(BO_BIG_ENDIAN); qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_aaaa); for(i = 0; i < dns->answer_count; i++) buffer_add_bytes(buf, dns->answers[i].answer->AAAA.bytes + 1, 15); answer_length = buffer_read_next_int8(buf); LOG_INFO("Received an AAAA response (%zu bytes)", answer_length); answer = safe_malloc(answer_length); buffer_read_bytes_at(buf, 1, answer, answer_length); } #endif else { LOG_ERROR("Unknown DNS type returned: %d", type); answer = NULL; } if(answer) { /*LOG_WARNING("Received a %zu-byte DNS response: %s [0x%04x]", answer_length, answer, type);*/ /* Pass the buffer to the caller */ if(answer_length > 0) { /* Pass the data elsewhere. */ message_post_packet_in(answer, answer_length); } safe_free(answer); } } dns_destroy(dns); return SELECT_OK; }