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