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
inet_addr(IN CONST CHAR FAR * cp)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
inet_ntoa(IN IN_ADDR in)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
htonl(IN ULONG hostlong)228 htonl(IN ULONG hostlong)
229 {
230 return DH2N(hostlong);
231 }
232
233 /*
234 * @implemented
235 */
236 USHORT
237 WSAAPI
htons(IN USHORT hostshort)238 htons(IN USHORT hostshort)
239 {
240 return WH2N(hostshort);
241 }
242
243 /*
244 * @implemented
245 */
246 ULONG
247 WSAAPI
ntohl(IN ULONG netlong)248 ntohl(IN ULONG netlong)
249 {
250 return DN2H(netlong);
251 }
252
253 /*
254 * @implemented
255 */
256 USHORT
257 WSAAPI
ntohs(IN USHORT netshort)258 ntohs(IN USHORT netshort)
259 {
260 return WN2H(netshort);
261 }
262
263 /*
264 * @implemented
265 */
266 INT
267 WSAAPI
WSAHtonl(IN SOCKET s,IN ULONG hostlong,OUT ULONG FAR * lpnetlong)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
WSAHtons(IN SOCKET s,IN USHORT hostshort,OUT USHORT FAR * lpnetshort)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
WSANtohl(IN SOCKET s,IN ULONG netlong,OUT ULONG FAR * lphostlong)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
WSANtohs(IN SOCKET s,IN USHORT netshort,OUT USHORT FAR * lphostshort)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
inet_ntop(_In_ INT Family,_In_ const VOID * pAddr,_Out_writes_ (StringBufSize)PSTR pStringBuf,_In_ size_t StringBufSize)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
InetNtopW(_In_ INT Family,_In_ const VOID * pAddr,_Out_writes_ (StringBufSize)PWSTR pStringBuf,_In_ size_t StringBufSize)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
inet_pton(_In_ INT Family,_In_ PCSTR pszAddrString,_Out_writes_bytes_ (sizeof (IN_ADDR6))PVOID pAddrBuf)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
InetPtonW(_In_ INT Family,_In_ PCWSTR pszAddrString,_Out_writes_bytes_ (sizeof (IN_ADDR6))PVOID pAddrBuf)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