ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

query.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS system libraries
00004  * FILE:        lib/dnsapi/dnsapi/query.c
00005  * PURPOSE:     DNSAPI functions built on the ADNS library.
00006  * PROGRAMER:   Art Yerkes
00007  * UPDATE HISTORY:
00008  *              12/15/03 -- Created
00009  */
00010 
00011 #include "precomp.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* DnsQuery ****************************
00017  * Begin a DNS query, and allow the result to be placed in the application
00018  * supplied result pointer.  The result can be manipulated with the record
00019  * functions.
00020  *
00021  * Name                 -- The DNS object to be queried.
00022  * Type                 -- The type of records to be returned.  These are
00023  *                          listed in windns.h
00024  * Options              -- Query options.  DNS_QUERY_STANDARD is the base
00025  *                          state, and every other option takes precedence.
00026  *                          multiple options can be combined.  Listed in
00027  *                          windns.h
00028  * Servers              -- List of alternate servers (optional)
00029  * QueryResultSet       -- Pointer to the result pointer that will be filled
00030  *                          when the response is available.
00031  * Reserved             -- Response as it appears on the wire.  Optional.
00032  */
00033 
00034 char
00035 *xstrsave(const char *str)
00036 {
00037     char *p;
00038 
00039     p = RtlAllocateHeap(RtlGetProcessHeap(), 0, strlen(str) + 1);
00040 
00041     if(p)
00042         strcpy(p, str);
00043 
00044     return p;
00045 }
00046 
00047 DNS_STATUS WINAPI
00048 DnsQuery_A(LPCSTR Name,
00049            WORD Type,
00050            DWORD Options,
00051            PIP4_ARRAY Servers,
00052            PDNS_RECORD *QueryResultSet,
00053            PVOID *Reserved)
00054 {
00055     adns_state astate;
00056     int quflags = 0;
00057     int adns_error;
00058     adns_answer *answer;
00059     LPSTR CurrentName;
00060     unsigned i, CNameLoop;
00061 
00062     *QueryResultSet = 0;
00063 
00064     switch(Type)
00065     {
00066         case DNS_TYPE_A:
00067             adns_error = adns_init(&astate, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn, 0);
00068 
00069             if(adns_error != adns_s_ok)
00070                 return DnsIntTranslateAdnsToDNS_STATUS(adns_error);
00071 
00072             if (Servers)
00073             {
00074                 for(i = 0; i < Servers->AddrCount; i++)
00075                 {
00076                     adns_addserver(astate, *((struct in_addr *)&Servers->AddrArray[i]));
00077                 }
00078             }
00079 
00080             /*
00081              * adns doesn't resolve chained CNAME records (a CNAME which points to
00082              * another CNAME pointing to another... pointing to an A record), according
00083              * to a mailing list thread the authors believe that chained CNAME records
00084              * are invalid and the DNS entries should be fixed. That's a nice academic
00085              * standpoint, but there certainly are chained CNAME records out there,
00086              * even some fairly major ones (at the time of this writing
00087              * download.mozilla.org is a chained CNAME). Everyone else seems to resolve
00088              * these fine, so we should too. So we loop here to try to resolve CNAME
00089              * chains ourselves. Of course, there must be a limit to protect against
00090              * CNAME loops.
00091              */
00092 
00093 #define CNAME_LOOP_MAX 16
00094 
00095             CurrentName = (LPSTR) Name;
00096 
00097             for (CNameLoop = 0; CNameLoop < CNAME_LOOP_MAX; CNameLoop++)
00098             {
00099                 adns_error = adns_synchronous(astate, CurrentName, adns_r_addr, quflags, &answer);
00100 
00101                 if(adns_error != adns_s_ok)
00102                 {
00103                     adns_finish(astate);
00104 
00105                     if (CurrentName != Name)
00106                         RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
00107 
00108                     return DnsIntTranslateAdnsToDNS_STATUS(adns_error);
00109                 }
00110 
00111                 if(answer && answer->rrs.addr)
00112                 {
00113                     if (CurrentName != Name)
00114                         RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
00115 
00116                     *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
00117 
00118                     if (NULL == *QueryResultSet)
00119                     {
00120                         adns_finish( astate );
00121                         return ERROR_OUTOFMEMORY;
00122                     }
00123 
00124                     (*QueryResultSet)->pNext = NULL;
00125                     (*QueryResultSet)->wType = Type;
00126                     (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
00127                     (*QueryResultSet)->Data.A.IpAddress = answer->rrs.addr->addr.inet.sin_addr.s_addr;
00128 
00129                     adns_finish(astate);
00130 
00131                     (*QueryResultSet)->pName = xstrsave( Name );
00132 
00133                     return NULL != (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
00134                 }
00135 
00136                 if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname)
00137                 {
00138                     adns_finish(astate);
00139 
00140                     if (CurrentName != Name)
00141                         RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
00142 
00143                     return ERROR_FILE_NOT_FOUND;
00144                 }
00145 
00146                 if (CurrentName != Name)
00147                     RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
00148 
00149                 CurrentName = xstrsave(answer->cname);
00150 
00151                 if (!CurrentName)
00152                 {
00153                     adns_finish(astate);
00154                     return ERROR_OUTOFMEMORY;
00155                 }
00156             }
00157 
00158             adns_finish(astate);
00159             RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
00160             return ERROR_FILE_NOT_FOUND;
00161 
00162         default:
00163             return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */
00164     }
00165 }
00166 
00167 static PCHAR
00168 DnsWToC(const WCHAR *WideString)
00169 {
00170     int chars = wcstombs(NULL, WideString, 0);
00171     PCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, chars + 1);
00172 
00173     wcstombs(out, WideString, chars + 1);
00174 
00175     return out;
00176 }
00177 
00178 static PWCHAR
00179 DnsCToW(const CHAR *NarrowString)
00180 {
00181     int chars = mbstowcs(NULL, NarrowString, 0);
00182     PWCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, (chars + 1) * sizeof(WCHAR));
00183 
00184     mbstowcs(out, NarrowString, chars + 1);
00185 
00186     return out;
00187 }
00188 
00189 DNS_STATUS WINAPI
00190 DnsQuery_W(LPCWSTR Name,
00191            WORD Type,
00192            DWORD Options,
00193            PIP4_ARRAY Servers,
00194            PDNS_RECORD *QueryResultSet,
00195            PVOID *Reserved)
00196 {
00197     UINT i;
00198     PCHAR Buffer;
00199     DNS_STATUS Status;
00200     PDNS_RECORD QueryResultWide;
00201     PDNS_RECORD ConvertedRecord = 0, LastRecord = 0;
00202 
00203     Buffer = DnsWToC(Name);
00204 
00205     Status = DnsQuery_A(Buffer, Type, Options, Servers, &QueryResultWide, Reserved);
00206 
00207     while(Status == ERROR_SUCCESS && QueryResultWide)
00208     {
00209         switch(QueryResultWide->wType)
00210         {
00211             case DNS_TYPE_A:
00212             case DNS_TYPE_WKS:
00213                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
00214                 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
00215                 ConvertedRecord->wType = QueryResultWide->wType;
00216                 ConvertedRecord->wDataLength = QueryResultWide->wDataLength;
00217                 memcpy(ConvertedRecord, QueryResultWide, QueryResultWide->wDataLength);
00218                 break;
00219 
00220             case DNS_TYPE_CNAME:
00221             case DNS_TYPE_PTR:
00222             case DNS_TYPE_NS:
00223             case DNS_TYPE_MB:
00224             case DNS_TYPE_MD:
00225             case DNS_TYPE_MF:
00226             case DNS_TYPE_MG:
00227             case DNS_TYPE_MR:
00228                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
00229                 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
00230                 ConvertedRecord->wType = QueryResultWide->wType;
00231                 ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATA);
00232                 ConvertedRecord->Data.PTR.pNameHost = (PCHAR)DnsCToW(QueryResultWide->Data.PTR.pNameHost);
00233                 break;
00234 
00235             case DNS_TYPE_MINFO:
00236                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
00237                 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
00238                 ConvertedRecord->wType = QueryResultWide->wType;
00239                 ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA);
00240                 ConvertedRecord->Data.MINFO.pNameMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameMailbox);
00241                 ConvertedRecord->Data.MINFO.pNameErrorsMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameErrorsMailbox);
00242                 break;
00243 
00244             case DNS_TYPE_MX:
00245                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
00246                 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
00247                 ConvertedRecord->wType = QueryResultWide->wType;
00248                 ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA);
00249                 ConvertedRecord->Data.MX.pNameExchange = (PCHAR)DnsCToW( QueryResultWide->Data.MX.pNameExchange);
00250                 ConvertedRecord->Data.MX.wPreference = QueryResultWide->Data.MX.wPreference;
00251                 break;
00252 
00253             case DNS_TYPE_HINFO:
00254                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA) + QueryResultWide->Data.TXT.dwStringCount);
00255                 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
00256                 ConvertedRecord->wType = QueryResultWide->wType;
00257                 ConvertedRecord->wDataLength = sizeof(DNS_TXT_DATA) + (sizeof(PWCHAR) * QueryResultWide->Data.TXT.dwStringCount);
00258                 ConvertedRecord->Data.TXT.dwStringCount = QueryResultWide->Data.TXT.dwStringCount;
00259 
00260                 for(i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++)
00261                     ConvertedRecord->Data.TXT.pStringArray[i] = (PCHAR)DnsCToW(QueryResultWide->Data.TXT.pStringArray[i]);
00262 
00263                 break;
00264 
00265             case DNS_TYPE_NULL:
00266                 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount);
00267                 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
00268                 ConvertedRecord->wType = QueryResultWide->wType;
00269                 ConvertedRecord->wDataLength = sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount;
00270                 ConvertedRecord->Data.Null.dwByteCount = QueryResultWide->Data.Null.dwByteCount;
00271                 memcpy(&ConvertedRecord->Data.Null.Data, &QueryResultWide->Data.Null.Data, QueryResultWide->Data.Null.dwByteCount);
00272                 break;
00273         }
00274 
00275         if(LastRecord)
00276         {
00277             LastRecord->pNext = ConvertedRecord;
00278             LastRecord = LastRecord->pNext;
00279         }
00280         else
00281         {
00282             LastRecord = *QueryResultSet = ConvertedRecord;
00283         }
00284     }
00285 
00286     LastRecord->pNext = 0;
00287 
00288     /* The name */
00289     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00290 
00291     return Status;
00292 }
00293 
00294 DNS_STATUS WINAPI
00295 DnsQuery_UTF8(LPCSTR Name,
00296               WORD Type,
00297               DWORD Options,
00298               PIP4_ARRAY Servers,
00299               PDNS_RECORD *QueryResultSet,
00300               PVOID *Reserved)
00301 {
00302     UNIMPLEMENTED;
00303     return ERROR_OUTOFMEMORY;
00304 }
00305 
00306 void
00307 DnsIntFreeRecordList(PDNS_RECORD ToDelete)
00308 {
00309     UINT i;
00310     PDNS_RECORD next = 0;
00311 
00312     while(ToDelete)
00313     {
00314         if(ToDelete->pName)
00315             RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->pName);
00316 
00317         switch(ToDelete->wType)
00318         {
00319             case DNS_TYPE_CNAME:
00320             case DNS_TYPE_PTR:
00321             case DNS_TYPE_NS:
00322             case DNS_TYPE_MB:
00323             case DNS_TYPE_MD:
00324             case DNS_TYPE_MF:
00325             case DNS_TYPE_MG:
00326             case DNS_TYPE_MR:
00327                 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.PTR.pNameHost);
00328                 break;
00329 
00330             case DNS_TYPE_MINFO:
00331             case DNS_TYPE_MX:
00332                 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.MX.pNameExchange);
00333                 break;
00334 
00335             case DNS_TYPE_HINFO:
00336                 for(i = 0; i < ToDelete->Data.TXT.dwStringCount; i++)
00337                     RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray[i]);
00338 
00339                 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray);
00340                 break;
00341         }
00342 
00343         next = ToDelete->pNext;
00344         RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete);
00345         ToDelete = next;
00346     }
00347 }

Generated on Sun May 27 2012 04:17:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.