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