Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
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);
	}
}