Mopup for #6207 and #6209.
[p5sagit/p5-mst-13.2.git] / win32 / win32sck.c
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 #ifdef __GNUC__
15 #define Win32_Winsock
16 #endif
17 #include <windows.h>
18 #include "EXTERN.h"
19 #include "perl.h"
20
21 #if defined(PERL_OBJECT)
22 #define NO_XSLOCKS
23 #include "XSUB.h"
24 #endif
25
26 #include "Win32iop.h"
27 #include <sys/socket.h>
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #ifndef __MINGW32__
31 #include <assert.h>
32 #endif
33 #include <io.h>
34
35 /* thanks to Beverly Brown      (beverly@datacube.com) */
36 #ifdef USE_SOCKETS_AS_HANDLES
37 #       define OPEN_SOCKET(x)   win32_open_osfhandle(x,O_RDWR|O_BINARY)
38 #       define TO_SOCKET(x)     _get_osfhandle(x)
39 #else
40 #       define OPEN_SOCKET(x)   (x)
41 #       define TO_SOCKET(x)     (x)
42 #endif  /* USE_SOCKETS_AS_HANDLES */
43
44 #if defined(USE_THREADS) || defined(USE_ITHREADS)
45 #define StartSockets() \
46     STMT_START {                                        \
47         if (!wsock_started)                             \
48             start_sockets();                            \
49        set_socktype();                         \
50     } STMT_END
51 #else
52 #define StartSockets() \
53     STMT_START {                                        \
54         if (!wsock_started) {                           \
55             start_sockets();                            \
56             set_socktype();                             \
57         }                                               \
58     } STMT_END
59 #endif
60
61 #define SOCKET_TEST(x, y) \
62     STMT_START {                                        \
63         StartSockets();                                 \
64         if((x) == (y))                                  \
65             errno = CALL(WSAGetLastError)();                    \
66     } STMT_END
67
68 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
69
70 static struct servent* win32_savecopyservent(struct servent*d,
71                                              struct servent*s,
72                                              const char *proto);
73
74 static int wsock_started = 0;
75
76 #ifdef PERL_WIN32_SOCK_DLOAD /* we load the socket libraries when needed -- BKS 5-29-2000 */
77 #define CALL(x) (*p ## x)
78 typedef SOCKET (PASCAL *Paccept)(SOCKET,struct sockaddr*,int*);
79 typedef int (PASCAL *Pbind)(SOCKET,const struct sockaddr*,int);
80 typedef int (PASCAL *Pclosesocket)(SOCKET);
81 typedef int (PASCAL *Pconnect)(SOCKET,const struct sockaddr*,int);
82 typedef int (PASCAL *Pioctlsocket)(SOCKET,long,u_long *);
83 typedef int (PASCAL *Pgetpeername)(SOCKET,struct sockaddr*,int*);
84 typedef int (PASCAL *Pgetsockname)(SOCKET,struct sockaddr*,int*);
85 typedef int (PASCAL *Pgetsockopt)(SOCKET,int,int,char*,int*);
86 typedef unsigned long (PASCAL *Pinet_addr)(const char*);
87 typedef char * (PASCAL *Pinet_ntoa)(struct in_addr);
88 typedef int (PASCAL *Plisten)(SOCKET,int);
89 typedef int (PASCAL *Precv)(SOCKET,char*,int,int);
90 typedef int (PASCAL *Precvfrom)(SOCKET,char*,int,int,struct sockaddr*,int*);
91 typedef int (PASCAL *Psend)(SOCKET,const char*,int,int);
92 typedef int (PASCAL *Psendto)(SOCKET,const char*,int,int,const struct sockaddr*,int);
93 typedef int (PASCAL *Psetsockopt)(SOCKET,int,int,const char*,int);
94 typedef int (PASCAL *Pshutdown)(SOCKET,int);
95 typedef SOCKET (PASCAL *Psocket)(int,int,int);
96 typedef struct hostent* (PASCAL *Pgethostbyaddr)(const char*,int,int);
97 typedef struct hostent* (PASCAL *Pgethostbyname)(const char*);
98 typedef struct servent* (PASCAL *Pgetservbyport)(int,const char*);
99 typedef struct servent* (PASCAL *Pgetservbyname)(const char*,const char*);
100 typedef struct protoent* (PASCAL *Pgetprotobynumber)(int);
101 typedef struct protoent* (PASCAL *Pgetprotobyname)(const char*);
102 typedef int (PASCAL *PWSACleanup)(void);
103 typedef int (PASCAL *PWSAStartup)(unsigned short, WSADATA*);
104 typedef void (PASCAL *PWSASetLastError)(int);
105 typedef int (PASCAL *PWSAGetLastError)(void);
106 typedef int (PASCAL *P__WSAFDIsSet)(SOCKET,fd_set*);
107 typedef int (PASCAL *Pselect)(int nfds,fd_set*,fd_set*,fd_set*,const struct timeval*);
108 typedef int (PASCAL *Pgethostname)(char*,int);
109 typedef u_long (PASCAL *Phtonl)(u_long), (PASCAL *Pntohl)(u_long);
110 typedef u_short (PASCAL *Phtons)(u_short), (PASCAL *Pntohs)(u_short);
111 static Paccept          paccept;
112 static Pbind            pbind;
113 static Pclosesocket     pclosesocket;
114 static Pconnect         pconnect;
115 static Pioctlsocket     pioctlsocket;
116 static Pgetpeername     pgetpeername;
117 static Pgetsockname     pgetsockname;
118 static Pgetsockopt      pgetsockopt;
119 static Pinet_addr       pinet_addr;
120 static Pinet_ntoa       pinet_ntoa;
121 static Plisten          plisten;
122 static Precv            precv;
123 static Precvfrom        precvfrom;
124 static Psend            psend;
125 static Psendto          psendto;
126 static Psetsockopt      psetsockopt;
127 static Pshutdown        pshutdown;
128 static Psocket          psocket;
129 static Pgethostbyaddr   pgethostbyaddr;
130 static Pgethostbyname   pgethostbyname;
131 static Pgetservbyport   pgetservbyport;
132 static Pgetservbyname   pgetservbyname;
133 static Pgetprotobynumber pgetprotobynumber;
134 static Pgetprotobyname  pgetprotobyname;
135 static PWSAStartup      pWSAStartup;
136 static PWSACleanup      pWSACleanup;
137 static PWSASetLastError pWSASetLastError;
138 static PWSAGetLastError pWSAGetLastError;
139 static P__WSAFDIsSet    p__WSAFDIsSet;
140 static Pselect          pselect;
141 static Pgethostname     pgethostname;
142 #if BYTEORDER != 0x1234
143 static Phtons           phtons;
144 static Pntohs           pntohs;
145 static Phtonl           phtonl;
146 static Pntohl           pntohl;
147 #endif
148 void end_sockets(pTHXo_ void *ptr)
149 {
150     CALL(WSACleanup)();
151     wsock_started = 0;
152     FreeLibrary(ptr);
153 }
154 #else
155 #define CALL(x) x
156 #endif /* PERL_WIN32_SOCK_DLOAD */
157 void
158 start_sockets(void) 
159 {
160     dTHXo;
161     unsigned short version;
162     WSADATA retdata;
163     int ret;
164 #ifdef PERL_WIN32_SOCK_DLOAD
165     HANDLE hDll = LoadLibraryA("wsock32.dll");
166
167     /*
168      * initalize the winsock interface and insure that it is
169      * cleaned up at exit.
170      * Also, only load the DLL when needed -- BKS, 4-2-2000
171      */
172     if (!(hDll &&
173         (paccept = (Paccept)GetProcAddress(hDll, "accept")) &&
174         (pbind = (Pbind)GetProcAddress(hDll, "bind")) &&
175         (pclosesocket = (Pclosesocket)GetProcAddress(hDll, "closesocket")) &&
176         (pconnect = (Pconnect)GetProcAddress(hDll, "connect")) &&
177         (pioctlsocket = (Pioctlsocket)GetProcAddress(hDll, "ioctlsocket")) &&
178         (pgetpeername = (Pgetpeername)GetProcAddress(hDll, "getpeername")) &&
179         (pgetsockname = (Pgetsockname)GetProcAddress(hDll, "getsockname")) &&
180         (pgetsockopt = (Pgetsockopt)GetProcAddress(hDll, "getsockopt")) &&
181         (pinet_addr = (Pinet_addr)GetProcAddress(hDll, "inet_addr")) &&
182         (pinet_ntoa = (Pinet_ntoa)GetProcAddress(hDll, "inet_ntoa")) &&
183         (plisten = (Plisten)GetProcAddress(hDll, "listen")) &&
184         (precv = (Precv)GetProcAddress(hDll, "recv")) &&
185         (precvfrom = (Precvfrom)GetProcAddress(hDll, "recvfrom")) &&
186         (psend = (Psend)GetProcAddress(hDll, "send")) &&
187         (psendto = (Psendto)GetProcAddress(hDll, "sendto")) &&
188         (psetsockopt = (Psetsockopt)GetProcAddress(hDll, "setsockopt")) &&
189         (pshutdown = (Pshutdown)GetProcAddress(hDll, "shutdown")) &&
190         (psocket = (Psocket)GetProcAddress(hDll, "socket")) &&
191         (pgethostbyaddr = (Pgethostbyaddr)GetProcAddress(hDll, "gethostbyaddr")) &&
192         (pgethostbyname = (Pgethostbyname)GetProcAddress(hDll, "gethostbyname")) &&
193         (pgetservbyport = (Pgetservbyport)GetProcAddress(hDll, "getservbyport")) &&
194         (pgetservbyname = (Pgetservbyname)GetProcAddress(hDll, "getservbyname")) &&
195         (pgetprotobynumber = (Pgetprotobynumber)GetProcAddress(hDll, "getprotobynumber")) &&
196         (pgetprotobyname = (Pgetprotobyname)GetProcAddress(hDll, "getprotobyname")) &&
197         (pWSAStartup = (PWSAStartup)GetProcAddress(hDll, "WSAStartup")) &&
198         (pWSACleanup = (PWSACleanup)GetProcAddress(hDll, "WSACleanup")) &&
199         (pWSASetLastError = (PWSASetLastError)GetProcAddress(hDll, "WSASetLastError")) &&
200         (pWSAGetLastError = (PWSAGetLastError)GetProcAddress(hDll, "WSAGetLastError")) &&
201         (p__WSAFDIsSet = (P__WSAFDIsSet)GetProcAddress(hDll, "__WSAFDIsSet")) &&
202         (pselect = (Pselect)GetProcAddress(hDll, "select")) &&
203         (pgethostname = (Pgethostname)GetProcAddress(hDll, "gethostname")) &&
204 #if BYTEORDER != 0x1234
205         (phtonl = (Phtonl)GetProcAddress(hDll, "htonl")) &&
206         (pntohl = (Pntohl)GetProcAddress(hDll, "ntohl")) &&
207         (phtons = (Pntohs)GetProcAddress(hDll, "htons")) &&
208         (pntohs = (Pntohs)GetProcAddress(hDll, "ntohs")
209 #else
210         1
211 #endif
212     )) {
213         Perl_croak(aTHX_ "Unable to load winsock library!\n");
214     }
215 #endif /* PERL_WIN32_SOCK_DLOAD */
216     version = 0x101;
217     if(ret = CALL(WSAStartup)(version, &retdata))
218         Perl_croak(aTHX_ "Unable to initialize winsock library!\n");
219     if(retdata.wVersion != version)
220         Perl_croak(aTHX_ "Could not find version 1.1 of winsock dll\n");
221
222 #ifdef PERL_WIN32_SOCK_DLOAD
223     call_atexit(end_sockets, hDll);
224 #endif
225     wsock_started = 1;
226 }
227
228 void
229 set_socktype(void)
230 {
231 #ifdef USE_SOCKETS_AS_HANDLES
232 #ifdef USE_THREADS
233     dTHX;
234     if (!w32_init_socktype) {
235 #endif
236         int iSockOpt = SO_SYNCHRONOUS_NONALERT;
237         /*
238          * Enable the use of sockets as filehandles
239          */
240         CALL(setsockopt)(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
241                     (char *)&iSockOpt, sizeof(iSockOpt));
242 #ifdef USE_THREADS
243         w32_init_socktype = 1;
244     }
245 #endif
246 #endif  /* USE_SOCKETS_AS_HANDLES */
247 }
248
249
250 #ifndef USE_SOCKETS_AS_HANDLES
251 #undef fdopen
252 FILE *
253 my_fdopen(int fd, char *mode)
254 {
255     FILE *fp;
256     char sockbuf[256];
257     int optlen = sizeof(sockbuf);
258     int retval;
259
260     if (!wsock_started)
261         return(fdopen(fd, mode));
262
263     retval = CALL(getsockopt)((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
264     if(retval == SOCKET_ERROR && CALL(WSAGetLastError)() == WSAENOTSOCK) {
265         return(fdopen(fd, mode));
266     }
267
268     /*
269      * If we get here, then fd is actually a socket.
270      */
271     Newz(1310, fp, 1, FILE);
272     if(fp == NULL) {
273         errno = ENOMEM;
274         return NULL;
275     }
276
277     fp->_file = fd;
278     if(*mode == 'r')
279         fp->_flag = _IOREAD;
280     else
281         fp->_flag = _IOWRT;
282    
283     return fp;
284 }
285 #endif  /* USE_SOCKETS_AS_HANDLES */
286
287 /* ntoh* and hton* are implemented here so that ByteLoader doesn't need to load WinSock;
288    these functions are simply copied from util.c */
289
290 u_long
291 win32_htonl(u_long l)
292 {
293 #if BYTEORDER == 0x1234
294     union { u_long r; char c[4]; } u;
295     u.c[0] = (l >> 24) & 255;
296     u.c[1] = (l >> 16) & 255;
297     u.c[2] = (l >> 8) & 255;
298     u.c[3] = l & 255;
299     return u.r;
300 #else
301     StartSockets();
302     return CALL(htonl)(l);
303 #endif
304 }
305
306 u_short
307 win32_htons(u_short s)
308 {
309 #if BYTEORDER == 0x1234
310     return (((s >> 8) & 255) | ((s & 255) << 8));
311 #else
312     StartSockets();
313     return CALL(htons)(s);
314 #endif
315 }
316
317 u_long
318 win32_ntohl(u_long l)
319 {
320 #if BYTEORDER == 0x1234
321     union { u_long r; char c[4]; } u;
322     u.c[0] = (l >> 24) & 255;
323     u.c[1] = (l >> 16) & 255;
324     u.c[2] = (l >> 8) & 255;
325     u.c[3] = l & 255;
326     return u.r;
327 #else
328     StartSockets();
329     return CALL(ntohl)(l);
330 #endif
331 }
332
333 u_short
334 win32_ntohs(u_short s)
335 {
336 #if BYTEORDER == 0x1234
337     return (((s >> 8) & 255) | ((s & 255) << 8));
338 #else
339     StartSockets();
340     return CALL(ntohs)(s);
341 #endif
342 }
343
344
345
346 SOCKET
347 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
348 {
349     SOCKET r;
350
351     SOCKET_TEST((r = CALL(accept)(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
352     return OPEN_SOCKET(r);
353 }
354
355 int
356 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
357 {
358     int r;
359
360     SOCKET_TEST_ERROR(r = CALL(bind)(TO_SOCKET(s), addr, addrlen));
361     return r;
362 }
363
364 int
365 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
366 {
367     int r;
368
369     SOCKET_TEST_ERROR(r = CALL(connect)(TO_SOCKET(s), addr, addrlen));
370     return r;
371 }
372
373
374 int
375 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
376 {
377     int r;
378
379     SOCKET_TEST_ERROR(r = CALL(getpeername)(TO_SOCKET(s), addr, addrlen));
380     return r;
381 }
382
383 int
384 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
385 {
386     int r;
387
388     SOCKET_TEST_ERROR(r = CALL(getsockname)(TO_SOCKET(s), addr, addrlen));
389     return r;
390 }
391
392 int
393 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
394 {
395     int r;
396
397     SOCKET_TEST_ERROR(r = CALL(getsockopt)(TO_SOCKET(s), level, optname, optval, optlen));
398     return r;
399 }
400
401 int
402 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
403 {
404     int r;
405
406     SOCKET_TEST_ERROR(r = CALL(ioctlsocket)(TO_SOCKET(s), cmd, argp));
407     return r;
408 }
409
410 int
411 win32_listen(SOCKET s, int backlog)
412 {
413     int r;
414
415     SOCKET_TEST_ERROR(r = CALL(listen)(TO_SOCKET(s), backlog));
416     return r;
417 }
418
419 int
420 win32_recv(SOCKET s, char *buf, int len, int flags)
421 {
422     int r;
423
424     SOCKET_TEST_ERROR(r = CALL(recv)(TO_SOCKET(s), buf, len, flags));
425     return r;
426 }
427
428 int
429 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
430 {
431     int r;
432     int frombufsize = *fromlen;
433
434     SOCKET_TEST_ERROR(r = CALL(recvfrom)(TO_SOCKET(s), buf, len, flags, from, fromlen));
435     /* Winsock's recvfrom() only returns a valid 'from' when the socket
436      * is connectionless.  Perl expects a valid 'from' for all types
437      * of sockets, so go the extra mile.
438      */
439     if (r != SOCKET_ERROR && frombufsize == *fromlen)
440         (void)win32_getpeername(s, from, fromlen);
441     return r;
442 }
443
444 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
445 int
446 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
447 {
448     int r;
449 #ifdef USE_SOCKETS_AS_HANDLES
450     Perl_fd_set dummy;
451     int i, fd, bit, offset;
452     FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
453
454     /* winsock seems incapable of dealing with all three null fd_sets,
455      * so do the (millisecond) sleep as a special case
456      */
457     if (!(rd || wr || ex)) {
458         if (timeout)
459             Sleep(timeout->tv_sec  * 1000 +
460                   timeout->tv_usec / 1000);     /* do the best we can */
461         else
462             Sleep(UINT_MAX);
463         return 0;
464     }
465     StartSockets();
466     PERL_FD_ZERO(&dummy);
467     if (!rd)
468         rd = &dummy, prd = NULL;
469     else
470         prd = &nrd;
471     if (!wr)
472         wr = &dummy, pwr = NULL;
473     else
474         pwr = &nwr;
475     if (!ex)
476         ex = &dummy, pex = NULL;
477     else
478         pex = &nex;
479
480     FD_ZERO(&nrd);
481     FD_ZERO(&nwr);
482     FD_ZERO(&nex);
483     for (i = 0; i < nfds; i++) {
484         fd = TO_SOCKET(i);
485         if (PERL_FD_ISSET(i,rd))
486             FD_SET(fd, &nrd);
487         if (PERL_FD_ISSET(i,wr))
488             FD_SET(fd, &nwr);
489         if (PERL_FD_ISSET(i,ex))
490             FD_SET(fd, &nex);
491     }
492
493     SOCKET_TEST_ERROR(r = CALL(select)(nfds, prd, pwr, pex, timeout));
494
495     for (i = 0; i < nfds; i++) {
496         fd = TO_SOCKET(i);
497         if (PERL_FD_ISSET(i,rd) && !CALL(__WSAFDIsSet)(fd, &nrd))
498             PERL_FD_CLR(i,rd);
499         if (PERL_FD_ISSET(i,wr) && !CALL(__WSAFDIsSet)(fd, &nwr))
500             PERL_FD_CLR(i,wr);
501         if (PERL_FD_ISSET(i,ex) && !CALL(__WSAFDIsSet)(fd, &nex))
502             PERL_FD_CLR(i,ex);
503     }
504 #else
505     SOCKET_TEST_ERROR(r = CALL(select)(nfds, rd, wr, ex, timeout));
506 #endif
507     return r;
508 }
509
510 int
511 win32_send(SOCKET s, const char *buf, int len, int flags)
512 {
513     int r;
514
515     SOCKET_TEST_ERROR(r = CALL(send)(TO_SOCKET(s), buf, len, flags));
516     return r;
517 }
518
519 int
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 = CALL(sendto)(TO_SOCKET(s), buf, len, flags, to, tolen));
526     return r;
527 }
528
529 int
530 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
531 {
532     int r;
533
534     SOCKET_TEST_ERROR(r = CALL(setsockopt)(TO_SOCKET(s), level, optname, optval, optlen));
535     return r;
536 }
537     
538 int
539 win32_shutdown(SOCKET s, int how)
540 {
541     int r;
542
543     SOCKET_TEST_ERROR(r = CALL(shutdown)(TO_SOCKET(s), how));
544     return r;
545 }
546
547 int
548 win32_closesocket(SOCKET s)
549 {
550     int r;
551
552     SOCKET_TEST_ERROR(r = CALL(closesocket)(TO_SOCKET(s)));
553     return r;
554 }
555
556 SOCKET
557 win32_socket(int af, int type, int protocol)
558 {
559     SOCKET s;
560
561 #ifndef USE_SOCKETS_AS_HANDLES
562     SOCKET_TEST(s = CALL(socket)(af, type, protocol), INVALID_SOCKET);
563 #else
564     StartSockets();
565     if((s = CALL(socket)(af, type, protocol)) == INVALID_SOCKET)
566         errno = CALL(WSAGetLastError)();
567     else
568         s = OPEN_SOCKET(s);
569 #endif  /* USE_SOCKETS_AS_HANDLES */
570
571     return s;
572 }
573
574 #undef fclose
575 int
576 my_fclose (FILE *pf)
577 {
578     int osf, retval;
579     if (!wsock_started)         /* No WinSock? */
580         return(fclose(pf));     /* Then not a socket. */
581     osf = TO_SOCKET(fileno(pf));/* Get it now before it's gone! */
582     retval = fclose(pf);        /* Must fclose() before closesocket() */
583     if (osf != -1
584         && CALL(closesocket)(osf) == SOCKET_ERROR
585         && CALL(WSAGetLastError)() != WSAENOTSOCK)
586     {
587         return EOF;
588     }
589     return retval;
590 }
591
592 struct hostent *
593 win32_gethostbyaddr(const char *addr, int len, int type)
594 {
595     struct hostent *r;
596
597     SOCKET_TEST(r = CALL(gethostbyaddr)(addr, len, type), NULL);
598     return r;
599 }
600
601 struct hostent *
602 win32_gethostbyname(const char *name)
603 {
604     struct hostent *r;
605
606     SOCKET_TEST(r = CALL(gethostbyname)(name), NULL);
607     return r;
608 }
609
610 int
611 win32_gethostname(char *name, int len)
612 {
613     int r;
614
615     SOCKET_TEST_ERROR(r = CALL(gethostname)(name, len));
616     return r;
617 }
618
619 struct protoent *
620 win32_getprotobyname(const char *name)
621 {
622     struct protoent *r;
623
624     SOCKET_TEST(r = CALL(getprotobyname)(name), NULL);
625     return r;
626 }
627
628 struct protoent *
629 win32_getprotobynumber(int num)
630 {
631     struct protoent *r;
632
633     SOCKET_TEST(r = CALL(getprotobynumber)(num), NULL);
634     return r;
635 }
636
637 struct servent *
638 win32_getservbyname(const char *name, const char *proto)
639 {
640     dTHXo;    
641     struct servent *r;
642
643     SOCKET_TEST(r = CALL(getservbyname)(name, proto), NULL);
644     if (r) {
645         r = win32_savecopyservent(&w32_servent, r, proto);
646     }
647     return r;
648 }
649
650 struct servent *
651 win32_getservbyport(int port, const char *proto)
652 {
653     dTHXo; 
654     struct servent *r;
655
656     SOCKET_TEST(r = CALL(getservbyport)(port, proto), NULL);
657     if (r) {
658         r = win32_savecopyservent(&w32_servent, r, proto);
659     }
660     return r;
661 }
662
663 int
664 win32_ioctl(int i, unsigned int u, char *data)
665 {
666     dTHXo;
667     u_long argp = (u_long)data;
668     int retval;
669
670     if (!wsock_started) {
671         Perl_croak_nocontext("ioctl implemented only on sockets");
672         /* NOTREACHED */
673     }
674
675     retval = CALL(ioctlsocket)(TO_SOCKET(i), (long)u, &argp);
676     if (retval == SOCKET_ERROR) {
677         if (CALL(WSAGetLastError)() == WSAENOTSOCK) {
678             Perl_croak_nocontext("ioctl implemented only on sockets");
679             /* NOTREACHED */
680         }
681         errno = CALL(WSAGetLastError)();
682     }
683     return retval;
684 }
685
686 char FAR *
687 win32_inet_ntoa(struct in_addr in)
688 {
689     StartSockets();
690     return CALL(inet_ntoa)(in);
691 }
692
693 unsigned long
694 win32_inet_addr(const char FAR *cp)
695 {
696     StartSockets();
697     return CALL(inet_addr)(cp);
698 }
699
700 /*
701  * Networking stubs
702  */
703
704 void
705 win32_endhostent() 
706 {
707     dTHXo;
708     Perl_croak_nocontext("endhostent not implemented!\n");
709 }
710
711 void
712 win32_endnetent()
713 {
714     dTHXo;
715     Perl_croak_nocontext("endnetent not implemented!\n");
716 }
717
718 void
719 win32_endprotoent()
720 {
721     dTHXo;
722     Perl_croak_nocontext("endprotoent not implemented!\n");
723 }
724
725 void
726 win32_endservent()
727 {
728     dTHXo;
729     Perl_croak_nocontext("endservent not implemented!\n");
730 }
731
732
733 struct netent *
734 win32_getnetent(void) 
735 {
736     dTHXo;
737     Perl_croak_nocontext("getnetent not implemented!\n");
738     return (struct netent *) NULL;
739 }
740
741 struct netent *
742 win32_getnetbyname(char *name) 
743 {
744     dTHXo;
745     Perl_croak_nocontext("getnetbyname not implemented!\n");
746     return (struct netent *)NULL;
747 }
748
749 struct netent *
750 win32_getnetbyaddr(long net, int type) 
751 {
752     dTHXo;
753     Perl_croak_nocontext("getnetbyaddr not implemented!\n");
754     return (struct netent *)NULL;
755 }
756
757 struct protoent *
758 win32_getprotoent(void) 
759 {
760     dTHXo;
761     Perl_croak_nocontext("getprotoent not implemented!\n");
762     return (struct protoent *) NULL;
763 }
764
765 struct servent *
766 win32_getservent(void) 
767 {
768     dTHXo;
769     Perl_croak_nocontext("getservent not implemented!\n");
770     return (struct servent *) NULL;
771 }
772
773 void
774 win32_sethostent(int stayopen)
775 {
776     dTHXo;
777     Perl_croak_nocontext("sethostent not implemented!\n");
778 }
779
780
781 void
782 win32_setnetent(int stayopen)
783 {
784     dTHXo;
785     Perl_croak_nocontext("setnetent not implemented!\n");
786 }
787
788
789 void
790 win32_setprotoent(int stayopen)
791 {
792     dTHXo;
793     Perl_croak_nocontext("setprotoent not implemented!\n");
794 }
795
796
797 void
798 win32_setservent(int stayopen)
799 {
800     dTHXo;
801     Perl_croak_nocontext("setservent not implemented!\n");
802 }
803
804 static struct servent*
805 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
806 {
807     d->s_name = s->s_name;
808     d->s_aliases = s->s_aliases;
809     d->s_port = s->s_port;
810 #ifndef __BORLANDC__    /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
811     if (!IsWin95() && s->s_proto && strlen(s->s_proto))
812         d->s_proto = s->s_proto;
813     else
814 #endif
815     if (proto && strlen(proto))
816         d->s_proto = (char *)proto;
817     else
818         d->s_proto = "tcp";
819    
820     return d;
821 }
822
823