summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Straz <nstraz@redhat.com>2010-09-30 14:49:18 -0400
committerNathan Straz <nstraz@redhat.com>2010-09-30 14:49:18 -0400
commit882ff23885f33c7f4eb097e31f49aefd6b5f8930 (patch)
tree50781e99b8951452e51c762654c884fb3532517f
parent314cc45e160cb0a2d6ccb51f95e40c42bed84c4e (diff)
parentedf6032e3395baa5e2a160e4f70d3b108ae31622 (diff)
downloadqarsh-882ff23885f33c7f4eb097e31f49aefd6b5f8930.tar.gz
qarsh-882ff23885f33c7f4eb097e31f49aefd6b5f8930.tar.xz
qarsh-882ff23885f33c7f4eb097e31f49aefd6b5f8930.zip
Merge branch 'ipv6' of ssh://sts-a//home/msp/djansa/src/git/qarsh into ipv6
Conflicts: qarsh.c sockutil.c
-rw-r--r--btime.c100
-rw-r--r--btimed.c2
-rw-r--r--btimed.xinetd1
-rw-r--r--hbeat.c30
-rw-r--r--qacp.c9
-rw-r--r--qarsh.c9
-rw-r--r--qarshd.c19
-rw-r--r--sockutil.c128
-rw-r--r--sockutil.h6
9 files changed, 207 insertions, 97 deletions
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
*
diff --git a/btimed.c b/btimed.c
index 83a5af6..0ba6c91 100644
--- a/btimed.c
+++ b/btimed.c
@@ -44,7 +44,7 @@ main(int argc, char **argv)
char btimeonly[BTIME_MSGLEN];
char cookiemsg[BTIME_MSGLEN];
char *outmsg;
- struct sockaddr_in cli_addr;
+ struct sockaddr_storage cli_addr;
socklen_t cli_addr_len;
ssize_t nbytes;
unsigned int local_btime;
diff --git a/btimed.xinetd b/btimed.xinetd
index 72e8244..ab8d1ff 100644
--- a/btimed.xinetd
+++ b/btimed.xinetd
@@ -10,5 +10,4 @@ service btimed
wait = yes
user = root
server = /usr/sbin/btimed
- flags = IPV4
}
diff --git a/hbeat.c b/hbeat.c
index 46b8ac1..8f781e0 100644
--- a/hbeat.c
+++ b/hbeat.c
@@ -56,25 +56,33 @@ hbeat_t
hbeat_init(const char *host, int max_timeout)
{
struct hbeat_s *hbeatp;
- struct hostent *hostent;
- struct in_addr tmpaddr;
+ struct addrinfo hints, *aip;
+ void *addr;
+ char ipstr[INET6_ADDRSTRLEN];
hbeatp = malloc(sizeof *hbeatp);
if (!hbeatp) {
return NULL;
}
- /* Store the dotted quad instead of the hostname so we
- * don't have to look it up ever time we hbeat. */
- if (inet_addr(host) == INADDR_NONE) {
- if ((hostent = gethostbyname(host)) == NULL) {
- return NULL;
- }
- memcpy(&tmpaddr, hostent->h_addr, hostent->h_length);
- hbeatp->host = strdup(inet_ntoa(tmpaddr));
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if (getaddrinfo(host, NULL, &hints, &aip) != 0) {
+ return NULL;
+ }
+
+ if (aip->ai_family == AF_INET) {
+ addr = &(((struct sockaddr_in *)aip->ai_addr)->sin_addr);
} else {
- hbeatp->host = strdup(host);
+ addr = &(((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr);
}
+
+ inet_ntop(aip->ai_family, addr, ipstr, sizeof ipstr);
+ freeaddrinfo(aip);
+
+ hbeatp->host = strdup(ipstr);
hbeatp->max_timeout = max_timeout;
hbeatp->rhost_state = HOST_ALIVE;
hbeatp->last_rhost_btime = 0;
diff --git a/qacp.c b/qacp.c
index 6ddf414..c6c143e 100644
--- a/qacp.c
+++ b/qacp.c
@@ -49,6 +49,7 @@
/* Globals */
int qacp_fd = -1; /* The control connection to qacpd */
+unsigned short qarsh_ss_family; /* AF_INET/AF_INET6, set on connect */
short quiet = 0;
void
@@ -148,7 +149,7 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile)
exit(errno);
}
- sd = bind_any(QARSH_MINPORT);
+ sd = bind_any(QARSH_MINPORT, qarsh_ss_family);
port = getsockport(sd);
/* Recall that the packet types are qarshd-centric, so if we want
@@ -251,7 +252,7 @@ qacp_recvonefile(const char *host, const char *srcfile, const char *destfile)
fchmod(outfd, rstatp->qp_st_mode);
- sd = bind_any(QARSH_MINPORT);
+ sd = bind_any(QARSH_MINPORT, qarsh_ss_family);
port = getsockport(sd);
/* Recall that the packet types are qarshd-centric, so if we want
@@ -420,7 +421,7 @@ recvfiles(char **argv, int argc, int fileidx, short recursive)
ruser = strdup(pw->pw_name);
}
- qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT);
+ qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT, &qarsh_ss_family);
if (qacp_fd == -1) {
if (errno == 0) {
fprintf(stderr, "Could not connect to %s:%d, %d: %s\n",
@@ -526,7 +527,7 @@ sendfiles(char **argv, int argc, int fileidx, short recursive)
ruser = strdup(pw->pw_name);
}
- qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT);
+ qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT, &qarsh_ss_family);
if (qacp_fd == -1) {
if (errno == 0) {
fprintf(stderr, "Could not connect to %s:%d, %d: %s\n",
diff --git a/qarsh.c b/qarsh.c
index ea272da..29b2cba 100644
--- a/qarsh.c
+++ b/qarsh.c
@@ -51,6 +51,7 @@
/* Globals */
int qarsh_fd = -1; /* The control connection to qarshd */
+unsigned short qarsh_ss_family; /* AF_INET/AF_INET6, set on connect */
hbeat_t qarsh_hb; /* Heartbeat handle */
int signal_to_send = 0;
int sigs_to_propogate[] = { SIGINT, SIGTERM, SIGHUP, SIGUSR1, SIGUSR2 };
@@ -192,11 +193,11 @@ run_remote_cmd(char *cmdline)
struct timespec timeout;
short cmd_finished;
- l_in = bind_any(QARSH_MINPORT);
+ l_in = bind_any(QARSH_MINPORT, qarsh_ss_family);
p_in = getsockport(l_in);
- l_out = bind_any(QARSH_MINPORT);
+ l_out = bind_any(QARSH_MINPORT, qarsh_ss_family);
p_out = getsockport(l_out);
- l_err = bind_any(QARSH_MINPORT);
+ l_err = bind_any(QARSH_MINPORT, qarsh_ss_family);
p_err = getsockport(l_err);
qp = make_qp_runcmd(cmdline, p_in, p_out, p_err);
@@ -509,7 +510,7 @@ again:
sigaction(SIGALRM, &sa, NULL);
alarm(CONNECT_TIMEOUT);
- qarsh_fd = connect_to_host(host, port);
+ qarsh_fd = connect_to_host(host, port, &qarsh_ss_family);
alarm(0);
if (qarsh_fd == -1) {
diff --git a/qarshd.c b/qarshd.c
index ec5d1f7..fd4ca08 100644
--- a/qarshd.c
+++ b/qarshd.c
@@ -33,6 +33,7 @@
#include <sys/socket.h>
#include <sys/sendfile.h>
#include <arpa/inet.h>
+#include <netdb.h>
#include <pwd.h>
#include <grp.h>
@@ -48,7 +49,7 @@ int debug = 0;
/* Globals */
-struct sockaddr_in peername;
+struct sockaddr_storage peername;
int child_exitted = 0;
/* A mini cache for rstat so we can check it in pushfile */
@@ -384,7 +385,9 @@ int
main(int argc, char *argv[])
{
int ch;
- socklen_t peernamelen;
+ socklen_t peerlen;
+ char peer_hoststr[NI_MAXHOST];
+ char peer_portstr[NI_MAXSERV];
openlog("qarshd", LOG_PID, LOG_DAEMON);
@@ -401,10 +404,14 @@ main(int argc, char *argv[])
}
/* daemon initialization */
- peernamelen = sizeof peername;
- getpeername(0, (struct sockaddr *)&peername, &peernamelen);
- syslog(LOG_INFO, "Talking to peer %s:%d",
- inet_ntoa(peername.sin_addr), ntohs(peername.sin_port));
+ peerlen = sizeof peername;
+ getpeername(0, (struct sockaddr *)&peername, &peerlen);
+ getnameinfo((struct sockaddr *)&peername, peerlen,
+ peer_hoststr, NI_MAXHOST, peer_portstr,
+ NI_MAXSERV, NI_NUMERICHOST);
+ syslog(LOG_INFO, "Talking to peer %s:%s (%s)", peer_hoststr, peer_portstr,
+ peername.ss_family == AF_INET ? "IPv4" : "IPv6");
+
/* Start reading packets from stdin */
handle_packets(0);
diff --git a/sockutil.c b/sockutil.c
index f13bcaf..824f378 100644
--- a/sockutil.c
+++ b/sockutil.c
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
@@ -35,24 +36,30 @@
int
getsockport(int sd)
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
socklen_t addrlen;
addrlen = sizeof addr;
if (getsockname(sd, (struct sockaddr *)&addr, &addrlen) == 0) {
- return ntohs(addr.sin_port);
+ if (addr.ss_family == AF_INET) {
+ struct sockaddr_in *ipv4p = (struct sockaddr_in *)&addr;
+ return ntohs(ipv4p->sin_port);
+ } else {
+ struct sockaddr_in6 *ipv6p = (struct sockaddr_in6 *)&addr;
+ return ntohs(ipv6p->sin6_port);
+ }
} else {
return -1;
}
}
int
-bind_any(int minport)
+bind_any(int minport, unsigned short ss_family)
{
static int lastminport = 0;
static int nextport = 0;
int sd;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
if (minport == lastminport) {
minport = nextport;
@@ -60,13 +67,24 @@ bind_any(int minport)
lastminport = minport;
}
- sd = socket(AF_INET, SOCK_STREAM, 0);
+ sd = socket(ss_family, SOCK_STREAM, 0);
if (sd == -1) return -1;
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- do {
- addr.sin_port = htons(minport++);
- } while (bind(sd, (struct sockaddr *)&addr, sizeof addr) != 0);
+
+ if (ss_family == AF_INET) {
+ struct sockaddr_in *ipv4p = (struct sockaddr_in *)&addr;
+ ipv4p->sin_family = AF_INET;
+ ipv4p->sin_addr.s_addr = htonl(INADDR_ANY);
+ do {
+ ipv4p->sin_port = htons(minport++);
+ } while (bind(sd, (struct sockaddr *)&addr, sizeof addr) != 0);
+ } else {
+ struct sockaddr_in6 *ipv6p = (struct sockaddr_in6 *)&addr;
+ ipv6p->sin6_family = AF_INET6;
+ ipv6p->sin6_addr = in6addr_any;
+ do {
+ ipv6p->sin6_port = htons(minport++);
+ } while (bind(sd, (struct sockaddr *)&addr, sizeof addr) != 0);
+ }
nextport = minport;
if (listen(sd, 0) == -1) {
@@ -77,39 +95,89 @@ bind_any(int minport)
}
int
-connect_to_host(char *hostname, int port)
+connect_to_host(char *hostname, int port, unsigned short *ss_family)
{
- struct hostent *h;
- struct sockaddr_in haddr;
+ struct addrinfo *ail;
+ struct addrinfo *aip;
+ struct addrinfo hints;
+ char portstr[NI_MAXSERV];
int sd;
+ int err;
- if ((h = gethostbyname(hostname)) == NULL) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ memset(portstr, 0, sizeof portstr);
+ snprintf(portstr, NI_MAXSERV, "%d", port);
+
+ if ((err = getaddrinfo(hostname, portstr, NULL, &ail)) != 0) {
+ fprintf(stderr, "Could not resolve hostname %s: %s\n",
+ hostname, gai_strerror(err));
return -1;
}
- haddr.sin_family = h->h_addrtype;
- haddr.sin_port = htons(port);
- memcpy(&haddr.sin_addr, h->h_addr, h->h_length);
- sd = socket(PF_INET, SOCK_STREAM, 0);
- if (sd == -1) return -1;
- if (connect(sd, (struct sockaddr *)&haddr, sizeof haddr) == -1) {
- return -1;
+ /* TBD -- do we loop over all of the addrinfos returned trying to
+ * connect, or just pick the first one? */
+
+ for (aip = ail; aip != NULL; aip = aip->ai_next) {
+#if 0
+ char hname[NI_MAXHOST] = "";
+ char nname[NI_MAXHOST] = "";
+
+ err = getnameinfo(aip->ai_addr, aip->ai_addrlen, hname, NI_MAXHOST, NULL, 0, 0);
+ err = getnameinfo(aip->ai_addr, aip->ai_addrlen, nname, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+
+ if (err != 0) {
+ printf("error in getnameinfo: %s\n", gai_strerror(err));
+ continue;
+ }
+
+ if (*hname && *nname) {
+ printf("Trying: %s (%s) -- ", hname, nname);
+ if (aip->ai_family == AF_INET6) puts("IPv6");
+ if (aip->ai_family == AF_INET) puts("IPv4");
+ }
+#endif
+
+ sd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
+ if (sd == -1) return -1;
+ if (connect(sd, aip->ai_addr, aip->ai_addrlen) == -1) {
+ close(sd);
+ continue;
+ } else {
+ *ss_family=aip->ai_family;
+ freeaddrinfo(ail);
+ return sd;
+ }
}
- return sd;
+
+ freeaddrinfo(ail);
+ return -1;
}
int
-connect_to_peer(struct sockaddr_in *peer, int port)
+connect_to_peer(struct sockaddr_storage *peer, int port)
{
- struct sockaddr_in in_peer;
int sd;
int fdflags;
+ struct sockaddr_in ipv4;
+ struct sockaddr_in6 ipv6;
+ struct sockaddr_storage *peeraddr;
+
+ if (peer->ss_family == AF_INET) {
+ ipv4.sin_family = AF_INET;
+ ipv4.sin_port=htons(port);
+ ipv4.sin_addr = ((struct sockaddr_in *)peer)->sin_addr;
+ peeraddr = (struct sockaddr_storage *)&ipv4;
+ } else {
+ ipv6.sin6_family = AF_INET6;
+ ipv6.sin6_port=htons(port);
+ ipv6.sin6_addr = ((struct sockaddr_in6 *)peer)->sin6_addr;
+ peeraddr = (struct sockaddr_storage *)&ipv6;
+ }
- in_peer.sin_family = AF_INET;
- in_peer.sin_port = htons(port);
- in_peer.sin_addr = peer->sin_addr;
-
- sd = socket(PF_INET, SOCK_STREAM, 0);
+ sd = socket(peer->ss_family, SOCK_STREAM, 0);
if (sd == -1) return -1;
/* Set close-on-exec for these sds */
@@ -122,7 +190,7 @@ connect_to_peer(struct sockaddr_in *peer, int port)
return -1;
}
- if (connect(sd, (struct sockaddr *)&in_peer, sizeof in_peer) == -1) {
+ if (connect(sd, (struct sockaddr *)peeraddr, sizeof *peeraddr) == -1) {
return -1;
}
return sd;
diff --git a/sockutil.h b/sockutil.h
index 820376f..3678b1f 100644
--- a/sockutil.h
+++ b/sockutil.h
@@ -20,8 +20,8 @@
#include <netinet/in.h>
int getsockport(int sd);
-int bind_any(int minport);
-int connect_to_host(char *hostname, int port);
-int connect_to_peer(struct sockaddr_in *peer, int port);
+int bind_any(int minport, unsigned short ss_family);
+int connect_to_host(char *hostname, int port, unsigned short *ss_family);
+int connect_to_peer(struct sockaddr_storage *peer, int port);
struct qa_packet * recv_packet(int fd);
int send_packet(int fd, struct qa_packet *qp);