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