📄 queryperf.c
字号:
case 'l': if (is_uint(optarg, &uint_arg_val) == TRUE) { use_timelimit = TRUE; run_timelimit = uint_arg_val; } else { fprintf(stderr, "Option requires a positive " "integer: -%c %s\n", c, optarg); return (-1); } break; case 'b': if (is_uint(optarg, &uint_arg_val) == TRUE) { socket_bufsize = uint_arg_val; } else { fprintf(stderr, "Option requires a positive " "integer: -%c %s\n", c, optarg); return (-1); } break; case 'e': edns = TRUE; break; case 'D': dnssec = TRUE; edns = TRUE; break; case 'c': countrcodes = TRUE; break; case 'v': verbose = 1; break; case 'h': return (-1); default: fprintf(stderr, "Invalid option: -%c\n", optopt); return (-1); } } if (run_only_once == FALSE && use_timelimit == FALSE) run_only_once = TRUE; return (0);}/* * open_datafile: * Open the data file ready for reading * * Return -1 on failure * Return non-negative integer on success */intopen_datafile(void) { if (use_stdin == TRUE) { datafile_ptr = stdin; return (0); } else { if ((datafile_ptr = fopen(datafile_name, "r")) == NULL) { fprintf(stderr, "Error: unable to open datafile: %s\n", datafile_name); return (-1); } else return (0); }}/* * close_datafile: * Close the data file if any is open * * Return -1 on failure * Return non-negative integer on success, including if not needed */intclose_datafile(void) { if ((use_stdin == FALSE) && (datafile_ptr != NULL)) { if (fclose(datafile_ptr) != 0) { fprintf(stderr, "Error: unable to close datafile\n"); return (-1); } } return (0);}/* * open_socket: * Open a socket for the queries. When we have an active socket already, * close it and open a new one. * * Return -1 on failure * Return the socket identifier */intopen_socket(void) { int sock; int ret; int bufsize; struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = server_ai->ai_family; hints.ai_socktype = server_ai->ai_socktype; hints.ai_protocol = server_ai->ai_protocol; hints.ai_flags = AI_PASSIVE; if ((ret = getaddrinfo(NULL, "0", &hints, &res)) != 0) { fprintf(stderr, "Error: getaddrinfo for bind socket failed: %s\n", gai_strerror(ret)); return (-1); } if ((sock = socket(res->ai_family, SOCK_DGRAM, res->ai_protocol)) == -1) { fprintf(stderr, "Error: socket call failed"); goto fail; }#if defined(AF_INET6) && defined(IPV6_V6ONLY) if (res->ai_family == AF_INET6) { int on = 1; if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) { fprintf(stderr, "Warning: setsockopt(IPV6_V6ONLY) failed\n"); } }#endif if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) fprintf(stderr, "Error: bind call failed"); freeaddrinfo(res); bufsize = 1024 * socket_bufsize; ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, sizeof(bufsize)); if (ret < 0) fprintf(stderr, "Warning: setsockbuf(SO_RCVBUF) failed\n"); ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, sizeof(bufsize)); if (ret < 0) fprintf(stderr, "Warning: setsockbuf(SO_SNDBUF) failed\n"); return (sock); fail: if (res) freeaddrinfo(res); return (-1);}/* * close_socket: * Close the query socket(s) * * Return -1 on failure * Return a non-negative integer otherwise */intclose_socket(void) { if (socket4 != -1) { if (close(socket4) != 0) { fprintf(stderr, "Error: unable to close IPv4 socket\n"); return (-1); } } if (socket6 != -1) { if (close(socket6) != 0) { fprintf(stderr, "Error: unable to close IPv6 socket\n"); return (-1); } } query_socket = -1; return (0);}/* * change_socket: * Choose an appropriate socket according to the address family of the * current server. Open a new socket if necessary. * * Return -1 on failure * Return the socket identifier */intchange_socket(void) { int s, *sockp; switch (server_ai->ai_family) { case AF_INET: sockp = &socket4; break;#ifdef AF_INET6 case AF_INET6: sockp = &socket6; break;#endif default: fprintf(stderr, "unexpected address family: %d\n", server_ai->ai_family); exit(1); } if (*sockp == -1) { if ((s = open_socket()) == -1) return (-1); *sockp = s; } return (*sockp);}/* * setup: * Set configuration options from command line arguments * Open datafile ready for reading * * Return -1 on failure * Return non-negative integer on success */intsetup(int argc, char **argv) { set_input_stdin(); if (set_max_queries(DEF_MAX_QUERIES_OUTSTANDING) == -1) { fprintf(stderr, "%s: Unable to set default max outstanding " "queries\n", argv[0]); return (-1); } if (set_server(DEF_SERVER_TO_QUERY) == -1) { fprintf(stderr, "%s: Error setting default server name\n", argv[0]); return (-1); } if (set_server_port(DEF_SERVER_PORT) == -1) { fprintf(stderr, "%s: Error setting default server port\n", argv[0]); return (-1); } if (parse_args(argc, argv) == -1) { show_usage(); return (-1); } if (open_datafile() == -1) return (-1); if (set_server_sa() == -1) return (-1); if ((query_socket = change_socket()) == -1) return (-1); return (0);}/* * set_timenow: * Set a timeval struct to indicate the current time */voidset_timenow(struct timeval *tv) { if (gettimeofday(tv, NULL) == -1) { fprintf(stderr, "Error in gettimeofday(). Using inaccurate " "time() instead\n"); tv->tv_sec = time(NULL); tv->tv_usec = 0; }}/* * difftv: * Find the difference in seconds between two timeval structs. * * Return the difference between tv1 and tv2 in seconds in a double. */doubledifftv(struct timeval tv1, struct timeval tv2) { long diff_sec, diff_usec; double diff; diff_sec = tv1.tv_sec - tv2.tv_sec; diff_usec = tv1.tv_usec - tv2.tv_usec; diff = (double)diff_sec + ((double)diff_usec / 1000000.0); return (diff);}/* * timelimit_reached: * Have we reached the time limit (if any)? * * Returns FALSE if there is no time limit or if we have not reached it * Returns TRUE otherwise */inttimelimit_reached(void) { struct timeval time_now; set_timenow(&time_now); if (use_timelimit == FALSE) return (FALSE); if (setup_phase == TRUE) { if (difftv(time_now, time_of_program_start) < (double)(run_timelimit + HARD_TIMEOUT_EXTRA)) return (FALSE); else return (TRUE); } else { if (difftv(time_now, time_of_first_query) < (double)run_timelimit) return (FALSE); else return (TRUE); }}/* * keep_sending: * Should we keep sending queries or stop here? * * Return TRUE if we should keep on sending queries * Return FALSE if we should stop * * 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++; 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 "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -