aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpowwow@askgustav.com <powwow@askgustav.com>2017-04-17 20:25:32 (GMT)
committerSteve Slaven <bpk@hoopajoo.net>2018-09-05 17:25:17 (GMT)
commit844db2a023a1cb18aedce337509ebbabe3994ade (patch)
tree0904cf17cda9ef52e7abc6375ea347abe8dba75a
parentae9da104acab2274040a66e3e40ee97c2b8c10d9 (diff)
downloadpowwow-844db2a023a1cb18aedce337509ebbabe3994ade.zip
powwow-844db2a023a1cb18aedce337509ebbabe3994ade.tar.gz
powwow-844db2a023a1cb18aedce337509ebbabe3994ade.tar.bz2
support IPv6
-rw-r--r--tcp.c113
-rw-r--r--tcp.h2
2 files changed, 69 insertions, 46 deletions
diff --git a/tcp.c b/tcp.c
index 977c6e3..8de41a4 100644
--- a/tcp.c
+++ b/tcp.c
@@ -129,67 +129,90 @@ static void sendopt __P2 (byte,what, byte,opt)
* connect to remote host
* Warning: some voodoo code here
*/
-int tcp_connect __P2 (char *,addr, int,port)
+int tcp_connect __P2 (const char *,addr, int,port)
{
- struct sockaddr_in address;
- struct hostent *host_info;
+ struct addrinfo *host_info;
+ struct addrinfo addrinfo;
+ struct sockaddr_in6 address;
+ int must_free = 0;
int err, newtcp_fd;
-
+
status(1);
-
- memzero((char *)&address, sizeof(address));
+
+ memset(&address, 0, sizeof address);
+ memset(&addrinfo, 0, sizeof addrinfo);
+
/*
* inet_addr has a strange design: It is documented to return -1 for
* malformed requests, but it is declared to return unsigned long!
* Anyway, this works.
- */
-
-#ifndef TERM
- address.sin_addr.s_addr = inet_addr(addr);
- if (address.sin_addr.s_addr != (unsigned int)-1)
- address.sin_family = AF_INET;
- else
+ */
+
+#ifndef TERM
+ switch (inet_pton(AF_INET6, addr, &address.sin6_addr))
{
+ case -1:
+ perror("inet_pton()");
+ return -1;
+ case 1:
+ address.sin6_family = AF_INET6;
+ addrinfo.ai_family = AF_INET6;
+ addrinfo.ai_socktype = SOCK_STREAM;
+ addrinfo.ai_addr = (struct sockaddr *)&address;
+ addrinfo.ai_addrlen = sizeof address;
+ host_info = &addrinfo;
+ break;
+ case 0:
if (opt_info)
tty_printf("#looking up %s... ", addr);
tty_flush();
- host_info = gethostbyname(addr);
- if (host_info == 0) {
- if (!opt_info) {
- tty_printf("#looking up %s... ", addr);
- }
- tty_printf("unknown host!\n");
- return -1;
- }
- memmove((char *)&address.sin_addr, host_info->h_addr,
- host_info->h_length);
- address.sin_family = host_info->h_addrtype;
+ addrinfo.ai_family = AF_INET6;
+ addrinfo.ai_socktype = SOCK_STREAM;
+ addrinfo.ai_flags = AI_V4MAPPED;
+ int gai = getaddrinfo(addr, NULL, &addrinfo, &host_info);
+ if (gai != 0) {
+ tty_printf("failed to look up host: %s\n",
+ gai_strerror(gai));
+ return -1;
+ }
+ must_free = 1;
if (opt_info)
tty_puts("found.\n");
+ break;
+ default:
+ abort();
}
- address.sin_port = htons(port);
-
- newtcp_fd = socket(address.sin_family, SOCK_STREAM, 0);
- if (newtcp_fd == -1) {
- errmsg("create socket");
- return -1;
- } else if (newtcp_fd >= MAX_FDSCAN) {
- tty_printf("#connect: #error: too many open connections\n");
- close(newtcp_fd);
- return -1;
+
+ for (; host_info; host_info = host_info->ai_next) {
+ newtcp_fd = socket(host_info->ai_family, host_info->ai_socktype, 0);
+ if (newtcp_fd == -1)
+ continue;
+ if (newtcp_fd >= MAX_FDSCAN) {
+ tty_printf("#connect: #error: too many open connections\n");
+ close(newtcp_fd);
+ return -1;
+ }
+
+ tty_printf("#trying %s... ", addr);
+ tty_flush();
+
+ ((struct sockaddr_in6 *)host_info->ai_addr)->sin6_port = htons(port);
+
+ err = connect(newtcp_fd, host_info->ai_addr, host_info->ai_addrlen);
+
+ if (err == -1) { /* CTRL-C pressed, or other errors */
+ errmsg("connect to host");
+ close(newtcp_fd);
+ return -1;
+ }
+ break;
}
-
- tty_printf("#trying %s... ", addr);
- tty_flush();
-
- err = connect(newtcp_fd, (struct sockaddr *)&address, sizeof(address));
-
- if (err == -1) { /* CTRL-C pressed, or other errors */
- errmsg("connect to host");
- close(newtcp_fd);
- return -1;
+
+ if (host_info == NULL) {
+ errmsg("failed to connect");
+ return -1;
}
-
+
#else /* term */
if ((newtcp_fd = connect_server(0)) < 0) {
diff --git a/tcp.h b/tcp.h
index 5aaecd9..1bddf83 100644
--- a/tcp.h
+++ b/tcp.h
@@ -58,7 +58,7 @@ extern byte conn_table[MAX_FDSCAN]; /* fd -> index translation table */
extern fd_set fdset; /* set of descriptors to select() on */
-int tcp_connect __P ((char *addr, int port));
+int tcp_connect __P ((const char *addr, int port));
int tcp_read __P ((int fd, char *buffer, int maxsize));
void tcp_raw_write __P ((int fd, const char *data, int len));
void tcp_write_escape_iac __P3 (int,fd, const char *,data, int,len);