multi-protocol support of queryperf
JINMEI Tatuya / 神明達哉
jinmei at isl.rdc.toshiba.co.jp
Thu Jul 4 05:40:01 UTC 2002
The attached patch will add an ability to support multiple protocols
(particularly IPv6) to bind9/contrib/queryperf. The patch is for
bind-9.3.0s20020618.
I believe the patch does not affect the current behavior in a single
protocol environment. If the patch is reasonable, please merge it to
the bind9 kit.
JINMEI, Tatuya
Communication Platform Lab.
Corporate R&D Center, Toshiba Corp.
jinmei at isl.rdc.toshiba.co.jp
--- queryperf.c.orig Thu Jul 4 14:21:44 2002
+++ queryperf.c Thu Jul 4 14:21:53 2002
@@ -46,7 +46,7 @@
#define DEF_MAX_QUERIES_OUTSTANDING 20
#define DEF_QUERY_TIMEOUT 5 /* in seconds */
#define DEF_SERVER_TO_QUERY "localhost"
-#define DEF_SERVER_PORT 53
+#define DEF_SERVER_PORT "53"
#define DEF_BUFFER_SIZE 32 /* in k */
/*
@@ -113,7 +113,8 @@
char *datafile_name; /* init NULL */
char *server_to_query; /* init NULL */
-unsigned int server_port = DEF_SERVER_PORT;
+char *server_port = DEF_SERVER_PORT;
+struct addrinfo *server_ai;
int run_only_once = FALSE;
int use_timelimit = FALSE;
@@ -145,8 +146,7 @@
struct query_status *status; /* init NULL */
unsigned int query_status_allocated; /* init 0 */
-int query_socket; /* init 0 */
-struct sockaddr_in qaddr;
+int query_socket = -1;
/*
* get_uint16:
@@ -185,7 +185,7 @@
" [-b bufsize] [-t timeout] [-n] [-l limit] [-1]\n"
" -d specifies the input data file (default: stdin)\n"
" -s sets the server to query (default: %s)\n"
-" -p sets the port on which to query the server (default: %u)\n"
+" -p sets the port on which to query the server (default: %s)\n"
" -q specifies the maximum number of queries outstanding (default: %d)\n"
" -t specifies the timeout for query completion in seconds (default: %d)\n"
" -n causes configuration changes to be ignored\n"
@@ -273,14 +273,7 @@
return (-1);
}
- if ((server_he = gethostbyname(new_name)) == NULL) {
- fprintf(stderr, "Error: gethostbyname(\"%s\") failed\n",
- new_name);
- return (-1);
- }
-
strcpy(server_to_query, new_name);
- qaddr.sin_addr = *((struct in_addr *)server_he->h_addr);
return (0);
}
@@ -293,16 +286,48 @@
* Return a non-negative integer otherwise
*/
int
-set_server_port(unsigned int new_port) {
- if (new_port > MAX_PORT)
+set_server_port(char *new_port) {
+ unsigned int uint_val;
+
+ if ((is_uint(new_port, &uint_val)) != TRUE)
+ return (-1);
+
+ if (uint_val && uint_val > MAX_PORT)
return (-1);
else {
server_port = new_port;
- qaddr.sin_port = htons(server_port);
return (0);
}
}
+int
+set_server_sa() {
+ struct addrinfo hints, *res;
+ static struct protoent *proto;
+ int error;
+
+ if (proto == NULL && (proto = getprotobyname("udp")) == NULL) {
+ fprintf(stderr, "Error: getprotobyname call failed");
+ return (-1);
+ }
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = proto->p_proto;
+ if ((error = getaddrinfo(server_to_query, server_port,
+ &hints, &res)) != 0) {
+ fprintf(stderr, "Error: getaddrinfo(%s, %s) failed\n",
+ server_to_query, server_port);
+ return(-1);
+ }
+
+ /* replace the server's addrinfo */
+ if (server_ai)
+ freeaddrinfo(server_ai);
+ server_ai = res;
+ return(0);
+}
+
/*
* is_digit:
* Tests if a character is a digit
@@ -462,7 +487,7 @@
if (is_uint(optarg, &uint_arg_val) == TRUE &&
uint_arg_val < MAX_PORT)
{
- set_server_port(uint_arg_val);
+ set_server_port(optarg);
portset = TRUE;
} else {
fprintf(stderr, "Option requires a positive "
@@ -564,7 +589,8 @@
/*
* open_socket:
- * Open a socket for the queries
+ * 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 a non-negative integer otherwise
@@ -572,32 +598,37 @@
int
open_socket(void) {
int sock;
- struct protoent *proto;
- struct sockaddr_in bind_addr;
int ret;
int bufsize;
+ struct addrinfo hints, *res;
- bind_addr.sin_family = AF_INET;
- bind_addr.sin_port = htons(0); /* Have bind allocate a random port */
- bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- bzero(&(bind_addr.sin_zero), 8);
-
- if ((proto = getprotobyname("udp")) == NULL) {
- fprintf(stderr, "Error: getprotobyname call failed");
- return (-1);
+ bzero(&hints, 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(PF_INET, SOCK_DGRAM, proto->p_proto)) == -1) {
+ if ((sock = socket(res->ai_family, SOCK_DGRAM,
+ res->ai_protocol)) == -1) {
fprintf(stderr, "Error: socket call failed");
- return (-1);
+ goto fail;
}
- if (bind(sock, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr))
- == -1) {
+ if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
fprintf(stderr, "Error: bind call failed");
- return (-1);
+ goto fail;
}
+ freeaddrinfo(res);
+
bufsize = 1024 * socket_bufsize;
ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
@@ -610,9 +641,16 @@
if (ret < 0)
fprintf(stderr, "Warning: setsockbuf(SO_SNDBUF) failed\n");
+ close_socket();
+
query_socket = sock;
return (0);
+
+ fail:
+ if (res)
+ freeaddrinfo(res);
+ return (-1);
}
/*
@@ -624,14 +662,14 @@
*/
int
close_socket(void) {
- if (query_socket != 0) {
+ if (query_socket != -1) {
if (close(query_socket) != 0) {
fprintf(stderr, "Error: unable to close socket\n");
return (-1);
}
}
- query_socket = 0;
+ query_socket = -1;
return (0);
}
@@ -646,11 +684,6 @@
*/
int
setup(int argc, char **argv) {
- qaddr.sin_family = AF_INET;
- qaddr.sin_port = htons(0);
- qaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- bzero(&(qaddr.sin_zero), 8);
-
set_input_stdin();
if (set_max_queries(DEF_MAX_QUERIES_OUTSTANDING) == -1) {
@@ -679,6 +712,9 @@
if (open_datafile() == -1)
return (-1);
+ if (set_server_sa() == -1)
+ return (-1);
+
if (open_socket() == -1)
return (-1);
@@ -857,6 +893,7 @@
unsigned int uint_val;
int directive_number;
int check;
+ int old_af;
if (ignore_config_changes == TRUE) {
fprintf(stderr, "Ignoring configuration change: %s",
@@ -910,9 +947,26 @@
return;
}
- if (set_server(config_value) == -1)
+ 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 && open_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:
@@ -925,7 +979,7 @@
check = is_uint(config_value, &uint_val);
if ((check == TRUE) && (uint_val > 0)) {
- if (set_server_port(uint_val) == -1) {
+ if (set_server_port(config_value) == -1) {
fprintf(stderr, "Invalid config: Bad value for"
" %s: %s\n", directive, config_value);
}
@@ -971,6 +1025,14 @@
directive);
break;
}
+
+ if (directive_number == V_SERVER || directive_number == V_PORT) {
+ if (set_server_sa() == -1) {
+ fprintf(stderr,
+ "Failed to set a new server or port\n");
+ return;
+ }
+ }
}
/*
@@ -1080,7 +1142,7 @@
packet_buffer[1] = id_ptr[1];
bytes_sent = sendto(query_socket, packet_buffer, buffer_len, 0,
- (struct sockaddr *)&qaddr, sockaddrlen);
+ server_ai->ai_addr, server_ai->ai_addrlen);
if (bytes_sent == -1) {
fprintf(stderr, "Failed to send query packet: %s %d\n",
dom, qt);
@@ -1215,15 +1277,18 @@
*/
void
process_single_response(int sockfd) {
- static struct sockaddr_in from_addr;
+ struct sockaddr_storage from_addr_ss;
+ struct sockaddr *from_addr;
static unsigned char in_buf[MAX_BUFFER_LEN];
int numbytes, addr_len, resp_id;
int flags;
- addr_len = sizeof(struct sockaddr);
+ memset(&from_addr_ss, 0, sizeof(from_addr_ss));
+ from_addr = (struct sockaddr *)&from_addr_ss;
+ addr_len = sizeof(from_addr_ss);
if ((numbytes = recvfrom(sockfd, in_buf, MAX_BUFFER_LEN,
- 0, (struct sockaddr *)&from_addr, &addr_len)) == -1) {
+ 0, from_addr, &addr_len)) == -1) {
fprintf(stderr, "Error receiving datagram\n");
return;
}
More information about the bind-workers
mailing list