1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS DNS Shared Library 4 * FILE: lib/dnslib/straddr.c 5 * PURPOSE: Functions for address<->string conversion. 6 */ 7 8 /* INCLUDES ******************************************************************/ 9 #include "precomp.h" 10 11 /* DATA **********************************************************************/ 12 13 /* FUNCTIONS *****************************************************************/ 14 15 LPWSTR 16 WINAPI 17 Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, 18 IN IN6_ADDR Address) 19 { 20 /* FIXME */ 21 return NULL; 22 } 23 24 LPWSTR 25 WINAPI 26 Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, 27 IN IN_ADDR Address) 28 { 29 /* Simply append the ARPA string */ 30 return Name + (wsprintfW(Name, 31 L"%u.%u.%u.%u.in-addr.arpa.", 32 Address.S_un.S_addr >> 24, 33 Address.S_un.S_addr >> 10, 34 Address.S_un.S_addr >> 8, 35 Address.S_un.S_addr) * sizeof(WCHAR)); 36 } 37 38 BOOLEAN 39 WINAPI 40 Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, 41 IN LPSTR Name) 42 { 43 /* FIXME */ 44 return FALSE; 45 } 46 47 BOOLEAN 48 WINAPI 49 Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, 50 IN LPSTR Name) 51 { 52 /* FIXME */ 53 return FALSE; 54 } 55 56 BOOLEAN 57 WINAPI 58 Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, 59 IN LPSTR Name) 60 { 61 PCHAR Terminator; 62 NTSTATUS Status; 63 64 /* Let RTL Do it for us */ 65 Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); 66 if (NT_SUCCESS(Status)) return TRUE; 67 68 /* We failed */ 69 return FALSE; 70 } 71 72 BOOLEAN 73 WINAPI 74 Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, 75 IN LPWSTR Name) 76 { 77 PCHAR Terminator; 78 NTSTATUS Status; 79 80 /* Let RTL Do it for us */ 81 Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); 82 if (NT_SUCCESS(Status)) return TRUE; 83 84 /* We failed */ 85 return FALSE; 86 } 87 88 BOOLEAN 89 WINAPI 90 Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, 91 IN LPSTR Name) 92 { 93 ULONG Addr; 94 95 /* Use inet_addr to convert it... */ 96 Addr = inet_addr(Name); 97 if (Addr == -1) 98 { 99 /* Check if it's the wildcard (which is ok...) */ 100 if (strcmp("255.255.255.255", Name)) return FALSE; 101 } 102 103 /* If we got here, then we suceeded... return the address */ 104 Address->S_un.S_addr = Addr; 105 return TRUE; 106 } 107 108 BOOLEAN 109 WINAPI 110 Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, 111 IN LPWSTR Name) 112 { 113 CHAR AnsiName[16]; 114 ULONG Size = sizeof(AnsiName); 115 INT ErrorCode; 116 117 /* Make a copy of the name in ANSI */ 118 ErrorCode = Dns_StringCopy(&AnsiName, 119 &Size, 120 Name, 121 0, 122 UnicodeString, 123 AnsiString); 124 if (ErrorCode) 125 { 126 /* Copy made sucesfully, now convert it */ 127 ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); 128 } 129 130 /* Return either 0 bytes copied (failure == false) or conversion status */ 131 return ErrorCode; 132 } 133 134 BOOLEAN 135 WINAPI 136 Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, 137 IN LPWSTR Name) 138 { 139 CHAR AnsiName[32]; 140 ULONG Size = sizeof(AnsiName); 141 INT ErrorCode; 142 143 /* Make a copy of the name in ANSI */ 144 ErrorCode = Dns_StringCopy(&AnsiName, 145 &Size, 146 Name, 147 0, 148 UnicodeString, 149 AnsiString); 150 if (ErrorCode) 151 { 152 /* Copy made sucesfully, now convert it */ 153 ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); 154 } 155 156 /* Return either 0 bytes copied (failure == false) or conversion status */ 157 return ErrorCode; 158 } 159 160 BOOLEAN 161 WINAPI 162 Dns_StringToAddressEx(OUT PVOID Address, 163 IN OUT PULONG AddressSize, 164 IN PVOID AddressName, 165 IN OUT PDWORD AddressFamily, 166 IN BOOLEAN Unicode, 167 IN BOOLEAN Reverse) 168 { 169 DWORD Af = *AddressFamily; 170 ULONG AddrSize = *AddressSize; 171 IN6_ADDR Addr; 172 BOOLEAN Return; 173 INT ErrorCode = ERROR_SUCCESS; 174 CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; 175 ULONG Size = sizeof(AnsiName); 176 177 /* First check if this is a reverse address string */ 178 if (Reverse) 179 { 180 /* Convert it right now to ANSI as an optimization */ 181 Dns_StringCopy(AnsiName, 182 &Size, 183 AddressName, 184 0, 185 UnicodeString, 186 AnsiString); 187 188 /* Use the ANSI Name instead */ 189 AddressName = AnsiName; 190 } 191 192 /* 193 * If the caller doesn't know what the family is, we'll assume IPv4 and 194 * check if we failed or not. If the caller told us it's IPv4, then just 195 * do IPv4... 196 */ 197 if ((Af == AF_UNSPEC) || (Af == AF_INET)) 198 { 199 /* Now check if the caller gave us the reverse name or not */ 200 if (Reverse) 201 { 202 /* Get the Address */ 203 Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); 204 } 205 else 206 { 207 /* Check if the caller gave us unicode or not */ 208 if (Unicode) 209 { 210 /* Get the Address */ 211 Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); 212 } 213 else 214 { 215 /* Get the Address */ 216 Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); 217 } 218 } 219 220 /* Check if we suceeded */ 221 if (Return) 222 { 223 /* Save address family */ 224 Af = AF_INET; 225 226 /* Check if the address size matches */ 227 if (AddrSize < sizeof(IN_ADDR)) 228 { 229 /* Invalid match, set error code */ 230 ErrorCode = ERROR_MORE_DATA; 231 } 232 else 233 { 234 /* It matches, save the address! */ 235 *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; 236 } 237 } 238 } 239 240 /* If we are here, either AF_INET6 was specified or IPv4 failed */ 241 if ((Af == AF_UNSPEC) || (Af == AF_INET6)) 242 { 243 /* Now check if the caller gave us the reverse name or not */ 244 if (Reverse) 245 { 246 /* Get the Address */ 247 Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); 248 } 249 else 250 { 251 /* Check if the caller gave us unicode or not */ 252 if (Unicode) 253 { 254 /* Get the Address */ 255 Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); 256 } 257 else 258 { 259 /* Get the Address */ 260 Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); 261 } 262 } 263 264 /* Check if we suceeded */ 265 if (Return) 266 { 267 /* Save address family */ 268 Af = AF_INET6; 269 270 /* Check if the address size matches */ 271 if (AddrSize < sizeof(IN6_ADDR)) 272 { 273 /* Invalid match, set error code */ 274 ErrorCode = ERROR_MORE_DATA; 275 } 276 else 277 { 278 /* It matches, save the address! */ 279 *(PIN6_ADDR)Address = Addr; 280 } 281 } 282 } 283 else if (Af != AF_INET) 284 { 285 /* You're like.. ATM or something? Get outta here! */ 286 Af = AF_UNSPEC; 287 ErrorCode = WSA_INVALID_PARAMETER; 288 } 289 290 /* Set error if we had one */ 291 if (ErrorCode) SetLastError(ErrorCode); 292 293 /* Return the address family and size */ 294 *AddressFamily = Af; 295 *AddressSize = AddrSize; 296 297 /* Return success or failure */ 298 return (ErrorCode == ERROR_SUCCESS); 299 } 300 301 BOOLEAN 302 WINAPI 303 Dns_StringToAddressW(OUT PVOID Address, 304 IN OUT PULONG AddressSize, 305 IN LPWSTR AddressName, 306 IN OUT PDWORD AddressFamily) 307 { 308 /* Call the common API */ 309 return Dns_StringToAddressEx(Address, 310 AddressSize, 311 AddressName, 312 AddressFamily, 313 TRUE, 314 FALSE); 315 } 316 317 BOOLEAN 318 WINAPI 319 Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, 320 IN PVOID AddressName, 321 IN DWORD AddressFamily, 322 IN BOOLEAN Unicode, 323 IN BOOLEAN Reverse) 324 { 325 IN6_ADDR Addr; 326 BOOLEAN Return; 327 INT ErrorCode = ERROR_SUCCESS; 328 CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; 329 ULONG Size = sizeof(AnsiName); 330 331 /* First check if this is a reverse address string */ 332 if ((Reverse) && (Unicode)) 333 { 334 /* Convert it right now to ANSI as an optimization */ 335 Dns_StringCopy(AnsiName, 336 &Size, 337 AddressName, 338 0, 339 UnicodeString, 340 AnsiString); 341 342 /* Use the ANSI Name instead */ 343 AddressName = AnsiName; 344 } 345 346 /* 347 * If the caller doesn't know what the family is, we'll assume IPv4 and 348 * check if we failed or not. If the caller told us it's IPv4, then just 349 * do IPv4... 350 */ 351 if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) 352 { 353 /* Now check if the caller gave us the reverse name or not */ 354 if (Reverse) 355 { 356 /* Get the Address */ 357 Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); 358 } 359 else 360 { 361 /* Check if the caller gave us unicode or not */ 362 if (Unicode) 363 { 364 /* Get the Address */ 365 Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); 366 } 367 else 368 { 369 /* Get the Address */ 370 Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); 371 } 372 } 373 374 /* Check if we suceeded */ 375 if (Return) 376 { 377 /* Build the IPv4 Address */ 378 DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); 379 380 /* So we don't go in the code below... */ 381 AddressFamily = AF_INET; 382 } 383 } 384 385 /* If we are here, either AF_INET6 was specified or IPv4 failed */ 386 if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) 387 { 388 /* Now check if the caller gave us the reverse name or not */ 389 if (Reverse) 390 { 391 /* Get the Address */ 392 Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); 393 if (Return) 394 { 395 /* Build the IPv6 Address */ 396 DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); 397 } 398 else 399 { 400 goto Quickie; 401 } 402 } 403 else 404 { 405 /* Check if the caller gave us unicode or not */ 406 if (Unicode) 407 { 408 /* Get the Address */ 409 if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, 410 &DnsAddr->Ip6Address.sin6_addr, 411 &DnsAddr->Ip6Address.sin6_scope_id, 412 &DnsAddr->Ip6Address.sin6_port))) 413 Return = TRUE; 414 else 415 Return = FALSE; 416 } 417 else 418 { 419 /* Get the Address */ 420 if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, 421 &DnsAddr->Ip6Address.sin6_addr, 422 &DnsAddr->Ip6Address.sin6_scope_id, 423 &DnsAddr->Ip6Address.sin6_port))) 424 Return = TRUE; 425 else 426 Return = FALSE; 427 } 428 } 429 430 /* Check if we suceeded */ 431 if (Return) 432 { 433 /* Finish setting up the structure */ 434 DnsAddr->Ip6Address.sin6_family = AF_INET6; 435 DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); 436 } 437 } 438 else if (AddressFamily != AF_INET) 439 { 440 /* You're like.. ATM or something? Get outta here! */ 441 RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); 442 SetLastError(WSA_INVALID_PARAMETER); 443 } 444 445 Quickie: 446 /* Return success or failure */ 447 return (ErrorCode == ERROR_SUCCESS); 448 } 449 450 BOOLEAN 451 WINAPI 452 Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, 453 IN LPWSTR Name) 454 { 455 /* Call the common API */ 456 return Dns_StringToDnsAddrEx(DnsAddr, 457 Name, 458 AF_UNSPEC, 459 TRUE, 460 TRUE); 461 } 462 463