1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32/src/addrconv.c 5 * PURPOSE: Address and Port Conversion Support 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ws2_32.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* DEFINES *******************************************************************/ 17 18 #ifndef BE 19 20 /* DWORD network to host byte order conversion for little endian machines */ 21 #define DN2H(dw) \ 22 ((((dw) & 0xFF000000L) >> 24) | \ 23 (((dw) & 0x00FF0000L) >> 8) | \ 24 (((dw) & 0x0000FF00L) << 8) | \ 25 (((dw) & 0x000000FFL) << 24)) 26 27 /* DWORD host to network byte order conversion for little endian machines */ 28 #define DH2N(dw) \ 29 ((((dw) & 0xFF000000L) >> 24) | \ 30 (((dw) & 0x00FF0000L) >> 8) | \ 31 (((dw) & 0x0000FF00L) << 8) | \ 32 (((dw) & 0x000000FFL) << 24)) 33 34 /* WORD network to host order conversion for little endian machines */ 35 #define WN2H(w) \ 36 ((((w) & 0xFF00) >> 8) | \ 37 (((w) & 0x00FF) << 8)) 38 39 /* WORD host to network byte order conversion for little endian machines */ 40 #define WH2N(w) \ 41 ((((w) & 0xFF00) >> 8) | \ 42 (((w) & 0x00FF) << 8)) 43 44 #else /* BE */ 45 46 /* DWORD network to host byte order conversion for big endian machines */ 47 #define DN2H(dw) \ 48 (dw) 49 50 /* DWORD host to network byte order conversion big endian machines */ 51 #define DH2N(dw) \ 52 (dw) 53 54 /* WORD network to host order conversion for big endian machines */ 55 #define WN2H(w) \ 56 (w) 57 58 /* WORD host to network byte order conversion for big endian machines */ 59 #define WH2N(w) \ 60 (w) 61 62 #endif /* BE */ 63 64 /* FUNCTIONS *****************************************************************/ 65 66 /* 67 * @implemented 68 */ 69 ULONG 70 WSAAPI 71 inet_addr(IN CONST CHAR FAR* cp) 72 { 73 register u_long val, base, n; 74 register unsigned char c; 75 u_long parts[4], *pp = parts; 76 if (!cp) return INADDR_ANY; 77 if (!isdigit(*cp)) return INADDR_NONE; 78 79 again: 80 /* 81 * Collect number up to ``.''. 82 * Values are specified as for C: 83 * 0x=hex, 0=octal, other=decimal. 84 */ 85 val = 0; base = 10; 86 if (*cp == '0') { 87 if (*++cp == 'x' || *cp == 'X') 88 base = 16, cp++; 89 else 90 base = 8; 91 } 92 while ((c = *cp)) { 93 if (isdigit(c)) { 94 val = (val * base) + (c - '0'); 95 cp++; 96 continue; 97 } 98 if (base == 16 && isxdigit(c)) { 99 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); 100 cp++; 101 continue; 102 } 103 break; 104 } 105 if (*cp == '.') { 106 /* 107 * Internet format: 108 * a.b.c.d 109 * a.b.c (with c treated as 16-bits) 110 * a.b (with b treated as 24 bits) 111 */ 112 if (pp >= parts + 4) return (INADDR_NONE); 113 *pp++ = val; 114 cp++; 115 goto again; 116 } 117 /* 118 * Check for trailing characters. 119 */ 120 if (*cp && !isspace((UCHAR)*cp)) return (INADDR_NONE); 121 122 *pp++ = val; 123 /* 124 * Concoct the address according to 125 * the number of parts specified. 126 */ 127 n = (u_long)(pp - parts); 128 switch (n) { 129 130 case 1: /* a -- 32 bits */ 131 val = parts[0]; 132 break; 133 134 case 2: /* a.b -- 8.24 bits */ 135 val = (parts[0] << 24) | (parts[1] & 0xffffff); 136 break; 137 138 case 3: /* a.b.c -- 8.8.16 bits */ 139 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) | 140 (parts[2] & 0xffff); 141 break; 142 143 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 144 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) | 145 ((parts[2] & 0xff) << 8) | (parts[3] & 0xff); 146 break; 147 148 default: 149 return (INADDR_NONE); 150 } 151 val = htonl(val); 152 return (val); 153 } 154 155 /* 156 * @implemented 157 */ 158 CHAR FAR* 159 WSAAPI 160 inet_ntoa(IN IN_ADDR in) 161 { 162 PWSPROCESS Process; 163 PWSTHREAD Thread; 164 INT ErrorCode; 165 WSADATA WsaData; 166 BOOL ManualLoad = FALSE; 167 CHAR b[10]; 168 PCHAR p; 169 DPRINT("inet_ntoa: %lx\n", in); 170 171 /* Enter prolog */ 172 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 173 { 174 DPRINT("MANUAL LOAD\n"); 175 176 /* Only fail if the error wasn't related to a missing WSAStartup */ 177 if (ErrorCode != WSANOTINITIALISED) 178 { 179 /* Fail */ 180 SetLastError(ErrorCode); 181 return NULL; 182 } 183 184 /* Apps aren't expected to call WSAStartup for this API, so we will */ 185 if ((ErrorCode = WSAStartup(MAKEWORD(2,2), &WsaData)) != ERROR_SUCCESS) 186 { 187 /* We failed */ 188 SetLastError(ErrorCode); 189 return NULL; 190 } 191 192 /* Try the prolog again */ 193 ManualLoad = TRUE; 194 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 195 { 196 /* Failed again... */ 197 WSACleanup(); 198 SetLastError(ErrorCode); 199 return NULL; 200 } 201 } 202 203 p = Thread->Buffer; 204 _itoa(in.S_un.S_addr & 0xFF, b, 10); 205 strcpy(p, b); 206 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10); 207 strcat(p, "."); 208 strcat(p, b); 209 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10); 210 strcat(p, "."); 211 strcat(p, b); 212 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10); 213 strcat(p, "."); 214 strcat(p, b); 215 216 /* Cleanup the manual load */ 217 if (ManualLoad) WSACleanup(); 218 219 /* Return the buffer */ 220 return p; 221 } 222 223 /* 224 * @implemented 225 */ 226 ULONG 227 WSAAPI 228 htonl(IN ULONG hostlong) 229 { 230 return DH2N(hostlong); 231 } 232 233 /* 234 * @implemented 235 */ 236 USHORT 237 WSAAPI 238 htons(IN USHORT hostshort) 239 { 240 return WH2N(hostshort); 241 } 242 243 /* 244 * @implemented 245 */ 246 ULONG 247 WSAAPI 248 ntohl(IN ULONG netlong) 249 { 250 return DN2H(netlong); 251 } 252 253 /* 254 * @implemented 255 */ 256 USHORT 257 WSAAPI 258 ntohs(IN USHORT netshort) 259 { 260 return WN2H(netshort); 261 } 262 263 /* 264 * @implemented 265 */ 266 INT 267 WSAAPI 268 WSAHtonl(IN SOCKET s, 269 IN ULONG hostlong, 270 OUT ULONG FAR* lpnetlong) 271 { 272 INT ErrorCode; 273 PWSSOCKET Socket; 274 DPRINT("WSAHtonl: %p, %lx, %p\n", s, hostlong, lpnetlong); 275 276 /* Check for WSAStartup */ 277 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 278 { 279 /* Make sure we got a parameter */ 280 if (!lpnetlong) 281 { 282 /* Fail */ 283 SetLastError(WSAEFAULT); 284 return SOCKET_ERROR; 285 } 286 287 /* Get the Socket Context */ 288 if ((Socket = WsSockGetSocket(s))) 289 { 290 /* Check which byte order to use */ 291 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder == 292 LITTLEENDIAN) 293 { 294 /* No conversion needed */ 295 *lpnetlong = hostlong; 296 } 297 else 298 { 299 /* Use a swap */ 300 *lpnetlong = DN2H(hostlong); 301 } 302 303 /* Dereference the socket */ 304 WsSockDereference(Socket); 305 306 /* Return success */ 307 return ERROR_SUCCESS; 308 } 309 else 310 { 311 /* Set the error code */ 312 ErrorCode = WSAENOTSOCK; 313 } 314 } 315 316 /* Return with error */ 317 SetLastError(ErrorCode); 318 return SOCKET_ERROR; 319 } 320 321 /* 322 * @implemented 323 */ 324 INT 325 WSAAPI 326 WSAHtons(IN SOCKET s, 327 IN USHORT hostshort, 328 OUT USHORT FAR* lpnetshort) 329 { 330 INT ErrorCode; 331 PWSSOCKET Socket; 332 DPRINT("WSAHtons: %p, %lx, %p\n", s, hostshort, lpnetshort); 333 334 /* Check for WSAStartup */ 335 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 336 { 337 /* Make sure we got a parameter */ 338 if (!lpnetshort) 339 { 340 /* Fail */ 341 SetLastError(WSAEFAULT); 342 return SOCKET_ERROR; 343 } 344 345 /* Get the Socket Context */ 346 if ((Socket = WsSockGetSocket(s))) 347 { 348 /* Check which byte order to use */ 349 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder == 350 LITTLEENDIAN) 351 { 352 /* No conversion needed */ 353 *lpnetshort = hostshort; 354 } 355 else 356 { 357 /* Use a swap */ 358 *lpnetshort = WN2H(hostshort); 359 } 360 361 /* Dereference the socket */ 362 WsSockDereference(Socket); 363 364 /* Return success */ 365 return ERROR_SUCCESS; 366 } 367 else 368 { 369 /* Set the error code */ 370 ErrorCode = WSAENOTSOCK; 371 } 372 } 373 374 /* Return with error */ 375 SetLastError(ErrorCode); 376 return SOCKET_ERROR; 377 } 378 379 /* 380 * @implemented 381 */ 382 INT 383 WSAAPI 384 WSANtohl(IN SOCKET s, 385 IN ULONG netlong, 386 OUT ULONG FAR* lphostlong) 387 { 388 INT ErrorCode; 389 PWSSOCKET Socket; 390 DPRINT("WSANtohl: %p, %lx, %p\n", s, netlong, lphostlong); 391 392 /* Check for WSAStartup */ 393 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 394 { 395 /* Make sure we got a parameter */ 396 if (!lphostlong) 397 { 398 /* Fail */ 399 SetLastError(WSAEFAULT); 400 return SOCKET_ERROR; 401 } 402 403 /* Get the Socket Context */ 404 if ((Socket = WsSockGetSocket(s))) 405 { 406 /* Check which byte order to use */ 407 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder == 408 LITTLEENDIAN) 409 { 410 /* No conversion needed */ 411 *lphostlong = netlong; 412 } 413 else 414 { 415 /* Use a swap */ 416 *lphostlong = DN2H(netlong); 417 } 418 419 /* Dereference the socket */ 420 WsSockDereference(Socket); 421 422 /* Return success */ 423 return ERROR_SUCCESS; 424 } 425 else 426 { 427 /* Set the error code */ 428 ErrorCode = WSAENOTSOCK; 429 } 430 } 431 432 /* Return with error */ 433 SetLastError(ErrorCode); 434 return SOCKET_ERROR; 435 } 436 437 /* 438 * @implemented 439 */ 440 INT 441 WSAAPI 442 WSANtohs(IN SOCKET s, 443 IN USHORT netshort, 444 OUT USHORT FAR* lphostshort) 445 { 446 INT ErrorCode; 447 PWSSOCKET Socket; 448 DPRINT("WSANtohs: %p, %lx, %p\n", s, netshort, lphostshort); 449 450 /* Check for WSAStartup */ 451 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 452 { 453 /* Make sure we got a parameter */ 454 if (!lphostshort) 455 { 456 /* Fail */ 457 SetLastError(WSAEFAULT); 458 return SOCKET_ERROR; 459 } 460 461 /* Get the Socket Context */ 462 if ((Socket = WsSockGetSocket(s))) 463 { 464 /* Check which byte order to use */ 465 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder == 466 LITTLEENDIAN) 467 { 468 /* No conversion needed */ 469 *lphostshort = netshort; 470 } 471 else 472 { 473 /* Use a swap */ 474 *lphostshort = WN2H(netshort); 475 } 476 477 /* Dereference the socket */ 478 WsSockDereference(Socket); 479 480 /* Return success */ 481 return ERROR_SUCCESS; 482 } 483 else 484 { 485 /* Set the error code */ 486 ErrorCode = WSAENOTSOCK; 487 } 488 } 489 490 /* Return with error */ 491 SetLastError(ErrorCode); 492 return SOCKET_ERROR; 493 } 494 495 PCSTR 496 WSAAPI 497 inet_ntop( 498 _In_ INT Family, 499 _In_ const VOID *pAddr, 500 _Out_writes_(StringBufSize) PSTR pStringBuf, 501 _In_ size_t StringBufSize) 502 { 503 NTSTATUS Status; 504 ULONG BufSize = StringBufSize; 505 506 switch (Family) 507 { 508 case AF_INET: 509 Status = RtlIpv4AddressToStringExA(pAddr, 0, pStringBuf, &BufSize); 510 break; 511 case AF_INET6: 512 Status = RtlIpv6AddressToStringExA(pAddr, 0, 0, pStringBuf, &BufSize); 513 break; 514 default: 515 SetLastError(WSAEAFNOSUPPORT); 516 return NULL; 517 } 518 519 if (!NT_SUCCESS(Status)) 520 { 521 SetLastError(WSAEINVAL); 522 return NULL; 523 } 524 525 return pStringBuf; 526 } 527 528 PCWSTR 529 WSAAPI 530 InetNtopW( 531 _In_ INT Family, 532 _In_ const VOID *pAddr, 533 _Out_writes_(StringBufSize) PWSTR pStringBuf, 534 _In_ size_t StringBufSize) 535 { 536 NTSTATUS Status; 537 ULONG BufSize = StringBufSize; 538 539 switch (Family) 540 { 541 case AF_INET: 542 Status = RtlIpv4AddressToStringExW(pAddr, 0, pStringBuf, &BufSize); 543 break; 544 case AF_INET6: 545 Status = RtlIpv6AddressToStringExW(pAddr, 0, 0, pStringBuf, &BufSize); 546 break; 547 default: 548 SetLastError(WSAEAFNOSUPPORT); 549 return NULL; 550 } 551 552 if (!NT_SUCCESS(Status)) 553 { 554 SetLastError(WSAEINVAL); 555 return NULL; 556 } 557 558 return pStringBuf; 559 } 560 561 INT 562 WSAAPI 563 inet_pton( 564 _In_ INT Family, 565 _In_ PCSTR pszAddrString, 566 _Out_writes_bytes_(sizeof(IN_ADDR6)) PVOID pAddrBuf) 567 { 568 NTSTATUS Status; 569 PCSTR ch; 570 571 if (!pszAddrString || !pAddrBuf) 572 { 573 SetLastError(WSAEFAULT); 574 return -1; 575 } 576 577 switch (Family) 578 { 579 case AF_INET: 580 Status = RtlIpv4StringToAddressA(pszAddrString, TRUE, &ch, pAddrBuf); 581 break; 582 case AF_INET6: 583 Status = RtlIpv6StringToAddressA(pszAddrString, &ch, pAddrBuf); 584 break; 585 default: 586 SetLastError(WSAEAFNOSUPPORT); 587 return -1; 588 } 589 590 if (!NT_SUCCESS(Status) || (*ch != 0)) 591 { 592 return 0; 593 } 594 595 return 1; 596 } 597 598 INT 599 WSAAPI 600 InetPtonW( 601 _In_ INT Family, 602 _In_ PCWSTR pszAddrString, 603 _Out_writes_bytes_(sizeof(IN_ADDR6)) PVOID pAddrBuf) 604 { 605 NTSTATUS Status; 606 PCWSTR ch; 607 608 if (!pszAddrString || !pAddrBuf) 609 { 610 SetLastError(WSAEFAULT); 611 return -1; 612 } 613 614 switch (Family) 615 { 616 case AF_INET: 617 Status = RtlIpv4StringToAddressW(pszAddrString, TRUE, &ch, pAddrBuf); 618 break; 619 case AF_INET6: 620 Status = RtlIpv6StringToAddressW(pszAddrString, &ch, pAddrBuf); 621 break; 622 default: 623 SetLastError(WSAEAFNOSUPPORT); 624 return -1; 625 } 626 627 if (!NT_SUCCESS(Status) || (*ch != 0)) 628 { 629 SetLastError(WSAEINVAL); /* Only unicode version sets this error */ 630 return 0; 631 } 632 633 return 1; 634 } 635