1 /* win32sck.c 2 * 3 * (c) 1995 Microsoft Corporation. All rights reserved. 4 * Developed by hip communications inc., http://info.hip.com/info/ 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 #ifdef USE_SOCKETS_AS_HANDLES 33 # define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) 34 # define TO_SOCKET(x) _get_osfhandle(x) 35 #else 36 # define OPEN_SOCKET(x) (x) 37 # define TO_SOCKET(x) (x) 38 #endif /* USE_SOCKETS_AS_HANDLES */ 39 40 #define StartSockets() \ 41 STMT_START { \ 42 if (!wsock_started) \ 43 start_sockets(); \ 44 } STMT_END 45 46 #define SOCKET_TEST(x, y) \ 47 STMT_START { \ 48 StartSockets(); \ 49 if((x) == (y)) \ 50 errno = WSAGetLastError(); \ 51 } STMT_END 52 53 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) 54 55 static struct servent* win32_savecopyservent(struct servent*d, 56 struct servent*s, 57 const char *proto); 58 59 static int wsock_started = 0; 60 61 EXTERN_C void 62 EndSockets(void) 63 { 64 if (wsock_started) 65 WSACleanup(); 66 } 67 68 void 69 start_sockets(void) 70 { 71 dTHX; 72 unsigned short version; 73 WSADATA retdata; 74 int ret; 75 76 /* 77 * initalize the winsock interface and insure that it is 78 * cleaned up at exit. 79 */ 80 version = 0x2; 81 if(ret = WSAStartup(version, &retdata)) 82 Perl_croak_nocontext("Unable to locate winsock library!\n"); 83 if(retdata.wVersion != version) 84 Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); 85 86 /* atexit((void (*)(void)) EndSockets); */ 87 wsock_started = 1; 88 } 89 90 #ifndef USE_SOCKETS_AS_HANDLES 91 #undef fdopen 92 FILE * 93 my_fdopen(int fd, char *mode) 94 { 95 FILE *fp; 96 char sockbuf[256]; 97 int optlen = sizeof(sockbuf); 98 int retval; 99 100 if (!wsock_started) 101 return(fdopen(fd, mode)); 102 103 retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); 104 if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) { 105 return(fdopen(fd, mode)); 106 } 107 108 /* 109 * If we get here, then fd is actually a socket. 110 */ 111 Newxz(fp, 1, FILE); /* XXX leak, good thing this code isn't used */ 112 if(fp == NULL) { 113 errno = ENOMEM; 114 return NULL; 115 } 116 117 fp->_file = fd; 118 if(*mode == 'r') 119 fp->_flag = _IOREAD; 120 else 121 fp->_flag = _IOWRT; 122 123 return fp; 124 } 125 #endif /* USE_SOCKETS_AS_HANDLES */ 126 127 128 u_long 129 win32_htonl(u_long hostlong) 130 { 131 StartSockets(); 132 return htonl(hostlong); 133 } 134 135 u_short 136 win32_htons(u_short hostshort) 137 { 138 StartSockets(); 139 return htons(hostshort); 140 } 141 142 u_long 143 win32_ntohl(u_long netlong) 144 { 145 StartSockets(); 146 return ntohl(netlong); 147 } 148 149 u_short 150 win32_ntohs(u_short netshort) 151 { 152 StartSockets(); 153 return ntohs(netshort); 154 } 155 156 157 158 SOCKET 159 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) 160 { 161 SOCKET r; 162 163 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); 164 return OPEN_SOCKET(r); 165 } 166 167 int 168 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) 169 { 170 int r; 171 172 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); 173 return r; 174 } 175 176 int 177 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) 178 { 179 int r; 180 181 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); 182 return r; 183 } 184 185 186 int 187 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) 188 { 189 int r; 190 191 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); 192 return r; 193 } 194 195 int 196 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) 197 { 198 int r; 199 200 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); 201 return r; 202 } 203 204 int 205 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) 206 { 207 int r; 208 209 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 210 return r; 211 } 212 213 int 214 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) 215 { 216 int r; 217 218 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); 219 return r; 220 } 221 222 int 223 win32_listen(SOCKET s, int backlog) 224 { 225 int r; 226 227 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); 228 return r; 229 } 230 231 int 232 win32_recv(SOCKET s, char *buf, int len, int flags) 233 { 234 int r; 235 236 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); 237 return r; 238 } 239 240 int 241 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) 242 { 243 int r; 244 int frombufsize = *fromlen; 245 246 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); 247 /* Winsock's recvfrom() only returns a valid 'from' when the socket 248 * is connectionless. Perl expects a valid 'from' for all types 249 * of sockets, so go the extra mile. 250 */ 251 if (r != SOCKET_ERROR && frombufsize == *fromlen) 252 (void)win32_getpeername(s, from, fromlen); 253 return r; 254 } 255 256 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ 257 int 258 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) 259 { 260 int r; 261 #ifdef USE_SOCKETS_AS_HANDLES 262 Perl_fd_set dummy; 263 int i, fd, save_errno = errno; 264 FD_SET nrd, nwr, nex, *prd, *pwr, *pex; 265 266 /* winsock seems incapable of dealing with all three null fd_sets, 267 * so do the (millisecond) sleep as a special case 268 */ 269 if (!(rd || wr || ex)) { 270 if (timeout) 271 Sleep(timeout->tv_sec * 1000 + 272 timeout->tv_usec / 1000); /* do the best we can */ 273 else 274 Sleep(UINT_MAX); 275 return 0; 276 } 277 StartSockets(); 278 PERL_FD_ZERO(&dummy); 279 if (!rd) 280 rd = &dummy, prd = NULL; 281 else 282 prd = &nrd; 283 if (!wr) 284 wr = &dummy, pwr = NULL; 285 else 286 pwr = &nwr; 287 if (!ex) 288 ex = &dummy, pex = NULL; 289 else 290 pex = &nex; 291 292 FD_ZERO(&nrd); 293 FD_ZERO(&nwr); 294 FD_ZERO(&nex); 295 for (i = 0; i < nfds; i++) { 296 fd = TO_SOCKET(i); 297 if (PERL_FD_ISSET(i,rd)) 298 FD_SET((unsigned)fd, &nrd); 299 if (PERL_FD_ISSET(i,wr)) 300 FD_SET((unsigned)fd, &nwr); 301 if (PERL_FD_ISSET(i,ex)) 302 FD_SET((unsigned)fd, &nex); 303 } 304 305 errno = save_errno; 306 SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout)); 307 save_errno = errno; 308 309 for (i = 0; i < nfds; i++) { 310 fd = TO_SOCKET(i); 311 if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd)) 312 PERL_FD_CLR(i,rd); 313 if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr)) 314 PERL_FD_CLR(i,wr); 315 if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex)) 316 PERL_FD_CLR(i,ex); 317 } 318 errno = save_errno; 319 #else 320 SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout)); 321 #endif 322 return r; 323 } 324 325 int 326 win32_send(SOCKET s, const char *buf, int len, int flags) 327 { 328 int r; 329 330 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); 331 return r; 332 } 333 334 int 335 win32_sendto(SOCKET s, const char *buf, int len, int flags, 336 const struct sockaddr *to, int tolen) 337 { 338 int r; 339 340 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); 341 return r; 342 } 343 344 int 345 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) 346 { 347 int r; 348 349 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 350 return r; 351 } 352 353 int 354 win32_shutdown(SOCKET s, int how) 355 { 356 int r; 357 358 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); 359 return r; 360 } 361 362 int 363 win32_closesocket(SOCKET s) 364 { 365 int r; 366 367 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); 368 return r; 369 } 370 371 #ifdef USE_SOCKETS_AS_HANDLES 372 #define WIN32_OPEN_SOCKET(af, type, protocol) open_ifs_socket(af, type, protocol) 373 374 void 375 convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) 376 { 377 Copy(in, out, 1, WSAPROTOCOL_INFOA); 378 wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol)); 379 } 380 381 SOCKET 382 open_ifs_socket(int af, int type, int protocol) 383 { 384 dTHX; 385 char *s; 386 unsigned long proto_buffers_len = 0; 387 int error_code; 388 SOCKET out = INVALID_SOCKET; 389 390 if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s)) 391 return WSASocket(af, type, protocol, NULL, 0, 0); 392 393 if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR 394 && error_code == WSAENOBUFS) 395 { 396 WSAPROTOCOL_INFOW *proto_buffers; 397 int protocols_available = 0; 398 399 Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW), 400 WSAPROTOCOL_INFOW); 401 402 if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, 403 &proto_buffers_len, &error_code)) != SOCKET_ERROR) 404 { 405 int i; 406 for (i = 0; i < protocols_available; i++) 407 { 408 WSAPROTOCOL_INFOA proto_info; 409 410 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily) 411 || (type != proto_buffers[i].iSocketType) 412 || (protocol != 0 && proto_buffers[i].iProtocol != 0 && 413 protocol != proto_buffers[i].iProtocol)) 414 continue; 415 416 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0) 417 continue; 418 419 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info); 420 421 out = WSASocket(af, type, protocol, &proto_info, 0, 0); 422 break; 423 } 424 } 425 426 Safefree(proto_buffers); 427 } 428 429 return out; 430 } 431 432 #else 433 #define WIN32_OPEN_SOCKET(af, type, protocol) socket(af, type, protocol) 434 #endif 435 436 SOCKET 437 win32_socket(int af, int type, int protocol) 438 { 439 SOCKET s; 440 441 #ifndef USE_SOCKETS_AS_HANDLES 442 SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET); 443 #else 444 StartSockets(); 445 446 if((s = WIN32_OPEN_SOCKET(af, type, protocol)) == INVALID_SOCKET) 447 errno = WSAGetLastError(); 448 else 449 s = OPEN_SOCKET(s); 450 #endif /* USE_SOCKETS_AS_HANDLES */ 451 452 return s; 453 } 454 455 /* 456 * close RTL fd while respecting sockets 457 * added as temporary measure until PerlIO has real 458 * Win32 native layer 459 * -- BKS, 11-11-2000 460 */ 461 462 int my_close(int fd) 463 { 464 int osf; 465 if (!wsock_started) /* No WinSock? */ 466 return(close(fd)); /* Then not a socket. */ 467 osf = TO_SOCKET(fd);/* Get it now before it's gone! */ 468 if (osf != -1) { 469 int err; 470 err = closesocket(osf); 471 if (err == 0) { 472 #if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX) 473 _set_osfhnd(fd, INVALID_HANDLE_VALUE); 474 #endif 475 (void)close(fd); /* handle already closed, ignore error */ 476 return 0; 477 } 478 else if (err == SOCKET_ERROR) { 479 err = WSAGetLastError(); 480 if (err != WSAENOTSOCK) { 481 (void)close(fd); 482 errno = err; 483 return EOF; 484 } 485 } 486 } 487 return close(fd); 488 } 489 490 #undef fclose 491 int 492 my_fclose (FILE *pf) 493 { 494 int osf; 495 if (!wsock_started) /* No WinSock? */ 496 return(fclose(pf)); /* Then not a socket. */ 497 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ 498 if (osf != -1) { 499 int err; 500 win32_fflush(pf); 501 err = closesocket(osf); 502 if (err == 0) { 503 #if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX) 504 _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE); 505 #endif 506 (void)fclose(pf); /* handle already closed, ignore error */ 507 return 0; 508 } 509 else if (err == SOCKET_ERROR) { 510 err = WSAGetLastError(); 511 if (err != WSAENOTSOCK) { 512 (void)fclose(pf); 513 errno = err; 514 return EOF; 515 } 516 } 517 } 518 return fclose(pf); 519 } 520 521 #undef fstat 522 int 523 my_fstat(int fd, Stat_t *sbufptr) 524 { 525 /* This fixes a bug in fstat() on Windows 9x. fstat() uses the 526 * GetFileType() win32 syscall, which will fail on Windows 9x. 527 * So if we recognize a socket on Windows 9x, we return the 528 * same results as on Windows NT/2000. 529 * XXX this should be extended further to set S_IFSOCK on 530 * sbufptr->st_mode. 531 */ 532 int osf; 533 if (!wsock_started || IsWinNT()) { 534 #if defined(WIN64) || defined(USE_LARGE_FILES) 535 #if defined(__BORLANDC__) /* buk */ 536 return win32_fstat(fd, sbufptr ); 537 #else 538 return _fstati64(fd, sbufptr); 539 #endif 540 #else 541 return fstat(fd, sbufptr); 542 #endif 543 } 544 545 osf = TO_SOCKET(fd); 546 if (osf != -1) { 547 char sockbuf[256]; 548 int optlen = sizeof(sockbuf); 549 int retval; 550 551 retval = getsockopt((SOCKET)osf, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); 552 if (retval != SOCKET_ERROR || WSAGetLastError() != WSAENOTSOCK) { 553 #if defined(__BORLANDC__)&&(__BORLANDC__<=0x520) 554 sbufptr->st_mode = S_IFIFO; 555 #else 556 sbufptr->st_mode = _S_IFIFO; 557 #endif 558 sbufptr->st_rdev = sbufptr->st_dev = (dev_t)fd; 559 sbufptr->st_nlink = 1; 560 sbufptr->st_uid = sbufptr->st_gid = sbufptr->st_ino = 0; 561 sbufptr->st_atime = sbufptr->st_mtime = sbufptr->st_ctime = 0; 562 sbufptr->st_size = (Off_t)0; 563 return 0; 564 } 565 } 566 #if defined(WIN64) || defined(USE_LARGE_FILES) 567 #if defined(__BORLANDC__) /* buk */ 568 return win32_fstat(fd, sbufptr ); 569 #else 570 return _fstati64(fd, sbufptr); 571 #endif 572 #else 573 return fstat(fd, sbufptr); 574 #endif 575 } 576 577 struct hostent * 578 win32_gethostbyaddr(const char *addr, int len, int type) 579 { 580 struct hostent *r; 581 582 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); 583 return r; 584 } 585 586 struct hostent * 587 win32_gethostbyname(const char *name) 588 { 589 struct hostent *r; 590 591 SOCKET_TEST(r = gethostbyname(name), NULL); 592 return r; 593 } 594 595 int 596 win32_gethostname(char *name, int len) 597 { 598 int r; 599 600 SOCKET_TEST_ERROR(r = gethostname(name, len)); 601 return r; 602 } 603 604 struct protoent * 605 win32_getprotobyname(const char *name) 606 { 607 struct protoent *r; 608 609 SOCKET_TEST(r = getprotobyname(name), NULL); 610 return r; 611 } 612 613 struct protoent * 614 win32_getprotobynumber(int num) 615 { 616 struct protoent *r; 617 618 SOCKET_TEST(r = getprotobynumber(num), NULL); 619 return r; 620 } 621 622 struct servent * 623 win32_getservbyname(const char *name, const char *proto) 624 { 625 dTHX; 626 struct servent *r; 627 628 SOCKET_TEST(r = getservbyname(name, proto), NULL); 629 if (r) { 630 r = win32_savecopyservent(&w32_servent, r, proto); 631 } 632 return r; 633 } 634 635 struct servent * 636 win32_getservbyport(int port, const char *proto) 637 { 638 dTHX; 639 struct servent *r; 640 641 SOCKET_TEST(r = getservbyport(port, proto), NULL); 642 if (r) { 643 r = win32_savecopyservent(&w32_servent, r, proto); 644 } 645 return r; 646 } 647 648 int 649 win32_ioctl(int i, unsigned int u, char *data) 650 { 651 dTHX; 652 u_long u_long_arg; 653 int retval; 654 655 if (!wsock_started) { 656 Perl_croak_nocontext("ioctl implemented only on sockets"); 657 /* NOTREACHED */ 658 } 659 660 /* mauke says using memcpy avoids alignment issues */ 661 memcpy(&u_long_arg, data, sizeof u_long_arg); 662 retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); 663 memcpy(data, &u_long_arg, sizeof u_long_arg); 664 665 if (retval == SOCKET_ERROR) { 666 if (WSAGetLastError() == WSAENOTSOCK) { 667 Perl_croak_nocontext("ioctl implemented only on sockets"); 668 /* NOTREACHED */ 669 } 670 errno = WSAGetLastError(); 671 } 672 return retval; 673 } 674 675 char FAR * 676 win32_inet_ntoa(struct in_addr in) 677 { 678 StartSockets(); 679 return inet_ntoa(in); 680 } 681 682 unsigned long 683 win32_inet_addr(const char FAR *cp) 684 { 685 StartSockets(); 686 return inet_addr(cp); 687 } 688 689 /* 690 * Networking stubs 691 */ 692 693 void 694 win32_endhostent() 695 { 696 dTHX; 697 Perl_croak_nocontext("endhostent not implemented!\n"); 698 } 699 700 void 701 win32_endnetent() 702 { 703 dTHX; 704 Perl_croak_nocontext("endnetent not implemented!\n"); 705 } 706 707 void 708 win32_endprotoent() 709 { 710 dTHX; 711 Perl_croak_nocontext("endprotoent not implemented!\n"); 712 } 713 714 void 715 win32_endservent() 716 { 717 dTHX; 718 Perl_croak_nocontext("endservent not implemented!\n"); 719 } 720 721 722 struct netent * 723 win32_getnetent(void) 724 { 725 dTHX; 726 Perl_croak_nocontext("getnetent not implemented!\n"); 727 return (struct netent *) NULL; 728 } 729 730 struct netent * 731 win32_getnetbyname(char *name) 732 { 733 dTHX; 734 Perl_croak_nocontext("getnetbyname not implemented!\n"); 735 return (struct netent *)NULL; 736 } 737 738 struct netent * 739 win32_getnetbyaddr(long net, int type) 740 { 741 dTHX; 742 Perl_croak_nocontext("getnetbyaddr not implemented!\n"); 743 return (struct netent *)NULL; 744 } 745 746 struct protoent * 747 win32_getprotoent(void) 748 { 749 dTHX; 750 Perl_croak_nocontext("getprotoent not implemented!\n"); 751 return (struct protoent *) NULL; 752 } 753 754 struct servent * 755 win32_getservent(void) 756 { 757 dTHX; 758 Perl_croak_nocontext("getservent not implemented!\n"); 759 return (struct servent *) NULL; 760 } 761 762 void 763 win32_sethostent(int stayopen) 764 { 765 dTHX; 766 Perl_croak_nocontext("sethostent not implemented!\n"); 767 } 768 769 770 void 771 win32_setnetent(int stayopen) 772 { 773 dTHX; 774 Perl_croak_nocontext("setnetent not implemented!\n"); 775 } 776 777 778 void 779 win32_setprotoent(int stayopen) 780 { 781 dTHX; 782 Perl_croak_nocontext("setprotoent not implemented!\n"); 783 } 784 785 786 void 787 win32_setservent(int stayopen) 788 { 789 dTHX; 790 Perl_croak_nocontext("setservent not implemented!\n"); 791 } 792 793 static struct servent* 794 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) 795 { 796 d->s_name = s->s_name; 797 d->s_aliases = s->s_aliases; 798 d->s_port = s->s_port; 799 #ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */ 800 if (!IsWin95() && s->s_proto && strlen(s->s_proto)) 801 d->s_proto = s->s_proto; 802 else 803 #endif 804 if (proto && strlen(proto)) 805 d->s_proto = (char *)proto; 806 else 807 d->s_proto = "tcp"; 808 809 return d; 810 } 811 812 813