shithub: drawterm

Download patch

ref: c9ff32c97711bc0a0150d3cc03e79aad3c80e381
parent: d14cd19f715966e736d7439aac7909f83f7a9159
author: cinap_lenrek <[email protected]>
date: Sat Aug 20 23:12:39 EDT 2016

devip: return multiple addresses in /net/cs for dial(), handle ipv6 for windows

--- a/Make.win32
+++ b/Make.win32
@@ -17,7 +17,7 @@
 IP=win32
 OS=win32
 GUI=win32
-LDADD=-lkernel32 -ladvapi32 -lgdi32 -lmpr -lwsock32 -lmsvcrt -lmingw32 -lwinmm
+LDADD=-lkernel32 -ladvapi32 -lgdi32 -lmpr -lwsock32 -lws2_32 -lmsvcrt -lmingw32 -lwinmm
 TARG=drawterm.exe
 XOFILES=glenda-t.$O
 
--- a/kern/devip-posix.c
+++ b/kern/devip-posix.c
@@ -207,54 +207,30 @@
 }
 
 int
-so_gethostbyname(char *host, char**hostv, int n)
+so_gethostbyname(char *host, char **hostv, int n)
 {
+	char buf[INET6_ADDRSTRLEN];
+	PADDRINFOA r, p;
 	int i;
-	char buf[32];
-	unsigned char *p;
-	struct hostent *hp;
 
-	hp = gethostbyname(host);
-	if(hp == 0)
+	r = NULL;
+	if(getaddrinfo(host, NULL, NULL, &r))
 		return 0;
-
-	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
-		p = (unsigned char*)hp->h_addr_list[i];
-		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-		hostv[i] = strdup(buf);
-		if(hostv[i] == 0)
-			break;
-	}
-	return i;
-}
-
-char*
-hostlookup(char *host)
-{
-	char buf[INET6_ADDRSTRLEN];
-	uchar *p;
-	struct hostent *he;
-	struct addrinfo *result;
-
-	he = gethostbyname(host);
-	if(he != 0 && he->h_addr_list[0]) {
-		p = (uchar*)he->h_addr_list[0];
-		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
-	} else if(getaddrinfo(host, NULL, NULL, &result) == 0) {
-		switch (result->ai_family) {
+	for(i = 0, p = r; i < n && p != NULL; p = p->ai_next){
+		switch (p->ai_family) {
+		default:
+			continue;
 		case AF_INET:
-			inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf));
+			inet_ntop(AF_INET, &((struct sockaddr_in*)p->ai_addr)->sin_addr, buf, sizeof(buf));
 			break;
 		case AF_INET6:
-			inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf));
+			inet_ntop(AF_INET6, &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, buf, sizeof(buf));
 			break;
-		default:
-			return nil;
 		}
-	} else
-		return nil;
-
-	return strdup(buf);
+		hostv[i++] = strdup(buf);
+	}
+	freeaddrinfo(r);
+	return i;
 }
 
 int
--- a/kern/devip-win32.c
+++ b/kern/devip-win32.c
@@ -212,42 +212,30 @@
 }
 
 int
-so_gethostbyname(char *host, char**hostv, int n)
+so_gethostbyname(char *host, char **hostv, int n)
 {
+	char buf[INET6_ADDRSTRLEN];
+	PADDRINFOA r, p;
+	DWORD l;
 	int i;
-	char buf[32];
-	unsigned char *p;
-	struct hostent *hp;
 
-	hp = gethostbyname(host);
-	if(hp == 0)
+	r = NULL;
+	if(getaddrinfo(host, NULL, NULL, &r))
 		return 0;
-
-	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
-		p = (unsigned char*)hp->h_addr_list[i];
-		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-		hostv[i] = strdup(buf);
-		if(hostv[i] == 0)
+	for(i = 0, p = r; i < n && p != NULL; p = p->ai_next){
+		switch (p->ai_family) {
+		default:
+			continue;
+		case AF_INET:
+		case AF_INET6:
+			l = sizeof(buf);
+			WSAAddressToStringA(p->ai_addr, p->ai_addrlen, NULL, buf, &l);
 			break;
+		}
+		hostv[i++] = strdup(buf);
 	}
+	freeaddrinfo(r);
 	return i;
-}
-
-char*
-hostlookup(char *host)
-{
-	char buf[100];
-	uchar *p;
-	struct hostent *he;
-
-	he = gethostbyname(host);
-	if(he != 0 && he->h_addr_list[0]) {
-		p = (uchar*)he->h_addr_list[0];
-		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
-	} else
-		strcpy(buf, host);
-
-	return strdup(buf);
 }
 
 int
--- a/kern/devip.c
+++ b/kern/devip.c
@@ -642,14 +642,30 @@
 csclose(Chan *c)
 {
 	free(c->aux);
+	c->aux = nil;
 }
 
 long
 csread(Chan *c, void *a, long n, vlong offset)
 {
-	if(c->aux == nil)
+	char *s, *e, *p;
+
+	s = c->aux;
+	if(s == nil)
 		return 0;
-	return readstr(offset, a, n, c->aux);
+	e = strchr(s, 0);
+	s += offset;
+	if(s >= e)
+		return 0;
+	p = strchr(s, '\n');
+	if(p != nil)
+		p++;
+	else
+		p = e;
+	if(p - s < n)
+		n = p - s;
+	memmove(a, s, n);
+	return n;
 }
 
 static struct
@@ -777,26 +793,13 @@
 	return 0;
 }
 
-static int
-lookuphost(char *s, uchar *to)
-{
-	ipzero(to);
-	if(parseip(to, s) != -1)
-		return 0;
-	if((s = hostlookup(s)) == nil)
-		return -1;
-	parseip(to, s);
-	free(s);
-	return 0;
-}
-
 long
 cswrite(Chan *c, void *a, long n, vlong offset)
 {
-	char *f[4];
+	char *f[4], *ips[8];
 	char *s, *ns;
 	uchar ip[IPaddrlen];
-	int nf, port;
+	int i, nf, port, nips;
 
 	s = malloc(n+1);
 	if(s == nil)
@@ -814,13 +817,22 @@
 	port = lookupport(f[2]);
 	if(port <= 0)
 		error("no translation for port found");
-
-	if(lookuphost(f[1], ip) < 0)
-		error("no translation for host found");
-
-	ns = smprint("/net/%s/clone %I!%d", f[0], ip, port);
-	if(ns == nil)
-		error(Enomem);
+	if(parseip(ip, f[1]) != -1){
+		ips[0] = smprint("%I", ip);
+		nips = 1;
+	} else {
+		nips = so_gethostbyname(f[1], ips, nelem(ips));
+		if(nips <= 0)
+			error("no translation for host found");
+	}
+	ns = smprint("/net/%s/clone %s!%d", f[0], ips[0], port);
+	free(ips[0]);
+	for(i=1; i<nips; i++){
+		ips[0] = smprint("%s\n/net/%s/clone %s!%d", ns, f[0], ips[i], port);
+		free(ips[i]);
+		free(ns);
+		ns = ips[0];
+	}
 	free(c->aux);
 	c->aux = ns;
 	poperror();
--- a/kern/devip.h
+++ b/kern/devip.h
@@ -14,6 +14,3 @@
 int		so_accept(int, unsigned char*, unsigned short*);
 int		so_getservbyname(char*, char*, char*);
 int		so_gethostbyname(char*, char**, int);
-
-char*	hostlookup(char*);
-