xref: /plan9/sys/src/cmd/unix/drawterm/kern/devip-win32.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
18ccd4a63SDavid du Colombier #include <windows.h>
2*58da3067SDavid du Colombier #include <ws2tcpip.h>
38ccd4a63SDavid du Colombier #include "u.h"
48ccd4a63SDavid du Colombier #include "lib.h"
58ccd4a63SDavid du Colombier #include "dat.h"
68ccd4a63SDavid du Colombier #include "fns.h"
78ccd4a63SDavid du Colombier #include "error.h"
8*58da3067SDavid du Colombier #include "ip.h"
98ccd4a63SDavid du Colombier 
108ccd4a63SDavid du Colombier #include "devip.h"
118ccd4a63SDavid du Colombier 
128ccd4a63SDavid du Colombier #ifdef MSVC
138ccd4a63SDavid du Colombier #pragma comment(lib, "wsock32.lib")
148ccd4a63SDavid du Colombier #endif
158ccd4a63SDavid du Colombier 
168ccd4a63SDavid du Colombier #undef listen
178ccd4a63SDavid du Colombier #undef accept
188ccd4a63SDavid du Colombier #undef bind
198ccd4a63SDavid du Colombier 
20*58da3067SDavid du Colombier static int
family(unsigned char * addr)21*58da3067SDavid du Colombier family(unsigned char *addr)
22*58da3067SDavid du Colombier {
23*58da3067SDavid du Colombier 	if(isv4(addr))
24*58da3067SDavid du Colombier 		return AF_INET;
25*58da3067SDavid du Colombier 	return AF_INET6;
26*58da3067SDavid du Colombier }
27*58da3067SDavid du Colombier 
28*58da3067SDavid du Colombier static int
addrlen(struct sockaddr_storage * ss)29*58da3067SDavid du Colombier addrlen(struct sockaddr_storage *ss)
30*58da3067SDavid du Colombier {
31*58da3067SDavid du Colombier 	switch(ss->ss_family){
32*58da3067SDavid du Colombier 	case AF_INET:
33*58da3067SDavid du Colombier 		return sizeof(struct sockaddr_in);
34*58da3067SDavid du Colombier 	case AF_INET6:
35*58da3067SDavid du Colombier 		return sizeof(struct sockaddr_in6);
36*58da3067SDavid du Colombier 	}
37*58da3067SDavid du Colombier 	return 0;
38*58da3067SDavid du Colombier }
39*58da3067SDavid du Colombier 
408ccd4a63SDavid du Colombier void
osipinit(void)418ccd4a63SDavid du Colombier osipinit(void)
428ccd4a63SDavid du Colombier {
438ccd4a63SDavid du Colombier 	WSADATA wasdat;
448ccd4a63SDavid du Colombier 	char buf[1024];
458ccd4a63SDavid du Colombier 
468ccd4a63SDavid du Colombier 	if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0)
478ccd4a63SDavid du Colombier 		panic("no winsock.dll");
488ccd4a63SDavid du Colombier 
498ccd4a63SDavid du Colombier 	gethostname(buf, sizeof(buf));
508ccd4a63SDavid du Colombier 	kstrdup(&sysname, buf);
518ccd4a63SDavid du Colombier }
528ccd4a63SDavid du Colombier 
538ccd4a63SDavid du Colombier int
so_socket(int type,unsigned char * addr)54*58da3067SDavid du Colombier so_socket(int type, unsigned char *addr)
558ccd4a63SDavid du Colombier {
568ccd4a63SDavid du Colombier 	int fd, one;
578ccd4a63SDavid du Colombier 
588ccd4a63SDavid du Colombier 	switch(type) {
598ccd4a63SDavid du Colombier 	default:
608ccd4a63SDavid du Colombier 		error("bad protocol type");
618ccd4a63SDavid du Colombier 	case S_TCP:
628ccd4a63SDavid du Colombier 		type = SOCK_STREAM;
638ccd4a63SDavid du Colombier 		break;
648ccd4a63SDavid du Colombier 	case S_UDP:
658ccd4a63SDavid du Colombier 		type = SOCK_DGRAM;
668ccd4a63SDavid du Colombier 		break;
678ccd4a63SDavid du Colombier 	}
688ccd4a63SDavid du Colombier 
69*58da3067SDavid du Colombier 	fd = socket(family(addr), type, 0);
708ccd4a63SDavid du Colombier 	if(fd < 0)
718ccd4a63SDavid du Colombier 		oserror();
728ccd4a63SDavid du Colombier 
738ccd4a63SDavid du Colombier 	one = 1;
748ccd4a63SDavid du Colombier 	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){
758ccd4a63SDavid du Colombier 		oserrstr();
768ccd4a63SDavid du Colombier 		print("setsockopt: %s\n", up->errstr);
778ccd4a63SDavid du Colombier 	}
788ccd4a63SDavid du Colombier 
798ccd4a63SDavid du Colombier 	return fd;
808ccd4a63SDavid du Colombier }
818ccd4a63SDavid du Colombier 
828ccd4a63SDavid du Colombier 
838ccd4a63SDavid du Colombier void
so_connect(int fd,unsigned char * raddr,unsigned short rport)84*58da3067SDavid du Colombier so_connect(int fd, unsigned char *raddr, unsigned short rport)
858ccd4a63SDavid du Colombier {
86*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
878ccd4a63SDavid du Colombier 
88*58da3067SDavid du Colombier 	memset(&ss, 0, sizeof(ss));
898ccd4a63SDavid du Colombier 
90*58da3067SDavid du Colombier 	ss.ss_family = family(raddr);
91*58da3067SDavid du Colombier 
92*58da3067SDavid du Colombier 	switch(ss.ss_family){
93*58da3067SDavid du Colombier 	case AF_INET:
94*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
95*58da3067SDavid du Colombier 		v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
96*58da3067SDavid du Colombier 		break;
97*58da3067SDavid du Colombier 	case AF_INET6:
98*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
99*58da3067SDavid du Colombier 		memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
100*58da3067SDavid du Colombier 		break;
101*58da3067SDavid du Colombier 	}
102*58da3067SDavid du Colombier 
103*58da3067SDavid du Colombier 	if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
1048ccd4a63SDavid du Colombier 		oserror();
1058ccd4a63SDavid du Colombier }
1068ccd4a63SDavid du Colombier 
1078ccd4a63SDavid du Colombier void
so_getsockname(int fd,unsigned char * laddr,unsigned short * lport)108*58da3067SDavid du Colombier so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
1098ccd4a63SDavid du Colombier {
1108ccd4a63SDavid du Colombier 	int len;
111*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1128ccd4a63SDavid du Colombier 
113*58da3067SDavid du Colombier 	len = sizeof(ss);
114*58da3067SDavid du Colombier 	if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
1158ccd4a63SDavid du Colombier 		oserror();
1168ccd4a63SDavid du Colombier 
117*58da3067SDavid du Colombier 	switch(ss.ss_family){
118*58da3067SDavid du Colombier 	case AF_INET:
119*58da3067SDavid du Colombier 		v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
120*58da3067SDavid du Colombier 		*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
121*58da3067SDavid du Colombier 		break;
122*58da3067SDavid du Colombier 	case AF_INET6:
123*58da3067SDavid du Colombier 		memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
124*58da3067SDavid du Colombier 		*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
125*58da3067SDavid du Colombier 		break;
126*58da3067SDavid du Colombier 	default:
127*58da3067SDavid du Colombier 		error("not AF_INET or AF_INET6");
128*58da3067SDavid du Colombier 	}
1298ccd4a63SDavid du Colombier }
1308ccd4a63SDavid du Colombier 
1318ccd4a63SDavid du Colombier void
so_listen(int fd)1328ccd4a63SDavid du Colombier so_listen(int fd)
1338ccd4a63SDavid du Colombier {
1348ccd4a63SDavid du Colombier 	if(listen(fd, 5) < 0)
1358ccd4a63SDavid du Colombier 		oserror();
1368ccd4a63SDavid du Colombier }
1378ccd4a63SDavid du Colombier 
1388ccd4a63SDavid du Colombier int
so_accept(int fd,unsigned char * raddr,unsigned short * rport)139*58da3067SDavid du Colombier so_accept(int fd, unsigned char *raddr, unsigned short *rport)
1408ccd4a63SDavid du Colombier {
141*58da3067SDavid du Colombier 	int nfd;
142*58da3067SDavid du Colombier 	int len;
143*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1448ccd4a63SDavid du Colombier 
145*58da3067SDavid du Colombier 	len = sizeof(ss);
146*58da3067SDavid du Colombier 	nfd = accept(fd, (struct sockaddr*)&ss, &len);
1478ccd4a63SDavid du Colombier 	if(nfd < 0)
1488ccd4a63SDavid du Colombier 		oserror();
1498ccd4a63SDavid du Colombier 
150*58da3067SDavid du Colombier 	switch(ss.ss_family){
151*58da3067SDavid du Colombier 	case AF_INET:
152*58da3067SDavid du Colombier 		v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
153*58da3067SDavid du Colombier 		*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
154*58da3067SDavid du Colombier 		break;
155*58da3067SDavid du Colombier 	case AF_INET6:
156*58da3067SDavid du Colombier 		memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
157*58da3067SDavid du Colombier 		*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
158*58da3067SDavid du Colombier 		break;
159*58da3067SDavid du Colombier 	default:
160*58da3067SDavid du Colombier 		error("not AF_INET or AF_INET6");
161*58da3067SDavid du Colombier 	}
1628ccd4a63SDavid du Colombier 	return nfd;
1638ccd4a63SDavid du Colombier }
1648ccd4a63SDavid du Colombier 
1658ccd4a63SDavid du Colombier void
so_bind(int fd,int su,unsigned short port,unsigned char * addr)166*58da3067SDavid du Colombier so_bind(int fd, int su, unsigned short port, unsigned char *addr)
1678ccd4a63SDavid du Colombier {
1688ccd4a63SDavid du Colombier 	int i, one;
169*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1708ccd4a63SDavid du Colombier 
1718ccd4a63SDavid du Colombier 	one = 1;
1728ccd4a63SDavid du Colombier 	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
1738ccd4a63SDavid du Colombier 		oserrstr();
174*58da3067SDavid du Colombier 		print("setsockopt: %r");
1758ccd4a63SDavid du Colombier 	}
1768ccd4a63SDavid du Colombier 
1778ccd4a63SDavid du Colombier 	if(su) {
1788ccd4a63SDavid du Colombier 		for(i = 600; i < 1024; i++) {
179*58da3067SDavid du Colombier 			memset(&ss, 0, sizeof(ss));
180*58da3067SDavid du Colombier 			ss.ss_family = family(addr);
1818ccd4a63SDavid du Colombier 
182*58da3067SDavid du Colombier 			switch(ss.ss_family){
183*58da3067SDavid du Colombier 			case AF_INET:
184*58da3067SDavid du Colombier 				((struct sockaddr_in*)&ss)->sin_port = i;
185*58da3067SDavid du Colombier 				break;
186*58da3067SDavid du Colombier 			case AF_INET6:
187*58da3067SDavid du Colombier 				((struct sockaddr_in6*)&ss)->sin6_port = i;
188*58da3067SDavid du Colombier 				break;
189*58da3067SDavid du Colombier 			}
190*58da3067SDavid du Colombier 
191*58da3067SDavid du Colombier 			if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0)
1928ccd4a63SDavid du Colombier 				return;
1938ccd4a63SDavid du Colombier 		}
1948ccd4a63SDavid du Colombier 		oserror();
1958ccd4a63SDavid du Colombier 	}
1968ccd4a63SDavid du Colombier 
197*58da3067SDavid du Colombier 	memset(&ss, 0, sizeof(ss));
198*58da3067SDavid du Colombier 	ss.ss_family = family(addr);
1998ccd4a63SDavid du Colombier 
200*58da3067SDavid du Colombier 	switch(ss.ss_family){
201*58da3067SDavid du Colombier 	case AF_INET:
202*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
203*58da3067SDavid du Colombier 		break;
204*58da3067SDavid du Colombier 	case AF_INET6:
205*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
206*58da3067SDavid du Colombier 		break;
207*58da3067SDavid du Colombier 	}
208*58da3067SDavid du Colombier 
209*58da3067SDavid du Colombier 	if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
2108ccd4a63SDavid du Colombier 		oserror();
2118ccd4a63SDavid du Colombier }
2128ccd4a63SDavid du Colombier 
2138ccd4a63SDavid du Colombier int
so_gethostbyname(char * host,char ** hostv,int n)2148ccd4a63SDavid du Colombier so_gethostbyname(char *host, char**hostv, int n)
2158ccd4a63SDavid du Colombier {
2168ccd4a63SDavid du Colombier 	int i;
2178ccd4a63SDavid du Colombier 	char buf[32];
2188ccd4a63SDavid du Colombier 	unsigned char *p;
2198ccd4a63SDavid du Colombier 	struct hostent *hp;
2208ccd4a63SDavid du Colombier 
2218ccd4a63SDavid du Colombier 	hp = gethostbyname(host);
2228ccd4a63SDavid du Colombier 	if(hp == 0)
2238ccd4a63SDavid du Colombier 		return 0;
2248ccd4a63SDavid du Colombier 
2258ccd4a63SDavid du Colombier 	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
2268ccd4a63SDavid du Colombier 		p = (unsigned char*)hp->h_addr_list[i];
2278ccd4a63SDavid du Colombier 		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
2288ccd4a63SDavid du Colombier 		hostv[i] = strdup(buf);
2298ccd4a63SDavid du Colombier 		if(hostv[i] == 0)
2308ccd4a63SDavid du Colombier 			break;
2318ccd4a63SDavid du Colombier 	}
2328ccd4a63SDavid du Colombier 	return i;
2338ccd4a63SDavid du Colombier }
2348ccd4a63SDavid du Colombier 
2358ccd4a63SDavid du Colombier char*
hostlookup(char * host)2368ccd4a63SDavid du Colombier hostlookup(char *host)
2378ccd4a63SDavid du Colombier {
2388ccd4a63SDavid du Colombier 	char buf[100];
2398ccd4a63SDavid du Colombier 	uchar *p;
240*58da3067SDavid du Colombier 	struct hostent *he;
2418ccd4a63SDavid du Colombier 
2428ccd4a63SDavid du Colombier 	he = gethostbyname(host);
2438ccd4a63SDavid du Colombier 	if(he != 0 && he->h_addr_list[0]) {
24414093dc2SDavid du Colombier 		p = (uchar*)he->h_addr_list[0];
2458ccd4a63SDavid du Colombier 		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
2468ccd4a63SDavid du Colombier 	} else
2478ccd4a63SDavid du Colombier 		strcpy(buf, host);
2488ccd4a63SDavid du Colombier 
2498ccd4a63SDavid du Colombier 	return strdup(buf);
2508ccd4a63SDavid du Colombier }
2518ccd4a63SDavid du Colombier 
2528ccd4a63SDavid du Colombier int
so_getservbyname(char * service,char * net,char * port)2538ccd4a63SDavid du Colombier so_getservbyname(char *service, char *net, char *port)
2548ccd4a63SDavid du Colombier {
2558ccd4a63SDavid du Colombier 	struct servent *s;
2568ccd4a63SDavid du Colombier 
2578ccd4a63SDavid du Colombier 	s = getservbyname(service, net);
2588ccd4a63SDavid du Colombier 	if(s == 0)
2598ccd4a63SDavid du Colombier 		return -1;
2608ccd4a63SDavid du Colombier 
2618ccd4a63SDavid du Colombier 	sprint(port, "%d", nhgets(&s->s_port));
2628ccd4a63SDavid du Colombier 	return 0;
2638ccd4a63SDavid du Colombier }
2648ccd4a63SDavid du Colombier 
2658ccd4a63SDavid du Colombier int
so_send(int fd,void * d,int n,int f)2668ccd4a63SDavid du Colombier so_send(int fd, void *d, int n, int f)
2678ccd4a63SDavid du Colombier {
2688ccd4a63SDavid du Colombier 	return send(fd, d, n, f);
2698ccd4a63SDavid du Colombier }
2708ccd4a63SDavid du Colombier 
2718ccd4a63SDavid du Colombier int
so_recv(int fd,void * d,int n,int f)2728ccd4a63SDavid du Colombier so_recv(int fd, void *d, int n, int f)
2738ccd4a63SDavid du Colombier {
2748ccd4a63SDavid du Colombier 	return recv(fd, d, n, f);
2758ccd4a63SDavid du Colombier }
276