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)
8 * CSH 01/08-2000 Created
22 * FUNCTION: Convert an IP address to a string (for debugging)
24 * Address = Pointer to an IP address structure
26 * Pointer to buffer with string representation of IP address
36 TI_DbgPrint(MIN_TRACE
, ("NULL address given.\n"));
41 switch (Address
->Type
) {
43 ip
= DN2H(Address
->Address
.IPv4Address
);
44 sprintf(p
, "%d.%d.%d.%d", (ip
>> 24) & 0xFF, (ip
>> 16) & 0xFF, (ip
>> 8) & 0xFF, ip
& 0xFF);
48 /* FIXME: IPv6 is not supported */
49 strcpy(p
, "(IPv6 address not supported)");
61 * FUNCTION: Frees an IP_ADDRESS object
63 * Object = Pointer to an IP address structure
72 BOOLEAN
AddrIsUnspecified(
75 * FUNCTION: Return wether IP address is an unspecified address
77 * Address = Pointer to an IP address structure
79 * TRUE if the IP address is an unspecified address, FALSE if not
82 switch (Address
->Type
) {
84 return (Address
->Address
.IPv4Address
== 0);
87 /* FIXME: IPv6 is not supported */
95 * FUNCTION: Extract IP address from TDI address structure
97 * AddrList = Pointer to transport address list to extract from
98 * Address = Address of a pointer to where an IP address is stored
99 * Port = Pointer to where port number is stored
100 * Cache = Address of pointer to a cached address (updated on return)
102 * Status of operation
104 NTSTATUS
AddrGetAddress(
105 PTRANSPORT_ADDRESS AddrList
,
106 PIP_ADDRESS
*Address
,
113 /* We can only use IP addresses. Search the list until we find one */
114 CurAddr
= AddrList
->Address
;
116 for (i
= 0; i
< AddrList
->TAAddressCount
; i
++) {
117 switch (CurAddr
->AddressType
) {
118 case TDI_ADDRESS_TYPE_IP
:
119 if (CurAddr
->AddressLength
>= TDI_ADDRESS_LENGTH_IP
) {
120 /* This is an IPv4 address */
121 PIP_ADDRESS IPAddress
;
122 PTDI_ADDRESS_IP ValidAddr
= (PTDI_ADDRESS_IP
)CurAddr
->Address
;
124 *Port
= ValidAddr
->sin_port
;
126 if ((Cache
) && (*Cache
)) {
127 if (((*Cache
)->Type
== IP_ADDRESS_V4
) &&
128 ((*Cache
)->Address
.IPv4Address
== ValidAddr
->in_addr
)) {
130 return STATUS_SUCCESS
;
132 /* Release the cached address as we cannot use it this time */
133 DereferenceObject(*Cache
);
138 IPAddress
= ExAllocatePool(NonPagedPool
, sizeof(IP_ADDRESS
));
140 AddrInitIPv4(IPAddress
, ValidAddr
->in_addr
);
141 *Address
= IPAddress
;
143 /* Update address cache */
146 ReferenceObject(*Cache
);
148 return STATUS_SUCCESS
;
150 return STATUS_INSUFFICIENT_RESOURCES
;
152 return STATUS_INVALID_ADDRESS
;
154 /* This is an unsupported address type.
155 Skip it and go to the next in the list */
156 CurAddr
= (PTA_ADDRESS
)((ULONG_PTR
)CurAddr
->Address
+ CurAddr
->AddressLength
);
160 return STATUS_INVALID_ADDRESS
;
165 * FUNCTION: Extract IP address from TDI address structure
167 * TdiAddress = Pointer to transport address list to extract from
168 * Address = Address of a pointer to where an IP address is stored
169 * Port = Pointer to where port number is stored
171 * Status of operation
173 NTSTATUS
AddrBuildAddress(
174 PTA_ADDRESS TdiAddress
,
175 PIP_ADDRESS
*Address
,
178 PTDI_ADDRESS_IP ValidAddr
;
179 PIP_ADDRESS IPAddress
;
181 if (TdiAddress
->AddressType
!= TDI_ADDRESS_TYPE_IP
)
182 return STATUS_INVALID_ADDRESS
;
184 if (TdiAddress
->AddressLength
!= TDI_ADDRESS_LENGTH_IP
)
185 return STATUS_INVALID_ADDRESS
;
187 ValidAddr
= (PTDI_ADDRESS_IP
)TdiAddress
->Address
;
189 IPAddress
= ExAllocatePool(NonPagedPool
, sizeof(IP_ADDRESS
));
191 return STATUS_INSUFFICIENT_RESOURCES
;
193 AddrInitIPv4(IPAddress
, ValidAddr
->in_addr
);
194 *Address
= IPAddress
;
195 *Port
= ValidAddr
->sin_port
;
197 return STATUS_SUCCESS
;
202 * FUNCTION: Returns wether two addresses are equal
204 * Address1 = Pointer to first address
205 * Address2 = Pointer to last address
207 * TRUE if Address1 = Address2, FALSE if not
210 PIP_ADDRESS Address1
,
211 PIP_ADDRESS Address2
)
213 if (Address1
->Type
!= Address2
->Type
)
216 switch (Address1
->Type
) {
218 return (Address1
->Address
.IPv4Address
== Address2
->Address
.IPv4Address
);
221 return (RtlCompareMemory(&Address1
->Address
, &Address2
->Address
,
222 sizeof(IPv6_RAW_ADDRESS
)) == sizeof(IPv6_RAW_ADDRESS
));
231 * FUNCTION: Returns wether Address1 is less than Address2
233 * Address1 = Pointer to first address
234 * Address2 = Pointer to last address
236 * -1 if Address1 < Address2, 1 if Address1 > Address2,
237 * or 0 if they are equal
240 PIP_ADDRESS Address1
,
241 PIP_ADDRESS Address2
)
243 switch (Address1
->Type
) {
244 case IP_ADDRESS_V4
: {
246 if (Address2
->Type
== IP_ADDRESS_V4
) {
247 Addr1
= DN2H(Address1
->Address
.IPv4Address
);
248 Addr2
= DN2H(Address2
->Address
.IPv4Address
);
257 /* FIXME: Support IPv6 */
261 /* FIXME: Support IPv6 */
271 * FUNCTION: Returns wether two addresses are equal with IPv4 as input
273 * Address1 = Pointer to first address
274 * Address2 = Pointer to last address
276 * TRUE if Address1 = Address2, FALSE if not
278 BOOLEAN
AddrIsEqualIPv4(
279 PIP_ADDRESS Address1
,
280 IPv4_RAW_ADDRESS Address2
)
282 if (Address1
->Type
== IP_ADDRESS_V4
)
283 return (Address1
->Address
.IPv4Address
== Address2
);
290 * FUNCTION: Build an IPv4 style address
292 * Address = Raw IPv4 address
294 * Pointer to IP address structure, NULL if there was not enough free
297 PIP_ADDRESS
AddrBuildIPv4(
298 IPv4_RAW_ADDRESS Address
)
300 PIP_ADDRESS IPAddress
;
302 IPAddress
= ExAllocatePool(NonPagedPool
, sizeof(IP_ADDRESS
));
304 IPAddress
->RefCount
= 1;
305 IPAddress
->Type
= IP_ADDRESS_V4
;
306 IPAddress
->Address
.IPv4Address
= Address
;
307 IPAddress
->Free
= IPAddressFree
;
315 * FUNCTION: Locates and returns an address entry using IPv4 adress as argument
317 * Address = Raw IPv4 address
319 * Pointer to address entry if found, NULL if not found
321 * Only unicast addresses are considered.
322 * If found, the address is referenced
324 PADDRESS_ENTRY
AddrLocateADEv4(
325 IPv4_RAW_ADDRESS Address
)
329 AddrInitIPv4(&Addr
, Address
);
331 return IPLocateADE(&Addr
, ADE_UNICAST
);
336 * FUNCTION: Searches through address file entries to find the first match
338 * Address = IP address
340 * Protocol = Protocol number
341 * SearchContext = Pointer to search context
343 * Pointer to address file, NULL if none was found
345 PADDRESS_FILE
AddrSearchFirst(
349 PAF_SEARCH SearchContext
)
351 SearchContext
->Address
= Address
;
352 SearchContext
->Port
= Port
;
353 SearchContext
->Next
= AddressFileListHead
.Flink
;
354 SearchContext
->Protocol
= Protocol
;
356 return AddrSearchNext(SearchContext
);
361 * FUNCTION: Searches through address file entries to find next match
363 * SearchContext = Pointer to search context
365 * Pointer to address file, NULL if none was found
367 PADDRESS_FILE
AddrSearchNext(
368 PAF_SEARCH SearchContext
)
370 PLIST_ENTRY CurrentEntry
;
371 PIP_ADDRESS IPAddress
;
373 PADDRESS_FILE Current
= NULL
;
374 BOOLEAN Found
= FALSE
;
376 if (IsListEmpty(SearchContext
->Next
))
379 CurrentEntry
= SearchContext
->Next
;
381 KeAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
383 while (CurrentEntry
!= &AddressFileListHead
) {
384 Current
= CONTAINING_RECORD(CurrentEntry
, ADDRESS_FILE
, ListEntry
);
386 IPAddress
= Current
->ADE
->Address
;
388 TI_DbgPrint(DEBUG_ADDRFILE
, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n",
392 WN2H(SearchContext
->Port
),
393 SearchContext
->Protocol
,
394 A2S(SearchContext
->Address
)));
396 /* See if this address matches the search criteria */
397 if (((Current
->Port
== SearchContext
->Port
) &&
398 (Current
->Protocol
== SearchContext
->Protocol
) &&
399 (AddrIsEqual(IPAddress
, SearchContext
->Address
))) ||
400 (AddrIsUnspecified(IPAddress
))) {
401 /* We've found a match */
405 CurrentEntry
= CurrentEntry
->Flink
;
408 KeReleaseSpinLock(&AddressFileListLock
, OldIrql
);
411 SearchContext
->Next
= CurrentEntry
->Flink
;
417 ULONG
inet_addr(PCSTR AddrString
)
419 * Convert an ansi string dotted-quad address to a ulong
421 * - this isn't quite like the real inet_addr() - * it doesn't
422 * handle "10.1" and similar - but it's good enough.
423 * - Returns in *host* byte order, unlike real inet_addr()
426 ULONG Octets
[4] = {0,0,0,0};
434 CHAR c
= *AddrString
;
443 if(c
< '0' || c
> '9')
447 Octets
[i
] += (c
- '0');
453 return (Octets
[3] << 24) + (Octets
[2] << 16) + (Octets
[1] << 8) + Octets
[0];