2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
5 * PURPOSE: Internet Protocol module
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 #define __LWIP_INET_H__
14 #include "lwip/netifapi.h"
17 LIST_ENTRY InterfaceListHead
;
18 KSPIN_LOCK InterfaceListLock
;
19 LIST_ENTRY NetTableListHead
;
20 KSPIN_LOCK NetTableListLock
;
21 BOOLEAN IPInitialized
= FALSE
;
22 BOOLEAN IpWorkItemQueued
= FALSE
;
23 /* Work around calling timer at Dpc level */
25 IP_PROTOCOL_HANDLER ProtocolTable
[IP_PROTOCOL_TABLE_SIZE
];
28 TCPRegisterInterface(PIP_INTERFACE IF
);
31 TCPUnregisterInterface(PIP_INTERFACE IF
);
36 * FUNCTION: Do nothing for when the IPPacket struct is part of another
38 * Object = Pointer to an IP packet structure
46 * FUNCTION: Frees an interface object
48 * Object = Pointer to an interface structure
51 ExFreePoolWithTag(Object
, IP_INTERFACE_TAG
);
54 PIP_PACKET
IPInitializePacket(
58 * FUNCTION: Creates an IP packet object
60 * Type = Type of IP packet
62 * Pointer to the created IP packet. NULL if there was not enough free resources.
65 /* FIXME: Is this needed? */
66 RtlZeroMemory(IPPacket
, sizeof(IP_PACKET
));
68 IPPacket
->Free
= DontFreePacket
;
69 IPPacket
->Type
= Type
;
75 VOID NTAPI
IPTimeoutDpcFn(PKDPC Dpc
,
76 PVOID DeferredContext
,
77 PVOID SystemArgument1
,
78 PVOID SystemArgument2
)
80 * FUNCTION: Timeout DPC
82 * Dpc = Pointer to our DPC object
83 * DeferredContext = Pointer to context information (unused)
84 * SystemArgument1 = Unused
85 * SystemArgument2 = Unused
87 * This routine is dispatched once in a while to do maintainance jobs
90 /* Check if datagram fragments have taken too long to assemble */
91 IPDatagramReassemblyTimeout();
93 /* Clean possible outdated cached neighbor addresses */
98 VOID
IPDispatchProtocol(
99 PIP_INTERFACE Interface
,
102 * FUNCTION: IP protocol dispatcher
104 * NTE = Pointer to net table entry which the packet was received on
105 * IPPacket = Pointer to an IP packet that was received
107 * This routine examines the IP header and passes the packet on to the
108 * right upper level protocol receive handler
112 IP_ADDRESS SrcAddress
;
114 switch (IPPacket
->Type
) {
116 Protocol
= ((PIPv4_HEADER
)(IPPacket
->Header
))->Protocol
;
117 AddrInitIPv4(&SrcAddress
, ((PIPv4_HEADER
)(IPPacket
->Header
))->SrcAddr
);
120 /* FIXME: IPv6 adresses not supported */
121 TI_DbgPrint(MIN_TRACE
, ("IPv6 datagram discarded.\n"));
124 TI_DbgPrint(MIN_TRACE
, ("Unrecognized datagram discarded.\n"));
128 NBResetNeighborTimeout(&SrcAddress
);
130 if (Protocol
< IP_PROTOCOL_TABLE_SIZE
)
132 /* Call the appropriate protocol handler */
133 (*ProtocolTable
[Protocol
])(Interface
, IPPacket
);
138 PIP_INTERFACE
IPCreateInterface(
139 PLLIP_BIND_INFO BindInfo
)
141 * FUNCTION: Creates an IP interface
143 * BindInfo = Pointer to link layer to IP binding information
145 * Pointer to IP_INTERFACE structure, NULL if there was
146 * not enough free resources
151 TI_DbgPrint(DEBUG_IP
, ("Called. BindInfo (0x%X).\n", BindInfo
));
154 if (BindInfo
->Address
) {
155 PUCHAR A
= BindInfo
->Address
;
156 TI_DbgPrint(DEBUG_IP
, ("Interface address (%02X %02X %02X %02X %02X %02X).\n",
157 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
161 IF
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(IP_INTERFACE
),
164 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
168 RtlZeroMemory(IF
, sizeof(IP_INTERFACE
));
171 IF
->Context
= BindInfo
->Context
;
172 IF
->HeaderSize
= BindInfo
->HeaderSize
;
173 IF
->MinFrameSize
= BindInfo
->MinFrameSize
;
174 IF
->MTU
= BindInfo
->MTU
;
175 IF
->Address
= BindInfo
->Address
;
176 IF
->AddressLength
= BindInfo
->AddressLength
;
177 IF
->Transmit
= BindInfo
->Transmit
;
179 IF
->Unicast
.Type
= IP_ADDRESS_V4
;
180 IF
->PointToPoint
.Type
= IP_ADDRESS_V4
;
181 IF
->Netmask
.Type
= IP_ADDRESS_V4
;
182 IF
->Broadcast
.Type
= IP_ADDRESS_V4
;
184 TcpipInitializeSpinLock(&IF
->Lock
);
186 IF
->TCPContext
= ExAllocatePool
187 ( NonPagedPool
, sizeof(struct netif
));
188 if (!IF
->TCPContext
) {
189 ExFreePoolWithTag(IF
, IP_INTERFACE_TAG
);
193 TCPRegisterInterface(IF
);
196 InsertTDIInterfaceEntity( IF
);
203 VOID
IPDestroyInterface(
206 * FUNCTION: Destroys an IP interface
208 * IF = Pointer to interface to destroy
211 TI_DbgPrint(DEBUG_IP
, ("Called. IF (0x%X).\n", IF
));
214 RemoveTDIInterfaceEntity( IF
);
217 TCPUnregisterInterface(IF
);
219 ExFreePool(IF
->TCPContext
);
220 ExFreePoolWithTag(IF
, IP_INTERFACE_TAG
);
223 VOID
IPAddInterfaceRoute( PIP_INTERFACE IF
) {
224 PNEIGHBOR_CACHE_ENTRY NCE
;
225 IP_ADDRESS NetworkAddress
;
227 /* Add a permanent neighbor for this NTE */
228 NCE
= NBAddNeighbor(IF
, &IF
->Unicast
,
229 IF
->Address
, IF
->AddressLength
,
232 TI_DbgPrint(MIN_TRACE
, ("Could not create NCE.\n"));
236 AddrWidenAddress( &NetworkAddress
, &IF
->Unicast
, &IF
->Netmask
);
238 if (!RouterAddRoute(&NetworkAddress
, &IF
->Netmask
, NCE
, 1)) {
239 TI_DbgPrint(MIN_TRACE
, ("Could not add route due to insufficient resources.\n"));
242 /* Send a gratuitous ARP packet to update the route caches of
245 ARPTransmit(NULL
, NULL
, IF
);
247 TCPUpdateInterfaceIPInformation(IF
);
250 BOOLEAN
IPRegisterInterface(
253 * FUNCTION: Registers an IP interface with IP layer
255 * IF = Pointer to interface to register
257 * TRUE if interface was successfully registered, FALSE if not
261 UINT ChosenIndex
= 0;
262 BOOLEAN IndexHasBeenChosen
;
263 IF_LIST_ITER(Interface
);
265 TI_DbgPrint(MID_TRACE
, ("Called. IF (0x%X).\n", IF
));
267 TcpipAcquireSpinLock(&IF
->Lock
, &OldIrql
);
269 /* Choose an index */
271 IndexHasBeenChosen
= TRUE
;
272 ForEachInterface(Interface
) {
273 if( Interface
->Index
== ChosenIndex
) {
275 IndexHasBeenChosen
= FALSE
;
278 } while( !IndexHasBeenChosen
);
280 IF
->Index
= ChosenIndex
;
282 if (!AddrIsUnspecified(&IF
->Unicast
))
284 IPAddInterfaceRoute(IF
);
287 /* Add interface to the global interface list */
288 TcpipInterlockedInsertTailList(&InterfaceListHead
,
292 TcpipReleaseSpinLock(&IF
->Lock
, OldIrql
);
297 VOID
IPRemoveInterfaceRoute( PIP_INTERFACE IF
) {
298 PNEIGHBOR_CACHE_ENTRY NCE
;
299 IP_ADDRESS GeneralRoute
;
301 NCE
= NBLocateNeighbor(&IF
->Unicast
);
304 TI_DbgPrint(DEBUG_IP
,("Removing interface Addr %s\n", A2S(&IF
->Unicast
)));
305 TI_DbgPrint(DEBUG_IP
,(" Mask %s\n", A2S(&IF
->Netmask
)));
307 AddrWidenAddress(&GeneralRoute
,&IF
->Unicast
,&IF
->Netmask
);
309 RouterRemoveRoute(&GeneralRoute
, &IF
->Unicast
);
311 NBRemoveNeighbor(NCE
);
315 VOID
IPUnregisterInterface(
318 * FUNCTION: Unregisters an IP interface with IP layer
320 * IF = Pointer to interface to unregister
325 TI_DbgPrint(DEBUG_IP
, ("Called. IF (0x%X).\n", IF
));
327 IPRemoveInterfaceRoute( IF
);
329 TcpipAcquireSpinLock(&InterfaceListLock
, &OldIrql3
);
330 RemoveEntryList(&IF
->ListEntry
);
331 TcpipReleaseSpinLock(&InterfaceListLock
, OldIrql3
);
335 VOID
DefaultProtocolHandler(
336 PIP_INTERFACE Interface
,
339 * FUNCTION: Default handler for Internet protocols
341 * NTE = Pointer to net table entry which the packet was received on
342 * IPPacket = Pointer to an IP packet that was received
345 TI_DbgPrint(MID_TRACE
, ("[IF %x] Packet of unknown Internet protocol "
346 "discarded.\n", Interface
));
348 Interface
->Stats
.InDiscardedUnknownProto
++;
352 VOID
IPRegisterProtocol(
354 IP_PROTOCOL_HANDLER Handler
)
356 * FUNCTION: Registers a handler for an IP protocol number
358 * ProtocolNumber = Internet Protocol number for which to register handler
359 * Handler = Pointer to handler to be called when a packet is received
361 * To unregister a protocol handler, call this function with Handler = NULL
364 if (ProtocolNumber
>= IP_PROTOCOL_TABLE_SIZE
) {
365 TI_DbgPrint(MIN_TRACE
, ("Protocol number is out of range (%d).\n", ProtocolNumber
));
369 ProtocolTable
[ProtocolNumber
] = Handler
? Handler
: DefaultProtocolHandler
;
373 NTSTATUS
IPStartup(PUNICODE_STRING RegistryPath
)
375 * FUNCTION: Initializes the IP subsystem
377 * RegistryPath = Our registry node for configuration parameters
379 * Status of operation
384 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
386 /* Initialize lookaside lists */
387 ExInitializeNPagedLookasideList(
388 &IPDRList
, /* Lookaside list */
389 NULL
, /* Allocate routine */
390 NULL
, /* Free routine */
392 sizeof(IPDATAGRAM_REASSEMBLY
), /* Size of each entry */
393 DATAGRAM_REASSEMBLY_TAG
, /* Tag */
396 ExInitializeNPagedLookasideList(
397 &IPFragmentList
, /* Lookaside list */
398 NULL
, /* Allocate routine */
399 NULL
, /* Free routine */
401 sizeof(IP_FRAGMENT
), /* Size of each entry */
402 DATAGRAM_FRAGMENT_TAG
, /* Tag */
405 ExInitializeNPagedLookasideList(
406 &IPHoleList
, /* Lookaside list */
407 NULL
, /* Allocate routine */
408 NULL
, /* Free routine */
410 sizeof(IPDATAGRAM_HOLE
), /* Size of each entry */
411 DATAGRAM_HOLE_TAG
, /* Tag */
414 /* Start routing subsystem */
417 /* Start neighbor cache subsystem */
420 /* Fill the protocol dispatch table with pointers
421 to the default protocol handler */
422 for (i
= 0; i
< IP_PROTOCOL_TABLE_SIZE
; i
++)
423 IPRegisterProtocol(i
, DefaultProtocolHandler
);
425 /* Initialize NTE list and protecting lock */
426 InitializeListHead(&NetTableListHead
);
427 TcpipInitializeSpinLock(&NetTableListLock
);
429 /* Initialize reassembly list and protecting lock */
430 InitializeListHead(&ReassemblyListHead
);
431 TcpipInitializeSpinLock(&ReassemblyListLock
);
433 IPInitialized
= TRUE
;
435 return STATUS_SUCCESS
;
442 * FUNCTION: Shuts down the IP subsystem
444 * Status of operation
447 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
450 return STATUS_SUCCESS
;
452 /* Shutdown neighbor cache subsystem */
455 /* Shutdown routing subsystem */
458 IPFreeReassemblyList();
460 /* Destroy lookaside lists */
461 ExDeleteNPagedLookasideList(&IPHoleList
);
462 ExDeleteNPagedLookasideList(&IPDRList
);
463 ExDeleteNPagedLookasideList(&IPFragmentList
);
465 IPInitialized
= FALSE
;
467 return STATUS_SUCCESS
;