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