1 #define Unknown win_Unknown 2 #include <windows.h> 3 #include <winbase.h> 4 #include <sys/types.h> 5 #include <winsock.h> 6 #undef Unknown 7 #include "dat.h" 8 #include "fns.h" 9 #include "ip.h" 10 #include "error.h" 11 12 typedef int socklen_t; /* Windows is leading edge as always */ 13 14 15 extern int SOCK_SELECT; 16 17 char Enotv4[] = "address not IPv4"; 18 19 static void 20 ipw6(uchar *a, ulong w) 21 { 22 memmove(a, v4prefix, IPv4off); 23 memmove(a+IPv4off, &w, IPv4addrlen); 24 } 25 26 int 27 so_socket(int type) 28 { 29 int fd, one; 30 31 switch(type) { 32 default: 33 error("bad protocol type"); 34 case S_TCP: 35 type = SOCK_STREAM; 36 break; 37 case S_UDP: 38 type = SOCK_DGRAM; 39 break; 40 } 41 fd = socket(AF_INET, type, 0); 42 if(fd < 0) 43 oserror(); 44 if(type == SOCK_DGRAM){ 45 one = 1; 46 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one)); 47 }else{ 48 one = 1; 49 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)); 50 } 51 return fd; 52 } 53 54 int 55 so_send(int sock, void *va, int len, void *hdr, int hdrlen) 56 { 57 int r; 58 struct sockaddr sa; 59 struct sockaddr_in *sin; 60 uchar *h = hdr; 61 62 63 osenter(); 64 if(hdr == 0) 65 r = send(sock, va, len, 0); 66 else { 67 memset(&sa, 0, sizeof(sa)); 68 sin = (struct sockaddr_in*)&sa; 69 sin->sin_family = AF_INET; 70 switch(hdrlen){ 71 case OUdphdrlenv4: 72 memmove(&sin->sin_addr, h, 4); 73 memmove(&sin->sin_port, h+8, 2); 74 break; 75 case OUdphdrlen: 76 v6tov4((uchar*)&sin->sin_addr, h); 77 memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ 78 break; 79 default: 80 v6tov4((uchar*)&sin->sin_addr, h); 81 memmove(&sin->sin_port, h+3*IPaddrlen, 2); 82 break; 83 } 84 r = sendto(sock, va, len, 0, &sa, sizeof(sa)); 85 } 86 osleave(); 87 return r; 88 } 89 90 static int 91 doselect(int sock) 92 { 93 fd_set waitr; 94 struct timeval seltime; 95 96 up->syscall = SOCK_SELECT; 97 FD_ZERO(&waitr); 98 FD_SET(sock, &waitr); 99 for(;;){ 100 int nfds; 101 fd_set in, exc; 102 103 in = waitr; 104 exc = waitr; 105 seltime.tv_sec = 1; 106 seltime.tv_usec = 0L; 107 nfds = select(sizeof(fd_set)*8, &in, (fd_set*)0, &exc, &seltime); 108 if(up->intwait) { 109 up->intwait = 0; 110 return -1; 111 } 112 if(nfds < 0) { 113 print("select error\n"); 114 return 0; 115 } 116 if(FD_ISSET(sock, &in) || FD_ISSET(sock, &exc)){ 117 return 0; 118 } 119 } 120 } 121 122 int 123 so_recv(int sock, void *va, int len, void *hdr, int hdrlen) 124 { 125 int r; 126 socklen_t l; 127 struct sockaddr sa; 128 struct sockaddr_in *sin; 129 uchar h[Udphdrlen]; 130 131 osenter(); 132 if(doselect(sock) < 0) { 133 osleave(); 134 return -1; 135 } 136 if(hdr == 0) 137 r = recv(sock, va, len, 0); 138 else { 139 sin = (struct sockaddr_in*)&sa; 140 l = sizeof(sa); 141 r = recvfrom(sock, va, len, 0, &sa, &l); 142 if(r >= 0) { 143 memset(h, 0, sizeof(h)); 144 switch(hdrlen){ 145 case OUdphdrlenv4: 146 memmove(h, &sin->sin_addr, IPv4addrlen); 147 memmove(h+2*IPv4addrlen, &sin->sin_port, 2); 148 break; 149 case OUdphdrlen: 150 v4tov6(h, (uchar*)&sin->sin_addr); 151 memmove(h+2*IPaddrlen, &sin->sin_port, 2); 152 break; 153 default: 154 v4tov6(h, (uchar*)&sin->sin_addr); 155 memmove(h+3*IPaddrlen, &sin->sin_port, 2); 156 break; 157 } 158 159 /* alas there's no way to get the local addr/port correctly. Pretend. */ 160 memset(&sa, 0, sizeof(sa)); 161 getsockname(sock, &sa, &l); 162 switch(hdrlen){ 163 case OUdphdrlenv4: 164 memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen); 165 memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2); 166 break; 167 case OUdphdrlen: 168 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 169 memmove(h+2*IPaddrlen+2, &sin->sin_port, 2); 170 break; 171 default: 172 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 173 v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr); /* ifcaddr */ 174 memmove(h+3*IPaddrlen+2, &sin->sin_port, 2); 175 break; 176 } 177 memmove(hdr, h, hdrlen); 178 } 179 } 180 osleave(); 181 return r; 182 } 183 184 void 185 so_close(int sock) 186 { 187 closesocket(sock); 188 } 189 190 void 191 so_connect(int fd, uchar *raddr, ushort rport) 192 { 193 int r; 194 struct sockaddr sa; 195 struct sockaddr_in *sin; 196 197 if(!isv4(raddr)) 198 error(Enotv4); 199 200 memset(&sa, 0, sizeof(sa)); 201 sin = (struct sockaddr_in*)&sa; 202 sin->sin_family = AF_INET; 203 hnputs(&sin->sin_port, rport); 204 memmove(&sin->sin_addr.s_addr, raddr+IPv4off, IPv4addrlen); 205 206 osenter(); 207 r = connect(fd, &sa, sizeof(sa)); 208 osleave(); 209 if(r < 0) 210 oserror(); 211 } 212 213 void 214 so_getsockname(int fd, uchar *laddr, ushort *lport) 215 { 216 socklen_t len; 217 struct sockaddr sa; 218 struct sockaddr_in *sin; 219 220 len = sizeof(sa); 221 if(getsockname(fd, &sa, &len) < 0) 222 oserror(); 223 224 sin = (struct sockaddr_in*)&sa; 225 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 226 error(Enotv4); 227 228 ipw6(laddr, sin->sin_addr.s_addr); 229 *lport = nhgets(&sin->sin_port); 230 } 231 232 void 233 so_listen(int fd) 234 { 235 int r; 236 237 osenter(); 238 r = listen(fd, 256); 239 osleave(); 240 if(r < 0) 241 oserror(); 242 } 243 244 int 245 so_accept(int fd, uchar *raddr, ushort *rport) 246 { 247 int nfd; 248 socklen_t len; 249 struct sockaddr sa; 250 struct sockaddr_in *sin; 251 252 sin = (struct sockaddr_in*)&sa; 253 254 len = sizeof(sa); 255 osenter(); 256 if(doselect(fd) < 0) { 257 osleave(); 258 return -1; 259 } 260 nfd = accept(fd, &sa, &len); 261 osleave(); 262 if(nfd < 0) 263 oserror(); 264 265 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 266 error(Enotv4); 267 268 ipw6(raddr, sin->sin_addr.s_addr); 269 *rport = nhgets(&sin->sin_port); 270 return nfd; 271 } 272 273 void 274 so_bind(int fd, int su, uchar *addr, ushort port) 275 { 276 int i, one; 277 struct sockaddr sa; 278 struct sockaddr_in *sin; 279 280 sin = (struct sockaddr_in*)&sa; 281 282 one = 1; 283 // if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { 284 // oserrstr(up->genbuf, sizeof(up->genbuf)); 285 // print("setsockopt: %s", err); 286 // } 287 288 if(su) { 289 for(i = 600; i < 1024; i++) { 290 memset(&sa, 0, sizeof(sa)); 291 sin->sin_family = AF_INET; 292 memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); 293 hnputs(&sin->sin_port, i); 294 295 if(bind(fd, &sa, sizeof(sa)) >= 0) 296 return; 297 } 298 oserror(); 299 } 300 301 memset(&sa, 0, sizeof(sa)); 302 sin->sin_family = AF_INET; 303 memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); 304 hnputs(&sin->sin_port, port); 305 306 if(bind(fd, &sa, sizeof(sa)) < 0) 307 oserror(); 308 } 309 310 int 311 so_gethostbyname(char *host, char**hostv, int n) 312 { 313 int i; 314 char buf[32]; 315 uchar *p; 316 struct hostent *hp; 317 318 hp = gethostbyname(host); 319 if(hp == 0) 320 return 0; 321 322 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 323 p = (uchar*)hp->h_addr_list[i]; 324 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 325 hostv[i] = strdup(buf); 326 if(hostv[i] == 0) 327 break; 328 } 329 return i; 330 } 331 332 int 333 so_gethostbyaddr(char *addr, char **hostv, int n) 334 { 335 int i; 336 struct hostent *hp; 337 unsigned long straddr; 338 339 straddr = inet_addr(addr); 340 if(straddr == -1) 341 return 0; 342 343 hp = gethostbyaddr((char *)&straddr, sizeof(straddr), AF_INET); 344 if(hp == 0) 345 return 0; 346 347 hostv[0] = strdup(hp->h_name); 348 if(hostv[0] == 0) 349 return 0; 350 for(i = 1; hp->h_aliases[i-1] && i < n; i++) { 351 hostv[i] = strdup(hp->h_aliases[i-1]); 352 if(hostv[i] == 0) 353 break; 354 } 355 return i; 356 } 357 358 int 359 so_getservbyname(char *service, char *net, char *port) 360 { 361 ushort p; 362 struct servent *s; 363 364 s = getservbyname(service, net); 365 if(s == 0) 366 return -1; 367 p = s->s_port; 368 sprint(port, "%d", nhgets(&p)); 369 return 0; 370 } 371 372 int 373 so_hangup(int fd, int nolinger) 374 { 375 int r; 376 static struct linger l = {1, 0}; 377 378 osenter(); 379 if(nolinger) 380 setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); 381 r = closesocket(fd); 382 osleave(); 383 return r; 384 } 385 386 void 387 arpadd(char *ipaddr, char *eaddr, int n) 388 { 389 error("arp not implemented"); 390 } 391 392 int 393 so_mustbind(int restricted, int port) 394 { 395 USED(restricted); 396 USED(port); 397 /* Windows requires bound sockets, even on port 0 */ 398 return 1; 399 } 400 401 void 402 so_keepalive(int fd, int ms) 403 { 404 int on; 405 406 USED(ms); 407 on = 1; 408 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); 409 } 410