This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Clarify a comment in errno2.h
[perl5.git] / win32 / win32sck.c
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 = get_last_socket_error();            \
46     } STMT_END
47
48 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
49
50 static int get_last_socket_error(void);
51 static struct servent* win32_savecopyservent(struct servent*d,
52                                              struct servent*s,
53                                              const char *proto);
54
55 static int wsock_started = 0;
56
57 EXTERN_C void
58 EndSockets(void)
59 {
60     if (wsock_started)
61         WSACleanup();
62 }
63
64 /* Translate WSAExxx values to corresponding Exxx values where possible. Not all
65  * WSAExxx constants have corresponding Exxx constants in <errno.h> (even in
66  * VC++ 2010 and above, which have expanded <errno.h> with more values), but
67  * most missing constants are provided by win32/include/sys/errno2.h. The few
68  * that are not are returned unchanged.
69  *
70  * The list of possible WSAExxx values used here comes from the MSDN page
71  * titled "Windows Sockets Error Codes".
72  *
73  * (Note: Only the WSAExxx values are handled here; other WSAxxx values are
74  * returned unchanged. The return value normally ends up in errno/$! and at
75  * the Perl code level may be tested against the Exxx constants exported by
76  * the Errno and POSIX modules, which have never handled the other WSAxxx
77  * values themselves, apparently without any ill effect so far.)
78  */
79 int
80 convert_wsa_error_to_errno(int wsaerr)
81 {
82     switch (wsaerr) {
83     case WSAEINTR:
84         return EINTR;
85     case WSAEBADF:
86         return EBADF;
87     case WSAEACCES:
88         return EACCES;
89     case WSAEFAULT:
90         return EFAULT;
91     case WSAEINVAL:
92         return EINVAL;
93     case WSAEMFILE:
94         return EMFILE;
95     case WSAEWOULDBLOCK:
96         return EWOULDBLOCK;
97     case WSAEINPROGRESS:
98         return EINPROGRESS;
99     case WSAEALREADY:
100         return EALREADY;
101     case WSAENOTSOCK:
102         return ENOTSOCK;
103     case WSAEDESTADDRREQ:
104         return EDESTADDRREQ;
105     case WSAEMSGSIZE:
106         return EMSGSIZE;
107     case WSAEPROTOTYPE:
108         return EPROTOTYPE;
109     case WSAENOPROTOOPT:
110         return ENOPROTOOPT;
111     case WSAEPROTONOSUPPORT:
112         return EPROTONOSUPPORT;
113     case WSAESOCKTNOSUPPORT:
114         return ESOCKTNOSUPPORT;
115     case WSAEOPNOTSUPP:
116         return EOPNOTSUPP;
117     case WSAEPFNOSUPPORT:
118         return EPFNOSUPPORT;
119     case WSAEAFNOSUPPORT:
120         return EAFNOSUPPORT;
121     case WSAEADDRINUSE:
122         return EADDRINUSE;
123     case WSAEADDRNOTAVAIL:
124         return EADDRNOTAVAIL;
125     case WSAENETDOWN:
126         return ENETDOWN;
127     case WSAENETUNREACH:
128         return ENETUNREACH;
129     case WSAENETRESET:
130         return ENETRESET;
131     case WSAECONNABORTED:
132         return ECONNABORTED;
133     case WSAECONNRESET:
134         return ECONNRESET;
135     case WSAENOBUFS:
136         return ENOBUFS;
137     case WSAEISCONN:
138         return EISCONN;
139     case WSAENOTCONN:
140         return ENOTCONN;
141     case WSAESHUTDOWN:
142         return ESHUTDOWN;
143     case WSAETOOMANYREFS:
144         return ETOOMANYREFS;
145     case WSAETIMEDOUT:
146         return ETIMEDOUT;
147     case WSAECONNREFUSED:
148         return ECONNREFUSED;
149     case WSAELOOP:
150         return ELOOP;
151     case WSAENAMETOOLONG:
152         return ENAMETOOLONG;
153     case WSAEHOSTDOWN:
154         return WSAEHOSTDOWN;            /* EHOSTDOWN is not defined */
155     case WSAEHOSTUNREACH:
156         return EHOSTUNREACH;
157     case WSAENOTEMPTY:
158         return ENOTEMPTY;
159     case WSAEPROCLIM:
160         return EPROCLIM;
161     case WSAEUSERS:
162         return EUSERS;
163     case WSAEDQUOT:
164         return EDQUOT;
165     case WSAESTALE:
166         return ESTALE;
167     case WSAEREMOTE:
168         return EREMOTE;
169     case WSAEDISCON:
170         return WSAEDISCON;              /* EDISCON is not defined */
171     case WSAENOMORE:
172         return WSAENOMORE;              /* ENOMORE is not defined */
173     case WSAECANCELLED:
174         return ECANCELED;
175     case WSAEINVALIDPROCTABLE:
176         return WSAEINVALIDPROCTABLE;    /* EINVALIDPROCTABLE is not defined */
177     case WSAEINVALIDPROVIDER:
178         return WSAEINVALIDPROVIDER;     /* EINVALIDPROVIDER is not defined */
179     case WSAEPROVIDERFAILEDINIT:
180         return WSAEPROVIDERFAILEDINIT;  /* EPROVIDERFAILEDINIT is not defined */
181     case WSAEREFUSED:
182         return WSAEREFUSED;             /* EREFUSED is not defined */
183     }
184
185     return wsaerr;
186 }
187
188 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
189 /* Translate Exxx values in the POSIX supplement range defined in VC++ 2010 and
190  * above (EADDRINUSE <= err <= EWOULDBLOCK) to corresponding WSAExxx values. Not
191  * all such Exxx constants have corresponding WSAExxx constants in <winsock2.h>;
192  * we just use ERROR_INVALID_FUNCTION for those that are missing but do not
193  * really expect to encounter them anyway in the context in which this function
194  * is called.
195  * Other Exxx values (err < sys_nerr) are returned unchanged.
196  */
197 int
198 convert_errno_to_wsa_error(int err)
199 {
200     switch (err) {
201     case EADDRINUSE:
202         return WSAEADDRINUSE;
203     case EADDRNOTAVAIL:
204         return WSAEADDRNOTAVAIL;
205     case EAFNOSUPPORT:
206         return WSAEAFNOSUPPORT;
207     case EALREADY:
208         return WSAEALREADY;
209     case EBADMSG:
210         return ERROR_INVALID_FUNCTION;
211     case ECANCELED:
212         return WSAECANCELLED;
213     case ECONNABORTED:
214         return WSAECONNABORTED;
215     case ECONNREFUSED:
216         return WSAECONNREFUSED;
217     case ECONNRESET:
218         return WSAECONNRESET;
219     case EDESTADDRREQ:
220         return WSAEDESTADDRREQ;
221     case EHOSTUNREACH:
222         return WSAEHOSTUNREACH;
223     case EIDRM:
224         return ERROR_INVALID_FUNCTION;
225     case EINPROGRESS:
226         return WSAEINPROGRESS;
227     case EISCONN:
228         return WSAEISCONN;
229     case ELOOP:
230         return WSAELOOP;
231     case EMSGSIZE:
232         return WSAEMSGSIZE;
233     case ENETDOWN:
234         return WSAENETDOWN;
235     case ENETRESET:
236         return WSAENETRESET;
237     case ENETUNREACH:
238         return WSAENETUNREACH;
239     case ENOBUFS:
240         return WSAENOBUFS;
241     case ENODATA:
242         return ERROR_INVALID_FUNCTION;
243     case ENOLINK:
244         return ERROR_INVALID_FUNCTION;
245     case ENOMSG:
246         return ERROR_INVALID_FUNCTION;
247     case ENOPROTOOPT:
248         return WSAENOPROTOOPT;
249     case ENOSR:
250         return ERROR_INVALID_FUNCTION;
251     case ENOSTR:
252         return ERROR_INVALID_FUNCTION;
253     case ENOTCONN:
254         return WSAENOTCONN;
255     case ENOTRECOVERABLE:
256         return ERROR_INVALID_FUNCTION;
257     case ENOTSOCK:
258         return WSAENOTSOCK;
259     case ENOTSUP:
260         return ERROR_INVALID_FUNCTION;
261     case EOPNOTSUPP:
262         return WSAEOPNOTSUPP;
263     case EOTHER:
264         return ERROR_INVALID_FUNCTION;
265     case EOVERFLOW:
266         return ERROR_INVALID_FUNCTION;
267     case EOWNERDEAD:
268         return ERROR_INVALID_FUNCTION;
269     case EPROTO:
270         return ERROR_INVALID_FUNCTION;
271     case EPROTONOSUPPORT:
272         return WSAEPROTONOSUPPORT;
273     case EPROTOTYPE:
274         return WSAEPROTOTYPE;
275     case ETIME:
276         return ERROR_INVALID_FUNCTION;
277     case ETIMEDOUT:
278         return WSAETIMEDOUT;
279     case ETXTBSY:
280         return ERROR_INVALID_FUNCTION;
281     case EWOULDBLOCK:
282         return WSAEWOULDBLOCK;
283     }
284
285     return err;
286 }
287 #endif /* ERRNO_HAS_POSIX_SUPPLEMENT */
288
289 static int
290 get_last_socket_error(void)
291 {
292     return convert_wsa_error_to_errno(WSAGetLastError());
293 }
294
295 void
296 start_sockets(void) 
297 {
298     unsigned short version;
299     WSADATA retdata;
300     int ret;
301
302     /*
303      * initalize the winsock interface and insure that it is
304      * cleaned up at exit.
305      */
306     version = 0x2;
307     if(ret = WSAStartup(version, &retdata))
308         Perl_croak_nocontext("Unable to locate winsock library!\n");
309     if(retdata.wVersion != version)
310         Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n");
311
312     /* atexit((void (*)(void)) EndSockets); */
313     wsock_started = 1;
314 }
315
316 /* in no sockets Win32 builds, these use the inline functions defined in
317  * perl.h
318  */
319 u_long
320 win32_htonl(u_long hostlong)
321 {
322 #ifndef WIN32_NO_SOCKETS
323     StartSockets();
324 #endif
325     return htonl(hostlong);
326 }
327
328 u_short
329 win32_htons(u_short hostshort)
330 {
331 #ifndef WIN32_NO_SOCKETS
332     StartSockets();
333 #endif
334     return htons(hostshort);
335 }
336
337 u_long
338 win32_ntohl(u_long netlong)
339 {
340 #ifndef WIN32_NO_SOCKETS
341     StartSockets();
342 #endif
343     return ntohl(netlong);
344 }
345
346 u_short
347 win32_ntohs(u_short netshort)
348 {
349 #ifndef WIN32_NO_SOCKETS
350     StartSockets();
351 #endif
352     return ntohs(netshort);
353 }
354
355
356
357 SOCKET
358 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
359 {
360     SOCKET r;
361
362     SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
363     return OPEN_SOCKET(r);
364 }
365
366 int
367 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
368 {
369     int r;
370
371     SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
372     return r;
373 }
374
375 int
376 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
377 {
378     int r;
379
380     SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
381     return r;
382 }
383
384
385 int
386 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
387 {
388     int r;
389
390     SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
391     return r;
392 }
393
394 int
395 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
396 {
397     int r;
398
399     SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
400     return r;
401 }
402
403 int
404 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
405 {
406     int r;
407
408     SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
409     return r;
410 }
411
412 int
413 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
414 {
415     int r;
416
417     SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
418     return r;
419 }
420
421 int
422 win32_listen(SOCKET s, int backlog)
423 {
424     int r;
425
426     SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
427     return r;
428 }
429
430 int
431 win32_recv(SOCKET s, char *buf, int len, int flags)
432 {
433     int r;
434
435     SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
436     return r;
437 }
438
439 int
440 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
441 {
442     int r;
443     int frombufsize = *fromlen;
444
445     SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
446     /* Winsock's recvfrom() only returns a valid 'from' when the socket
447      * is connectionless.  Perl expects a valid 'from' for all types
448      * of sockets, so go the extra mile.
449      */
450     if (r != SOCKET_ERROR && frombufsize == *fromlen)
451         (void)win32_getpeername(s, from, fromlen);
452     return r;
453 }
454
455 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
456 int
457 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
458 {
459     int r;
460     int i, fd, save_errno = errno;
461     FD_SET nrd, nwr, nex;
462     bool just_sleep = TRUE;
463
464     StartSockets();
465
466     FD_ZERO(&nrd);
467     FD_ZERO(&nwr);
468     FD_ZERO(&nex);
469     for (i = 0; i < nfds; i++) {
470         if (rd && PERL_FD_ISSET(i,rd)) {
471             fd = TO_SOCKET(i);
472             FD_SET((unsigned)fd, &nrd);
473             just_sleep = FALSE;
474         }
475         if (wr && PERL_FD_ISSET(i,wr)) {
476             fd = TO_SOCKET(i);
477             FD_SET((unsigned)fd, &nwr);
478             just_sleep = FALSE;
479         }
480         if (ex && PERL_FD_ISSET(i,ex)) {
481             fd = TO_SOCKET(i);
482             FD_SET((unsigned)fd, &nex);
483             just_sleep = FALSE;
484         }
485     }
486
487     /* winsock seems incapable of dealing with all three fd_sets being empty,
488      * so do the (millisecond) sleep as a special case
489      */
490     if (just_sleep) {
491         if (timeout)
492             Sleep(timeout->tv_sec  * 1000 +
493                   timeout->tv_usec / 1000);     /* do the best we can */
494         else
495             Sleep(UINT_MAX);
496         return 0;
497     }
498
499     errno = save_errno;
500     SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, timeout));
501     save_errno = errno;
502
503     for (i = 0; i < nfds; i++) {
504         if (rd && PERL_FD_ISSET(i,rd)) {
505             fd = TO_SOCKET(i);
506             if (!FD_ISSET(fd, &nrd))
507                 PERL_FD_CLR(i,rd);
508         }
509         if (wr && PERL_FD_ISSET(i,wr)) {
510             fd = TO_SOCKET(i);
511             if (!FD_ISSET(fd, &nwr))
512                 PERL_FD_CLR(i,wr);
513         }
514         if (ex && PERL_FD_ISSET(i,ex)) {
515             fd = TO_SOCKET(i);
516             if (!FD_ISSET(fd, &nex))
517                 PERL_FD_CLR(i,ex);
518         }
519     }
520     errno = save_errno;
521     return r;
522 }
523
524 int
525 win32_send(SOCKET s, const char *buf, int len, int flags)
526 {
527     int r;
528
529     SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
530     return r;
531 }
532
533 int
534 win32_sendto(SOCKET s, const char *buf, int len, int flags,
535              const struct sockaddr *to, int tolen)
536 {
537     int r;
538
539     SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
540     return r;
541 }
542
543 int
544 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
545 {
546     int r;
547
548     SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
549     return r;
550 }
551     
552 int
553 win32_shutdown(SOCKET s, int how)
554 {
555     int r;
556
557     SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
558     return r;
559 }
560
561 int
562 win32_closesocket(SOCKET s)
563 {
564     int r;
565
566     SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
567     return r;
568 }
569
570 void
571 convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out)
572 {
573     Copy(in, out, 1, WSAPROTOCOL_INFOA);
574     wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol));
575 }
576
577 SOCKET
578 open_ifs_socket(int af, int type, int protocol)
579 {
580     dTHX;
581     char *s;
582     unsigned long proto_buffers_len = 0;
583     int error_code;
584     SOCKET out = INVALID_SOCKET;
585
586     if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s))
587         return WSASocket(af, type, protocol, NULL, 0, 0);
588
589     if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
590         && error_code == WSAENOBUFS)
591     {
592         WSAPROTOCOL_INFOW *proto_buffers;
593         int protocols_available = 0;       
594  
595         Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW),
596             WSAPROTOCOL_INFOW);
597
598         if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, 
599             &proto_buffers_len, &error_code)) != SOCKET_ERROR)
600         {
601             int i;
602             for (i = 0; i < protocols_available; i++)
603             {
604                 WSAPROTOCOL_INFOA proto_info;
605
606                 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily)
607                     || (type != proto_buffers[i].iSocketType)
608                     || (protocol != 0 && proto_buffers[i].iProtocol != 0 &&
609                         protocol != proto_buffers[i].iProtocol))
610                     continue;
611
612                 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
613                     continue;
614
615                 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info);
616
617                 out = WSASocket(af, type, protocol, &proto_info, 0, 0);
618                 break;
619             }
620         }
621
622         Safefree(proto_buffers);
623     }
624
625     return out;
626 }
627
628 SOCKET
629 win32_socket(int af, int type, int protocol)
630 {
631     SOCKET s;
632
633     StartSockets();
634
635     if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET)
636         errno = get_last_socket_error();
637     else
638         s = OPEN_SOCKET(s);
639
640     return s;
641 }
642
643 /*
644  * close RTL fd while respecting sockets
645  * added as temporary measure until PerlIO has real
646  * Win32 native layer
647  *   -- BKS, 11-11-2000
648 */
649
650 int my_close(int fd)
651 {
652     int osf;
653     if (!wsock_started)         /* No WinSock? */
654         return(close(fd));      /* Then not a socket. */
655     osf = TO_SOCKET(fd);/* Get it now before it's gone! */
656     if (osf != -1) {
657         int err;
658         err = closesocket(osf);
659         if (err == 0) {
660             (void)close(fd);    /* handle already closed, ignore error */
661             return 0;
662         }
663         else if (err == SOCKET_ERROR) {
664             err = get_last_socket_error();
665             if (err != ENOTSOCK) {
666                 (void)close(fd);
667                 errno = err;
668                 return EOF;
669             }
670         }
671     }
672     return close(fd);
673 }
674
675 #undef fclose
676 int
677 my_fclose (FILE *pf)
678 {
679     int osf;
680     if (!wsock_started)         /* No WinSock? */
681         return(fclose(pf));     /* Then not a socket. */
682     osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */
683     if (osf != -1) {
684         int err;
685         win32_fflush(pf);
686         err = closesocket(osf);
687         if (err == 0) {
688             (void)fclose(pf);   /* handle already closed, ignore error */
689             return 0;
690         }
691         else if (err == SOCKET_ERROR) {
692             err = get_last_socket_error();
693             if (err != ENOTSOCK) {
694                 (void)fclose(pf);
695                 errno = err;
696                 return EOF;
697             }
698         }
699     }
700     return fclose(pf);
701 }
702
703 struct hostent *
704 win32_gethostbyaddr(const char *addr, int len, int type)
705 {
706     struct hostent *r;
707
708     SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
709     return r;
710 }
711
712 struct hostent *
713 win32_gethostbyname(const char *name)
714 {
715     struct hostent *r;
716
717     SOCKET_TEST(r = gethostbyname(name), NULL);
718     return r;
719 }
720
721 int
722 win32_gethostname(char *name, int len)
723 {
724     int r;
725
726     SOCKET_TEST_ERROR(r = gethostname(name, len));
727     return r;
728 }
729
730 struct protoent *
731 win32_getprotobyname(const char *name)
732 {
733     struct protoent *r;
734
735     SOCKET_TEST(r = getprotobyname(name), NULL);
736     return r;
737 }
738
739 struct protoent *
740 win32_getprotobynumber(int num)
741 {
742     struct protoent *r;
743
744     SOCKET_TEST(r = getprotobynumber(num), NULL);
745     return r;
746 }
747
748 struct servent *
749 win32_getservbyname(const char *name, const char *proto)
750 {
751     dTHXa(NULL);    
752     struct servent *r;
753
754     SOCKET_TEST(r = getservbyname(name, proto), NULL);
755     if (r) {
756         aTHXa(PERL_GET_THX);
757         r = win32_savecopyservent(&w32_servent, r, proto);
758     }
759     return r;
760 }
761
762 struct servent *
763 win32_getservbyport(int port, const char *proto)
764 {
765     dTHXa(NULL); 
766     struct servent *r;
767
768     SOCKET_TEST(r = getservbyport(port, proto), NULL);
769     if (r) {
770         aTHXa(PERL_GET_THX);
771         r = win32_savecopyservent(&w32_servent, r, proto);
772     }
773     return r;
774 }
775
776 int
777 win32_ioctl(int i, unsigned int u, char *data)
778 {
779     u_long u_long_arg; 
780     int retval;
781     
782     if (!wsock_started) {
783         Perl_croak_nocontext("ioctl implemented only on sockets");
784         /* NOTREACHED */
785     }
786
787     /* mauke says using memcpy avoids alignment issues */
788     memcpy(&u_long_arg, data, sizeof u_long_arg); 
789     retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg);
790     memcpy(data, &u_long_arg, sizeof u_long_arg);
791     
792     if (retval == SOCKET_ERROR) {
793         int err = get_last_socket_error();
794         if (err == ENOTSOCK) {
795             Perl_croak_nocontext("ioctl implemented only on sockets");
796             /* NOTREACHED */
797         }
798         errno = err;
799     }
800     return retval;
801 }
802
803 char FAR *
804 win32_inet_ntoa(struct in_addr in)
805 {
806     StartSockets();
807     return inet_ntoa(in);
808 }
809
810 unsigned long
811 win32_inet_addr(const char FAR *cp)
812 {
813     StartSockets();
814     return inet_addr(cp);
815 }
816
817 /*
818  * Networking stubs
819  */
820
821 void
822 win32_endhostent() 
823 {
824     win32_croak_not_implemented("endhostent");
825 }
826
827 void
828 win32_endnetent()
829 {
830     win32_croak_not_implemented("endnetent");
831 }
832
833 void
834 win32_endprotoent()
835 {
836     win32_croak_not_implemented("endprotoent");
837 }
838
839 void
840 win32_endservent()
841 {
842     win32_croak_not_implemented("endservent");
843 }
844
845
846 struct netent *
847 win32_getnetent(void) 
848 {
849     win32_croak_not_implemented("getnetent");
850     return (struct netent *) NULL;
851 }
852
853 struct netent *
854 win32_getnetbyname(char *name) 
855 {
856     win32_croak_not_implemented("getnetbyname");
857     return (struct netent *)NULL;
858 }
859
860 struct netent *
861 win32_getnetbyaddr(long net, int type) 
862 {
863     win32_croak_not_implemented("getnetbyaddr");
864     return (struct netent *)NULL;
865 }
866
867 struct protoent *
868 win32_getprotoent(void) 
869 {
870     win32_croak_not_implemented("getprotoent");
871     return (struct protoent *) NULL;
872 }
873
874 struct servent *
875 win32_getservent(void) 
876 {
877     win32_croak_not_implemented("getservent");
878     return (struct servent *) NULL;
879 }
880
881 void
882 win32_sethostent(int stayopen)
883 {
884     win32_croak_not_implemented("sethostent");
885 }
886
887
888 void
889 win32_setnetent(int stayopen)
890 {
891     win32_croak_not_implemented("setnetent");
892 }
893
894
895 void
896 win32_setprotoent(int stayopen)
897 {
898     win32_croak_not_implemented("setprotoent");
899 }
900
901
902 void
903 win32_setservent(int stayopen)
904 {
905     win32_croak_not_implemented("setservent");
906 }
907
908 static struct servent*
909 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
910 {
911     d->s_name = s->s_name;
912     d->s_aliases = s->s_aliases;
913     d->s_port = s->s_port;
914     if (s->s_proto && strlen(s->s_proto))
915         d->s_proto = s->s_proto;
916     else
917     if (proto && strlen(proto))
918         d->s_proto = (char *)proto;
919     else
920         d->s_proto = "tcp";
921    
922     return d;
923 }
924
925