summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qacp.c9
-rw-r--r--qarsh.c9
-rw-r--r--qarshd.c19
-rw-r--r--sockutil.c129
-rw-r--r--sockutil.h6
5 files changed, 125 insertions, 47 deletions
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 6575bd0..116779d 100644
--- a/qarsh.c
+++ b/qarsh.c
@@ -50,6 +50,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 };
@@ -191,11 +192,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);
@@ -508,7 +509,7 @@ again:
sigaction(SIGALRM, &sa, NULL);
alarm(max_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 05097b2..6e74993 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,30 +36,48 @@
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)
{
int sd;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
- 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);
+ }
+
if (listen(sd, 0) == -1) {
syslog(LOG_WARNING, "listen error %d, %s", errno,
strerror(errno));
@@ -67,39 +86,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 */
@@ -112,7 +181,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);