- New winsock (part 3 of x)
[reactos.git] / dll / win32 / ws2_32_new / src / addrconv.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: addrconv.c
5 * PURPOSE: Address and Port Conversion Support
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10 #include "ws2_32.h"
11
12 //#define NDEBUG
13 #include <debug.h>
14
15 /* DEFINES *******************************************************************/
16
17 #ifndef BE
18
19 /* DWORD network to host byte order conversion for little endian machines */
20 #define DN2H(dw) \
21 ((((dw) & 0xFF000000L) >> 24) | \
22 (((dw) & 0x00FF0000L) >> 8) | \
23 (((dw) & 0x0000FF00L) << 8) | \
24 (((dw) & 0x000000FFL) << 24))
25
26 /* DWORD host to network byte order conversion for little endian machines */
27 #define DH2N(dw) \
28 ((((dw) & 0xFF000000L) >> 24) | \
29 (((dw) & 0x00FF0000L) >> 8) | \
30 (((dw) & 0x0000FF00L) << 8) | \
31 (((dw) & 0x000000FFL) << 24))
32
33 /* WORD network to host order conversion for little endian machines */
34 #define WN2H(w) \
35 ((((w) & 0xFF00) >> 8) | \
36 (((w) & 0x00FF) << 8))
37
38 /* WORD host to network byte order conversion for little endian machines */
39 #define WH2N(w) \
40 ((((w) & 0xFF00) >> 8) | \
41 (((w) & 0x00FF) << 8))
42
43 #else /* BE */
44
45 /* DWORD network to host byte order conversion for big endian machines */
46 #define DN2H(dw) \
47 (dw)
48
49 /* DWORD host to network byte order conversion big endian machines */
50 #define DH2N(dw) \
51 (dw)
52
53 /* WORD network to host order conversion for big endian machines */
54 #define WN2H(w) \
55 (w)
56
57 /* WORD host to network byte order conversion for big endian machines */
58 #define WH2N(w) \
59 (w)
60
61 #endif /* BE */
62
63 /* FUNCTIONS *****************************************************************/
64
65 /*
66 * @implemented
67 */
68 ULONG
69 WSAAPI
70 inet_addr(IN CONST CHAR FAR* cp)
71 {
72 register u_long val, base, n;
73 register unsigned char c;
74 u_long parts[4], *pp = parts;
75
76 again:
77 /*
78 * Collect number up to ``.''.
79 * Values are specified as for C:
80 * 0x=hex, 0=octal, other=decimal.
81 */
82 val = 0; base = 10;
83 if (*cp == '0') {
84 if (*++cp == 'x' || *cp == 'X')
85 base = 16, cp++;
86 else
87 base = 8;
88 }
89 while ((c = *cp)) {
90 if (isdigit(c)) {
91 val = (val * base) + (c - '0');
92 cp++;
93 continue;
94 }
95 if (base == 16 && isxdigit(c)) {
96 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
97 cp++;
98 continue;
99 }
100 break;
101 }
102 if (*cp == '.') {
103 /*
104 * Internet format:
105 * a.b.c.d
106 * a.b.c (with c treated as 16-bits)
107 * a.b (with b treated as 24 bits)
108 */
109 if (pp >= parts + 4) return (INADDR_NONE);
110 *pp++ = val;
111 cp++;
112 goto again;
113 }
114 /*
115 * Check for trailing characters.
116 */
117 if (*cp && !isspace((UCHAR)*cp)) return (INADDR_NONE);
118
119 *pp++ = val;
120 /*
121 * Concoct the address according to
122 * the number of parts specified.
123 */
124 n = (u_long)(pp - parts);
125 switch (n) {
126
127 case 1: /* a -- 32 bits */
128 val = parts[0];
129 break;
130
131 case 2: /* a.b -- 8.24 bits */
132 val = (parts[0] << 24) | (parts[1] & 0xffffff);
133 break;
134
135 case 3: /* a.b.c -- 8.8.16 bits */
136 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
137 (parts[2] & 0xffff);
138 break;
139
140 case 4: /* a.b.c.d -- 8.8.8.8 bits */
141 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
142 ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
143 break;
144
145 default:
146 return (-1);
147 }
148 val = htonl(val);
149 return (val);
150 }
151
152 /*
153 * @implemented
154 */
155 CHAR FAR*
156 WSAAPI
157 inet_ntoa(IN IN_ADDR in)
158 {
159 PWSPROCESS Process;
160 PWSTHREAD Thread;
161 INT ErrorCode;
162 WSADATA WsaData;
163 BOOL ManualLoad = FALSE;
164 CHAR b[10];
165 PCHAR p;
166 DPRINT("inet_ntoa: %lx\n", in);
167
168 /* Enter prolog */
169 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
170 {
171 DPRINT("MANUAL LOAD\n");
172
173 /* Only fail if the error wasn't related to a missing WSAStartup */
174 if (ErrorCode != WSANOTINITIALISED)
175 {
176 /* Fail */
177 SetLastError(ErrorCode);
178 return NULL;
179 }
180
181 /* Apps aren't expected to call WSAStartup for this API, so we will */
182 if ((ErrorCode = WSAStartup(MAKEWORD(2,2), &WsaData)) != ERROR_SUCCESS)
183 {
184 /* We failed */
185 SetLastError(ErrorCode);
186 return NULL;
187 }
188
189 /* Try the prolog again */
190 ManualLoad = TRUE;
191 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
192 {
193 /* Failed again... */
194 WSACleanup();
195 SetLastError(ErrorCode);
196 return NULL;
197 }
198 }
199
200 p = Thread->Buffer;
201 _itoa(in.S_un.S_addr & 0xFF, b, 10);
202 strcpy(p, b);
203 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
204 strcat(p, ".");
205 strcat(p, b);
206 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
207 strcat(p, ".");
208 strcat(p, b);
209 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
210 strcat(p, ".");
211 strcat(p, b);
212
213 /* Cleanup the manual load */
214 if (ManualLoad) WSACleanup();
215
216 /* Return the buffer */
217 return p;
218 }
219
220 /*
221 * @implemented
222 */
223 ULONG
224 WSAAPI
225 htonl(IN ULONG hostlong)
226 {
227 return DH2N(hostlong);
228 }
229
230 /*
231 * @implemented
232 */
233 USHORT
234 WSAAPI
235 htons(IN USHORT hostshort)
236 {
237 return WH2N(hostshort);
238 }
239
240 /*
241 * @implemented
242 */
243 ULONG
244 WSAAPI
245 ntohl(IN ULONG netlong)
246 {
247 return DN2H(netlong);
248 }
249
250 /*
251 * @implemented
252 */
253 USHORT
254 WSAAPI
255 ntohs(IN USHORT netshort)
256 {
257 return WN2H(netshort);
258 }
259
260 /*
261 * @implemented
262 */
263 INT
264 WSAAPI
265 WSAHtonl(IN SOCKET s,
266 IN ULONG hostlong,
267 OUT ULONG FAR* lpnetlong)
268 {
269 INT ErrorCode;
270 PWSSOCKET Socket;
271 DPRINT("WSAHtonl: %p, %lx, %p\n", s, hostlong, lpnetlong);
272
273 /* Check for WSAStartup */
274 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
275 {
276 /* Make sure we got a parameter */
277 if (!lpnetlong)
278 {
279 /* Fail */
280 SetLastError(WSAEFAULT);
281 return SOCKET_ERROR;
282 }
283
284 /* Get the Socket Context */
285 if ((Socket = WsSockGetSocket(s)))
286 {
287 /* Check which byte order to use */
288 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
289 LITTLEENDIAN)
290 {
291 /* No conversion needed */
292 *lpnetlong = hostlong;
293 }
294 else
295 {
296 /* Use a swap */
297 *lpnetlong = DN2H(hostlong);
298 }
299
300 /* Dereference the socket */
301 WsSockDereference(Socket);
302
303 /* Return success */
304 return ERROR_SUCCESS;
305 }
306 else
307 {
308 /* Set the error code */
309 ErrorCode = WSAENOTSOCK;
310 }
311 }
312
313 /* Return with error */
314 SetLastError(ErrorCode);
315 return SOCKET_ERROR;
316 }
317
318 /*
319 * @implemented
320 */
321 INT
322 WSAAPI
323 WSAHtons(IN SOCKET s,
324 IN USHORT hostshort,
325 OUT USHORT FAR* lpnetshort)
326 {
327 INT ErrorCode;
328 PWSSOCKET Socket;
329 DPRINT("WSAHtons: %p, %lx, %p\n", s, hostshort, lpnetshort);
330
331 /* Check for WSAStartup */
332 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
333 {
334 /* Make sure we got a parameter */
335 if (!lpnetshort)
336 {
337 /* Fail */
338 SetLastError(WSAEFAULT);
339 return SOCKET_ERROR;
340 }
341
342 /* Get the Socket Context */
343 if ((Socket = WsSockGetSocket(s)))
344 {
345 /* Check which byte order to use */
346 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
347 LITTLEENDIAN)
348 {
349 /* No conversion needed */
350 *lpnetshort = hostshort;
351 }
352 else
353 {
354 /* Use a swap */
355 *lpnetshort = WN2H(hostshort);
356 }
357
358 /* Dereference the socket */
359 WsSockDereference(Socket);
360
361 /* Return success */
362 return ERROR_SUCCESS;
363 }
364 else
365 {
366 /* Set the error code */
367 ErrorCode = WSAENOTSOCK;
368 }
369 }
370
371 /* Return with error */
372 SetLastError(ErrorCode);
373 return SOCKET_ERROR;
374 }
375
376 /*
377 * @implemented
378 */
379 INT
380 WSAAPI
381 WSANtohl(IN SOCKET s,
382 IN ULONG netlong,
383 OUT ULONG FAR* lphostlong)
384 {
385 INT ErrorCode;
386 PWSSOCKET Socket;
387 DPRINT("WSANtohl: %p, %lx, %p\n", s, netlong, lphostlong);
388
389 /* Check for WSAStartup */
390 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
391 {
392 /* Make sure we got a parameter */
393 if (!lphostlong)
394 {
395 /* Fail */
396 SetLastError(WSAEFAULT);
397 return SOCKET_ERROR;
398 }
399
400 /* Get the Socket Context */
401 if ((Socket = WsSockGetSocket(s)))
402 {
403 /* Check which byte order to use */
404 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
405 LITTLEENDIAN)
406 {
407 /* No conversion needed */
408 *lphostlong = netlong;
409 }
410 else
411 {
412 /* Use a swap */
413 *lphostlong = DN2H(netlong);
414 }
415
416 /* Dereference the socket */
417 WsSockDereference(Socket);
418
419 /* Return success */
420 return ERROR_SUCCESS;
421 }
422 else
423 {
424 /* Set the error code */
425 ErrorCode = WSAENOTSOCK;
426 }
427 }
428
429 /* Return with error */
430 SetLastError(ErrorCode);
431 return SOCKET_ERROR;
432 }
433
434 /*
435 * @implemented
436 */
437 INT
438 WSAAPI
439 WSANtohs(IN SOCKET s,
440 IN USHORT netshort,
441 OUT USHORT FAR* lphostshort)
442 {
443 INT ErrorCode;
444 PWSSOCKET Socket;
445 DPRINT("WSANtohs: %p, %lx, %p\n", s, netshort, lphostshort);
446
447 /* Check for WSAStartup */
448 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
449 {
450 /* Make sure we got a parameter */
451 if (!lphostshort)
452 {
453 /* Fail */
454 SetLastError(WSAEFAULT);
455 return SOCKET_ERROR;
456 }
457
458 /* Get the Socket Context */
459 if ((Socket = WsSockGetSocket(s)))
460 {
461 /* Check which byte order to use */
462 if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
463 LITTLEENDIAN)
464 {
465 /* No conversion needed */
466 *lphostshort = netshort;
467 }
468 else
469 {
470 /* Use a swap */
471 *lphostshort = WN2H(netshort);
472 }
473
474 /* Dereference the socket */
475 WsSockDereference(Socket);
476
477 /* Return success */
478 return ERROR_SUCCESS;
479 }
480 else
481 {
482 /* Set the error code */
483 ErrorCode = WSAENOTSOCK;
484 }
485 }
486
487 /* Return with error */
488 SetLastError(ErrorCode);
489 return SOCKET_ERROR;
490 }
491