⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queryperf.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	default:		fprintf(stderr, "Invalid config: Bad directive: %s\n",		        directive);		break;	}}/* * parse_query: *   Parse a query line from the input file * *   Set qname to be the domain to query (up to a max of qnlen chars) *   Set qtype to be the type of the query * *   Return -1 on failure *   Return a non-negative integer otherwise */intparse_query(char *input, char *qname, int qnlen, int *qtype) {	static char *qtype_strings[] = QTYPE_STRINGS;	static int qtype_codes[] = QTYPE_CODES;	int num_types, index;	int found = FALSE;	char incopy[MAX_INPUT_LEN + 1];	char *domain_str, *type_str;	num_types = sizeof(qtype_strings) / sizeof(qtype_strings[0]);	if (num_types > (sizeof(qtype_codes) / sizeof(int)))		num_types = sizeof(qtype_codes) / sizeof(int);	strcpy(incopy, input);	domain_str = strtok(incopy, WHITESPACE);	type_str = strtok(NULL, WHITESPACE);	if ((domain_str == NULL) || (type_str == NULL)) {		fprintf(stderr, "Invalid query input format: %s\n", input);		return (-1);	}	if (strlen(domain_str) > qnlen) {		fprintf(stderr, "Query domain too long: %s\n", domain_str);		return (-1);	}	for (index = 0; (index < num_types) && (found == FALSE); index++) {		if (strcasecmp(type_str, qtype_strings[index]) == 0) {			*qtype = qtype_codes[index];			found = TRUE;		}	}	if (found == FALSE) {		fprintf(stderr, "Query type not understood: %s\n", type_str);		return (-1);	}	strcpy(qname, domain_str);	return (0);}/* * dispatch_query: *   Send the query packet for the entry  * *   Return -1 on failure *   Return a non-negative integer otherwise */intdispatch_query(unsigned short int id, char *dom, int qt) {	static u_char packet_buffer[PACKETSZ + 1];	static socklen_t sockaddrlen = sizeof(struct sockaddr);	int buffer_len = PACKETSZ;	int bytes_sent;	unsigned short int net_id = htons(id);	char *id_ptr = (char *)&net_id;	buffer_len = res_mkquery(QUERY, dom, C_IN, qt, NULL, 0,				 NULL, packet_buffer, PACKETSZ);	if (buffer_len == -1) {		fprintf(stderr, "Failed to create query packet: %s %d\n",		        dom, qt);		return (-1);	}	if (edns) {		unsigned char *p;		if (buffer_len + EDNSLEN >= PACKETSZ) {			fprintf(stderr, "Failed to add OPT to query packet\n");			return (-1);		}		packet_buffer[11] = 1;		p = &packet_buffer[buffer_len];		*p++ = 0;	/* root name */		*p++ = 0;		*p++ = 41;	/* OPT */		*p++ = 16;			*p++ = 0;	/* UDP payload size (4K) */		*p++ = 0;	/* extended rcode */		*p++ = 0;	/* version */		if (dnssec)			*p++ = 0x80;	/* upper flag bits - DO set */		else			*p++ = 0;	/* upper flag bits */		*p++ = 0;	/* lower flag bit */		*p++ = 0;		*p++ = 0;	/* rdlen == 0 */		buffer_len += EDNSLEN;	}	packet_buffer[0] = id_ptr[0];	packet_buffer[1] = id_ptr[1];	bytes_sent = sendto(query_socket, packet_buffer, buffer_len, 0,			    (struct sockaddr *)&qaddr, sockaddrlen);	if (bytes_sent == -1) {		fprintf(stderr, "Failed to send query packet: %s %d\n",		        dom, qt);		return (-1);	}	if (bytes_sent != buffer_len)		fprintf(stderr, "Warning: incomplete packet sent: %s %d\n",		        dom, qt);	return (0);}/* * send_query: *   Send a query based on a line of input */voidsend_query(char *query_desc) {	static unsigned short int use_query_id = 0;	static int qname_len = MAX_DOMAIN_LEN;	static char domain[MAX_DOMAIN_LEN + 1];	int query_type;	unsigned int count;	use_query_id++;	if (parse_query(query_desc, domain, qname_len, &query_type) == -1) {		fprintf(stderr, "Error parsing query: %s\n", query_desc);		return;	}	if (dispatch_query(use_query_id, domain, query_type) == -1) {		fprintf(stderr, "Error sending query: %s\n", query_desc);		return;	}	if (setup_phase == TRUE) {		set_timenow(&time_of_first_query);		setup_phase = FALSE;		printf("[Status] Sending queries\n");	}	/* Find the first slot in status[] that is not in use */	for(count = 0; (status[count].in_use == TRUE)	    && (count < max_queries_outstanding); count++);	if (status[count].in_use == TRUE) {		fprintf(stderr, "Unexpected error: We have run out of "		        "status[] space!\n");		return;	}	/* Register the query in status[] */	status[count].in_use = TRUE;	status[count].id = use_query_id;	if (verbose)		status[count].desc = strdup(query_desc);	set_timenow(&status[count].sent_timestamp);	num_queries_sent++;	num_queries_outstanding++;}/* * data_available: *   Is there data available on the given file descriptor? * *   Return TRUE if there is *   Return FALSE otherwise */intdata_available(int fd, double wait) {	fd_set read_fds;	struct timeval tv;	int retval;	/* Set list of file descriptors */	FD_ZERO(&read_fds);	FD_SET(fd, &read_fds);	if ((wait > 0.0) && (wait < (double)LONG_MAX)) {		tv.tv_sec = (long)floor(wait);		tv.tv_usec = (long)(1000000.0 * (wait - floor(wait)));	} else {		tv.tv_sec = 0;		tv.tv_usec = 0;	}	retval = select(fd + 1, &read_fds, NULL, NULL, &tv);	if (FD_ISSET(fd, &read_fds))		return (TRUE);	else		return (FALSE);}/* * register_response: *   Register receipt of a query * *   Removes (sets in_use = FALSE) the record for the given query id in *   status[] if any exists. */voidregister_response(unsigned short int id, unsigned int rcode) {	unsigned int ct = 0;	int found = FALSE;	for(; (ct < query_status_allocated) && (found == FALSE); ct++) {		if ((status[ct].in_use == TRUE) && (status[ct].id == id)) {			status[ct].in_use = FALSE;			num_queries_outstanding--;			found = TRUE;			if (status[ct].desc) {				printf("> %s %s\n", rcode_strings[rcode],				       status[ct].desc);				free(status[ct].desc);			}			if (countrcodes)				rcodecounts[rcode]++;		}	}	if (found == FALSE)		fprintf(stderr, "Warning: Received a response with an "		        "unexpected (maybe timed out) id: %u\n", id);}/* * process_single_response: *   Receive from the given socket & process an invididual response packet. *   Remove it from the list of open queries (status[]) and decrement the *   number of outstanding queries if it matches an open query. */voidprocess_single_response(int sockfd) {	static struct sockaddr_in from_addr;	static unsigned char in_buf[MAX_BUFFER_LEN];	int numbytes, addr_len, resp_id;	int flags;	addr_len = sizeof(struct sockaddr);	if ((numbytes = recvfrom(sockfd, in_buf, MAX_BUFFER_LEN,	     0, (struct sockaddr *)&from_addr, &addr_len)) == -1) {		fprintf(stderr, "Error receiving datagram\n");		return;	}	resp_id = get_uint16(in_buf);	flags = get_uint16(in_buf + 2);	register_response(resp_id, flags & 0xF);}/* * process_responses: *   Go through any/all received responses and remove them from the list of *   open queries (set in_use = FALSE for their entry in status[]), also *   decrementing the number of outstanding queries. */voidprocess_responses(void) {	double first_packet_wait = RESPONSE_BLOCKING_WAIT_TIME;	unsigned int outstanding = queries_outstanding();	/*	 * Don't block waiting for packets at all if we aren't looking for	 * any responses or if we are now able to send new queries.	 */	if ((outstanding == 0) || (outstanding < max_queries_outstanding)) {		first_packet_wait = 0.0;	}	if (data_available(query_socket, first_packet_wait) == TRUE) {		process_single_response(query_socket);		while (data_available(query_socket, 0.0) == TRUE)			process_single_response(query_socket);	}}/* * retire_old_queries: *   Go through the list of open queries (status[]) and remove any queries *   (i.e. set in_use = FALSE) which are older than the timeout, decrementing *   the number of queries outstanding for each one removed. */voidretire_old_queries(void) {	unsigned int count = 0;	struct timeval curr_time;	set_timenow(&curr_time);	for(; count < query_status_allocated; count++) {		if ((status[count].in_use == TRUE)		    && (difftv(curr_time, status[count].sent_timestamp)		    >= (double)query_timeout)) {			status[count].in_use = FALSE;			num_queries_outstanding--;			num_queries_timed_out++;			if (status[count].desc) {				printf("> T %s\n", status[count].desc);				free(status[count].desc);			} else {				printf("[Timeout] Query timed out: msg id %u\n",				       status[count].id);			}		}	}}/* * print_statistics: *   Print out statistics based on the results of the test */voidprint_statistics(void) {	unsigned int num_queries_completed;	double per_lost, per_completed;	double run_time, queries_per_sec;	struct timeval start_time;	num_queries_completed = num_queries_sent - num_queries_timed_out;	if (num_queries_completed == 0) {		per_lost = 0.0;		per_completed = 0.0;	} else {		per_lost = 100.0 * (double)num_queries_timed_out		           / (double)num_queries_sent;		per_completed = 100.0 - per_lost;	}	if (num_queries_sent == 0) {		start_time.tv_sec = time_of_program_start.tv_sec;		start_time.tv_usec = time_of_program_start.tv_usec;		run_time = 0.0;		queries_per_sec = 0.0;	} else {		start_time.tv_sec = time_of_first_query.tv_sec;		start_time.tv_usec = time_of_first_query.tv_usec;		run_time = difftv(time_of_end_of_run, time_of_first_query);		queries_per_sec = (double)num_queries_completed / run_time;	}	printf("\n");	printf("Statistics:\n");	printf("\n");	printf("  Parse input file:     %s\n",	       ((run_only_once == TRUE) ? "once" : "multiple times"));	if (use_timelimit)		printf("  Run time limit:       %u seconds\n", run_timelimit);	if (run_only_once == FALSE)		printf("  Ran through file:     %u times\n",		       runs_through_file);	else		printf("  Ended due to:         reaching %s\n",		       ((runs_through_file == 0) ? "time limit"		       : "end of file"));	printf("\n");	printf("  Queries sent:         %u queries\n", num_queries_sent);	printf("  Queries completed:    %u queries\n", num_queries_completed);	printf("  Queries lost:         %u queries\n", num_queries_timed_out);	printf("\n");	if (countrcodes) {		unsigned int i;		for (i = 0; i < 16; i++) {			if (rcodecounts[i] == 0)				continue;			printf("  Returned %8s:    %u queries\n",			       rcode_strings[i], rcodecounts[i]);		}		printf("\n");	}	printf("  Percentage completed: %6.2lf%%\n", per_completed);	printf("  Percentage lost:      %6.2lf%%\n", per_lost);	printf("\n");	printf("  Started at:           %s", ctime(&start_time.tv_sec));	printf("  Finished at:          %s",	       ctime(&time_of_end_of_run.tv_sec));	printf("  Ran for:              %.6lf seconds\n", run_time);	printf("\n");	printf("  Queries per second:   %.6lf qps\n", queries_per_sec);	printf("\n");}/* * dnsqtest Program Mainline */intmain(int argc, char **argv) {	int got_eof = FALSE;	int input_length = MAX_INPUT_LEN;	char input_line[MAX_INPUT_LEN + 1];	set_timenow(&time_of_program_start);	time_of_first_query.tv_sec = 0;	time_of_first_query.tv_usec = 0;	time_of_end_of_run.tv_sec = 0;	time_of_end_of_run.tv_usec = 0;	input_line[0] = '\0';	show_startup_info();	if (setup(argc, argv) == -1)		return (-1);	printf("[Status] Processing input data\n");	while (keep_sending(&got_eof) == TRUE || queries_outstanding() > 0) {		while (keep_sending(&got_eof) == TRUE		       && queries_outstanding() < max_queries_outstanding) {			int len = next_input_line(input_line, input_length);			if (len == 0) {				got_eof = TRUE;			} else {				/* Zap the trailing newline */				if (input_line[len - 1] == '\n')					input_line[len - 1] = '\0';				/*				 * TODO: Should test if we got a whole line				 * and flush to the next \n in input if not				 * here... Add this later. Only do the next				 * few lines if we got a whole line, else				 * print a warning. Alternative: Make the				 * max line size really big. BAD! :)				 */				if (input_line[0] == CONFIG_CHAR)					update_config(input_line);				else {					send_query(input_line);				}			}		}		retire_old_queries();		process_responses();	}	set_timenow(&time_of_end_of_run);	printf("[Status] Testing complete\n");	close_socket();	close_datafile();	print_statistics();	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -