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