From 158d69d419595ba2c79e85b9d6d0d9b324654433 Mon Sep 17 00:00:00 2001 From: Dean Jansa Date: Fri, 3 Sep 2010 12:57:38 -0500 Subject: update btime and hbeat libs to understand ipv6 as well as ipv4. --- btime.c | 100 ++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 37 deletions(-) (limited to 'btime.c') diff --git a/btime.c b/btime.c index b3a9334..bf90f1c 100644 --- a/btime.c +++ b/btime.c @@ -31,7 +31,7 @@ #include "btime_int.h" -static int same_addr(struct sockaddr_in *a, struct sockaddr_in *b); +static int same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b); static void gen_cookie(char *s); /* * btime -- @@ -49,55 +49,70 @@ btime(const char *host) int sd; char cookie[BTIME_MSGLEN]; char response[BTIME_MSGLEN]; - struct sockaddr_in serv_addr; - struct sockaddr_in my_addr; - struct sockaddr_in resp_addr; - socklen_t serv_addr_len; + 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; - struct hostent *hostent; - in_addr_t inaddr; unsigned int btime = 0; ssize_t nbytes; int retry; fd_set sdset; struct timeval timeout; - if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - fprintf(stderr, "Could not create socket: %s\n", - strerror(errno)); + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + if (getaddrinfo(host, "23456", &hints, &serv_ail) != 0) { + fprintf(stderr, "Could not get address info for %s: %s\n", + host, strerror(errno)); return 0; } + + for (serv_aip = serv_ail; serv_aip != NULL; serv_aip = serv_aip->ai_next) { + if ((sd = socket(serv_aip->ai_family, serv_aip->ai_socktype, + serv_aip->ai_protocol)) < 0) { + continue; + } - memset(&serv_addr, 0, sizeof serv_addr); - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(BTIME_PORT); + break; + } - if ((inaddr = inet_addr(host)) != INADDR_NONE) { - memcpy(&serv_addr.sin_addr, &inaddr, sizeof inaddr); - } else { - if ((hostent = gethostbyname(host)) == NULL) { - return 0; + if (serv_aip == NULL) { + fprintf(stderr, "Could not create socket: %s\n", strerror(errno)); + freeaddrinfo(serv_ail); + return 0; + } + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + 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; + } + + for (my_aip = my_ail; my_aip != NULL; my_aip = my_aip->ai_next) { + if (bind(sd, my_aip->ai_addr, my_aip->ai_addrlen) < 0) { + continue; } - memcpy(&serv_addr.sin_addr, hostent->h_addr, hostent->h_length); + break; } - memset(&my_addr, 0, sizeof my_addr); - my_addr.sin_family = AF_INET; - my_addr.sin_addr.s_addr = htonl(INADDR_ANY); - my_addr.sin_port = htons(0); - if (bind(sd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) { + if (my_aip == NULL) { fprintf(stderr, "Could not bind to local address: %s\n", - strerror(errno)); + strerror(errno)); + freeaddrinfo(my_ail); return 0; } memset(cookie, 0, BTIME_MSGLEN); gen_cookie(cookie); for (retry = 0; retry < MAX_RETRY; retry++) { - serv_addr_len = sizeof serv_addr; if ((nbytes = sendto(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT, - (struct sockaddr *)&serv_addr, serv_addr_len)) < 0) { + serv_aip->ai_addr, serv_aip->ai_addrlen)) < 0) { if (errno == EAGAIN) { usleep(retry * 100); } else { @@ -140,14 +155,15 @@ btime(const char *host) retry = 1; continue; } - } else if (!same_addr(&serv_addr, &resp_addr)) { + } else if (!same_addr((struct sockaddr_storage *)serv_aip->ai_addr, &resp_addr)) { /* If no cookie, check peer */ - char *rstr = strdup(inet_ntoa(resp_addr.sin_addr)); - char *sstr = strdup(inet_ntoa(serv_addr.sin_addr)); + 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); - free(rstr); - free(sstr); retry = 1; continue; } else { @@ -158,28 +174,38 @@ btime(const char *host) } while (retry); close(sd); + freeaddrinfo(serv_ail); + freeaddrinfo(my_ail); return btime; } /* same_addr * - * Compare to struct sockaddr_in's + * Compare two struct sockaddr_storage * * Returns: * 1 if the addresses match * 0 if the addresses are different */ static int -same_addr(struct sockaddr_in *a, struct sockaddr_in *b) +same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b) { - if (a->sin_family != b->sin_family) { - return 0; - } else if (a->sin_addr.s_addr != b->sin_addr.s_addr) { + 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; } + } /* gen_cookie * -- cgit