queryperf.c

来自「非常好的dns解析软件」· C语言 代码 · 共 2,111 行 · 第 1/4 页

C
2,111
字号
 *   Side effects: *   Rewinds the input and clears reached_end_input if we have reached the *   end of the input, but we are meant to run through it multiple times *   and have not hit the time limit yet (if any is set). */intkeep_sending(int *reached_end_input) {	static int stop = FALSE;	if (stop == TRUE)		return (FALSE);	if ((*reached_end_input == FALSE) && (timelimit_reached() == FALSE))		return (TRUE);	else if ((*reached_end_input == TRUE) && (run_only_once == FALSE)	         && (timelimit_reached() == FALSE)) {		rewind(datafile_ptr);		*reached_end_input = FALSE;		runs_through_file++;		return (TRUE);	} else {		if (*reached_end_input == TRUE)			runs_through_file++;		set_timenow(&time_of_stop_sending);		stop = TRUE;		return (FALSE);	}}/* * queries_outstanding: *   How many queries are outstanding? * *   Returns the number of outstanding queries */unsigned intqueries_outstanding(void) {	return (num_queries_outstanding);}/* * next_input_line: *   Get the next non-comment line from the input file * *   Put text in line, up to max of n chars. Skip comment lines. *   Skip empty lines. * *   Return line length on success *   Return 0 if cannot read a non-comment line (EOF or error) */intnext_input_line(char *line, int n) {	char *result;	do {		result = fgets(line, n, datafile_ptr);	} while ((result != NULL) &&	         ((line[0] == COMMENT_CHAR) || (line[0] == '\n')));	if (result == NULL)		return (0);	else		return (strlen(line));}/* * identify_directive: *   Gives us a numerical value equivelant for a directive string * *   Returns the value for the directive *   Returns -1 if not a valid directive */intidentify_directive(char *dir) {	static char *directives[] = DIRECTIVES;	static int dir_values[] = DIR_VALUES;	unsigned int index, num_directives;	num_directives = sizeof(directives) / sizeof(directives[0]);	if (num_directives > (sizeof(dir_values) / sizeof(int)))		num_directives = sizeof(dir_values) / sizeof(int);	for (index = 0; index < num_directives; index++) {		if (strcmp(dir, directives[index]) == 0)			return (dir_values[index]);	}	return (-1);}/* * update_config: *   Update configuration options from a line from the input file */voidupdate_config(char *config_change_desc) {	char *directive, *config_value, *trailing_garbage;	char conf_copy[MAX_INPUT_LEN + 1];	unsigned int uint_val;	int directive_number;	int check;	int old_af;	if (ignore_config_changes == TRUE) {		fprintf(stderr, "Ignoring configuration change: %s",		        config_change_desc);		return;	}	strcpy(conf_copy, config_change_desc);	++config_change_desc;	if (*config_change_desc == '\0') {		fprintf(stderr, "Invalid config: No directive present: %s\n",		        conf_copy);		return;	}	if (index(WHITESPACE, *config_change_desc) != NULL) {		fprintf(stderr, "Invalid config: Space before directive or "		        "no directive present: %s\n", conf_copy);		return;	}	directive = strtok(config_change_desc, WHITESPACE);	config_value = strtok(NULL, WHITESPACE);	trailing_garbage = strtok(NULL, WHITESPACE);	if ((directive_number = identify_directive(directive)) == -1) {		fprintf(stderr, "Invalid config: Bad directive: %s\n",		        conf_copy);		return;	}	if (config_value == NULL) {		fprintf(stderr, "Invalid config: No value present: %s\n",		        conf_copy);		return;	}	if (trailing_garbage != NULL) {		fprintf(stderr, "Config warning: "		        "trailing garbage: %s\n", conf_copy);	}	switch(directive_number) {	case V_SERVER:		if (serverset && (setup_phase == TRUE)) {			fprintf(stderr, "Config change overridden by command "			        "line: %s\n", directive);			return;		}		if (set_server(config_value) == -1) {			fprintf(stderr, "Set server error: unable to change "			        "the server name to '%s'\n", config_value);			return;		}		old_af = server_ai->ai_family;		if (set_server_sa() == -1) {			fprintf(stderr, "Set server error: unable to resolve "				"a new server '%s'\n",				config_value);			return;		}		if (old_af != server_ai->ai_family) {			if ((query_socket = change_socket()) == -1) {				/* XXX: this is fatal */				fprintf(stderr, "Set server error: "					"unable to open a new socket "					"for '%s'\n", config_value);				exit(1);			}		}		break;	case V_PORT:		if (portset && (setup_phase == TRUE)) {			fprintf(stderr, "Config change overridden by command "			        "line: %s\n", directive);			return;		}		check = is_uint(config_value, &uint_val);		if ((check == TRUE) && (uint_val > 0)) {			if (set_server_port(config_value) == -1) {				fprintf(stderr, "Invalid config: Bad value for"				        " %s: %s\n", directive, config_value);			} else {				if (set_server_sa() == -1) {					fprintf(stderr,						"Failed to set a new port\n");					return;				}			}		} else			fprintf(stderr, "Invalid config: Bad value for "			        "%s: %s\n", directive, config_value);		break;	case V_MAXQUERIES:		if (queriesset && (setup_phase == TRUE)) {			fprintf(stderr, "Config change overridden by command "			        "line: %s\n", directive);			return;		}		check = is_uint(config_value, &uint_val);		if ((check == TRUE) && (uint_val > 0)) {			set_max_queries(uint_val);		} else			fprintf(stderr, "Invalid config: Bad value for "			        "%s: %s\n", directive, config_value);		break;	case V_MAXWAIT:		if (timeoutset && (setup_phase == TRUE)) {			fprintf(stderr, "Config change overridden by command "			        "line: %s\n", directive);			return;		}		check = is_uint(config_value, &uint_val);		if ((check == TRUE) && (uint_val > 0)) {			query_timeout = uint_val;		} else			fprintf(stderr, "Invalid config: Bad value for "			        "%s: %s\n", directive, config_value);		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,			    server_ai->ai_addr, server_ai->ai_addrlen);	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];	char serveraddr[NI_MAXHOST];	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) {		char *addrstr;		if (getnameinfo(server_ai->ai_addr, server_ai->ai_addrlen,				serveraddr, sizeof(serveraddr), NULL, 0,				NI_NUMERICHOST) == 0) {			addrstr = serveraddr;		} else			addrstr = "???"; /* XXX: this should not happen */		fprintf(stderr, "Error sending query to %s: %s\n",			addrstr, query_desc);		return;	}	if (setup_phase == TRUE) {		set_timenow(&time_of_first_query);		time_of_first_query_sec = (double)time_of_first_query.tv_sec +			((double)time_of_first_query.tv_usec / 1000000.0);		setup_phase = FALSE;		if (getnameinfo(server_ai->ai_addr, server_ai->ai_addrlen,				serveraddr, sizeof(serveraddr), NULL, 0,				NI_NUMERICHOST) != 0) {			fprintf(stderr, "Error printing server address\n");			return;		}		printf("[Status] Sending queries (beginning with %s)\n",		       serveraddr);	}	/* 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);	if (num_queries_sent_interval == 0)		set_timenow(&time_of_first_query_interval);	num_queries_sent++;	num_queries_sent_interval++;	num_queries_outstanding++;}voidregister_rtt(struct timeval *timestamp) {	int i;	int oldquery = FALSE;	struct timeval now;	double rtt;	set_timenow(&now);	rtt = difftv(now, *timestamp);	if (difftv(*timestamp, time_of_first_query_interval) < 0)		oldquery = TRUE;	if (rtt_max < 0 || rtt_max < rtt)		rtt_max = rtt;	if (rtt_min < 0 || rtt_min > rtt)		rtt_min = rtt;	rtt_total += rtt;	if (!oldquery) {		if (rtt_max_interval < 0 || rtt_max_interval < rtt)			rtt_max_interval = rtt;		if (rtt_min_interval < 0 || rtt_min_interval > rtt)			rtt_min_interval = rtt;		rtt_total_interval += rtt;	}	if (rttarray == NULL)		return;	i = (int)(rtt * (1000000.0 / rttarray_unit));	if (i < rttarray_size) {		rttarray[i]++;		if (!oldquery)			rttarray_interval[i]++;	} else {		fprintf(stderr, "Warning: RTT is out of range: %.6lf\n",			rtt);		rtt_overflows++;		if (!oldquery)			rtt_overflows_interval++;	}}/* * 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;	struct timeval now;	double rtt;	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;			register_rtt(&status[ct].sent_timestamp);			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) {		if (target_qps > 0) {			num_queries_possiblydelayed++;			num_queries_possiblydelayed_interval++;		} else {			fprintf(stderr, "Warning: Received a response with an "				"unexpected (maybe timed out) id: %u\n", id);		}

⌨️ 快捷键说明

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