1 /* win32sck.c 2 * 3 * (c) 1995 Microsoft Corporation. All rights reserved. 4 * Developed by hip communications inc. 5 * Portions (c) 1993 Intergraph Corporation. All rights reserved. 6 * 7 * You may distribute under the terms of either the GNU General Public 8 * License or the Artistic License, as specified in the README file. 9 */ 10 11 #define WIN32IO_IS_STDIO 12 #define WIN32SCK_IS_STDSCK 13 #define WIN32_LEAN_AND_MEAN 14 #define PERLIO_NOT_STDIO 0 15 #ifdef __GNUC__ 16 #define Win32_Winsock 17 #endif 18 #include <windows.h> 19 #include <ws2spi.h> 20 21 #include "EXTERN.h" 22 #include "perl.h" 23 24 #include "Win32iop.h" 25 #include <sys/socket.h> 26 #include <fcntl.h> 27 #include <sys/stat.h> 28 #include <assert.h> 29 #include <io.h> 30 31 /* thanks to Beverly Brown (beverly@datacube.com) */ 32 #define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) 33 #define TO_SOCKET(x) _get_osfhandle(x) 34 35 #define StartSockets() \ 36 STMT_START { \ 37 if (!wsock_started) \ 38 start_sockets(); \ 39 } STMT_END 40 41 #define SOCKET_TEST(x, y) \ 42 STMT_START { \ 43 StartSockets(); \ 44 if((x) == (y)) \ 45 errno = WSAGetLastError(); \ 46 } STMT_END 47 48 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) 49 50 static struct servent* win32_savecopyservent(struct servent*d, 51 struct servent*s, 52 const char *proto); 53 54 static int wsock_started = 0; 55 56 EXTERN_C void 57 EndSockets(void) 58 { 59 if (wsock_started) 60 WSACleanup(); 61 } 62 63 void 64 start_sockets(void) 65 { 66 unsigned short version; 67 WSADATA retdata; 68 int ret; 69 70 /* 71 * initalize the winsock interface and insure that it is 72 * cleaned up at exit. 73 */ 74 version = 0x2; 75 if(ret = WSAStartup(version, &retdata)) 76 Perl_croak_nocontext("Unable to locate winsock library!\n"); 77 if(retdata.wVersion != version) 78 Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); 79 80 /* atexit((void (*)(void)) EndSockets); */ 81 wsock_started = 1; 82 } 83 84 /* in no sockets Win32 builds, this fowards to replacements in util.c, dTHX 85 * is required 86 */ 87 u_long 88 win32_htonl(u_long hostlong) 89 { 90 #ifdef MYSWAP 91 dTHX; 92 #else 93 StartSockets(); 94 #endif 95 return htonl(hostlong); 96 } 97 98 u_short 99 win32_htons(u_short hostshort) 100 { 101 #ifdef MYSWAP 102 dTHX; 103 #else 104 StartSockets(); 105 #endif 106 return htons(hostshort); 107 } 108 109 u_long 110 win32_ntohl(u_long netlong) 111 { 112 #ifdef MYSWAP 113 dTHX; 114 #else 115 StartSockets(); 116 #endif 117 return ntohl(netlong); 118 } 119 120 u_short 121 win32_ntohs(u_short netshort) 122 { 123 #ifdef MYSWAP 124 dTHX; 125 #else 126 StartSockets(); 127 #endif 128 return ntohs(netshort); 129 } 130 131 132 133 SOCKET 134 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) 135 { 136 SOCKET r; 137 138 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); 139 return OPEN_SOCKET(r); 140 } 141 142 int 143 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) 144 { 145 int r; 146 147 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); 148 return r; 149 } 150 151 int 152 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) 153 { 154 int r; 155 156 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); 157 return r; 158 } 159 160 161 int 162 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) 163 { 164 int r; 165 166 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); 167 return r; 168 } 169 170 int 171 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) 172 { 173 int r; 174 175 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); 176 return r; 177 } 178 179 int 180 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) 181 { 182 int r; 183 184 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 185 return r; 186 } 187 188 int 189 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) 190 { 191 int r; 192 193 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); 194 return r; 195 } 196 197 int 198 win32_listen(SOCKET s, int backlog) 199 { 200 int r; 201 202 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); 203 return r; 204 } 205 206 int 207 win32_recv(SOCKET s, char *buf, int len, int flags) 208 { 209 int r; 210 211 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); 212 return r; 213 } 214 215 int 216 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) 217 { 218 int r; 219 int frombufsize = *fromlen; 220 221 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); 222 /* Winsock's recvfrom() only returns a valid 'from' when the socket 223 * is connectionless. Perl expects a valid 'from' for all types 224 * of sockets, so go the extra mile. 225 */ 226 if (r != SOCKET_ERROR && frombufsize == *fromlen) 227 (void)win32_getpeername(s, from, fromlen); 228 return r; 229 } 230 231 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ 232 int 233 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) 234 { 235 int r; 236 int i, fd, save_errno = errno; 237 FD_SET nrd, nwr, nex; 238 bool just_sleep = TRUE; 239 240 StartSockets(); 241 242 FD_ZERO(&nrd); 243 FD_ZERO(&nwr); 244 FD_ZERO(&nex); 245 for (i = 0; i < nfds; i++) { 246 if (rd && PERL_FD_ISSET(i,rd)) { 247 fd = TO_SOCKET(i); 248 FD_SET((unsigned)fd, &nrd); 249 just_sleep = FALSE; 250 } 251 if (wr && PERL_FD_ISSET(i,wr)) { 252 fd = TO_SOCKET(i); 253 FD_SET((unsigned)fd, &nwr); 254 just_sleep = FALSE; 255 } 256 if (ex && PERL_FD_ISSET(i,ex)) { 257 fd = TO_SOCKET(i); 258 FD_SET((unsigned)fd, &nex); 259 just_sleep = FALSE; 260 } 261 } 262 263 /* winsock seems incapable of dealing with all three fd_sets being empty, 264 * so do the (millisecond) sleep as a special case 265 */ 266 if (just_sleep) { 267 if (timeout) 268 Sleep(timeout->tv_sec * 1000 + 269 timeout->tv_usec / 1000); /* do the best we can */ 270 else 271 Sleep(UINT_MAX); 272 return 0; 273 } 274 275 errno = save_errno; 276 SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, timeout)); 277 save_errno = errno; 278 279 for (i = 0; i < nfds; i++) { 280 if (rd && PERL_FD_ISSET(i,rd)) { 281 fd = TO_SOCKET(i); 282 if (!FD_ISSET(fd, &nrd)) 283 PERL_FD_CLR(i,rd); 284 } 285 if (wr && PERL_FD_ISSET(i,wr)) { 286 fd = TO_SOCKET(i); 287 if (!FD_ISSET(fd, &nwr)) 288 PERL_FD_CLR(i,wr); 289 } 290 if (ex && PERL_FD_ISSET(i,ex)) { 291 fd = TO_SOCKET(i); 292 if (!FD_ISSET(fd, &nex)) 293 PERL_FD_CLR(i,ex); 294 } 295 } 296 errno = save_errno; 297 return r; 298 } 299 300 int 301 win32_send(SOCKET s, const char *buf, int len, int flags) 302 { 303 int r; 304 305 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); 306 return r; 307 } 308 309 int 310 win32_sendto(SOCKET s, const char *buf, int len, int flags, 311 const struct sockaddr *to, int tolen) 312 { 313 int r; 314 315 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); 316 return r; 317 } 318 319 int 320 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) 321 { 322 int r; 323 324 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 325 return r; 326 } 327 328 int 329 win32_shutdown(SOCKET s, int how) 330 { 331 int r; 332 333 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); 334 return r; 335 } 336 337 int 338 win32_closesocket(SOCKET s) 339 { 340 int r; 341 342 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); 343 return r; 344 } 345 346 void 347 convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) 348 { 349 Copy(in, out, 1, WSAPROTOCOL_INFOA); 350 wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol)); 351 } 352 353 SOCKET 354 open_ifs_socket(int af, int type, int protocol) 355 { 356 dTHX; 357 char *s; 358 unsigned long proto_buffers_len = 0; 359 int error_code; 360 SOCKET out = INVALID_SOCKET; 361 362 if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s)) 363 return WSASocket(af, type, protocol, NULL, 0, 0); 364 365 if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR 366 && error_code == WSAENOBUFS) 367 { 368 WSAPROTOCOL_INFOW *proto_buffers; 369 int protocols_available = 0; 370 371 Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW), 372 WSAPROTOCOL_INFOW); 373 374 if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, 375 &proto_buffers_len, &error_code)) != SOCKET_ERROR) 376 { 377 int i; 378 for (i = 0; i < protocols_available; i++) 379 { 380 WSAPROTOCOL_INFOA proto_info; 381 382 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily) 383 || (type != proto_buffers[i].iSocketType) 384 || (protocol != 0 && proto_buffers[i].iProtocol != 0 && 385 protocol != proto_buffers[i].iProtocol)) 386 continue; 387 388 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0) 389 continue; 390 391 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info); 392 393 out = WSASocket(af, type, protocol, &proto_info, 0, 0); 394 break; 395 } 396 } 397 398 Safefree(proto_buffers); 399 } 400 401 return out; 402 } 403 404 SOCKET 405 win32_socket(int af, int type, int protocol) 406 { 407 SOCKET s; 408 409 StartSockets(); 410 411 if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET) 412 errno = WSAGetLastError(); 413 else 414 s = OPEN_SOCKET(s); 415 416 return s; 417 } 418 419 /* 420 * close RTL fd while respecting sockets 421 * added as temporary measure until PerlIO has real 422 * Win32 native layer 423 * -- BKS, 11-11-2000 424 */ 425 426 int my_close(int fd) 427 { 428 int osf; 429 if (!wsock_started) /* No WinSock? */ 430 return(close(fd)); /* Then not a socket. */ 431 osf = TO_SOCKET(fd);/* Get it now before it's gone! */ 432 if (osf != -1) { 433 int err; 434 err = closesocket(osf); 435 if (err == 0) { 436 (void)close(fd); /* handle already closed, ignore error */ 437 return 0; 438 } 439 else if (err == SOCKET_ERROR) { 440 err = WSAGetLastError(); 441 if (err != WSAENOTSOCK) { 442 (void)close(fd); 443 errno = err; 444 return EOF; 445 } 446 } 447 } 448 return close(fd); 449 } 450 451 #undef fclose 452 int 453 my_fclose (FILE *pf) 454 { 455 int osf; 456 if (!wsock_started) /* No WinSock? */ 457 return(fclose(pf)); /* Then not a socket. */ 458 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ 459 if (osf != -1) { 460 int err; 461 win32_fflush(pf); 462 err = closesocket(osf); 463 if (err == 0) { 464 (void)fclose(pf); /* handle already closed, ignore error */ 465 return 0; 466 } 467 else if (err == SOCKET_ERROR) { 468 err = WSAGetLastError(); 469 if (err != WSAENOTSOCK) { 470 (void)fclose(pf); 471 errno = err; 472 return EOF; 473 } 474 } 475 } 476 return fclose(pf); 477 } 478 479 struct hostent * 480 win32_gethostbyaddr(const char *addr, int len, int type) 481 { 482 struct hostent *r; 483 484 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); 485 return r; 486 } 487 488 struct hostent * 489 win32_gethostbyname(const char *name) 490 { 491 struct hostent *r; 492 493 SOCKET_TEST(r = gethostbyname(name), NULL); 494 return r; 495 } 496 497 int 498 win32_gethostname(char *name, int len) 499 { 500 int r; 501 502 SOCKET_TEST_ERROR(r = gethostname(name, len)); 503 return r; 504 } 505 506 struct protoent * 507 win32_getprotobyname(const char *name) 508 { 509 struct protoent *r; 510 511 SOCKET_TEST(r = getprotobyname(name), NULL); 512 return r; 513 } 514 515 struct protoent * 516 win32_getprotobynumber(int num) 517 { 518 struct protoent *r; 519 520 SOCKET_TEST(r = getprotobynumber(num), NULL); 521 return r; 522 } 523 524 struct servent * 525 win32_getservbyname(const char *name, const char *proto) 526 { 527 dTHXa(NULL); 528 struct servent *r; 529 530 SOCKET_TEST(r = getservbyname(name, proto), NULL); 531 if (r) { 532 aTHXa(PERL_GET_THX); 533 r = win32_savecopyservent(&w32_servent, r, proto); 534 } 535 return r; 536 } 537 538 struct servent * 539 win32_getservbyport(int port, const char *proto) 540 { 541 dTHXa(NULL); 542 struct servent *r; 543 544 SOCKET_TEST(r = getservbyport(port, proto), NULL); 545 if (r) { 546 aTHXa(PERL_GET_THX); 547 r = win32_savecopyservent(&w32_servent, r, proto); 548 } 549 return r; 550 } 551 552 int 553 win32_ioctl(int i, unsigned int u, char *data) 554 { 555 u_long u_long_arg; 556 int retval; 557 558 if (!wsock_started) { 559 Perl_croak_nocontext("ioctl implemented only on sockets"); 560 /* NOTREACHED */ 561 } 562 563 /* mauke says using memcpy avoids alignment issues */ 564 memcpy(&u_long_arg, data, sizeof u_long_arg); 565 retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); 566 memcpy(data, &u_long_arg, sizeof u_long_arg); 567 568 if (retval == SOCKET_ERROR) { 569 if (WSAGetLastError() == WSAENOTSOCK) { 570 Perl_croak_nocontext("ioctl implemented only on sockets"); 571 /* NOTREACHED */ 572 } 573 errno = WSAGetLastError(); 574 } 575 return retval; 576 } 577 578 char FAR * 579 win32_inet_ntoa(struct in_addr in) 580 { 581 StartSockets(); 582 return inet_ntoa(in); 583 } 584 585 unsigned long 586 win32_inet_addr(const char FAR *cp) 587 { 588 StartSockets(); 589 return inet_addr(cp); 590 } 591 592 /* 593 * Networking stubs 594 */ 595 596 void 597 win32_endhostent() 598 { 599 win32_croak_not_implemented("endhostent"); 600 } 601 602 void 603 win32_endnetent() 604 { 605 win32_croak_not_implemented("endnetent"); 606 } 607 608 void 609 win32_endprotoent() 610 { 611 win32_croak_not_implemented("endprotoent"); 612 } 613 614 void 615 win32_endservent() 616 { 617 win32_croak_not_implemented("endservent"); 618 } 619 620 621 struct netent * 622 win32_getnetent(void) 623 { 624 win32_croak_not_implemented("getnetent"); 625 return (struct netent *) NULL; 626 } 627 628 struct netent * 629 win32_getnetbyname(char *name) 630 { 631 win32_croak_not_implemented("getnetbyname"); 632 return (struct netent *)NULL; 633 } 634 635 struct netent * 636 win32_getnetbyaddr(long net, int type) 637 { 638 win32_croak_not_implemented("getnetbyaddr"); 639 return (struct netent *)NULL; 640 } 641 642 struct protoent * 643 win32_getprotoent(void) 644 { 645 win32_croak_not_implemented("getprotoent"); 646 return (struct protoent *) NULL; 647 } 648 649 struct servent * 650 win32_getservent(void) 651 { 652 win32_croak_not_implemented("getservent"); 653 return (struct servent *) NULL; 654 } 655 656 void 657 win32_sethostent(int stayopen) 658 { 659 win32_croak_not_implemented("sethostent"); 660 } 661 662 663 void 664 win32_setnetent(int stayopen) 665 { 666 win32_croak_not_implemented("setnetent"); 667 } 668 669 670 void 671 win32_setprotoent(int stayopen) 672 { 673 win32_croak_not_implemented("setprotoent"); 674 } 675 676 677 void 678 win32_setservent(int stayopen) 679 { 680 win32_croak_not_implemented("setservent"); 681 } 682 683 static struct servent* 684 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) 685 { 686 d->s_name = s->s_name; 687 d->s_aliases = s->s_aliases; 688 d->s_port = s->s_port; 689 if (s->s_proto && strlen(s->s_proto)) 690 d->s_proto = s->s_proto; 691 else 692 if (proto && strlen(proto)) 693 d->s_proto = (char *)proto; 694 else 695 d->s_proto = "tcp"; 696 697 return d; 698 } 699 700 701