Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensablob.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
1.7.6.1
|