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

sablob.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS DNS Shared Library
00004  * FILE:        lib/dnslib/sablob.c
00005  * PURPOSE:     Functions for the Saved Answer Blob Implementation
00006  */
00007 
00008 /* INCLUDES ******************************************************************/
00009 #include "precomp.h"
00010 
00011 /* DATA **********************************************************************/
00012 
00013 /* FUNCTIONS *****************************************************************/
00014 
00015 PVOID
00016 WINAPI
00017 FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position,
00018                                 IN PSIZE_T FreeSize,
00019                                 IN SIZE_T Size)
00020 {
00021     /* Just a little helper that we use */
00022     return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID));
00023 }
00024 
00025 PDNS_BLOB
00026 WINAPI
00027 SaBlob_Create(IN ULONG Count)
00028 {
00029     PDNS_BLOB Blob;
00030     PDNS_ARRAY DnsAddrArray;
00031 
00032     /* Allocate the blob */
00033     Blob = Dns_AllocZero(sizeof(DNS_BLOB));
00034     if (Blob)
00035     {
00036         /* Check if it'll hold any addresses */
00037         if (Count)
00038         {
00039             /* Create the DNS Address Array */
00040             DnsAddrArray = DnsAddrArray_Create(Count);
00041             if (!DnsAddrArray)
00042             {
00043                 /* Failure, free the blob */
00044                 SaBlob_Free(Blob);
00045                 SetLastError(ERROR_OUTOFMEMORY);
00046             }
00047             else
00048             {
00049                 /* Link it with the blob */
00050                 Blob->DnsAddrArray = DnsAddrArray;
00051             }
00052         }
00053     }
00054 
00055     /* Return the blob */
00056     return Blob;
00057 }
00058 
00059 PDNS_BLOB
00060 WINAPI
00061 SaBlob_CreateFromIp4(IN LPWSTR Name,
00062                      IN ULONG Count,
00063                      IN PIN_ADDR AddressArray)
00064 {
00065     PDNS_BLOB Blob;
00066     LPWSTR NameCopy;
00067     ULONG i;
00068 
00069     /* Create the blob */
00070     Blob = SaBlob_Create(Count);
00071     if (!Blob) goto Quickie;
00072 
00073     /* If we have a name */
00074     if (Name)
00075     {
00076         /* Create a copy of it */
00077         NameCopy = Dns_CreateStringCopy_W(Name);
00078         if (!NameCopy) goto Quickie;
00079 
00080         /* Save the pointer to the name */
00081         Blob->Name = NameCopy;
00082     }
00083 
00084     /* Loop all the addresses */
00085     for (i = 0; i < Count; i++)
00086     {
00087         /* Add an entry for this address */
00088         DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address);
00089     }
00090 
00091     /* Return the blob */
00092     return Blob;
00093 
00094 Quickie:
00095     /* Free the blob, set error and fail */
00096     SaBlob_Free(Blob);
00097     SetLastError(ERROR_OUTOFMEMORY);
00098     return NULL;
00099 }
00100 
00101 VOID
00102 WINAPI
00103 SaBlob_Free(IN PDNS_BLOB Blob)
00104 {
00105     /* Make sure we got a blob */
00106     if (Blob)
00107     {
00108         /* Free the name */
00109         Dns_Free(Blob->Name);
00110 
00111         /* Loop the aliases */
00112         while (Blob->AliasCount)
00113         {
00114             /* Free the alias */
00115             Dns_Free(Blob->Aliases[Blob->AliasCount]);
00116 
00117             /* Decrease number of aliases */
00118             Blob->AliasCount--;
00119         }
00120 
00121         /* Free the DNS Address Array */
00122         DnsAddrArray_Free(Blob->DnsAddrArray);
00123 
00124         /* Free the blob itself */
00125         Dns_Free(Blob);
00126     }
00127 }
00128 
00129 PHOSTENT
00130 WINAPI
00131 SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition,
00132                      IN OUT PSIZE_T FreeBufferSpace,
00133                      IN OUT PSIZE_T HostEntrySize,
00134                      IN PDNS_BLOB Blob,
00135                      IN DWORD StringType,
00136                      IN BOOLEAN Relative,
00137                      IN BOOLEAN BufferAllocated)
00138 {
00139     PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray;
00140     ULONG AliasCount = Blob->AliasCount;
00141     WORD AddressFamily = AF_UNSPEC;
00142     ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize;
00143     ULONG AliasPointerSize;
00144     PDNS_FAMILY_INFO FamilyInfo = NULL;
00145     ULONG StringLength = 0;
00146     ULONG i;
00147     ULONG HostentSize = 0;
00148     PHOSTENT Hostent = NULL;
00149     ULONG_PTR HostentPtr;
00150     PVOID CurrentAddress;
00151 
00152     /* Check if we actually have any addresses */
00153     if (DnsAddrArray)
00154     {
00155         /* Get the address family */
00156         AddressFamily = DnsAddrArray->Addresses[0].AddressFamily;
00157 
00158         /* Get family information */
00159         FamilyInfo = FamilyInfo_GetForFamily(AddressFamily);
00160 
00161         /* Save the current address count and their size */
00162         AddressCount = DnsAddrArray->UsedAddresses;
00163         AddressSize = FamilyInfo->AddressSize;
00164     }
00165 
00166     /* Calculate total size for all the addresses, and their pointers */
00167     TotalSize = AddressSize * AddressCount;
00168     NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID);
00169 
00170     /* Check if we have a name */
00171     if (Blob->Name)
00172     {
00173         /* Find out the size we'll need for a copy */
00174         StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name,
00175                                                          0,
00176                                                          UnicodeString,
00177                                                          StringType) + 1) & ~1;
00178     }
00179 
00180     /*  Now do the same for the aliases */
00181     for (i = AliasCount; i; i--)
00182     {
00183         /* Find out the size we'll need for a copy */
00184         HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i],
00185                                                          0,
00186                                                          UnicodeString,
00187                                                          StringType) + 1) & ~1;
00188     }
00189 
00190     /* Find out how much the pointers will take */
00191     AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID);
00192 
00193     /* Calculate Hostent Size */
00194     HostentSize += TotalSize +
00195                    NamePointerSize +
00196                    AliasPointerSize +
00197                    StringLength +
00198                    sizeof(HOSTENT);
00199 
00200     /* Check if we already have a buffer */
00201     if (!BufferAllocated)
00202     {
00203         /* We don't, allocate space ourselves */
00204         HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize);
00205     }
00206     else
00207     {
00208         /* We do, so allocate space in the buffer */
00209         HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition,
00210                                                                 FreeBufferSpace,
00211                                                                 HostentSize);
00212     }
00213 
00214     /* Make sure we got space */
00215     if (HostentPtr)
00216     {
00217         /* Initialize it */
00218         Hostent = Hostent_Init((PVOID)&HostentPtr,
00219                                AddressFamily,
00220                                AddressSize,
00221                                AddressCount,
00222                                AliasCount);
00223     }
00224 
00225     /* Loop the addresses */
00226     for (i = 0; i < AddressCount; i++)
00227     {
00228         /* Get the pointer of the current address */
00229         CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] +
00230                                              FamilyInfo->AddressOffset);
00231 
00232         /* Write the pointer */
00233         Hostent->h_addr_list[i] = (PCHAR)HostentPtr;
00234 
00235         /* Copy the address */
00236         RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize);
00237 
00238         /* Advance the buffer */
00239         HostentPtr += AddressSize;
00240     }
00241 
00242     /* Check if we have a name */
00243     if (Blob->Name)
00244     {
00245         /* Align our current position */
00246         HostentPtr += 1 & ~1;
00247 
00248         /* Save our name here */
00249         Hostent->h_name = (LPSTR)HostentPtr;
00250 
00251         /* Now copy it in the blob */
00252         HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
00253                                      NULL,
00254                                      Blob->Name,
00255                                      0,
00256                                      UnicodeString,
00257                                      StringType);
00258     }
00259 
00260     /* Loop the Aliases */
00261     for (i = AliasCount; i; i--)
00262     {
00263         /* Align our current position */
00264         HostentPtr += 1 & ~1;
00265 
00266         /* Save our alias here */
00267         Hostent->h_aliases[i] = (LPSTR)HostentPtr;
00268 
00269         /* Now copy it in the blob */
00270         HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
00271                                      NULL,
00272                                      Blob->Aliases[i],
00273                                      0,
00274                                      UnicodeString,
00275                                      StringType);
00276     }
00277 
00278     /* Check if the caller didn't have a buffer */
00279     if (!BufferAllocated)
00280     {
00281         /* Return the size; not needed if we had a blob, since it's internal */
00282         *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr;
00283     }
00284 
00285     /* Convert to Offsets if requested */
00286     if(Relative) Hostent_ConvertToOffsets(Hostent);
00287 
00288     /* Return the full, complete, hostent */
00289     return Hostent;
00290 }
00291 
00292 INT
00293 WINAPI
00294 SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob,
00295                         IN LPWSTR String,
00296                         IN BOOLEAN IsAlias)
00297 {
00298     /* Check if this is an alias */
00299     if (!IsAlias)
00300     {
00301         /* It's not. Simply create a copy of the string */
00302         Blob->Name = Dns_CreateStringCopy_W(String);
00303         if (!Blob->Name) return GetLastError();
00304     }
00305     else
00306     {
00307         /* Does it have a name, and less then 8 aliases? */
00308         if ((Blob->Name) && (Blob->AliasCount <= 8))
00309         {
00310             /* Yup, create a copy of the string and increase the alias count */
00311             Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String);
00312             Blob->AliasCount++;
00313         }
00314         else
00315         {
00316             /* Invalid request! */
00317             return ERROR_MORE_DATA;
00318         }
00319     }
00320 
00321     /* Return Success */
00322     return ERROR_SUCCESS;
00323 }
00324 
00325 INT
00326 WINAPI
00327 SaBlob_WriteAddress(IN PDNS_BLOB Blob,
00328                     OUT PDNS_ADDRESS DnsAddr)
00329 {
00330     /* Check if we have an array yet */
00331     if (!Blob->DnsAddrArray)
00332     {
00333         /* Allocate one! */
00334         Blob->DnsAddrArray = DnsAddrArray_Create(1);
00335         if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY;
00336     }
00337 
00338     /* Add this address */
00339     return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ?
00340            ERROR_SUCCESS:
00341            ERROR_MORE_DATA;
00342 }
00343 
00344 BOOLEAN
00345 WINAPI
00346 SaBlob_IsSupportedAddrType(WORD DnsType)
00347 {
00348     /* Check for valid Types that we support */
00349     return (DnsType == DNS_TYPE_A ||
00350             DnsType == DNS_TYPE_ATMA ||
00351             DnsType == DNS_TYPE_AAAA);
00352 }
00353 
00354 INT
00355 WINAPI
00356 SaBlob_WriteRecords(OUT PDNS_BLOB Blob,
00357                     IN PDNS_RECORD DnsRecord,
00358                     IN BOOLEAN DoAlias)
00359 {
00360     DNS_ADDRESS DnsAddress;
00361     INT ErrorCode = STATUS_INVALID_PARAMETER;
00362     BOOLEAN WroteOnce = FALSE;
00363 
00364     /* Zero out the Address */
00365     RtlZeroMemory(&DnsAddress, sizeof(DnsAddress));
00366 
00367     /* Loop through all the Records */
00368     while (DnsRecord)
00369     {
00370         /* Is this not an answer? */
00371         if (DnsRecord->Flags.S.Section != DNSREC_ANSWER)
00372         {
00373             /* Then simply move on to the next DNS Record */
00374             DnsRecord = DnsRecord->pNext;
00375             continue;
00376         }
00377 
00378         /* Check the type of thsi record */
00379         switch(DnsRecord->wType)
00380         {
00381             /* Regular IPv4, v6 or ATM Record */
00382             case DNS_TYPE_A:
00383             case DNS_TYPE_AAAA:
00384             case DNS_TYPE_ATMA:
00385 
00386                 /* Create a DNS Address from the record */
00387                 DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress);
00388 
00389                 /* Add it to the DNS Blob */
00390                 ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress);
00391 
00392                 /* Add the name, if needed */
00393                 if ((DoAlias) &&
00394                     (!WroteOnce) &&
00395                     (!Blob->Name) &&
00396                     (DnsRecord->pName))
00397                 {
00398                     /* Write the name from the DNS Record */
00399                     ErrorCode = SaBlob_WriteNameOrAlias(Blob,
00400                                                         DnsRecord->pName,
00401                                                         FALSE);
00402                     WroteOnce = TRUE;
00403                 }
00404                 break;
00405 
00406             case DNS_TYPE_CNAME:
00407 
00408                 /* Just write the alias name */
00409                 ErrorCode = SaBlob_WriteNameOrAlias(Blob,
00410                                                     DnsRecord->pName,
00411                                                     TRUE);
00412                 break;
00413 
00414             case DNS_TYPE_PTR:
00415 
00416                 /* Check if we already have a name */
00417                 if (Blob->Name)
00418                 {
00419                     /* We don't, so add this as a name */
00420                     ErrorCode = SaBlob_WriteNameOrAlias(Blob,
00421                                                         DnsRecord->pName,
00422                                                         FALSE);
00423                 }
00424                 else
00425                 {
00426                     /* We do, so add it as an alias */
00427                     ErrorCode = SaBlob_WriteNameOrAlias(Blob,
00428                                                         DnsRecord->pName,
00429                                                         TRUE);
00430                 }
00431                 break;
00432             default:
00433                 break;
00434         }
00435 
00436         /* Next record */
00437         DnsRecord = DnsRecord->pNext;
00438     }
00439 
00440     /* Return error code */
00441     return ErrorCode;
00442 }
00443 
00444 PDNS_BLOB
00445 WINAPI
00446 SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord,
00447                          IN BOOLEAN DoAliases,
00448                          IN DWORD DnsType)
00449 {
00450     PDNS_RECORD LocalDnsRecord;
00451     ULONG ProcessedCount = 0;
00452     PDNS_BLOB DnsBlob;
00453     INT ErrorCode;
00454     DNS_ADDRESS DnsAddress;
00455 
00456     /* Find out how many DNS Addresses to allocate */
00457     LocalDnsRecord = DnsRecord;
00458     while (LocalDnsRecord)
00459     {
00460         /* Make sure this record is an answer */
00461         if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) &&
00462             (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType)))
00463         {
00464             /* Increase number of records to process */
00465             ProcessedCount++;
00466         }
00467 
00468         /* Move to the next record */
00469         LocalDnsRecord = LocalDnsRecord->pNext;
00470     }
00471 
00472     /* Create the DNS Blob */
00473     DnsBlob = SaBlob_Create(ProcessedCount);
00474     if (!DnsBlob)
00475     {
00476         /* Fail */
00477         ErrorCode = GetLastError();
00478         goto Quickie;
00479     }
00480 
00481     /* Write the record to the DNS Blob */
00482     ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE);
00483     if (ErrorCode != NO_ERROR)
00484     {
00485         /* We failed... but do we still have valid data? */
00486         if ((DnsBlob->Name) || (DnsBlob->AliasCount))
00487         {
00488             /* We'll just assume success then */
00489             ErrorCode = NO_ERROR;
00490         }
00491         else
00492         {
00493             /* Ok, last chance..do you have a DNS Address Array? */
00494             if ((DnsBlob->DnsAddrArray) &&
00495                 (DnsBlob->DnsAddrArray->UsedAddresses))
00496             {
00497                 /* Boy are you lucky! */
00498                 ErrorCode = NO_ERROR;
00499             }
00500         }
00501 
00502         /* Buh-bye! */
00503         goto Quickie;
00504     }
00505 
00506     /* Check if this is a PTR record */
00507     if ((DnsRecord->wType == DNS_TYPE_PTR) ||
00508         ((DnsType == DNS_TYPE_PTR) &&
00509          (DnsRecord->wType == DNS_TYPE_CNAME) &&
00510          (DnsRecord->Flags.S.Section == DNSREC_ANSWER)))
00511     {
00512         /* Get a DNS Address Structure */
00513         if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName))
00514         {
00515             /* Add it to the Blob */
00516             if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR;
00517         }
00518     }
00519 
00520     /* Ok...do we still not have a name? */
00521     if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord))
00522     {
00523         /* We have an local DNS Record, so just use it to write the name */
00524         ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob,
00525                                             LocalDnsRecord->pName,
00526                                             FALSE);
00527     }
00528 
00529 Quickie:
00530     /* Check error code */
00531     if (ErrorCode != NO_ERROR)
00532     {
00533         /* Free the blob and set the error */
00534         SaBlob_Free(DnsBlob);
00535         DnsBlob = NULL;
00536         SetLastError(ErrorCode);
00537     }
00538 
00539     /* Return */
00540     return DnsBlob;
00541 }
00542 
00543 PDNS_BLOB
00544 WINAPI
00545 SaBlob_Query(IN LPWSTR Name,
00546              IN WORD DnsType,
00547              IN ULONG Flags,
00548              IN PVOID *Reserved,
00549              IN DWORD AddressFamily)
00550 {
00551     PDNS_RECORD DnsRecord = NULL;
00552     INT ErrorCode;
00553     PDNS_BLOB DnsBlob = NULL;
00554     LPWSTR LocalName, LocalNameCopy;
00555 
00556     /* If they want reserved data back, clear it out in case we fail */
00557     if (Reserved) *Reserved = NULL;
00558 
00559     /* Query DNS */
00560     ErrorCode = DnsQuery_W(Name,
00561                            DnsType,
00562                            Flags,
00563                            NULL,
00564                            &DnsRecord,
00565                            Reserved);
00566     if (ErrorCode != ERROR_SUCCESS)
00567     {
00568         /* We failed... did the caller use reserved data? */
00569         if (Reserved && *Reserved)
00570         {
00571             /* He did, and it was valid. Free it */
00572             DnsApiFree(*Reserved);
00573             *Reserved = NULL;
00574         }
00575 
00576         /* Normalize error code */
00577         if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
00578         goto Quickie;
00579     }
00580 
00581     /* Now create the Blob from the DNS Records */
00582     DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
00583     if (!DnsBlob)
00584     {
00585         /* Failed, get error code */
00586         ErrorCode = GetLastError();
00587         goto Quickie;
00588     }
00589 
00590     /* Make sure it has a name */
00591     if (!DnsBlob->Name)
00592     {
00593         /* It doesn't, fail */
00594         ErrorCode = DNS_INFO_NO_RECORDS;
00595         goto Quickie;
00596     }
00597 
00598     /* Check if the name is local or loopback */
00599     if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
00600         !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
00601     {
00602         /* Nothing left to do, exit! */
00603         goto Quickie;
00604     }
00605 
00606     /* This is a local name...query it */
00607     LocalName = DnsQueryConfigAllocEx(DnsConfigFullHostName_W, NULL, NULL);
00608     if (LocalName)
00609     {
00610         /* Create a copy for the caller */
00611         LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
00612         if (LocalNameCopy)
00613         {
00614             /* Overwrite the one in the blob */
00615             DnsBlob->Name = LocalNameCopy;
00616         }
00617         else
00618         {
00619             /* We failed to make a copy, free memory */
00620             DnsApiFree(LocalName);
00621         }
00622     }
00623 
00624 Quickie:
00625     /* Free the DNS Record if we have one */
00626     if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);
00627 
00628     /* Check if this is a failure path with an active blob */
00629     if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
00630     {
00631         /* Free the blob */
00632         SaBlob_Free(DnsBlob);
00633         DnsBlob = NULL;
00634     }
00635 
00636     /* Set the last error and return */
00637     SetLastError(ErrorCode);
00638     return DnsBlob;
00639 }
00640 

Generated on Sun May 27 2012 04:35:57 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.