[USB-BRINGUP-TRUNK]
[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 = 0;
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 0,
526 sizeof(char *) * 2);
527
528 RtlZeroMemory(new_he->h_addr_list,
529 sizeof(char *) * 2);
530 *he = new_he;
531 }
532 }
533
534 void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr)
535 {
536 ASSERT(he);
537
538 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
539 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
540
541 strncpy(he->h_name,
542 name,
543 MAX_HOSTNAME_LEN);
544
545 if( !he->h_aliases ) {
546 he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
547 he->h_aliases[0] = 0;
548 }
549 he->h_addrtype = AF_INET;
550 he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
551
552 if( he->h_addr_list[0] )
553 {
554 HeapFree(GlobalHeap,
555 0,
556 he->h_addr_list[0]);
557 }
558
559 he->h_addr_list[0] = HeapAlloc(GlobalHeap,
560 0,
561 MAX_HOSTNAME_LEN + 1);
562
563 WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
564
565 RtlCopyMemory(he->h_addr_list[0],
566 (char*)&addr.IpAddress,
567 sizeof(addr.IpAddress));
568
569 he->h_addr_list[1] = 0;
570 }
571
572
573 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
574 void free_hostent(struct hostent *he)
575 {
576 if(he)
577 {
578 char *next = 0;
579 HFREE(he->h_name);
580 if(he->h_aliases)
581 {
582 next = he->h_aliases[0];
583 while(next) { HFREE(next); next++; }
584 }
585 if(he->h_addr_list)
586 {
587 next = he->h_addr_list[0];
588 while(next) { HFREE(next); next++; }
589 }
590 HFREE(he->h_addr_list);
591 HFREE(he->h_aliases);
592 HFREE(he);
593 }
594 }
595
596 /* WinSock 1.1 compatible name resolution APIs */
597
598 /*
599 * @unimplemented
600 */
601 LPHOSTENT
602 EXPORT
603 gethostbyaddr(IN CONST CHAR FAR* addr,
604 IN INT len,
605 IN INT type)
606 {
607 UNIMPLEMENTED
608
609 return (LPHOSTENT)NULL;
610 }
611
612 /*
613 Assumes rfc 1123 - adam *
614 addr[1] = 0;
615 addr[0] = inet_addr(name);
616 strcpy( hostname, name );
617 if(addr[0] == 0xffffffff) return NULL;
618 he.h_addr_list = (void *)addr;
619 he.h_name = hostname;
620 he.h_aliases = NULL;
621 he.h_addrtype = AF_INET;
622 he.h_length = sizeof(addr);
623 return &he;
624
625 <RANT>
626 From the MSDN Platform SDK: Windows Sockets 2
627 "The gethostbyname function cannot resolve IP address strings passed to it.
628 Such a request is treated exactly as if an unknown host name were passed."
629 </RANT>
630
631 Defferring to the the documented behaviour, rather than the unix behaviour
632 What if the hostname is in the HOSTS file? see getservbyname
633
634 * @implemented
635 */
636
637 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
638 /* see ws2_32.h, winsock2.h*/
639 /*getnetworkparameters - iphlp api */
640 /*
641 REFERENCES
642
643 servent -- w32api/include/winsock2.h
644 PWINSOCK_THREAD_BLOCK -- ws2_32.h
645 dllmain.c -- threadlocal memory allocation / deallocation
646 lib/dnsapi
647
648
649 */
650 /* lib/adns/src/adns.h XXX */
651
652
653 /*
654 struct hostent {
655 char *h_name;
656 char **h_aliases;
657 short h_addrtype;
658 short h_length;
659 char **h_addr_list;
660 #define h_addr h_addr_list[0]
661 };
662 struct servent {
663 char *s_name;
664 char **s_aliases;
665 short s_port;
666 char *s_proto;
667 };
668
669
670 struct hostent defined in w32api/include/winsock2.h
671 */
672
673 void free_servent(struct servent* s)
674 {
675 char* next;
676 HFREE(s->s_name);
677 next = s->s_aliases[0];
678 while(next) { HFREE(next); next++; }
679 s->s_port = 0;
680 HFREE(s->s_proto);
681 HFREE(s);
682 }
683
684 /* This function is far from perfect but it works enough */
685 static
686 LPHOSTENT
687 FindEntryInHosts(IN CONST CHAR FAR* name)
688 {
689 BOOL Found = FALSE;
690 HANDLE HostsFile;
691 CHAR HostsDBData[BUFSIZ] = { 0 };
692 PCHAR SystemDirectory = HostsDBData;
693 PCHAR HostsLocation = "\\drivers\\etc\\hosts";
694 PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
695 UINT SystemDirSize = sizeof(HostsDBData) - 1, ValidData = 0;
696 DWORD ReadSize;
697 ULONG Address;
698 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
699
700 /* We assume that the parameters are valid */
701
702 if (!GetSystemDirectoryA(SystemDirectory, SystemDirSize))
703 {
704 WSASetLastError(WSANO_RECOVERY);
705 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
706 return NULL; /* Can't get system directory */
707 }
708
709 strncat(SystemDirectory,
710 HostsLocation,
711 SystemDirSize );
712
713 HostsFile = CreateFileA(SystemDirectory,
714 GENERIC_READ,
715 FILE_SHARE_READ,
716 NULL,
717 OPEN_EXISTING,
718 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
719 NULL);
720 if (HostsFile == INVALID_HANDLE_VALUE)
721 {
722 WSASetLastError(WSANO_RECOVERY);
723 return NULL;
724 }
725
726 while(!Found &&
727 ReadFile(HostsFile,
728 HostsDBData + ValidData,
729 sizeof(HostsDBData) - ValidData,
730 &ReadSize,
731 NULL))
732 {
733 ValidData += ReadSize;
734 ReadSize = 0;
735 NextLine = ThisLine = HostsDBData;
736
737 /* Find the beginning of the next line */
738 while(NextLine < HostsDBData + ValidData &&
739 *NextLine != '\r' && *NextLine != '\n' )
740 {
741 NextLine++;
742 }
743
744 /* Zero and skip, so we can treat what we have as a string */
745 if( NextLine > HostsDBData + ValidData )
746 break;
747
748 *NextLine = 0; NextLine++;
749
750 Comment = strchr( ThisLine, '#' );
751 if( Comment ) *Comment = 0; /* Terminate at comment start */
752
753 AddressStr = ThisLine;
754 /* Find the first space separating the IP address from the DNS name */
755 AddrTerm = strchr(ThisLine, ' ');
756 if (AddrTerm)
757 {
758 /* Terminate the address string */
759 *AddrTerm = 0;
760
761 /* Find the last space before the DNS name */
762 NameSt = strrchr(ThisLine, ' ');
763
764 /* If there is only one space (the one we removed above), then just use the address terminator */
765 if (!NameSt)
766 NameSt = AddrTerm;
767
768 /* Move from the space to the first character of the DNS name */
769 NameSt++;
770
771 DnsName = NameSt;
772
773 if (!strcmp(name, DnsName))
774 {
775 Found = TRUE;
776 break;
777 }
778 }
779
780 /* Get rid of everything we read so far */
781 while( NextLine <= HostsDBData + ValidData &&
782 isspace (*NextLine))
783 {
784 NextLine++;
785 }
786
787 if (HostsDBData + ValidData - NextLine <= 0)
788 break;
789
790 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
791 HostsDBData + ValidData - NextLine));
792
793 memmove(HostsDBData,
794 NextLine,
795 HostsDBData + ValidData - NextLine );
796 ValidData -= NextLine - HostsDBData;
797 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
798 }
799
800 CloseHandle(HostsFile);
801
802 if (!Found)
803 {
804 WS_DbgPrint(MAX_TRACE,("Not found\n"));
805 WSASetLastError(WSANO_DATA);
806 return NULL;
807 }
808
809 if( !p->Hostent )
810 {
811 p->Hostent = HeapAlloc(GlobalHeap, 0, sizeof(*p->Hostent));
812 if( !p->Hostent )
813 {
814 WSASetLastError( WSATRY_AGAIN );
815 return NULL;
816 }
817 }
818
819 p->Hostent->h_name = HeapAlloc(GlobalHeap, 0, strlen(DnsName));
820 if( !p->Hostent->h_name )
821 {
822 WSASetLastError( WSATRY_AGAIN );
823 return NULL;
824 }
825
826 RtlCopyMemory(p->Hostent->h_name,
827 DnsName,
828 strlen(DnsName));
829
830 p->Hostent->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
831 if( !p->Hostent->h_aliases )
832 {
833 WSASetLastError( WSATRY_AGAIN );
834 return NULL;
835 }
836
837 p->Hostent->h_aliases[0] = 0;
838
839 if (strstr(AddressStr, ":"))
840 {
841 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
842 WSASetLastError(WSAEINVAL);
843 return NULL;
844 }
845 else
846 p->Hostent->h_addrtype = AF_INET;
847
848 p->Hostent->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *));
849 if( !p->Hostent->h_addr_list )
850 {
851 WSASetLastError( WSATRY_AGAIN );
852 return NULL;
853 }
854
855 Address = inet_addr(AddressStr);
856 if (Address == INADDR_NONE)
857 {
858 WSASetLastError(WSAEINVAL);
859 return NULL;
860 }
861
862 p->Hostent->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, sizeof(Address));
863 if( !p->Hostent->h_addr_list[0] )
864 {
865 WSASetLastError( WSATRY_AGAIN );
866 return NULL;
867 }
868
869 RtlCopyMemory(p->Hostent->h_addr_list[0],
870 &Address,
871 sizeof(Address));
872
873 p->Hostent->h_length = sizeof(Address);
874
875 return p->Hostent;
876 }
877
878 LPHOSTENT
879 EXPORT
880 gethostbyname(IN CONST CHAR FAR* name)
881 {
882 enum addr_type
883 {
884 GH_INVALID,
885 GH_IPV6,
886 GH_IPV4,
887 GH_RFC1123_DNS
888 };
889 typedef enum addr_type addr_type;
890 addr_type addr;
891 int ret = 0;
892 char* found = 0;
893 DNS_STATUS dns_status = {0};
894 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
895 PDNS_RECORD dp = 0;
896 PWINSOCK_THREAD_BLOCK p;
897 LPHOSTENT Hostent;
898
899 addr = GH_INVALID;
900
901 p = NtCurrentTeb()->WinSockData;
902
903 if( !p )
904 {
905 WSASetLastError( WSANOTINITIALISED );
906 return NULL;
907 }
908
909 check_hostent(&p->Hostent); /*XXX alloc_hostent*/
910
911 /* Hostname NULL - behave like gethostname */
912 if(name == NULL)
913 {
914 ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
915 if(ret)
916 {
917 WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ??
918 return NULL;
919 }
920 return p->Hostent;
921 }
922
923 /* Is it an IPv6 address? */
924 found = strstr(name, ":");
925 if( found != NULL )
926 {
927 addr = GH_IPV6;
928 goto act;
929 }
930
931 /* Is it an IPv4 address? */
932 if (!isalpha(name[0]))
933 {
934 addr = GH_IPV4;
935 goto act;
936 }
937
938 addr = GH_RFC1123_DNS;
939
940 /* Broken out in case we want to get fancy later */
941 act:
942 switch(addr)
943 {
944 case GH_IPV6:
945 WSASetLastError(STATUS_NOT_IMPLEMENTED);
946 return NULL;
947 break;
948
949 case GH_INVALID:
950 WSASetLastError(WSAEFAULT);
951 return NULL;
952 break;
953
954 /* Note: If passed an IP address, MSDN says that gethostbyname()
955 treats it as an unknown host.
956 This is different from the unix implementation. Use inet_addr()
957 */
958 case GH_IPV4:
959 case GH_RFC1123_DNS:
960 /* DNS_TYPE_A: include/WinDNS.h */
961 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
962
963 /* Look for the DNS name in the hosts file */
964 Hostent = FindEntryInHosts(name);
965 if (Hostent)
966 return Hostent;
967
968 dns_status = DnsQuery_A(name,
969 DNS_TYPE_A,
970 DNS_QUERY_STANDARD,
971 0,
972 /* extra dns servers */ &dp,
973 0);
974
975 if(dns_status == 0)
976 {
977 //ASSERT(dp->wType == DNS_TYPE_A);
978 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
979 PDNS_RECORD curr;
980 for(curr=dp;
981 curr != NULL && curr->wType != DNS_TYPE_A;
982 curr = curr->pNext )
983 {
984 WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
985 /*empty */
986 }
987
988 if(curr)
989 {
990 WS_DbgPrint(MID_TRACE,("populating hostent\n"));
991 WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
992 populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
993 DnsRecordListFree(dp, DnsFreeRecordList);
994 return p->Hostent;
995 }
996 else
997 {
998 DnsRecordListFree(dp, DnsFreeRecordList);
999 }
1000 }
1001
1002 WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
1003 dns_status));
1004 WSASetLastError(WSAHOST_NOT_FOUND);
1005 return NULL;
1006
1007 break;
1008
1009 default:
1010 WSASetLastError(WSANO_RECOVERY);
1011 return NULL;
1012 break;
1013 }
1014
1015 WSASetLastError(WSANO_RECOVERY);
1016 return NULL;
1017 }
1018
1019 /*
1020 * @implemented
1021 */
1022 INT
1023 EXPORT
1024 gethostname(OUT CHAR FAR* name,
1025 IN INT namelen)
1026 {
1027 DWORD size = namelen;
1028
1029 int ret = GetComputerNameExA(ComputerNameDnsHostname,
1030 name,
1031 &size);
1032 if(ret == 0)
1033 {
1034 WSASetLastError(WSAEFAULT);
1035 return SOCKET_ERROR;
1036 }
1037 else
1038 {
1039 name[namelen-1] = '\0';
1040 return 0;
1041 }
1042 }
1043
1044
1045 /*
1046 * XXX arty -- Partial implementation pending a better one. This one will
1047 * do for normal purposes.#include <ws2_32.h>
1048 *
1049 * Return the address of a static LPPROTOENT corresponding to the named
1050 * protocol. These structs aren't very interesting, so I'm not too ashamed
1051 * to have this function work on builtins for now.
1052 *
1053 * @unimplemented
1054 */
1055
1056 static CHAR *no_aliases = 0;
1057 static PROTOENT protocols[] =
1058 {
1059 {"icmp",&no_aliases, IPPROTO_ICMP},
1060 {"tcp", &no_aliases, IPPROTO_TCP},
1061 {"udp", &no_aliases, IPPROTO_UDP},
1062 {NULL, NULL, 0}
1063 };
1064
1065 LPPROTOENT
1066 EXPORT
1067 getprotobyname(IN CONST CHAR FAR* name)
1068 {
1069 UINT i;
1070 for (i = 0; protocols[i].p_name; i++)
1071 {
1072 if (_stricmp(protocols[i].p_name, name) == 0)
1073 return &protocols[i];
1074 }
1075 return NULL;
1076 }
1077
1078 /*
1079 * @unimplemented
1080 */
1081 LPPROTOENT
1082 EXPORT
1083 getprotobynumber(IN INT number)
1084 {
1085 UINT i;
1086 for (i = 0; protocols[i].p_name; i++)
1087 {
1088 if (protocols[i].p_proto == number)
1089 return &protocols[i];
1090 }
1091 return NULL;
1092 }
1093
1094 #define SKIPWS(ptr,act) \
1095 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1096 #define SKIPANDMARKSTR(ptr,act) \
1097 {while(*ptr && !isspace(*ptr)) ptr++; \
1098 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1099
1100
1101 static BOOL
1102 DecodeServEntFromString(IN PCHAR ServiceString,
1103 OUT PCHAR *ServiceName,
1104 OUT PCHAR *PortNumberStr,
1105 OUT PCHAR *ProtocolStr,
1106 IN PCHAR *Aliases,
1107 IN DWORD MaxAlias)
1108 {
1109 UINT NAliases = 0;
1110
1111 WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
1112
1113 SKIPWS(ServiceString, return FALSE);
1114 *ServiceName = ServiceString;
1115 SKIPANDMARKSTR(ServiceString, return FALSE);
1116 SKIPWS(ServiceString, return FALSE);
1117 *PortNumberStr = ServiceString;
1118 SKIPANDMARKSTR(ServiceString, ;);
1119
1120 while( *ServiceString && NAliases < MaxAlias - 1 )
1121 {
1122 SKIPWS(ServiceString, break);
1123 if( *ServiceString )
1124 {
1125 SKIPANDMARKSTR(ServiceString, ;);
1126 if( strlen(ServiceString) )
1127 {
1128 WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
1129 *Aliases++ = ServiceString;
1130 NAliases++;
1131 }
1132 }
1133 }
1134 *Aliases = NULL;
1135
1136 *ProtocolStr = strchr(*PortNumberStr,'/');
1137 if( !*ProtocolStr ) return FALSE;
1138 **ProtocolStr = 0; (*ProtocolStr)++;
1139
1140 WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
1141 *ServiceName, *ProtocolStr, *PortNumberStr,
1142 NAliases));
1143
1144 return TRUE;
1145 }
1146
1147 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1148
1149 /*
1150 * @implemented
1151 */
1152 LPSERVENT
1153 EXPORT
1154 getservbyname(IN CONST CHAR FAR* name,
1155 IN CONST CHAR FAR* proto)
1156 {
1157 BOOL Found = FALSE;
1158 HANDLE ServicesFile;
1159 CHAR ServiceDBData[BUFSIZ] = { 0 };
1160 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
1161 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
1162 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
1163 ProtocolStr = 0, Comment = 0, EndValid;
1164 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
1165 UINT i,SizeNeeded = 0,
1166 SystemDirSize = sizeof(ServiceDBData) - 1;
1167 DWORD ReadSize = 0;
1168 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
1169
1170 if( !p )
1171 {
1172 WSASetLastError( WSANOTINITIALISED );
1173 return NULL;
1174 }
1175
1176 if( !name )
1177 {
1178 WSASetLastError( WSANO_RECOVERY );
1179 return NULL;
1180 }
1181
1182 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
1183 {
1184 WSASetLastError( WSANO_RECOVERY );
1185 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
1186 return NULL; /* Can't get system directory */
1187 }
1188
1189 strncat(SystemDirectory,
1190 ServicesFileLocation,
1191 SystemDirSize );
1192
1193 ServicesFile = CreateFileA(SystemDirectory,
1194 GENERIC_READ,
1195 FILE_SHARE_READ,
1196 NULL,
1197 OPEN_EXISTING,
1198 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
1199 NULL );
1200
1201 if( ServicesFile == INVALID_HANDLE_VALUE )
1202 {
1203 WSASetLastError( WSANO_RECOVERY );
1204 return NULL;
1205 }
1206
1207 /* Scan the services file ...
1208 *
1209 * We will be share the buffer on the lines. If the line does not fit in
1210 * the buffer, then moving it to the beginning of the buffer and read
1211 * the remnants of line from file.
1212 */
1213
1214 /* Initial Read */
1215 ReadFile(ServicesFile,
1216 ServiceDBData,
1217 sizeof( ServiceDBData ) - 1,
1218 &ReadSize, NULL );
1219 ThisLine = NextLine = ServiceDBData;
1220 EndValid = ServiceDBData + ReadSize;
1221 ServiceDBData[sizeof(ServiceDBData) - 1] = '\0';
1222
1223 while(ReadSize)
1224 {
1225 for(; *NextLine != '\r' && *NextLine != '\n'; NextLine++)
1226 {
1227 if(NextLine == EndValid)
1228 {
1229 int LineLen = NextLine - ThisLine;
1230
1231 if(ThisLine == ServiceDBData)
1232 {
1233 WS_DbgPrint(MIN_TRACE,("Line too long"));
1234 WSASetLastError( WSANO_RECOVERY );
1235 return NULL;
1236 }
1237
1238 memmove(ServiceDBData, ThisLine, LineLen);
1239
1240 ReadFile(ServicesFile, ServiceDBData + LineLen,
1241 sizeof( ServiceDBData )-1 - LineLen,
1242 &ReadSize, NULL );
1243
1244 EndValid = ServiceDBData + LineLen + ReadSize;
1245 NextLine = ServiceDBData + LineLen;
1246 ThisLine = ServiceDBData;
1247
1248 if(!ReadSize) break;
1249 }
1250 }
1251
1252 *NextLine = '\0';
1253 Comment = strchr( ThisLine, '#' );
1254 if( Comment ) *Comment = '\0'; /* Terminate at comment start */
1255
1256 if(DecodeServEntFromString(ThisLine,
1257 &ServiceName,
1258 &PortNumberStr,
1259 &ProtocolStr,
1260 Aliases,
1261 WS2_INTERNAL_MAX_ALIAS) &&
1262 !strcmp( ServiceName, name ) &&
1263 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
1264 {
1265
1266 WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
1267 Found = TRUE;
1268 SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
1269 (NextLine - ThisLine);
1270 break;
1271 }
1272 NextLine++;
1273 ThisLine = NextLine;
1274 }
1275
1276 /* This we'll do no matter what */
1277 CloseHandle( ServicesFile );
1278
1279 if( !Found )
1280 {
1281 WS_DbgPrint(MAX_TRACE,("Not found\n"));
1282 WSASetLastError( WSANO_DATA );
1283 return NULL;
1284 }
1285
1286 if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded )
1287 {
1288 /* Free previous getservbyname buffer, allocate bigger */
1289 if( p->Getservbyname )
1290 HeapFree(GlobalHeap, 0, p->Getservbyname);
1291 p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
1292 if( !p->Getservbyname )
1293 {
1294 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1295 SizeNeeded));
1296 WSASetLastError( WSATRY_AGAIN );
1297 return NULL;
1298 }
1299 p->Getservbyname->Size = SizeNeeded;
1300 }
1301
1302 /* Copy the data */
1303 memmove(p->Getservbyname->Data,
1304 ThisLine,
1305 NextLine - ThisLine );
1306
1307 ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
1308 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
1309 WS_DbgPrint(MAX_TRACE, ("ServiceName: %s, Protocol: %s\n",
1310 ServiceName,
1311 ProtocolStr));
1312
1313 for( i = 0; Aliases[i]; i++ )
1314 {
1315 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
1316 WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
1317 }
1318
1319 memcpy(p->Getservbyname,
1320 Aliases,
1321 sizeof(Aliases));
1322
1323 /* Create the struct proper */
1324 p->Getservbyname->ServerEntry.s_name = ServiceName;
1325 p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases;
1326 p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr));
1327 p->Getservbyname->ServerEntry.s_proto = ProtocolStr;
1328
1329 return &p->Getservbyname->ServerEntry;
1330 }
1331
1332
1333 /*
1334 * @implemented
1335 */
1336 LPSERVENT
1337 EXPORT
1338 getservbyport(IN INT port,
1339 IN CONST CHAR FAR* proto)
1340 {
1341 BOOL Found = FALSE;
1342 HANDLE ServicesFile;
1343 CHAR ServiceDBData[BUFSIZ] = { 0 };
1344 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
1345 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
1346 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
1347 ProtocolStr = 0, Comment = 0;
1348 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
1349 UINT i,SizeNeeded = 0,
1350 SystemDirSize = sizeof(ServiceDBData) - 1;
1351 DWORD ReadSize = 0, ValidData = 0;
1352 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
1353
1354 if( !p )
1355 {
1356 WSASetLastError( WSANOTINITIALISED );
1357 return NULL;
1358 }
1359
1360 if ( !port )
1361 {
1362 WSASetLastError( WSANO_RECOVERY );
1363 return NULL;
1364 }
1365
1366 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
1367 {
1368 WSASetLastError( WSANO_RECOVERY );
1369 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
1370 return NULL; /* Can't get system directory */
1371 }
1372
1373 strncat(SystemDirectory,
1374 ServicesFileLocation,
1375 SystemDirSize );
1376
1377 ServicesFile = CreateFileA(SystemDirectory,
1378 GENERIC_READ,
1379 FILE_SHARE_READ,
1380 NULL,
1381 OPEN_EXISTING,
1382 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
1383 NULL );
1384
1385 if( ServicesFile == INVALID_HANDLE_VALUE )
1386 {
1387 WSASetLastError( WSANO_RECOVERY );
1388 return NULL;
1389 }
1390
1391 /* Scan the services file ...
1392 *
1393 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1394 * contain a full line, then we will try to read more.
1395 *
1396 * We fall from the loop if the buffer does not have a line terminator.
1397 */
1398
1399 /* Initial Read */
1400 while(!Found &&
1401 ReadFile(ServicesFile,
1402 ServiceDBData + ValidData,
1403 sizeof( ServiceDBData ) - ValidData,
1404 &ReadSize, NULL ) )
1405 {
1406 ValidData += ReadSize;
1407 ReadSize = 0;
1408 NextLine = ThisLine = ServiceDBData;
1409
1410 /* Find the beginning of the next line */
1411 while( NextLine < ServiceDBData + ValidData &&
1412 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
1413
1414 /* Zero and skip, so we can treat what we have as a string */
1415 if( NextLine > ServiceDBData + ValidData )
1416 break;
1417
1418 *NextLine = 0; NextLine++;
1419
1420 Comment = strchr( ThisLine, '#' );
1421 if( Comment ) *Comment = 0; /* Terminate at comment start */
1422
1423 if(DecodeServEntFromString(ThisLine,
1424 &ServiceName,
1425 &PortNumberStr,
1426 &ProtocolStr,
1427 Aliases,
1428 WS2_INTERNAL_MAX_ALIAS ) &&
1429 (htons(atoi( PortNumberStr )) == port ) &&
1430 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
1431 {
1432
1433 WS_DbgPrint(MAX_TRACE,("Found the port entry.\n"));
1434
1435 Found = TRUE;
1436 SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) +
1437 (NextLine - ThisLine);
1438 break;
1439 }
1440
1441 /* Get rid of everything we read so far */
1442 while( NextLine <= ServiceDBData + ValidData &&
1443 isspace( *NextLine ) )
1444 {
1445 NextLine++;
1446 }
1447
1448 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
1449 ServiceDBData + ValidData - NextLine));
1450
1451 memmove(ServiceDBData,
1452 NextLine,
1453 ServiceDBData + ValidData - NextLine );
1454 ValidData -= NextLine - ServiceDBData;
1455 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
1456 }
1457
1458 /* This we'll do no matter what */
1459 CloseHandle( ServicesFile );
1460
1461 if( !Found )
1462 {
1463 WS_DbgPrint(MAX_TRACE,("Not found\n"));
1464 WSASetLastError( WSANO_DATA );
1465 return NULL;
1466 }
1467
1468 if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded )
1469 {
1470 /* Free previous getservbyport buffer, allocate bigger */
1471 if( p->Getservbyport )
1472 HeapFree(GlobalHeap, 0, p->Getservbyport);
1473 p->Getservbyport = HeapAlloc(GlobalHeap,
1474 0,
1475 SizeNeeded);
1476 if( !p->Getservbyport )
1477 {
1478 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1479 SizeNeeded));
1480 WSASetLastError( WSATRY_AGAIN );
1481 return NULL;
1482 }
1483 p->Getservbyport->Size = SizeNeeded;
1484 }
1485 /* Copy the data */
1486 memmove(p->Getservbyport->Data,
1487 ThisLine,
1488 NextLine - ThisLine );
1489
1490 ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data);
1491 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data);
1492 WS_DbgPrint(MAX_TRACE, ("Port Number: %s, Protocol: %s\n",
1493 PortNumberStr, ProtocolStr));
1494
1495 for( i = 0; Aliases[i]; i++ )
1496 {
1497 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
1498 WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
1499 }
1500
1501 memcpy(p->Getservbyport,Aliases,sizeof(Aliases));
1502
1503 /* Create the struct proper */
1504 p->Getservbyport->ServerEntry.s_name = ServiceName;
1505 p->Getservbyport->ServerEntry.s_aliases = p->Getservbyport->Aliases;
1506 p->Getservbyport->ServerEntry.s_port = port;
1507 p->Getservbyport->ServerEntry.s_proto = ProtocolStr;
1508
1509 WS_DbgPrint(MID_TRACE,("s_name: %s\n", ServiceName));
1510
1511 return &p->Getservbyport->ServerEntry;
1512
1513 }
1514
1515
1516 /*
1517 * @implemented
1518 */
1519 ULONG
1520 EXPORT
1521 inet_addr(IN CONST CHAR FAR* cp)
1522 /*
1523 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1524 * ARGUMENTS:
1525 * cp = Pointer to string with address to convert
1526 * RETURNS:
1527 * Binary representation of IPv4 address, or INADDR_NONE
1528 */
1529 {
1530 UINT i;
1531 PCHAR p;
1532 ULONG u = 0;
1533
1534 p = (PCHAR)cp;
1535
1536 if (!p)
1537 {
1538 WSASetLastError(WSAEFAULT);
1539 return INADDR_NONE;
1540 }
1541
1542 if (strlen(p) == 0)
1543 return INADDR_NONE;
1544
1545 if (strcmp(p, " ") == 0)
1546 return 0;
1547
1548 for (i = 0; i <= 3; i++)
1549 {
1550 u += (strtoul(p, &p, 0) << (i * 8));
1551
1552 if (strlen(p) == 0)
1553 return u;
1554
1555 if (p[0] != '.')
1556 return INADDR_NONE;
1557
1558 p++;
1559 }
1560
1561 return u;
1562 }
1563
1564
1565 /*
1566 * @implemented
1567 */
1568 CHAR FAR*
1569 EXPORT
1570 inet_ntoa(IN IN_ADDR in)
1571 {
1572 CHAR b[10];
1573 PCHAR p;
1574
1575 p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa;
1576 _itoa(in.S_un.S_addr & 0xFF, b, 10);
1577 strcpy(p, b);
1578 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
1579 strcat(p, ".");
1580 strcat(p, b);
1581 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
1582 strcat(p, ".");
1583 strcat(p, b);
1584 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
1585 strcat(p, ".");
1586 strcat(p, b);
1587
1588 return (CHAR FAR*)p;
1589 }
1590
1591
1592 /*
1593 * @implemented
1594 */
1595 VOID
1596 EXPORT
1597 freeaddrinfo(struct addrinfo *pAddrInfo)
1598 {
1599 struct addrinfo *next, *cur;
1600 cur = pAddrInfo;
1601 while (cur)
1602 {
1603 next = cur->ai_next;
1604 if (cur->ai_addr)
1605 HeapFree(GetProcessHeap(), 0, cur->ai_addr);
1606 if (cur->ai_canonname)
1607 HeapFree(GetProcessHeap(), 0, cur->ai_canonname);
1608 HeapFree(GetProcessHeap(), 0, cur);
1609 cur = next;
1610 }
1611 }
1612
1613
1614 struct addrinfo *
1615 new_addrinfo(struct addrinfo *prev)
1616 {
1617 struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo));
1618 if (prev)
1619 prev->ai_next = ret;
1620 return ret;
1621 }
1622
1623 /*
1624 * @implemented
1625 */
1626 INT
1627 EXPORT
1628 getaddrinfo(const char FAR * nodename,
1629 const char FAR * servname,
1630 const struct addrinfo FAR * hints,
1631 struct addrinfo FAR * FAR * res)
1632 {
1633 struct addrinfo *ret = NULL, *ai;
1634 ULONG addr;
1635 USHORT port;
1636 struct servent *se;
1637 char *proto;
1638 LPPROTOENT pent;
1639 DNS_STATUS dns_status;
1640 PDNS_RECORD dp, currdns;
1641 struct sockaddr_in *sin;
1642
1643 if (res == NULL)
1644 return WSAEINVAL;
1645 if (nodename == NULL && servname == NULL)
1646 return WSAHOST_NOT_FOUND;
1647
1648 if (!WSAINITIALIZED)
1649 return WSANOTINITIALISED;
1650
1651 if (servname)
1652 {
1653 /* converting port number */
1654 port = strtoul(servname, NULL, 10);
1655 /* service name was specified? */
1656 if (port == 0)
1657 {
1658 /* protocol was specified? */
1659 if (hints && hints->ai_protocol)
1660 {
1661 pent = getprotobynumber(hints->ai_protocol);
1662 if (pent == NULL)
1663 return WSAEINVAL;
1664 proto = pent->p_name;
1665 }
1666 else
1667 proto = NULL;
1668 se = getservbyname(servname, proto);
1669 if (se == NULL)
1670 return WSATYPE_NOT_FOUND;
1671 port = se->s_port;
1672 }
1673 else
1674 port = htons(port);
1675 }
1676 else
1677 port = 0;
1678
1679 if (nodename)
1680 {
1681 /* Is it an IPv6 address? */
1682 if (strstr(nodename, ":"))
1683 return WSAHOST_NOT_FOUND;
1684
1685 /* Is it an IPv4 address? */
1686 addr = inet_addr(nodename);
1687 if (addr != INADDR_NONE)
1688 {
1689 ai = new_addrinfo(NULL);
1690 ai->ai_family = PF_INET;
1691 ai->ai_addrlen = sizeof(struct sockaddr_in);
1692 ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
1693 sin = (struct sockaddr_in *)ai->ai_addr;
1694 sin->sin_family = AF_INET;
1695 sin->sin_port = port;
1696 RtlCopyMemory(&sin->sin_addr, &addr, sizeof(sin->sin_addr));
1697 if (hints)
1698 {
1699 if (ai->ai_socktype == 0)
1700 ai->ai_socktype = hints->ai_socktype;
1701 if (ai->ai_protocol == 0)
1702 ai->ai_protocol = hints->ai_protocol;
1703 }
1704 ret = ai;
1705 }
1706 else
1707 {
1708 /* resolving host name */
1709 dns_status = DnsQuery_A(nodename,
1710 DNS_TYPE_A,
1711 DNS_QUERY_STANDARD,
1712 0,
1713 /* extra dns servers */ &dp,
1714 0);
1715
1716 if (dns_status == 0)
1717 {
1718 ai = NULL;
1719 for (currdns = dp; currdns; currdns = currdns->pNext )
1720 {
1721 /* accept only A records */
1722 if (currdns->wType != DNS_TYPE_A) continue;
1723
1724 ai = new_addrinfo(ai);
1725 if (ret == NULL)
1726 ret = ai;
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 *)ret->ai_addr;
1731 sin->sin_family = AF_INET;
1732 sin->sin_port = port;
1733 RtlCopyMemory(&sin->sin_addr, &currdns->Data.A.IpAddress, sizeof(sin->sin_addr));
1734 if (hints)
1735 {
1736 if (ai->ai_socktype == 0)
1737 ai->ai_socktype = hints->ai_socktype;
1738 if (ai->ai_protocol == 0)
1739 ai->ai_protocol = hints->ai_protocol;
1740 }
1741 }
1742 DnsRecordListFree(dp, DnsFreeRecordList);
1743 }
1744 }
1745 }
1746 else
1747 {
1748 ai = new_addrinfo(NULL);
1749 ai->ai_family = PF_INET;
1750 ai->ai_addrlen = sizeof(struct sockaddr_in);
1751 ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
1752 sin = (struct sockaddr_in *)ai->ai_addr;
1753 sin->sin_family = AF_INET;
1754 sin->sin_port = port;
1755 if (hints)
1756 {
1757 if (!(hints->ai_flags & AI_PASSIVE))
1758 {
1759 sin->sin_addr.S_un.S_un_b.s_b1 = 127;
1760 sin->sin_addr.S_un.S_un_b.s_b2 = 0;
1761 sin->sin_addr.S_un.S_un_b.s_b3 = 0;
1762 sin->sin_addr.S_un.S_un_b.s_b4 = 1;
1763 }
1764 if (ai->ai_socktype == 0)
1765 ai->ai_socktype = hints->ai_socktype;
1766 if (ai->ai_protocol == 0)
1767 ai->ai_protocol = hints->ai_protocol;
1768 }
1769 ret = ai;
1770 }
1771
1772 if (ret == NULL)
1773 return WSAHOST_NOT_FOUND;
1774
1775 if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET)
1776 {
1777 freeaddrinfo(ret);
1778 return WSAEAFNOSUPPORT;
1779 }
1780
1781 *res = ret;
1782 return 0;
1783 }
1784
1785 /* EOF */