[WS2_32]
[reactos.git] / reactos / dll / win32 / ws2_32 / misc / ns.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: misc/ns.c
5 * PURPOSE: Namespace APIs
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10
11 #include "ws2_32.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <winnls.h>
16
17 #ifndef BUFSIZ
18 #define BUFSIZ 1024
19 #endif/*BUFSIZ*/
20
21 #ifndef MAX_HOSTNAME_LEN
22 #define MAX_HOSTNAME_LEN 256
23 #endif
24
25 /* Name resolution APIs */
26
27 /*
28 * @unimplemented
29 */
30 INT
31 EXPORT
32 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress,
33 IN DWORD dwAddressLength,
34 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
35 OUT LPSTR lpszAddressString,
36 IN OUT LPDWORD lpdwAddressStringLength)
37 {
38 DWORD size;
39 CHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
40 CHAR *p;
41
42 if (!lpsaAddress) return SOCKET_ERROR;
43 if (!lpszAddressString || !lpdwAddressStringLength) return SOCKET_ERROR;
44
45 switch(lpsaAddress->sa_family)
46 {
47 case AF_INET:
48 if (dwAddressLength < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
49 sprintf( buffer, "%u.%u.%u.%u:%u",
50 (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 24 & 0xff),
51 (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 16 & 0xff),
52 (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 8 & 0xff),
53 (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) & 0xff),
54 ntohs( ((SOCKADDR_IN *)lpsaAddress)->sin_port ) );
55
56 p = strchr( buffer, ':' );
57 if (!((SOCKADDR_IN *)lpsaAddress)->sin_port) *p = 0;
58 break;
59 default:
60 WSASetLastError(WSAEINVAL);
61 return SOCKET_ERROR;
62 }
63
64 size = strlen( buffer ) + 1;
65
66 if (*lpdwAddressStringLength < size)
67 {
68 *lpdwAddressStringLength = size;
69 WSASetLastError(WSAEFAULT);
70 return SOCKET_ERROR;
71 }
72
73 *lpdwAddressStringLength = size;
74 strcpy( lpszAddressString, buffer );
75 return 0;
76 }
77
78
79 /*
80 * @unimplemented
81 */
82 INT
83 EXPORT
84 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress,
85 IN DWORD dwAddressLength,
86 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
87 OUT LPWSTR lpszAddressString,
88 IN OUT LPDWORD lpdwAddressStringLength)
89 {
90 INT ret;
91 DWORD size;
92 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
93 CHAR bufAddr[54];
94
95 size = *lpdwAddressStringLength;
96 ret = WSAAddressToStringA(lpsaAddress, dwAddressLength, NULL, bufAddr, &size);
97
98 if (ret) return ret;
99
100 MultiByteToWideChar( CP_ACP, 0, bufAddr, size, buffer, sizeof( buffer )/sizeof(WCHAR));
101
102 if (*lpdwAddressStringLength < size)
103 {
104 *lpdwAddressStringLength = size;
105 WSASetLastError(WSAEFAULT);
106 return SOCKET_ERROR;
107 }
108
109 *lpdwAddressStringLength = size;
110 lstrcpyW( lpszAddressString, buffer );
111 return 0;
112 }
113
114
115 /*
116 * @unimplemented
117 */
118 INT
119 EXPORT
120 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength,
121 OUT LPWSANAMESPACE_INFOA lpnspBuffer)
122 {
123 UNIMPLEMENTED
124
125 WSASetLastError(WSASYSCALLFAILURE);
126 return SOCKET_ERROR;
127 }
128
129
130 /*
131 * @unimplemented
132 */
133 INT
134 EXPORT
135 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength,
136 OUT LPWSANAMESPACE_INFOW lpnspBuffer)
137 {
138 UNIMPLEMENTED
139
140 WSASetLastError(WSASYSCALLFAILURE);
141 return SOCKET_ERROR;
142 }
143
144
145 /*
146 * @unimplemented
147 */
148 INT
149 EXPORT
150 WSAGetServiceClassInfoA(IN LPGUID lpProviderId,
151 IN LPGUID lpServiceClassId,
152 IN OUT LPDWORD lpdwBufferLength,
153 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo)
154 {
155 UNIMPLEMENTED
156
157 WSASetLastError(WSASYSCALLFAILURE);
158 return SOCKET_ERROR;
159 }
160
161
162 /*
163 * @unimplemented
164 */
165 INT
166 EXPORT
167 WSAGetServiceClassInfoW(IN LPGUID lpProviderId,
168 IN LPGUID lpServiceClassId,
169 IN OUT LPDWORD lpdwBufferLength,
170 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
171 {
172 UNIMPLEMENTED
173
174 WSASetLastError(WSASYSCALLFAILURE);
175 return SOCKET_ERROR;
176 }
177
178
179 /*
180 * @unimplemented
181 */
182 INT
183 EXPORT
184 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId,
185 OUT LPSTR lpszServiceClassName,
186 IN OUT LPDWORD lpdwBufferLength)
187 {
188 UNIMPLEMENTED
189
190 WSASetLastError(WSASYSCALLFAILURE);
191 return SOCKET_ERROR;
192 }
193
194
195 /*
196 * @unimplemented
197 */
198 INT
199 EXPORT
200 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId,
201 OUT LPWSTR lpszServiceClassName,
202 IN OUT LPDWORD lpdwBufferLength)
203 {
204 UNIMPLEMENTED
205
206 WSASetLastError(WSASYSCALLFAILURE);
207 return SOCKET_ERROR;
208 }
209
210
211 /*
212 * @unimplemented
213 */
214 INT
215 EXPORT
216 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo)
217 {
218 UNIMPLEMENTED
219
220 WSASetLastError(WSASYSCALLFAILURE);
221 return SOCKET_ERROR;
222 }
223
224
225 /*
226 * @unimplemented
227 */
228 INT
229 EXPORT
230 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo)
231 {
232 UNIMPLEMENTED
233
234 WSASetLastError(WSASYSCALLFAILURE);
235 return SOCKET_ERROR;
236 }
237
238
239 /*
240 * @unimplemented
241 */
242 INT
243 EXPORT
244 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions,
245 IN DWORD dwControlFlags,
246 OUT LPHANDLE lphLookup)
247 {
248 UNIMPLEMENTED
249
250 WSASetLastError(WSASYSCALLFAILURE);
251 return SOCKET_ERROR;
252 }
253
254
255 /*
256 * @unimplemented
257 */
258 INT
259 EXPORT
260 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions,
261 IN DWORD dwControlFlags,
262 OUT LPHANDLE lphLookup)
263 {
264 UNIMPLEMENTED
265
266 WSASetLastError(WSASYSCALLFAILURE);
267 return SOCKET_ERROR;
268 }
269
270
271 /*
272 * @unimplemented
273 */
274 INT
275 EXPORT
276 WSALookupServiceEnd(IN HANDLE hLookup)
277 {
278 UNIMPLEMENTED
279
280 WSASetLastError(WSASYSCALLFAILURE);
281 return SOCKET_ERROR;
282 }
283
284
285 /*
286 * @unimplemented
287 */
288 INT
289 EXPORT
290 WSALookupServiceNextA(IN HANDLE hLookup,
291 IN DWORD dwControlFlags,
292 IN OUT LPDWORD lpdwBufferLength,
293 OUT LPWSAQUERYSETA lpqsResults)
294 {
295 UNIMPLEMENTED
296
297 WSASetLastError(WSASYSCALLFAILURE);
298 return SOCKET_ERROR;
299 }
300
301
302 /*
303 * @unimplemented
304 */
305 INT
306 EXPORT
307 WSALookupServiceNextW(IN HANDLE hLookup,
308 IN DWORD dwControlFlags,
309 IN OUT LPDWORD lpdwBufferLength,
310 OUT LPWSAQUERYSETW lpqsResults)
311 {
312 UNIMPLEMENTED
313
314 WSASetLastError(WSASYSCALLFAILURE);
315 return SOCKET_ERROR;
316 }
317
318
319 /*
320 * @unimplemented
321 */
322 INT
323 EXPORT
324 WSARemoveServiceClass(IN LPGUID lpServiceClassId)
325 {
326 UNIMPLEMENTED
327
328 WSASetLastError(WSASYSCALLFAILURE);
329 return SOCKET_ERROR;
330 }
331
332
333 /*
334 * @unimplemented
335 */
336 INT
337 EXPORT
338 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo,
339 IN WSAESETSERVICEOP essOperation,
340 IN DWORD dwControlFlags)
341 {
342 UNIMPLEMENTED
343
344 WSASetLastError(WSASYSCALLFAILURE);
345 return SOCKET_ERROR;
346 }
347
348
349 /*
350 * @unimplemented
351 */
352 INT
353 EXPORT
354 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo,
355 IN WSAESETSERVICEOP essOperation,
356 IN DWORD dwControlFlags)
357 {
358 UNIMPLEMENTED
359
360 WSASetLastError(WSASYSCALLFAILURE);
361 return SOCKET_ERROR;
362 }
363
364
365 /*
366 * @unimplemented
367 */
368 INT
369 EXPORT
370 WSAStringToAddressA(IN LPSTR AddressString,
371 IN INT AddressFamily,
372 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
373 OUT LPSOCKADDR lpAddress,
374 IN OUT LPINT lpAddressLength)
375 {
376 INT ret, len;
377 LPWSTR szTemp;
378 WSAPROTOCOL_INFOW ProtoInfoW;
379
380 len = MultiByteToWideChar(CP_ACP,
381 0,
382 AddressString,
383 -1,
384 NULL,
385 0);
386
387 szTemp = HeapAlloc(GetProcessHeap(),
388 0,
389 len * sizeof(WCHAR));
390
391 MultiByteToWideChar(CP_ACP,
392 0,
393 AddressString,
394 -1,
395 szTemp,
396 len);
397
398 if (lpProtocolInfo)
399 {
400 memcpy(&ProtoInfoW,
401 lpProtocolInfo,
402 FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol));
403
404 MultiByteToWideChar(CP_ACP,
405 0,
406 lpProtocolInfo->szProtocol,
407 -1,
408 ProtoInfoW.szProtocol,
409 WSAPROTOCOL_LEN + 1);
410 }
411
412 ret = WSAStringToAddressW(szTemp,
413 AddressFamily,
414 &ProtoInfoW,
415 lpAddress,
416 lpAddressLength);
417
418 HeapFree(GetProcessHeap(),
419 0,
420 szTemp );
421
422 WSASetLastError(ret);
423 return ret;
424 }
425
426
427
428 /*
429 * @implemented
430 */
431 INT
432 EXPORT
433 WSAStringToAddressW(IN LPWSTR AddressString,
434 IN INT AddressFamily,
435 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
436 OUT LPSOCKADDR lpAddress,
437 IN OUT LPINT lpAddressLength)
438 {
439 int pos=0;
440 int res=0;
441 LONG inetaddr = 0;
442 LPWSTR *bp=NULL;
443 SOCKADDR_IN *sockaddr;
444
445 if (!lpAddressLength || !lpAddress || !AddressString)
446 {
447 WSASetLastError(WSAEINVAL);
448 return SOCKET_ERROR;
449 }
450
451 sockaddr = (SOCKADDR_IN *) lpAddress;
452
453 /* Set right adress family */
454 if (lpProtocolInfo!=NULL)
455 sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
456 else
457 sockaddr->sin_family = AddressFamily;
458
459 /* Report size */
460 if (AddressFamily == AF_INET)
461 {
462 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
463 {
464 *lpAddressLength = sizeof(SOCKADDR_IN);
465 res = WSAEFAULT;
466 }
467 else
468 {
469 // translate ip string to ip
470
471 /* rest sockaddr.sin_addr.s_addr
472 for we need to be sure it is zero when we come to while */
473 memset(lpAddress,0,sizeof(SOCKADDR_IN));
474
475 /* Set right adress family */
476 sockaddr->sin_family = AF_INET;
477
478 /* Get port number */
479 pos = wcscspn(AddressString,L":") + 1;
480
481 if (pos < (int)wcslen(AddressString))
482 sockaddr->sin_port = wcstol(&AddressString[pos],
483 bp,
484 10);
485
486 else
487 sockaddr->sin_port = 0;
488
489 /* Get ip number */
490 pos=0;
491 inetaddr=0;
492
493 while (pos < (int)wcslen(AddressString))
494 {
495 inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos],
496 bp,
497 10));
498 pos += wcscspn( &AddressString[pos],L".") +1 ;
499 }
500
501 res = 0;
502 sockaddr->sin_addr.s_addr = inetaddr;
503
504 }
505 }
506
507 WSASetLastError(res);
508 if (!res) return 0;
509 return SOCKET_ERROR;
510 }
511
512 void check_hostent(struct hostent **he)
513 {
514 struct hostent *new_he;
515
516 WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
517
518 if(!*he)
519 {
520 new_he = HeapAlloc(GlobalHeap,
521 0,
522 sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
523
524 new_he->h_name = (PCHAR)(new_he + 1);
525 new_he->h_aliases = NULL;
526 new_he->h_addrtype = 0; // AF_INET
527 new_he->h_length = 0; // sizeof(in_addr)
528 new_he->h_addr_list = HeapAlloc(GlobalHeap,
529 HEAP_ZERO_MEMORY,
530 sizeof(char *) * 2);
531
532 *he = new_he;
533 }
534 }
535
536 void populate_hostent(struct hostent *he, char* name, IP4_ADDRESS addr)
537 {
538 ASSERT(he);
539
540 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
541 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
542
543 strncpy(he->h_name,
544 name,
545 MAX_HOSTNAME_LEN);
546
547 if( !he->h_aliases ) {
548 he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
549 he->h_aliases[0] = NULL;
550 }
551 he->h_addrtype = AF_INET;
552 he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
553
554 if( he->h_addr_list[0] )
555 {
556 HeapFree(GlobalHeap,
557 0,
558 he->h_addr_list[0]);
559 }
560
561 he->h_addr_list[0] = HeapAlloc(GlobalHeap,
562 0,
563 MAX_HOSTNAME_LEN + 1);
564
565 WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
566
567 RtlCopyMemory(he->h_addr_list[0],
568 &addr,
569 sizeof(addr));
570
571 he->h_addr_list[1] = NULL;
572 }
573
574 void free_hostent(struct hostent *he)
575 {
576 int i;
577
578 if (he)
579 {
580 if (he->h_name)
581 HeapFree(GlobalHeap, 0, he->h_name);
582 if (he->h_aliases)
583 {
584 for (i = 0; he->h_aliases[i]; i++)
585 HeapFree(GlobalHeap, 0, he->h_aliases[i]);
586 HeapFree(GlobalHeap, 0, he->h_aliases);
587 }
588 if (he->h_addr_list)
589 {
590 for (i = 0; he->h_addr_list[i]; i++)
591 HeapFree(GlobalHeap, 0, he->h_addr_list[i]);
592 HeapFree(GlobalHeap, 0, he->h_addr_list);
593 }
594 HeapFree(GlobalHeap, 0, he);
595 }
596 }
597
598 /* WinSock 1.1 compatible name resolution APIs */
599
600 /*
601 * @unimplemented
602 */
603 LPHOSTENT
604 EXPORT
605 gethostbyaddr(IN CONST CHAR FAR* addr,
606 IN INT len,
607 IN INT type)
608 {
609 UNIMPLEMENTED
610
611 return (LPHOSTENT)NULL;
612 }
613
614 /*
615 Assumes rfc 1123 - adam *
616 addr[1] = 0;
617 addr[0] = inet_addr(name);
618 strcpy( hostname, name );
619 if(addr[0] == 0xffffffff) return NULL;
620 he.h_addr_list = (void *)addr;
621 he.h_name = hostname;
622 he.h_aliases = NULL;
623 he.h_addrtype = AF_INET;
624 he.h_length = sizeof(addr);
625 return &he;
626
627 <RANT>
628 From the MSDN Platform SDK: Windows Sockets 2
629 "The gethostbyname function cannot resolve IP address strings passed to it.
630 Such a request is treated exactly as if an unknown host name were passed."
631 </RANT>
632
633 Defferring to the the documented behaviour, rather than the unix behaviour
634 What if the hostname is in the HOSTS file? see getservbyname
635
636 * @implemented
637 */
638
639 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
640 /* see ws2_32.h, winsock2.h*/
641 /*getnetworkparameters - iphlp api */
642 /*
643 REFERENCES
644
645 servent -- w32api/include/winsock2.h
646 PWINSOCK_THREAD_BLOCK -- ws2_32.h
647 dllmain.c -- threadlocal memory allocation / deallocation
648 lib/dnsapi
649
650
651 */
652 /* lib/adns/src/adns.h XXX */
653
654
655 /*
656 struct hostent {
657 char *h_name;
658 char **h_aliases;
659 short h_addrtype;
660 short h_length;
661 char **h_addr_list;
662 #define h_addr h_addr_list[0]
663 };
664 struct servent {
665 char *s_name;
666 char **s_aliases;
667 short s_port;
668 char *s_proto;
669 };
670
671
672 struct hostent defined in w32api/include/winsock2.h
673 */
674
675 void free_servent(struct servent* s)
676 {
677 int i;
678
679 if (s)
680 {
681 if (s->s_name)
682 HeapFree(GlobalHeap, 0, s->s_name);
683 if (s->s_aliases)
684 {
685 for (i = 0; s->s_aliases[i]; i++)
686 HeapFree(GlobalHeap, 0, s->s_aliases[i]);
687 HeapFree(GlobalHeap, 0, s->s_aliases);
688 }
689 if (s->s_proto)
690 HeapFree(GlobalHeap, 0, s->s_proto);
691 HeapFree(GlobalHeap, 0, s);
692 }
693 }
694
695 /* This function is far from perfect but it works enough */
696 static
697 LPHOSTENT
698 FindEntryInHosts(IN CONST CHAR FAR* name)
699 {
700 BOOL Found = FALSE;
701 HANDLE HostsFile;
702 CHAR HostsDBData[BUFSIZ] = { 0 };
703 PCHAR SystemDirectory = HostsDBData;
704 PCHAR HostsLocation = "\\drivers\\etc\\hosts";
705 PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
706 UINT SystemDirSize = sizeof(HostsDBData) - 1, ValidData = 0;
707 DWORD ReadSize;
708 ULONG Address;
709 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
710
711 /* We assume that the parameters are valid */
712
713 if (!GetSystemDirectoryA(SystemDirectory, SystemDirSize))
714 {
715 WSASetLastError(WSANO_RECOVERY);
716 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
717 return NULL; /* Can't get system directory */
718 }
719
720 strncat(SystemDirectory,
721 HostsLocation,
722 SystemDirSize );
723
724 HostsFile = CreateFileA(SystemDirectory,
725 GENERIC_READ,
726 FILE_SHARE_READ,
727 NULL,
728 OPEN_EXISTING,
729 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
730 NULL);
731 if (HostsFile == INVALID_HANDLE_VALUE)
732 {
733 WSASetLastError(WSANO_RECOVERY);
734 return NULL;
735 }
736
737 while(!Found &&
738 ReadFile(HostsFile,
739 HostsDBData + ValidData,
740 sizeof(HostsDBData) - ValidData,
741 &ReadSize,
742 NULL))
743 {
744 ValidData += ReadSize;
745 ReadSize = 0;
746 NextLine = ThisLine = HostsDBData;
747
748 /* Find the beginning of the next line */
749 while(NextLine < HostsDBData + ValidData &&
750 *NextLine != '\r' && *NextLine != '\n' )
751 {
752 NextLine++;
753 }
754
755 /* Zero and skip, so we can treat what we have as a string */
756 if( NextLine > HostsDBData + ValidData )
757 break;
758
759 *NextLine = 0; NextLine++;
760
761 Comment = strchr( ThisLine, '#' );
762 if( Comment ) *Comment = 0; /* Terminate at comment start */
763
764 AddressStr = ThisLine;
765 /* Find the first space separating the IP address from the DNS name */
766 AddrTerm = strchr(ThisLine, ' ');
767 if (AddrTerm)
768 {
769 /* Terminate the address string */
770 *AddrTerm = 0;
771
772 /* Find the last space before the DNS name */
773 NameSt = strrchr(ThisLine, ' ');
774
775 /* If there is only one space (the one we removed above), then just use the address terminator */
776 if (!NameSt)
777 NameSt = AddrTerm;
778
779 /* Move from the space to the first character of the DNS name */
780 NameSt++;
781
782 DnsName = NameSt;
783
784 if (!strcmp(name, DnsName))
785 {
786 Found = TRUE;
787 break;
788 }
789 }
790
791 /* Get rid of everything we read so far */
792 while( NextLine <= HostsDBData + ValidData &&
793 isspace (*NextLine))
794 {
795 NextLine++;
796 }
797
798 if (HostsDBData + ValidData - NextLine <= 0)
799 break;
800
801 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
802 HostsDBData + ValidData - NextLine));
803
804 memmove(HostsDBData,
805 NextLine,
806 HostsDBData + ValidData - NextLine );
807 ValidData -= NextLine - HostsDBData;
808 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
809 }
810
811 CloseHandle(HostsFile);
812
813 if (!Found)
814 {
815 WS_DbgPrint(MAX_TRACE,("Not found\n"));
816 WSASetLastError(WSANO_DATA);
817 return NULL;
818 }
819
820 if (strstr(AddressStr, ":"))
821 {
822 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
823 WSASetLastError(WSAEINVAL);
824 return NULL;
825 }
826
827 Address = inet_addr(AddressStr);
828 if (Address == INADDR_NONE)
829 {
830 WSASetLastError(WSAEINVAL);
831 return NULL;
832 }
833
834 populate_hostent(p->Hostent, DnsName, Address);
835
836 return p->Hostent;
837 }
838
839 LPHOSTENT
840 EXPORT
841 gethostbyname(IN CONST CHAR FAR* name)
842 {
843 enum addr_type
844 {
845 GH_INVALID,
846 GH_IPV6,
847 GH_IPV4,
848 GH_RFC1123_DNS
849 };
850 typedef enum addr_type addr_type;
851 addr_type addr;
852 int ret = 0;
853 char* found = 0;
854 DNS_STATUS dns_status = {0};
855 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
856 PDNS_RECORD dp = 0;
857 PWINSOCK_THREAD_BLOCK p;
858 LPHOSTENT Hostent;
859
860 addr = GH_INVALID;
861
862 p = NtCurrentTeb()->WinSockData;
863
864 if (!p || !WSAINITIALIZED)
865 {
866 WSASetLastError( WSANOTINITIALISED );
867 return NULL;
868 }
869
870 check_hostent(&p->Hostent); /*XXX alloc_hostent*/
871
872 /* Hostname NULL - behave like gethostname */
873 if(name == NULL)
874 {
875 ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
876 if(ret)
877 {
878 WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ??
879 return NULL;
880 }
881 return p->Hostent;
882 }
883
884 /* Is it an IPv6 address? */
885 found = strstr(name, ":");
886 if( found != NULL )
887 {
888 addr = GH_IPV6;
889 goto act;
890 }
891
892 /* Is it an IPv4 address? */
893 if (!isalpha(name[0]))
894 {
895 addr = GH_IPV4;
896 goto act;
897 }
898
899 addr = GH_RFC1123_DNS;
900
901 /* Broken out in case we want to get fancy later */
902 act:
903 switch(addr)
904 {
905 case GH_IPV6:
906 WSASetLastError(STATUS_NOT_IMPLEMENTED);
907 return NULL;
908 break;
909
910 case GH_INVALID:
911 WSASetLastError(WSAEFAULT);
912 return NULL;
913 break;
914
915 /* Note: If passed an IP address, MSDN says that gethostbyname()
916 treats it as an unknown host.
917 This is different from the unix implementation. Use inet_addr()
918 */
919 case GH_IPV4:
920 case GH_RFC1123_DNS:
921 /* DNS_TYPE_A: include/WinDNS.h */
922 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
923
924 /* Look for the DNS name in the hosts file */
925 Hostent = FindEntryInHosts(name);
926 if (Hostent)
927 return Hostent;
928
929 dns_status = DnsQuery_A(name,
930 DNS_TYPE_A,
931 DNS_QUERY_STANDARD,
932 0,
933 /* extra dns servers */ &dp,
934 0);
935
936 if(dns_status == 0)
937 {
938 //ASSERT(dp->wType == DNS_TYPE_A);
939 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
940 PDNS_RECORD curr;
941 for(curr=dp;
942 curr != NULL && curr->wType != DNS_TYPE_A;
943 curr = curr->pNext )
944 {
945 WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
946 /*empty */
947 }
948
949 if(curr)
950 {
951 WS_DbgPrint(MID_TRACE,("populating hostent\n"));
952 WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
953 populate_hostent(p->Hostent,
954 (PCHAR)curr->pName,
955 curr->Data.A.IpAddress);
956 DnsRecordListFree(dp, DnsFreeRecordList);
957 return p->Hostent;
958 }
959 else
960 {
961 DnsRecordListFree(dp, DnsFreeRecordList);
962 }
963 }
964
965 WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
966 dns_status));
967 WSASetLastError(WSAHOST_NOT_FOUND);
968 return NULL;
969
970 break;
971
972 default:
973 WSASetLastError(WSANO_RECOVERY);
974 return NULL;
975 break;
976 }
977
978 WSASetLastError(WSANO_RECOVERY);
979 return NULL;
980 }
981
982 /*
983 * @implemented
984 */
985 INT
986 EXPORT
987 gethostname(OUT CHAR FAR* name,
988 IN INT namelen)
989 {
990 DWORD size = namelen;
991
992 int ret = GetComputerNameExA(ComputerNameDnsHostname,
993 name,
994 &size);
995 if(ret == 0)
996 {
997 WSASetLastError(WSAEFAULT);
998 return SOCKET_ERROR;
999 }
1000 else
1001 {
1002 name[namelen-1] = '\0';
1003 return 0;
1004 }
1005 }
1006
1007
1008 /*
1009 * XXX arty -- Partial implementation pending a better one. This one will
1010 * do for normal purposes.#include <ws2_32.h>
1011 *
1012 * Return the address of a static LPPROTOENT corresponding to the named
1013 * protocol. These structs aren't very interesting, so I'm not too ashamed
1014 * to have this function work on builtins for now.
1015 *
1016 * @unimplemented
1017 */
1018
1019 static CHAR *no_aliases = 0;
1020 static PROTOENT protocols[] =
1021 {
1022 {"icmp",&no_aliases, IPPROTO_ICMP},
1023 {"tcp", &no_aliases, IPPROTO_TCP},
1024 {"udp", &no_aliases, IPPROTO_UDP},
1025 {NULL, NULL, 0}
1026 };
1027
1028 LPPROTOENT
1029 EXPORT
1030 getprotobyname(IN CONST CHAR FAR* name)
1031 {
1032 UINT i;
1033 for (i = 0; protocols[i].p_name; i++)
1034 {
1035 if (_stricmp(protocols[i].p_name, name) == 0)
1036 return &protocols[i];
1037 }
1038 return NULL;
1039 }
1040
1041 /*
1042 * @unimplemented
1043 */
1044 LPPROTOENT
1045 EXPORT
1046 getprotobynumber(IN INT number)
1047 {
1048 UINT i;
1049 for (i = 0; protocols[i].p_name; i++)
1050 {
1051 if (protocols[i].p_proto == number)
1052 return &protocols[i];
1053 }
1054 return NULL;
1055 }
1056
1057 #define SKIPWS(ptr,act) \
1058 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1059 #define SKIPANDMARKSTR(ptr,act) \
1060 {while(*ptr && !isspace(*ptr)) ptr++; \
1061 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1062
1063
1064 static BOOL
1065 DecodeServEntFromString(IN PCHAR ServiceString,
1066 OUT PCHAR *ServiceName,
1067 OUT PCHAR *PortNumberStr,
1068 OUT PCHAR *ProtocolStr,
1069 IN PCHAR *Aliases,
1070 IN DWORD MaxAlias)
1071 {
1072 UINT NAliases = 0;
1073
1074 WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
1075
1076 SKIPWS(ServiceString, return FALSE);
1077 *ServiceName = ServiceString;
1078 SKIPANDMARKSTR(ServiceString, return FALSE);
1079 SKIPWS(ServiceString, return FALSE);
1080 *PortNumberStr = ServiceString;
1081 SKIPANDMARKSTR(ServiceString, ;);
1082
1083 while( *ServiceString && NAliases < MaxAlias - 1 )
1084 {
1085 SKIPWS(ServiceString, break);
1086 if( *ServiceString )
1087 {
1088 SKIPANDMARKSTR(ServiceString, ;);
1089 if( strlen(ServiceString) )
1090 {
1091 WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
1092 *Aliases++ = ServiceString;
1093 NAliases++;
1094 }
1095 }
1096 }
1097 *Aliases = NULL;
1098
1099 *ProtocolStr = strchr(*PortNumberStr,'/');
1100 if( !*ProtocolStr ) return FALSE;
1101 **ProtocolStr = 0; (*ProtocolStr)++;
1102
1103 WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
1104 *ServiceName, *ProtocolStr, *PortNumberStr,
1105 NAliases));
1106
1107 return TRUE;
1108 }
1109
1110 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1111
1112 /*
1113 * @implemented
1114 */
1115 LPSERVENT
1116 EXPORT
1117 getservbyname(IN CONST CHAR FAR* name,
1118 IN CONST CHAR FAR* proto)
1119 {
1120 BOOL Found = FALSE;
1121 HANDLE ServicesFile;
1122 CHAR ServiceDBData[BUFSIZ] = { 0 };
1123 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
1124 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
1125 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
1126 ProtocolStr = 0, Comment = 0, EndValid;
1127 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
1128 UINT i,SizeNeeded = 0,
1129 SystemDirSize = sizeof(ServiceDBData) - 1;
1130 DWORD ReadSize = 0;
1131 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
1132
1133 if (!p || !WSAINITIALIZED)
1134 {
1135 WSASetLastError( WSANOTINITIALISED );
1136 return NULL;
1137 }
1138
1139 if( !name )
1140 {
1141 WSASetLastError( WSANO_RECOVERY );
1142 return NULL;
1143 }
1144
1145 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
1146 {
1147 WSASetLastError( WSANO_RECOVERY );
1148 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
1149 return NULL; /* Can't get system directory */
1150 }
1151
1152 strncat(SystemDirectory,
1153 ServicesFileLocation,
1154 SystemDirSize );
1155
1156 ServicesFile = CreateFileA(SystemDirectory,
1157 GENERIC_READ,
1158 FILE_SHARE_READ,
1159 NULL,
1160 OPEN_EXISTING,
1161 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
1162 NULL );
1163
1164 if( ServicesFile == INVALID_HANDLE_VALUE )
1165 {
1166 WSASetLastError( WSANO_RECOVERY );
1167 return NULL;
1168 }
1169
1170 /* Scan the services file ...
1171 *
1172 * We will be share the buffer on the lines. If the line does not fit in
1173 * the buffer, then moving it to the beginning of the buffer and read
1174 * the remnants of line from file.
1175 */
1176
1177 /* Initial Read */
1178 ReadFile(ServicesFile,
1179 ServiceDBData,
1180 sizeof( ServiceDBData ) - 1,
1181 &ReadSize, NULL );
1182 ThisLine = NextLine = ServiceDBData;
1183 EndValid = ServiceDBData + ReadSize;
1184 ServiceDBData[sizeof(ServiceDBData) - 1] = '\0';
1185
1186 while(ReadSize)
1187 {
1188 for(; *NextLine != '\r' && *NextLine != '\n'; NextLine++)
1189 {
1190 if(NextLine == EndValid)
1191 {
1192 int LineLen = NextLine - ThisLine;
1193
1194 if(ThisLine == ServiceDBData)
1195 {
1196 WS_DbgPrint(MIN_TRACE,("Line too long"));
1197 WSASetLastError( WSANO_RECOVERY );
1198 return NULL;
1199 }
1200
1201 memmove(ServiceDBData, ThisLine, LineLen);
1202
1203 ReadFile(ServicesFile, ServiceDBData + LineLen,
1204 sizeof( ServiceDBData )-1 - LineLen,
1205 &ReadSize, NULL );
1206
1207 EndValid = ServiceDBData + LineLen + ReadSize;
1208 NextLine = ServiceDBData + LineLen;
1209 ThisLine = ServiceDBData;
1210
1211 if(!ReadSize) break;
1212 }
1213 }
1214
1215 *NextLine = '\0';
1216 Comment = strchr( ThisLine, '#' );
1217 if( Comment ) *Comment = '\0'; /* Terminate at comment start */
1218
1219 if(DecodeServEntFromString(ThisLine,
1220 &ServiceName,
1221 &PortNumberStr,
1222 &ProtocolStr,
1223 Aliases,
1224 WS2_INTERNAL_MAX_ALIAS) &&
1225 !strcmp( ServiceName, name ) &&
1226 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
1227 {
1228
1229 WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
1230 Found = TRUE;
1231 SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
1232 (NextLine - ThisLine);
1233 break;
1234 }
1235 NextLine++;
1236 ThisLine = NextLine;
1237 }
1238
1239 /* This we'll do no matter what */
1240 CloseHandle( ServicesFile );
1241
1242 if( !Found )
1243 {
1244 WS_DbgPrint(MAX_TRACE,("Not found\n"));
1245 WSASetLastError( WSANO_DATA );
1246 return NULL;
1247 }
1248
1249 if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded )
1250 {
1251 /* Free previous getservbyname buffer, allocate bigger */
1252 if( p->Getservbyname )
1253 HeapFree(GlobalHeap, 0, p->Getservbyname);
1254 p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
1255 if( !p->Getservbyname )
1256 {
1257 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1258 SizeNeeded));
1259 WSASetLastError( WSATRY_AGAIN );
1260 return NULL;
1261 }
1262 p->Getservbyname->Size = SizeNeeded;
1263 }
1264
1265 /* Copy the data */
1266 memmove(p->Getservbyname->Data,
1267 ThisLine,
1268 NextLine - ThisLine );
1269
1270 ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
1271 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
1272 WS_DbgPrint(MAX_TRACE, ("ServiceName: %s, Protocol: %s\n",
1273 ServiceName,
1274 ProtocolStr));
1275
1276 for( i = 0; Aliases[i]; i++ )
1277 {
1278 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
1279 WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
1280 }
1281
1282 memcpy(p->Getservbyname->Aliases,
1283 Aliases,
1284 sizeof(Aliases));
1285
1286 /* Create the struct proper */
1287 p->Getservbyname->ServerEntry.s_name = ServiceName;
1288 p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases;
1289 p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr));
1290 p->Getservbyname->ServerEntry.s_proto = ProtocolStr;
1291
1292 return &p->Getservbyname->ServerEntry;
1293 }
1294
1295
1296 /*
1297 * @implemented
1298 */
1299 LPSERVENT
1300 EXPORT
1301 getservbyport(IN INT port,
1302 IN CONST CHAR FAR* proto)
1303 {
1304 BOOL Found = FALSE;
1305 HANDLE ServicesFile;
1306 CHAR ServiceDBData[BUFSIZ] = { 0 };
1307 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
1308 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
1309 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
1310 ProtocolStr = 0, Comment = 0;
1311 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
1312 UINT i,SizeNeeded = 0,
1313 SystemDirSize = sizeof(ServiceDBData) - 1;
1314 DWORD ReadSize = 0, ValidData = 0;
1315 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
1316
1317 if( !p || !WSAINITIALIZED)
1318 {
1319 WSASetLastError( WSANOTINITIALISED );
1320 return NULL;
1321 }
1322
1323 if ( !port )
1324 {
1325 WSASetLastError( WSANO_RECOVERY );
1326 return NULL;
1327 }
1328
1329 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
1330 {
1331 WSASetLastError( WSANO_RECOVERY );
1332 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
1333 return NULL; /* Can't get system directory */
1334 }
1335
1336 strncat(SystemDirectory,
1337 ServicesFileLocation,
1338 SystemDirSize );
1339
1340 ServicesFile = CreateFileA(SystemDirectory,
1341 GENERIC_READ,
1342 FILE_SHARE_READ,
1343 NULL,
1344 OPEN_EXISTING,
1345 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
1346 NULL );
1347
1348 if( ServicesFile == INVALID_HANDLE_VALUE )
1349 {
1350 WSASetLastError( WSANO_RECOVERY );
1351 return NULL;
1352 }
1353
1354 /* Scan the services file ...
1355 *
1356 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1357 * contain a full line, then we will try to read more.
1358 *
1359 * We fall from the loop if the buffer does not have a line terminator.
1360 */
1361
1362 /* Initial Read */
1363 while(!Found &&
1364 ReadFile(ServicesFile,
1365 ServiceDBData + ValidData,
1366 sizeof( ServiceDBData ) - ValidData,
1367 &ReadSize, NULL ) )
1368 {
1369 ValidData += ReadSize;
1370 ReadSize = 0;
1371 NextLine = ThisLine = ServiceDBData;
1372
1373 /* Find the beginning of the next line */
1374 while( NextLine < ServiceDBData + ValidData &&
1375 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
1376
1377 /* Zero and skip, so we can treat what we have as a string */
1378 if( NextLine > ServiceDBData + ValidData )
1379 break;
1380
1381 *NextLine = 0; NextLine++;
1382
1383 Comment = strchr( ThisLine, '#' );
1384 if( Comment ) *Comment = 0; /* Terminate at comment start */
1385
1386 if(DecodeServEntFromString(ThisLine,
1387 &ServiceName,
1388 &PortNumberStr,
1389 &ProtocolStr,
1390 Aliases,
1391 WS2_INTERNAL_MAX_ALIAS ) &&
1392 (htons(atoi( PortNumberStr )) == port ) &&
1393 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
1394 {
1395
1396 WS_DbgPrint(MAX_TRACE,("Found the port entry.\n"));
1397
1398 Found = TRUE;
1399 SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) +
1400 (NextLine - ThisLine);
1401 break;
1402 }
1403
1404 /* Get rid of everything we read so far */
1405 while( NextLine <= ServiceDBData + ValidData &&
1406 isspace( *NextLine ) )
1407 {
1408 NextLine++;
1409 }
1410
1411 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
1412 ServiceDBData + ValidData - NextLine));
1413
1414 memmove(ServiceDBData,
1415 NextLine,
1416 ServiceDBData + ValidData - NextLine );
1417 ValidData -= NextLine - ServiceDBData;
1418 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
1419 }
1420
1421 /* This we'll do no matter what */
1422 CloseHandle( ServicesFile );
1423
1424 if( !Found )
1425 {
1426 WS_DbgPrint(MAX_TRACE,("Not found\n"));
1427 WSASetLastError( WSANO_DATA );
1428 return NULL;
1429 }
1430
1431 if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded )
1432 {
1433 /* Free previous getservbyport buffer, allocate bigger */
1434 if( p->Getservbyport )
1435 HeapFree(GlobalHeap, 0, p->Getservbyport);
1436 p->Getservbyport = HeapAlloc(GlobalHeap,
1437 0,
1438 SizeNeeded);
1439 if( !p->Getservbyport )
1440 {
1441 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1442 SizeNeeded));
1443 WSASetLastError( WSATRY_AGAIN );
1444 return NULL;
1445 }
1446 p->Getservbyport->Size = SizeNeeded;
1447 }
1448 /* Copy the data */
1449 memmove(p->Getservbyport->Data,
1450 ThisLine,
1451 NextLine - ThisLine );
1452
1453 ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data);
1454 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data);
1455 WS_DbgPrint(MAX_TRACE, ("Port Number: %s, Protocol: %s\n",
1456 PortNumberStr, ProtocolStr));
1457
1458 for( i = 0; Aliases[i]; i++ )
1459 {
1460 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
1461 WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
1462 }
1463
1464 memcpy(p->Getservbyport->Aliases,Aliases,sizeof(Aliases));
1465
1466 /* Create the struct proper */
1467 p->Getservbyport->ServerEntry.s_name = ServiceName;
1468 p->Getservbyport->ServerEntry.s_aliases = p->Getservbyport->Aliases;
1469 p->Getservbyport->ServerEntry.s_port = port;
1470 p->Getservbyport->ServerEntry.s_proto = ProtocolStr;
1471
1472 WS_DbgPrint(MID_TRACE,("s_name: %s\n", ServiceName));
1473
1474 return &p->Getservbyport->ServerEntry;
1475
1476 }
1477
1478
1479 /*
1480 * @implemented
1481 */
1482 ULONG
1483 EXPORT
1484 inet_addr(IN CONST CHAR FAR* cp)
1485 /*
1486 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1487 * ARGUMENTS:
1488 * cp = Pointer to string with address to convert
1489 * RETURNS:
1490 * Binary representation of IPv4 address, or INADDR_NONE
1491 */
1492 {
1493 UINT i;
1494 PCHAR p;
1495 ULONG u = 0;
1496
1497 p = (PCHAR)cp;
1498
1499 if (!p || !WSAINITIALIZED)
1500 {
1501 WSASetLastError(WSAEFAULT);
1502 return INADDR_NONE;
1503 }
1504
1505 if (strlen(p) == 0)
1506 return INADDR_NONE;
1507
1508 if (strcmp(p, " ") == 0)
1509 return 0;
1510
1511 for (i = 0; i <= 3; i++)
1512 {
1513 u += (strtoul(p, &p, 0) << (i * 8));
1514
1515 if (strlen(p) == 0)
1516 return u;
1517
1518 if (p[0] != '.')
1519 return INADDR_NONE;
1520
1521 p++;
1522 }
1523
1524 return u;
1525 }
1526
1527
1528 /*
1529 * @implemented
1530 */
1531 CHAR FAR*
1532 EXPORT
1533 inet_ntoa(IN IN_ADDR in)
1534 {
1535 CHAR b[10];
1536 PCHAR p;
1537
1538 p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa;
1539 _itoa(in.S_un.S_addr & 0xFF, b, 10);
1540 strcpy(p, b);
1541 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
1542 strcat(p, ".");
1543 strcat(p, b);
1544 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
1545 strcat(p, ".");
1546 strcat(p, b);
1547 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
1548 strcat(p, ".");
1549 strcat(p, b);
1550
1551 return (CHAR FAR*)p;
1552 }
1553
1554
1555 /*
1556 * @implemented
1557 */
1558 VOID
1559 EXPORT
1560 freeaddrinfo(struct addrinfo *pAddrInfo)
1561 {
1562 struct addrinfo *next, *cur;
1563 cur = pAddrInfo;
1564 while (cur)
1565 {
1566 next = cur->ai_next;
1567 if (cur->ai_addr)
1568 HeapFree(GetProcessHeap(), 0, cur->ai_addr);
1569 if (cur->ai_canonname)
1570 HeapFree(GetProcessHeap(), 0, cur->ai_canonname);
1571 HeapFree(GetProcessHeap(), 0, cur);
1572 cur = next;
1573 }
1574 }
1575
1576
1577 struct addrinfo *
1578 new_addrinfo(struct addrinfo *prev)
1579 {
1580 struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo));
1581 if (prev)
1582 prev->ai_next = ret;
1583 return ret;
1584 }
1585
1586 /*
1587 * @implemented
1588 */
1589 INT
1590 EXPORT
1591 getaddrinfo(const char FAR * nodename,
1592 const char FAR * servname,
1593 const struct addrinfo FAR * hints,
1594 struct addrinfo FAR * FAR * res)
1595 {
1596 struct addrinfo *ret = NULL, *ai;
1597 ULONG addr;
1598 USHORT port;
1599 PCHAR pc;
1600 struct servent *se;
1601 char *proto;
1602 LPPROTOENT pent;
1603 DNS_STATUS dns_status;
1604 PDNS_RECORD dp, currdns;
1605 struct sockaddr_in *sin;
1606 INT error;
1607
1608 if (res == NULL)
1609 {
1610 error = WSAEINVAL;
1611 goto End;
1612 }
1613 if (nodename == NULL && servname == NULL)
1614 {
1615 error = WSAHOST_NOT_FOUND;
1616 goto End;
1617 }
1618
1619 if (!WSAINITIALIZED)
1620 {
1621 error = WSANOTINITIALISED;
1622 goto End;
1623 }
1624
1625 if (servname)
1626 {
1627 /* converting port number */
1628 port = strtoul(servname, &pc, 10);
1629 /* service name was specified? */
1630 if (*pc != ANSI_NULL)
1631 {
1632 /* protocol was specified? */
1633 if (hints && hints->ai_protocol)
1634 {
1635 pent = getprotobynumber(hints->ai_protocol);
1636 if (pent == NULL)
1637 {
1638 error = WSAEINVAL;
1639 goto End;
1640 }
1641 proto = pent->p_name;
1642 }
1643 else
1644 proto = NULL;
1645 se = getservbyname(servname, proto);
1646 if (se == NULL)
1647 {
1648 error = WSATYPE_NOT_FOUND;
1649 goto End;
1650 }
1651 port = se->s_port;
1652 }
1653 else
1654 port = htons(port);
1655 }
1656 else
1657 port = 0;
1658
1659 if (nodename)
1660 {
1661 /* Is it an IPv6 address? */
1662 if (strstr(nodename, ":"))
1663 {
1664 error = WSAHOST_NOT_FOUND;
1665 goto End;
1666 }
1667
1668 /* Is it an IPv4 address? */
1669 addr = inet_addr(nodename);
1670 if (addr != INADDR_NONE)
1671 {
1672 ai = new_addrinfo(NULL);
1673 ai->ai_family = PF_INET;
1674 ai->ai_addrlen = sizeof(struct sockaddr_in);
1675 ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
1676 sin = (struct sockaddr_in *)ai->ai_addr;
1677 sin->sin_family = AF_INET;
1678 sin->sin_port = port;
1679 RtlCopyMemory(&sin->sin_addr, &addr, sizeof(sin->sin_addr));
1680 if (hints)
1681 {
1682 if (ai->ai_socktype == 0)
1683 ai->ai_socktype = hints->ai_socktype;
1684 if (ai->ai_protocol == 0)
1685 ai->ai_protocol = hints->ai_protocol;
1686 }
1687 ret = ai;
1688 }
1689 else
1690 {
1691 /* resolving host name */
1692 dns_status = DnsQuery_A(nodename,
1693 DNS_TYPE_A,
1694 DNS_QUERY_STANDARD,
1695 0,
1696 /* extra dns servers */ &dp,
1697 0);
1698
1699 if (dns_status == 0)
1700 {
1701 ai = NULL;
1702 for (currdns = dp; currdns; currdns = currdns->pNext )
1703 {
1704 /* accept only A records */
1705 if (currdns->wType != DNS_TYPE_A) continue;
1706
1707 ai = new_addrinfo(ai);
1708 if (ret == NULL)
1709 ret = ai;
1710 ai->ai_family = PF_INET;
1711 ai->ai_addrlen = sizeof(struct sockaddr_in);
1712 ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
1713 sin = (struct sockaddr_in *)ret->ai_addr;
1714 sin->sin_family = AF_INET;
1715 sin->sin_port = port;
1716 RtlCopyMemory(&sin->sin_addr, &currdns->Data.A.IpAddress, sizeof(sin->sin_addr));
1717 if (hints)
1718 {
1719 if (ai->ai_socktype == 0)
1720 ai->ai_socktype = hints->ai_socktype;
1721 if (ai->ai_protocol == 0)
1722 ai->ai_protocol = hints->ai_protocol;
1723 }
1724 }
1725 DnsRecordListFree(dp, DnsFreeRecordList);
1726 }
1727 }
1728 }
1729 else
1730 {
1731 ai = new_addrinfo(NULL);
1732 ai->ai_family = PF_INET;
1733 ai->ai_addrlen = sizeof(struct sockaddr_in);
1734 ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
1735 sin = (struct sockaddr_in *)ai->ai_addr;
1736 sin->sin_family = AF_INET;
1737 sin->sin_port = port;
1738 if (hints)
1739 {
1740 if (!(hints->ai_flags & AI_PASSIVE))
1741 {
1742 sin->sin_addr.S_un.S_un_b.s_b1 = 127;
1743 sin->sin_addr.S_un.S_un_b.s_b2 = 0;
1744 sin->sin_addr.S_un.S_un_b.s_b3 = 0;
1745 sin->sin_addr.S_un.S_un_b.s_b4 = 1;
1746 }
1747 if (ai->ai_socktype == 0)
1748 ai->ai_socktype = hints->ai_socktype;
1749 if (ai->ai_protocol == 0)
1750 ai->ai_protocol = hints->ai_protocol;
1751 }
1752 ret = ai;
1753 }
1754
1755 if (ret == NULL)
1756 {
1757 error = WSAHOST_NOT_FOUND;
1758 goto End;
1759 }
1760
1761 if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET)
1762 {
1763 freeaddrinfo(ret);
1764 error = WSAEAFNOSUPPORT;
1765 goto End;
1766 }
1767
1768 *res = ret;
1769 error = 0;
1770
1771 End:
1772 WSASetLastError(error);
1773 return error;
1774 }
1775
1776 /* EOF */