diff options
-rw-r--r-- | qacp.c | 9 | ||||
-rw-r--r-- | qarsh.c | 9 | ||||
-rw-r--r-- | qarshd.c | 19 | ||||
-rw-r--r-- | sockutil.c | 129 | ||||
-rw-r--r-- | sockutil.h | 6 |
5 files changed, 125 insertions, 47 deletions
@@ -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", @@ -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) { @@ -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); @@ -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; @@ -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); |