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
14 LIST_ENTRY InterfaceListHead
;
15 KSPIN_LOCK InterfaceListLock
;
16 LIST_ENTRY NetTableListHead
;
17 KSPIN_LOCK NetTableListLock
;
18 UINT MaxLLHeaderSize
; /* Largest maximum header size */
19 UINT MinLLFrameSize
; /* Largest minimum frame size */
20 BOOLEAN IPInitialized
= FALSE
;
21 NPAGED_LOOKASIDE_LIST IPPacketList
;
22 /* Work around calling timer at Dpc level */
24 IP_PROTOCOL_HANDLER ProtocolTable
[IP_PROTOCOL_TABLE_SIZE
];
30 * FUNCTION: Frees an IP packet object
32 * Object = Pointer to an IP packet structure
35 TcpipFreeToNPagedLookasideList(&IPPacketList
, Object
);
42 * FUNCTION: Do nothing for when the IPPacket struct is part of another
44 * Object = Pointer to an IP packet structure
52 * FUNCTION: Frees an interface object
54 * Object = Pointer to an interface structure
61 PIP_PACKET
IPCreatePacket(ULONG Type
)
63 * FUNCTION: Creates an IP packet object
65 * Type = Type of IP packet
67 * Pointer to the created IP packet. NULL if there was not enough free resources.
72 IPPacket
= TcpipAllocateFromNPagedLookasideList(&IPPacketList
);
76 /* FIXME: Is this needed? */
77 RtlZeroMemory(IPPacket
, sizeof(IP_PACKET
));
79 INIT_TAG(IPPacket
, TAG('I','P','K','T'));
81 IPPacket
->Free
= FreePacket
;
82 IPPacket
->Type
= Type
;
83 IPPacket
->HeaderSize
= 20;
88 PIP_PACKET
IPInitializePacket(
92 * FUNCTION: Creates an IP packet object
94 * Type = Type of IP packet
96 * Pointer to the created IP packet. NULL if there was not enough free resources.
99 /* FIXME: Is this needed? */
100 RtlZeroMemory(IPPacket
, sizeof(IP_PACKET
));
102 INIT_TAG(IPPacket
, TAG('I','P','K','T'));
104 IPPacket
->Free
= DontFreePacket
;
105 IPPacket
->Type
= Type
;
111 void STDCALL
IPTimeout( PVOID Context
) {
112 /* Check if datagram fragments have taken too long to assemble */
113 IPDatagramReassemblyTimeout();
115 /* Clean possible outdated cached neighbor addresses */
118 /* Call upper layer timeout routines */
123 VOID
IPDispatchProtocol(
124 PIP_INTERFACE Interface
,
127 * FUNCTION: IP protocol dispatcher
129 * NTE = Pointer to net table entry which the packet was received on
130 * IPPacket = Pointer to an IP packet that was received
132 * This routine examines the IP header and passes the packet on to the
133 * right upper level protocol receive handler
138 switch (IPPacket
->Type
) {
140 Protocol
= ((PIPv4_HEADER
)(IPPacket
->Header
))->Protocol
;
143 /* FIXME: IPv6 adresses not supported */
144 TI_DbgPrint(MIN_TRACE
, ("IPv6 datagram discarded.\n"));
150 /* Call the appropriate protocol handler */
151 (*ProtocolTable
[Protocol
])(Interface
, IPPacket
);
155 PIP_INTERFACE
IPCreateInterface(
156 PLLIP_BIND_INFO BindInfo
)
158 * FUNCTION: Creates an IP interface
160 * BindInfo = Pointer to link layer to IP binding information
162 * Pointer to IP_INTERFACE structure, NULL if there was
163 * not enough free resources
168 TI_DbgPrint(DEBUG_IP
, ("Called. BindInfo (0x%X).\n", BindInfo
));
171 if (BindInfo
->Address
) {
172 PUCHAR A
= BindInfo
->Address
;
173 TI_DbgPrint(DEBUG_IP
, ("Interface address (%02X %02X %02X %02X %02X %02X).\n",
174 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
178 IF
= exAllocatePool(NonPagedPool
, sizeof(IP_INTERFACE
));
180 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
184 INIT_TAG(IF
, TAG('F','A','C','E'));
187 IF
->Context
= BindInfo
->Context
;
188 IF
->HeaderSize
= BindInfo
->HeaderSize
;
189 if (IF
->HeaderSize
> MaxLLHeaderSize
)
190 MaxLLHeaderSize
= IF
->HeaderSize
;
192 IF
->MinFrameSize
= BindInfo
->MinFrameSize
;
193 if (IF
->MinFrameSize
> MinLLFrameSize
)
194 MinLLFrameSize
= IF
->MinFrameSize
;
196 IF
->MTU
= BindInfo
->MTU
;
197 IF
->Address
= BindInfo
->Address
;
198 IF
->AddressLength
= BindInfo
->AddressLength
;
199 IF
->Transmit
= BindInfo
->Transmit
;
201 TcpipInitializeSpinLock(&IF
->Lock
);
204 InsertTDIInterfaceEntity( IF
);
211 VOID
IPDestroyInterface(
214 * FUNCTION: Destroys an IP interface
216 * IF = Pointer to interface to destroy
219 TI_DbgPrint(DEBUG_IP
, ("Called. IF (0x%X).\n", IF
));
222 RemoveTDIInterfaceEntity( IF
);
229 BOOLEAN
IPRegisterInterface(
232 * FUNCTION: Registers an IP interface with IP layer
234 * IF = Pointer to interface to register
236 * TRUE if interface was successfully registered, FALSE if not
240 PROUTE_CACHE_NODE RCN
;
241 PNEIGHBOR_CACHE_ENTRY NCE
;
243 TI_DbgPrint(MID_TRACE
, ("Called. IF (0x%X).\n", IF
));
245 TcpipAcquireSpinLock(&IF
->Lock
, &OldIrql
);
247 /* Add a permanent neighbor for this NTE */
248 NCE
= NBAddNeighbor(IF
, &IF
->Unicast
,
249 IF
->Address
, IF
->AddressLength
,
252 TI_DbgPrint(MIN_TRACE
, ("Could not create NCE.\n"));
253 TcpipReleaseSpinLock(&IF
->Lock
, OldIrql
);
257 /* NCE is already referenced */
258 if (!RouterAddRoute(&IF
->Unicast
, &IF
->Netmask
, NCE
, 1)) {
259 TI_DbgPrint(MIN_TRACE
, ("Could not add route due to insufficient resources.\n"));
262 RCN
= RouteAddRouteToDestination(&IF
->Unicast
, IF
, NCE
);
264 TI_DbgPrint(MIN_TRACE
, ("Could not create RCN.\n"));
265 TcpipReleaseSpinLock(&IF
->Lock
, OldIrql
);
268 /* Add interface to the global interface list */
269 ASSERT(&IF
->ListEntry
);
270 TcpipInterlockedInsertTailList(&InterfaceListHead
,
274 /* Allow TCP to hang some configuration on this interface */
275 IF
->TCPContext
= TCPPrepareInterface( IF
);
277 TcpipReleaseSpinLock(&IF
->Lock
, OldIrql
);
283 VOID
IPUnregisterInterface(
286 * FUNCTION: Unregisters an IP interface with IP layer
288 * IF = Pointer to interface to unregister
292 PNEIGHBOR_CACHE_ENTRY NCE
;
294 TI_DbgPrint(DEBUG_IP
, ("Called. IF (0x%X).\n", IF
));
296 /* Remove permanent NCE, but first we have to find it */
297 NCE
= NBLocateNeighbor(&IF
->Unicast
);
299 NBRemoveNeighbor(NCE
);
301 TcpipAcquireSpinLock(&InterfaceListLock
, &OldIrql3
);
302 /* Ouch...three spinlocks acquired! Fortunately
303 we don't unregister interfaces very often */
304 RemoveEntryList(&IF
->ListEntry
);
305 TcpipReleaseSpinLock(&InterfaceListLock
, OldIrql3
);
309 VOID
IPRegisterProtocol(
311 IP_PROTOCOL_HANDLER Handler
)
313 * FUNCTION: Registers a handler for an IP protocol number
315 * ProtocolNumber = Internet Protocol number for which to register handler
316 * Handler = Pointer to handler to be called when a packet is received
318 * To unregister a protocol handler, call this function with Handler = NULL
322 if (ProtocolNumber
>= IP_PROTOCOL_TABLE_SIZE
)
323 TI_DbgPrint(MIN_TRACE
, ("Protocol number is out of range (%d).\n", ProtocolNumber
));
326 ProtocolTable
[ProtocolNumber
] = Handler
;
330 VOID
DefaultProtocolHandler(
331 PIP_INTERFACE Interface
,
334 * FUNCTION: Default handler for Internet protocols
336 * NTE = Pointer to net table entry which the packet was received on
337 * IPPacket = Pointer to an IP packet that was received
340 TI_DbgPrint(MID_TRACE
, ("[IF %x] Packet of unknown Internet protocol "
341 "discarded.\n", Interface
));
345 NTSTATUS
IPStartup(PUNICODE_STRING RegistryPath
)
347 * FUNCTION: Initializes the IP subsystem
349 * RegistryPath = Our registry node for configuration parameters
351 * Status of operation
356 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
361 /* Initialize lookaside lists */
362 ExInitializeNPagedLookasideList(
363 &IPDRList
, /* Lookaside list */
364 NULL
, /* Allocate routine */
365 NULL
, /* Free routine */
367 sizeof(IPDATAGRAM_REASSEMBLY
), /* Size of each entry */
368 TAG('I','P','D','R'), /* Tag */
371 ExInitializeNPagedLookasideList(
372 &IPPacketList
, /* Lookaside list */
373 NULL
, /* Allocate routine */
374 NULL
, /* Free routine */
376 sizeof(IP_PACKET
), /* Size of each entry */
377 TAG('I','P','P','K'), /* Tag */
380 ExInitializeNPagedLookasideList(
381 &IPFragmentList
, /* Lookaside list */
382 NULL
, /* Allocate routine */
383 NULL
, /* Free routine */
385 sizeof(IP_FRAGMENT
), /* Size of each entry */
386 TAG('I','P','F','G'), /* Tag */
389 ExInitializeNPagedLookasideList(
390 &IPHoleList
, /* Lookaside list */
391 NULL
, /* Allocate routine */
392 NULL
, /* Free routine */
394 sizeof(IPDATAGRAM_HOLE
), /* Size of each entry */
395 TAG('I','P','H','L'), /* Tag */
398 /* Start routing subsystem */
401 /* Start route cache subsystem */
404 /* Start neighbor cache subsystem */
407 /* Fill the protocol dispatch table with pointers
408 to the default protocol handler */
409 for (i
= 0; i
< IP_PROTOCOL_TABLE_SIZE
; i
++)
410 IPRegisterProtocol(i
, DefaultProtocolHandler
);
412 /* Register network level protocol receive handlers */
413 IPRegisterProtocol(IPPROTO_ICMP
, ICMPReceive
);
415 /* Initialize NTE list and protecting lock */
416 InitializeListHead(&NetTableListHead
);
417 TcpipInitializeSpinLock(&NetTableListLock
);
419 /* Initialize reassembly list and protecting lock */
420 InitializeListHead(&ReassemblyListHead
);
421 TcpipInitializeSpinLock(&ReassemblyListLock
);
423 IPInitialized
= TRUE
;
425 return STATUS_SUCCESS
;
432 * FUNCTION: Shuts down the IP subsystem
434 * Status of operation
437 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
440 return STATUS_SUCCESS
;
442 /* Shutdown neighbor cache subsystem */
445 /* Shutdown route cache subsystem */
448 /* Shutdown routing subsystem */
451 IPFreeReassemblyList();
453 /* Destroy lookaside lists */
454 ExDeleteNPagedLookasideList(&IPHoleList
);
455 ExDeleteNPagedLookasideList(&IPDRList
);
456 ExDeleteNPagedLookasideList(&IPPacketList
);
457 ExDeleteNPagedLookasideList(&IPFragmentList
);
459 IPInitialized
= FALSE
;
461 return STATUS_SUCCESS
;