- Add locking to ICMPSendDatagram
[reactos.git] / lib / drivers / ip / network / address.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/address.c
5 * PURPOSE: Routines for handling addresses
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 extern int sprintf( char *out, const char *fmt, ... );
14
15 CHAR A2SStr[128];
16
17 PCHAR A2S(
18 PIP_ADDRESS Address)
19 /*
20 * FUNCTION: Convert an IP address to a string (for debugging)
21 * ARGUMENTS:
22 * Address = Pointer to an IP address structure
23 * RETURNS:
24 * Pointer to buffer with string representation of IP address
25 */
26 {
27 ULONG ip;
28 PCHAR p;
29
30 p = A2SStr;
31
32 if (!Address) {
33 TI_DbgPrint(MIN_TRACE, ("NULL address given.\n"));
34 strcpy(p, "(NULL)");
35 return p;
36 }
37
38 switch (Address->Type) {
39 case IP_ADDRESS_V4:
40 ip = DN2H(Address->Address.IPv4Address);
41 sprintf(p, "%d.%d.%d.%d",
42 (INT)((ip >> 24) & 0xFF),
43 (INT)((ip >> 16) & 0xFF),
44 (INT)((ip >> 8) & 0xFF),
45 (INT)(ip & 0xFF));
46 break;
47
48 case IP_ADDRESS_V6:
49 /* FIXME: IPv6 is not supported */
50 strcpy(p, "(IPv6 address not supported)");
51 break;
52 }
53 return p;
54 }
55
56 ULONG IPv4NToHl( ULONG Address ) {
57 return
58 ((Address & 0xff) << 24) |
59 ((Address & 0xff00) << 8) |
60 ((Address >> 8) & 0xff00) |
61 ((Address >> 24) & 0xff);
62 }
63
64 UINT AddrCountPrefixBits( PIP_ADDRESS Netmask ) {
65 UINT Prefix = 0;
66 if( Netmask->Type == IP_ADDRESS_V4 ) {
67 ULONG BitTest = 0x80000000;
68
69 /* The mask has been read in network order. Put it in host order
70 * in order to scan it. */
71
72 ULONG TestMask = IPv4NToHl(Netmask->Address.IPv4Address);
73
74 while( (BitTest & TestMask) == BitTest ) {
75 Prefix++;
76 BitTest >>= 1;
77 }
78 return Prefix;
79 } else {
80 TI_DbgPrint(DEBUG_DATALINK, ("Don't know address type %d\n",
81 Netmask->Type));
82 return 0;
83 }
84 }
85
86 VOID AddrWidenAddress( PIP_ADDRESS Network, PIP_ADDRESS Source,
87 PIP_ADDRESS Netmask ) {
88 if( Netmask->Type == IP_ADDRESS_V4 ) {
89 Network->Type = Netmask->Type;
90 Network->Address.IPv4Address =
91 Source->Address.IPv4Address & Netmask->Address.IPv4Address;
92 } else {
93 TI_DbgPrint(DEBUG_DATALINK, ("Don't know address type %d\n",
94 Netmask->Type));
95 *Network = *Source;
96 }
97 }
98
99 VOID IPAddressFree(
100 PVOID Object)
101 /*
102 * FUNCTION: Frees an IP_ADDRESS object
103 * ARGUMENTS:
104 * Object = Pointer to an IP address structure
105 * RETURNS:
106 * Nothing
107 */
108 {
109 ExFreePoolWithTag(Object, IP_ADDRESS_TAG);
110 }
111
112
113 BOOLEAN AddrIsUnspecified(
114 PIP_ADDRESS Address)
115 /*
116 * FUNCTION: Return wether IP address is an unspecified address
117 * ARGUMENTS:
118 * Address = Pointer to an IP address structure
119 * RETURNS:
120 * TRUE if the IP address is an unspecified address, FALSE if not
121 */
122 {
123 switch (Address->Type) {
124 case IP_ADDRESS_V4:
125 return (Address->Address.IPv4Address == 0 ||
126 Address->Address.IPv4Address == 0xFFFFFFFF);
127
128 case IP_ADDRESS_V6:
129 /* FIXME: IPv6 is not supported */
130 default:
131 return FALSE;
132 }
133 }
134
135
136 /*
137 * FUNCTION: Extract IP address from TDI address structure
138 * ARGUMENTS:
139 * AddrList = Pointer to transport address list to extract from
140 * Address = Address of a pointer to where an IP address is stored
141 * Port = Pointer to where port number is stored
142 * Cache = Address of pointer to a cached address (updated on return)
143 * RETURNS:
144 * Status of operation
145 */
146 NTSTATUS AddrGetAddress(
147 PTRANSPORT_ADDRESS AddrList,
148 PIP_ADDRESS Address,
149 PUSHORT Port)
150 {
151 PTA_ADDRESS CurAddr;
152 INT i;
153
154 /* We can only use IP addresses. Search the list until we find one */
155 CurAddr = AddrList->Address;
156
157 for (i = 0; i < AddrList->TAAddressCount; i++) {
158 switch (CurAddr->AddressType) {
159 case TDI_ADDRESS_TYPE_IP:
160 if (CurAddr->AddressLength >= TDI_ADDRESS_LENGTH_IP) {
161 /* This is an IPv4 address */
162 PTDI_ADDRESS_IP ValidAddr = (PTDI_ADDRESS_IP)CurAddr->Address;
163 *Port = ValidAddr->sin_port;
164 Address->Type = CurAddr->AddressType;
165 ValidAddr = (PTDI_ADDRESS_IP)CurAddr->Address;
166 AddrInitIPv4(Address, ValidAddr->in_addr);
167 return STATUS_SUCCESS;
168 }
169 }
170 }
171
172 return STATUS_INVALID_ADDRESS;
173 }
174
175 /*
176 * FUNCTION: Extract IP address from TDI address structure
177 * ARGUMENTS:
178 * TdiAddress = Pointer to transport address list to extract from
179 * Address = Address of a pointer to where an IP address is stored
180 * Port = Pointer to where port number is stored
181 * RETURNS:
182 * Status of operation
183 */
184 NTSTATUS AddrBuildAddress(
185 PTRANSPORT_ADDRESS TaAddress,
186 PIP_ADDRESS Address,
187 PUSHORT Port)
188 {
189 PTDI_ADDRESS_IP ValidAddr;
190 PTA_ADDRESS TdiAddress = &TaAddress->Address[0];
191
192 if (TdiAddress->AddressType != TDI_ADDRESS_TYPE_IP) {
193 TI_DbgPrint
194 (MID_TRACE,("AddressType %x, Not valid\n", TdiAddress->AddressType));
195 return STATUS_INVALID_ADDRESS;
196 }
197 if (TdiAddress->AddressLength < TDI_ADDRESS_LENGTH_IP) {
198 TI_DbgPrint
199 (MID_TRACE,("AddressLength %x, Not valid (expected %x)\n",
200 TdiAddress->AddressLength, TDI_ADDRESS_LENGTH_IP));
201 return STATUS_INVALID_ADDRESS;
202 }
203
204
205 ValidAddr = (PTDI_ADDRESS_IP)TdiAddress->Address;
206
207 AddrInitIPv4(Address, ValidAddr->in_addr);
208 *Port = ValidAddr->sin_port;
209
210 return STATUS_SUCCESS;
211 }
212
213 /*
214 * FUNCTION: Returns wether two addresses are equal
215 * ARGUMENTS:
216 * Address1 = Pointer to first address
217 * Address2 = Pointer to last address
218 * RETURNS:
219 * TRUE if Address1 = Address2, FALSE if not
220 */
221 BOOLEAN AddrIsEqual(
222 PIP_ADDRESS Address1,
223 PIP_ADDRESS Address2)
224 {
225 if (Address1->Type != Address2->Type) {
226 DbgPrint("AddrIsEqual: Unequal Address Types\n");
227 return FALSE;
228 }
229
230 switch (Address1->Type) {
231 case IP_ADDRESS_V4:
232 return (Address1->Address.IPv4Address == Address2->Address.IPv4Address);
233
234 case IP_ADDRESS_V6:
235 return (RtlCompareMemory(&Address1->Address, &Address2->Address,
236 sizeof(IPv6_RAW_ADDRESS)) == sizeof(IPv6_RAW_ADDRESS));
237 break;
238
239 default:
240 DbgPrint("AddrIsEqual: Bad address type\n");
241 break;
242 }
243
244 return FALSE;
245 }
246
247
248 /*
249 * FUNCTION: Returns wether Address1 is less than Address2
250 * ARGUMENTS:
251 * Address1 = Pointer to first address
252 * Address2 = Pointer to last address
253 * RETURNS:
254 * -1 if Address1 < Address2, 1 if Address1 > Address2,
255 * or 0 if they are equal
256 */
257 INT AddrCompare(
258 PIP_ADDRESS Address1,
259 PIP_ADDRESS Address2)
260 {
261 switch (Address1->Type) {
262 case IP_ADDRESS_V4: {
263 ULONG Addr1, Addr2;
264 if (Address2->Type == IP_ADDRESS_V4) {
265 Addr1 = DN2H(Address1->Address.IPv4Address);
266 Addr2 = DN2H(Address2->Address.IPv4Address);
267 if (Addr1 < Addr2)
268 return -1;
269 else
270 if (Addr1 == Addr2)
271 return 0;
272 else
273 return 1;
274 } else
275 /* FIXME: Support IPv6 */
276 return -1;
277
278 case IP_ADDRESS_V6:
279 /* FIXME: Support IPv6 */
280 break;
281 }
282 }
283
284 return FALSE;
285 }
286
287
288 /*
289 * FUNCTION: Returns wether two addresses are equal with IPv4 as input
290 * ARGUMENTS:
291 * Address1 = Pointer to first address
292 * Address2 = Pointer to last address
293 * RETURNS:
294 * TRUE if Address1 = Address2, FALSE if not
295 */
296 BOOLEAN AddrIsEqualIPv4(
297 PIP_ADDRESS Address1,
298 IPv4_RAW_ADDRESS Address2)
299 {
300 if (Address1->Type == IP_ADDRESS_V4)
301 return (Address1->Address.IPv4Address == Address2);
302
303 return FALSE;
304 }
305
306
307 unsigned long NTAPI inet_addr(const char *AddrString)
308 /*
309 * Convert an ansi string dotted-quad address to a ulong
310 * NOTES:
311 * - this isn't quite like the real inet_addr() - * it doesn't
312 * handle "10.1" and similar - but it's good enough.
313 * - Returns in *host* byte order, unlike real inet_addr()
314 */
315 {
316 ULONG Octets[4] = {0,0,0,0};
317 ULONG i = 0;
318
319 if(!AddrString)
320 return -1;
321
322 while(*AddrString)
323 {
324 CHAR c = *AddrString;
325 AddrString++;
326
327 if(c == '.')
328 {
329 i++;
330 continue;
331 }
332
333 if(c < '0' || c > '9')
334 return -1;
335
336 Octets[i] *= 10;
337 Octets[i] += (c - '0');
338
339 if(Octets[i] > 255)
340 return -1;
341 }
342
343 return (Octets[3] << 24) + (Octets[2] << 16) + (Octets[1] << 8) + Octets[0];
344 }
345
346 /* EOF */