From 806ec3c06915b19c3ab6bb3cb8e1e146bfba5c29 Mon Sep 17 00:00:00 2001 From: Nathan Straz Date: Wed, 11 Sep 2013 16:35:04 -0400 Subject: Split btime into two parts We don't need to lookup the addresses every time we get btime. Do it once during hbeat_init and reuse the socket in hbeat. This cleans up the qarsh strace so the hbeat is only a send and recv. --- btime.c | 140 ++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 66 insertions(+), 74 deletions(-) (limited to 'btime.c') diff --git a/btime.c b/btime.c index 15d52f1..962615c 100644 --- a/btime.c +++ b/btime.c @@ -31,34 +31,20 @@ #include "btime_int.h" -static int same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b); static void gen_cookie(char *s); /* - * btime -- - * - * Return the boot time of a remote host if that host is running the - * btimed deamon. + * btime_init -- * - * Returns: - * btime, or 0 on failure. + * Prepare a socket to use for getting boot time from btimed */ -unsigned int -btime(const char *host) +int +btime_init(const char *host) { - int sd; - char cookie[BTIME_MSGLEN]; - char response[BTIME_MSGLEN]; + int sd = 0; struct addrinfo *serv_ail, *serv_aip; struct addrinfo *my_ail, *my_aip; - struct sockaddr_storage resp_addr; struct addrinfo hints; - socklen_t resp_addr_len; - unsigned int btime = 0; - ssize_t nbytes; - int retry; - fd_set sdset; - struct timeval timeout; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; @@ -80,8 +66,8 @@ btime(const char *host) if (serv_aip == NULL) { fprintf(stderr, "Could not create socket: %s\n", strerror(errno)); - freeaddrinfo(serv_ail); - return 0; + sd = 0; + goto free_serv; } memset(&hints, 0, sizeof hints); @@ -90,7 +76,8 @@ btime(const char *host) hints.ai_flags = AI_PASSIVE; /* Fill in my IP for me */ if (getaddrinfo(NULL, "0", &hints, &my_ail) != 0) { fprintf(stderr, "Could not get address info for myself!: %s\n", strerror(errno)); - return 0; + sd = 0; + goto free_serv; } for (my_aip = my_ail; my_aip != NULL; my_aip = my_aip->ai_next) { @@ -104,15 +91,47 @@ btime(const char *host) if (my_aip == NULL) { fprintf(stderr, "Could not bind to local address: %s\n", strerror(errno)); - freeaddrinfo(my_ail); - return 0; + sd = 0; + goto free_my; + } + + if (connect(sd, serv_aip->ai_addr, serv_aip->ai_addrlen) < 0) { + fprintf(stderr, "Could not connect to host: %s\n", + strerror(errno)); + sd = 0; } +free_my: + freeaddrinfo(my_ail); +free_serv: + freeaddrinfo(serv_ail); + + return sd; +} + +/* + * btime_do -- + * + * Get the boot time from btimed using an already prepared socket + * + * Returns: + * btime, or 0 on failure. + */ +unsigned int +btime_do(const int sd) +{ + char cookie[BTIME_MSGLEN]; + char response[BTIME_MSGLEN]; + unsigned int btime = 0; + ssize_t nbytes; + int retry; + fd_set sdset; + struct timeval timeout; + memset(cookie, 0, BTIME_MSGLEN); gen_cookie(cookie); for (retry = 0; retry < MAX_RETRY; retry++) { - if ((nbytes = sendto(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT, - serv_aip->ai_addr, serv_aip->ai_addrlen)) < 0) { + if ((nbytes = send(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT)) < 0) { if (errno == EAGAIN) { usleep(retry * 100); } else { @@ -137,15 +156,12 @@ btime(const char *host) break; } - memset(&resp_addr, 0, sizeof resp_addr); memset(response, 0, BTIME_MSGLEN); - resp_addr_len = sizeof resp_addr; - nbytes = recvfrom(sd, &response, BTIME_MSGLEN, MSG_DONTWAIT, - (struct sockaddr *)&resp_addr, &resp_addr_len); - if (nbytes == 0) { - /* Nothing received */ - continue; - } else if (response[0] == 'B' && response[1] == 'T') { + nbytes = recv(sd, &response, BTIME_MSGLEN, MSG_DONTWAIT); + + if (nbytes == 0) continue; /* Nothing received */ + + if (response[0] == 'B' && response[1] == 'T') { /* Check for new style cookie */ if (memcmp(cookie, response, COOKIE_LEN) == 0) { btime = strtoul(response+COOKIE_LEN, NULL, 10); @@ -155,58 +171,34 @@ btime(const char *host) retry = 1; continue; } - } else if (!same_addr((struct sockaddr_storage *)serv_aip->ai_addr, &resp_addr)) { - /* If no cookie, check peer */ - char rstr[NI_MAXHOST]; - char sstr[NI_MAXHOST]; - - inet_ntop(resp_addr.ss_family, &resp_addr, rstr, NI_MAXHOST); - inet_ntop(serv_aip->ai_family, serv_aip->ai_addr, sstr, NI_MAXHOST); - fprintf(stderr, "Got response from %s instead of %s\n", - rstr, sstr); - retry = 1; - continue; - } else { - /* If peer matches, accept the bare btime */ - btime = strtoul(response, (char **)NULL, 10); - break; } } while (retry); - close(sd); - freeaddrinfo(serv_ail); - freeaddrinfo(my_ail); - return btime; } -/* same_addr - * - * Compare two struct sockaddr_storage +/* + * btime -- + * + * Return the boot time of a remote host if that host is running the + * btimed deamon. * * Returns: - * 1 if the addresses match - * 0 if the addresses are different + * btime, or 0 on failure. */ -static int -same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b) + +unsigned int +btime(const char *host) { - return 1; - if (a->ss_family != b->ss_family) { - return 0; - } else if ((a->ss_family == AF_INET) - && (((struct sockaddr_in *)a)->sin_addr.s_addr - != ((struct sockaddr_in *)b)->sin_addr.s_addr)) { - return 0; - } else if ((a->ss_family == AF_INET6) - && (((struct sockaddr_in6 *)a)->sin6_addr.s6_addr - != ((struct sockaddr_in6 *)b)->sin6_addr.s6_addr)) { - return 0; - } else { - return 1; - } + int s; + unsigned int b; + s = btime_init(host); + b = btime_do(s); + close(s); + return b; } + /* gen_cookie * * Generate a random string that btimed will send back to us. -- cgit