Compare commits

...

29 Commits

Author SHA1 Message Date
Hermès Bélusca-Maïto
d9fceab325 Fix build. 2017-10-09 21:05:58 +02:00
Zuodian Hu
5c170dba4a Multi-threaded the server side of the TCP test.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72437
2017-10-09 21:05:58 +02:00
Zuodian Hu
cafd261b58 Fixed mixing of declarations and case statements.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72412
2017-10-09 21:05:58 +02:00
Zuodian Hu
53d6c153c1 Re-enabled some leftover UDP code that I missed earlier
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72411
2017-10-09 21:05:58 +02:00
Zuodian Hu
5c00746715 Added back UDP code from the original driver I received to work on. Modified address creation function to support UDP, ICMP, and RAW. Added TDI_QUERY_ADDRESS_INFO handler.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72334
2017-10-09 21:05:58 +02:00
Zuodian Hu
0e5f1a8172 Disabled more UDP code I missed earlier
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72247
2017-10-09 21:05:58 +02:00
Zuodian Hu
b307304597 Disabled UDP code, which was broken by my changes
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72246
2017-10-09 21:05:58 +02:00
Zuodian Hu
5b8f12afd5 Put MTSerialMutex around a call into lwIP that I previously missed.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72245
2017-10-09 21:05:58 +02:00
Zuodian Hu
ae49055b2d More complete shutdown forces lwIP to get rid of lingering, dead connections to allow re-binding to dead TCP ports.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72243
2017-10-09 21:05:58 +02:00
Zuodian Hu
fa552bc182 Set Irp->CancelRoutine when enqueueing IRPs.
More detailed debug printouts. Deleted old debug printouts. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72237
2017-10-09 21:05:58 +02:00
Zuodian Hu
fe828c7869 Rewrite of many address.c functions to simplify locking and resolve deadlocks, special attention paid to whether AFD and lwIP have pointers to my data or not. Added deadlock resolution to MTSerialMutex acquisition macros. Better organization of TCP functions in source code. Removed unnecessary helper functions.
Reduced number of types of pending requests and the number of possible TCP states. Removed uselessly flawed IRPSP debugging array. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72200
2017-10-09 21:05:58 +02:00
Zuodian Hu
9152dcd395 Massively simplified the mutex guarding each TCP_CONTEXT struct. Before, manually handled recursion. Now uses KMUTEX to handle recursion. Corrected the way debug printouts get the current thread context. Added code to walk Request linked lists for pending TDI_SEND and TDI_RECEIVE requests upon completion of a TDI_SEND and TDI_RECEIVE request, respectively. Without this check, backed-up request were left hanging forever. Split off the lwIP tcp_write() call into a helper function to aid this. Various deadlock fixes.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72159
2017-10-09 21:05:58 +02:00
Zuodian Hu
0419b23db6 Mostly fully working TCP. Occasional crash due to faulty mbox implementation in sys_arch.c.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72106
2017-10-09 21:05:58 +02:00
Zuodian Hu
1ff4744677 Added global KMUTEX serializing all threads that access lwIP. Added global arrays to debug IRPs. Implemented TDI_LISTEN handler. Made the Context mutex recursive within a thread.
Modified the way listening connection contexts are handled. Now creates a new TCP_CONTEXT struct on a TDI_LISTEN, which dies on the TDI_LISTEN's cancellation. 
Minor modifications to make some functions work better with the large changes. Removed the majority of debug printout statements. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72104
2017-10-09 21:05:58 +02:00
Zuodian Hu
ee238ae9a7 Major rewrite of address.c, completely restructuring internal data. No longer maintaining linked list of connection endpoints; their references are handed off to lwIP to keep track of in protocol control blocks. Scrapped redundant functions in duplicate address checking code in favor of exposing lwIP's free-port checking function and letting lwIP handle address collisions when binding. Added a custom mutex that allows only one execution context to access each connection endpoint (TCP_CONTEXT). Massively improved coding style consistency.
Server side can handle multiple incoming connections in series without crashing, but there is an undiagnosed issue that causes frequent crashes on repeated attempts to connect to a server. The crash always happens after a call to tcp_connect() has been made, and before it returns. 
No attempted solution to the lwIP multi-threading problem in this commit. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=72051
2017-10-09 21:05:58 +02:00
Zuodian Hu
7c78e13710 Added global static lists to keep track of memory allocations for debugging purposes.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71943
2017-10-09 21:05:58 +02:00
Zuodian Hu
f4ffbd00d1 Changed test programs. Server now echoes messages sent by client, and client is now multi-threaded.
Modified spinlocks to serialize access to metadata as well as linked lists. Very inefficient, and does not pass my own test bench right now. 
Defined and wrote initialization code for global variables intended solely as debugging aids. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71935
2017-10-09 21:05:58 +02:00
Zuodian Hu
6b24b98072 Cleaned out debug printouts. Fixed all crashes for strictly serial client-handling.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71908
2017-10-09 21:05:58 +02:00
Zuodian Hu
04571e1dbb Multitude of bug fixes for state TCP Context state transitions, memory allocation/deallocation, and LIST_ENTRY usage.
Corrected handling of dying sockets. Previously, connected sockets assigned by lwIP through the accepted callback were not assigned an error callback. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71905
2017-10-09 21:05:58 +02:00
Zuodian Hu
24ee5b3396 Structural, style, correctness fixes.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71865
2017-10-09 21:05:58 +02:00
Zuodian Hu
606af0c099 Mostly cleanup. Removed abusive use of cancel spin lock, thanks to David for pointing that out for me.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71835
2017-10-09 21:05:58 +02:00
Zuodian Hu
b9556ea719 Fixed crash on client and server exit:
Corrected some NULL data marking and checking. 
Moved some cleanup code so they actually execute on function failure (incomplete).
Removed redundant tcp_close() call in error callback.
Changed listen request cancel mode from ABORT to CLOSE, since ABORT is illegal for a listening pcb. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71823
2017-10-09 21:05:58 +02:00
Zuodian Hu
3ef725b96b State variables implemented. A QueryNdisBuffer macro is expanded out in my code because I'm trying to chase down a page fault that happens during that particular call.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71713
2017-10-09 21:05:58 +02:00
Zuodian Hu
55c372b2c3 Server now handles multiple connections without crashing, as long as each connection terminates before the next one is established.
Removed misuse of the datagram request lock. 
Added two more memory allocation tags, one for connection contexts and one for TCP requests. 
Added state variable to ADDRESS_FILE struct to make socket state management cleaner. 

svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71665
2017-10-09 21:05:58 +02:00
Zuodian Hu
b26dc390cc Added my user-mode test programs
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71663
2017-10-09 21:05:58 +02:00
Zuodian Hu
19adc74ebd Backlogging successful. Server is able to simultaneously receive messages from two different clients. Crashes on client exit due to referencing deallocated memory.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71661
2017-10-09 21:05:58 +02:00
Zuodian Hu
3411247830 Partial support for lwIP backlogging. Extra connection contexts are stored in a seemingly valid linked list, but their associated TDI_LISTEN IRPs are overwritten on new TDI_LISTEN calls because they are not yet logged.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71658
2017-10-09 21:05:58 +02:00
Zuodian Hu
11059493a3 TDI_SEND and TDI_RECEIVE handlers code-complete. None of it has been tested yet.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71652
2017-10-09 21:05:58 +02:00
Zuodian Hu
67ff49b0a5 Merge changes from GsOC network branch. Last commit from the other branch added IRQ cancellation.
svn path=/branches/GSoC_2016/lwIP-tcpip/; revision=71646

# Conflicts:
#	drivers/network/tcpip/include/linux.h
#	drivers/network/tcpip/include/tags.h
#	drivers/network/tcpip/include/tcpcore.h
#	drivers/network/tcpip/include/tcpdef.h
#	drivers/network/tcpip/include/ticonsts.h
#	drivers/network/tcpip/include/titypes.h
#	drivers/network/tcpip/tcpip/ainfo.c
#	drivers/network/tcpip/tcpip/buffer.c
#	drivers/network/tcpip/tcpip/mockbuffer.c
#	drivers/network/tcpip/tcpip/ninfo.c
#	drivers/network/tcpip/tests/tests/ipreceive.c
2017-10-09 21:05:58 +02:00
82 changed files with 5286 additions and 4444 deletions

View File

@@ -10,6 +10,8 @@ add_subdirectory(netstat)
add_subdirectory(nslookup)
add_subdirectory(ping)
add_subdirectory(route)
add_subdirectory(tcpclient)
add_subdirectory(tcpserver)
add_subdirectory(telnet)
add_subdirectory(tracert)
add_subdirectory(whois)

View File

@@ -0,0 +1,11 @@
add_definitions(-D__USE_W32_SOCKETS)
add_executable(client main.c)
set_module_type(client win32cui UNICODE)
add_importlibs(client user32 ws2_32 msvcrt kernel32)
if(MSVC)
add_importlibs(client ntdll)
endif()
add_cd_file(TARGET client DESTINATION reactos/system32 FOR all)

View File

@@ -0,0 +1,122 @@
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#define LENGTH 255
#define NUM_CLIENTS 128
DWORD WINAPI ClientThreadMain(LPVOID lpParam) {
SOCKET Sock;
struct sockaddr_in ServerAddr;
char buff[LENGTH];
int self;
int ret;
int len;
self = (int)lpParam;
printf("Client %d startup\n", self);
Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Sock == INVALID_SOCKET) {
printf("Client %d failed to create socket: %d\n", self, WSAGetLastError());
return 1;
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ServerAddr.sin_port = htons(10000);
printf("Client %d attempting to connect\n", self);
ret = connect(Sock, (struct sockaddr *)&ServerAddr, sizeof(struct sockaddr_in));
if (ret == SOCKET_ERROR) {
printf("Client %d failed to connect: %d\n", self, WSAGetLastError());
closesocket(Sock);
return 1;
}
sprintf(buff, "Client %d pinging server", self);
len = strlen(buff);
printf("Client %d attempting to send\n", self);
ret = send(Sock, buff, len, 0);
if (ret != len) {
printf("Client %d failed to send properly. Should send %d bytes, send() returned %d\n WSA Error: %d\n",
self, len, ret, WSAGetLastError());
closesocket(Sock);
return 1;
}
printf("Client %d attempting to receive\n", self);
ret = recv(Sock, buff, LENGTH, 0);
buff[LENGTH - 1] = '\0';
if (ret <= 0) {
printf("Client %d received no response from server: %d\n", self, WSAGetLastError());
}
else {
printf("Client %d received %d-byte response from server:\n %s\n",
self, ret, buff);
}
closesocket(Sock);
printf("Client %d exit\n", self);
return 0;
}
int wmain(int argc, LPWSTR argv[]) {
WSADATA wsa;
SYSTEMTIME StartTime;
SYSTEMTIME EndTime;
HANDLE ClientThreadHandles[NUM_CLIENTS];
DWORD ClientThreadIDs[NUM_CLIENTS];
char buff[LENGTH];
int ret;
int i;
ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0) {
printf("Windows Socket API Startup Failed: %d\n", WSAGetLastError());
return 1;
}
GetSystemTime(&StartTime);
for (i = 0; i < NUM_CLIENTS; i++) {
ClientThreadHandles[i] = CreateThread(
NULL,
0,
ClientThreadMain,
(LPVOID)i,
0,
&ClientThreadIDs[i]);
if (ClientThreadHandles[i] == NULL) {
printf("Thread %d failed to spawn\n", i);
return 1;
}
}
WaitForMultipleObjects(NUM_CLIENTS, ClientThreadHandles, TRUE, INFINITE);
GetSystemTime(&EndTime);
for (i = 0; i < NUM_CLIENTS; i++) {
CloseHandle(ClientThreadHandles[i]);
}
fgets(buff, LENGTH, stdin);
printf("Elapsed: %d.%03d s\n",
EndTime.wSecond - StartTime.wSecond, EndTime.wMilliseconds - StartTime.wMilliseconds);
fgets(buff, LENGTH, stdin);
return 0;
}

View File

@@ -0,0 +1,11 @@
add_definitions(-D__USE_W32_SOCKETS)
add_executable(server main.c)
set_module_type(server win32cui UNICODE)
add_importlibs(server user32 ws2_32 msvcrt kernel32)
if(MSVC)
add_importlibs(server ntdll)
endif()
add_cd_file(TARGET server DESTINATION reactos/system32 FOR all)

View File

@@ -0,0 +1,147 @@
#include <stdio.h>
#include <winsock2.h>
#define backlog 4
#define LENGTH 256
struct ClientInfo {
int ClientID;
SOCKET ClientSock;
};
DWORD WINAPI ServerThreadMain(LPVOID lpParam) {
SOCKET ClientSock;
struct ClientInfo *CInfo;
char buff[LENGTH];
int count;
int ret;
CInfo = (struct ClientInfo *)lpParam;
count = CInfo->ClientID;
ClientSock = CInfo->ClientSock;
printf("Connection established to client %d\n", count);
ret = recv(ClientSock, buff, LENGTH, 0);
if (ret < 0) {
printf(" Receive failure on socket %d: %d\n", ClientSock, WSAGetLastError());
return 1;
}
buff[ret] = '\0';
printf(" Received %d-byte message from client %d: %s\n", ret, count, buff);
ret = send(ClientSock, buff, ret, 0);
if (ret == SOCKET_ERROR) {
printf("Send failed: %d\n", WSAGetLastError());
closesocket(ClientSock);
fgets(buff, LENGTH, stdin);
return 1;
}
printf("Message echoed\n");
closesocket(ClientSock);
free(CInfo);
return 0;
}
int wmain(int argc, LPWSTR argv[]) {
DWORD ServerThreadID;
WSADATA wsa;
SOCKET ListenSock;
SOCKET ClientSock;
struct ClientInfo *CInfo;
struct sockaddr_in ListenAddr;
struct sockaddr_in ClientAddr;
char buff[LENGTH];
int ret;
int addrSize;
int count;
printf("Server startup\n");
ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0) {
printf("Windows Socket API Startup Failed: %d\n", WSAGetLastError());
fgets(buff, LENGTH, stdin);
return 1;
}
memset(&ListenAddr, 0, sizeof(struct sockaddr_in));
ListenAddr.sin_family = AF_INET;
ListenAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ListenAddr.sin_port = htons(10000);
ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSock == INVALID_SOCKET) {
printf("Socket creation failed: %d\n", WSAGetLastError());
WSACleanup();
fgets(buff, LENGTH, stdin);
return 1;
}
printf("Server listening socket created\n");
ret = bind(ListenSock, (struct sockaddr *)&ListenAddr, sizeof(ListenAddr));
if (ret == SOCKET_ERROR) {
printf("Bind failed: %d\n", WSAGetLastError());
closesocket(ListenSock);
WSACleanup();
fgets(buff, LENGTH, stdin);
return 1;
}
printf("Server listening socket bound\n");
ret = listen(ListenSock, backlog);
if (ret == SOCKET_ERROR) {
printf("Listen failed: %d\n", WSAGetLastError());
closesocket(ListenSock);
WSACleanup();
fgets(buff, LENGTH, stdin);
return 1;
}
printf("Server listening socket is now listening\n");
count = 0;
while (1) {
addrSize = sizeof(struct sockaddr_in);
memset(buff, 0, sizeof(buff));
printf("\nWaiting to accept connection %d\n", count);
ClientSock = accept(ListenSock, (struct sockaddr *)&ClientAddr, &addrSize);
if (ClientSock == INVALID_SOCKET) {
printf("Accept failed: %d\n", WSAGetLastError());
closesocket(ListenSock);
WSACleanup();
fgets(buff, LENGTH, stdin);
exit(1);
}
CInfo = malloc(sizeof(*CInfo));
CInfo->ClientID = count;
CInfo->ClientSock = ClientSock;
CreateThread(
NULL,
0,
ServerThreadMain,
(LPVOID)CInfo,
0,
&ServerThreadID);
count++;
}
printf("Server exit\n");
fgets(buff, LENGTH, stdin);
return 0;
}

View File

@@ -1,39 +1,31 @@
include_directories(
BEFORE include
${REACTOS_SOURCE_DIR}/sdk/lib/drivers/lwip/src/include
${REACTOS_SOURCE_DIR}/sdk/lib/drivers/lwip/src/include/ipv4)
add_definitions(
-DNDIS40
-D_NTDRIVER_)
add_definitions(-DNDIS51)
spec2def(tcpip.sys tcpip.spec)
list(APPEND SOURCE
datalink/lan.c
tcpip/ainfo.c
tcpip/buffer.c
tcpip/cinfo.c
tcpip/dispatch.c
tcpip/fileobjs.c
tcpip/iinfo.c
tcpip/info.c
tcpip/lock.c
tcpip/main.c
tcpip/ninfo.c
tcpip/proto.c
tcpip/tinfo.c
tcpip/wait.c
include/precomp.h)
address.c
entities.c
information.c
interface.c
main.c
ndis_lwip.c
tcp.c
stubs.c
precomp.h
)
add_library(tcpip SHARED
${SOURCE}
tcpip.rc
${CMAKE_CURRENT_BINARY_DIR}/tcpip.def)
target_link_libraries(tcpip ip lwip ${PSEH_LIB} chew)
target_link_libraries(tcpip lwip ${PSEH_LIB} libcntpr)
set_module_type(tcpip kernelmodedriver)
add_importlibs(tcpip ndis ntoskrnl hal)
add_pch(tcpip include/precomp.h SOURCE)
add_pch(tcpip precomp.h SOURCE)
add_cd_file(TARGET tcpip DESTINATION reactos/system32/drivers FOR all)

View File

@@ -1,5 +0,0 @@
DIRS= datalink \
network \
transport \
tcpip

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
#pragma once
#define TCP_REQUEST_CANCEL_MODE_ABORT 1
#define TCP_REQUEST_CANCEL_MODE_CLOSE 2
#define TCP_REQUEST_CANCEL_MODE_SHUTDOWN 3
#define TCP_REQUEST_CANCEL_MODE_PRESERVE 4
#define TCP_REQUEST_PENDING_SEND 1
#define TCP_REQUEST_PENDING_RECEIVE 2
#define TCP_REQUEST_PENDING_CONNECT 3
#define TCP_REQUEST_PENDING_LISTEN 4
#define TCP_REQUEST_PENDING_ACCEPTED_CONNECTION 5
#define TCP_REQUEST_PAYLOAD_IRP 1
#define TCP_REQUEST_PAYLOAD_PCB 2
// TODO: simplify states
#define TCP_STATE_CREATED 0x1 << 0
#define TCP_STATE_BOUND 0x1 << 1
#define TCP_STATE_LISTENING 0x1 << 2
#define TCP_STATE_RECEIVING 0x1 << 3
#define TCP_STATE_ABORTED 0x1 << 4
#define TCP_STATE_CONNECTING 0x1 << 5
#define TCP_STATE_CONNECTED 0x1 << 6
#define TCP_STATE_SENDING 0x1 << 7
#define TCP_STATE_CLOSED 0x1 << 8
//#define TCPIP_NDEBUG
#define _IoCompleteRequest(Irp,Mode) \
DPRINT("Complete IRP %p with IO Status %08X\n", Irp, Irp->IoStatus.Status); \
IoCompleteRequest(Irp, Mode)
struct _TCP_CONTEXT;
typedef struct _TCP_CONTEXT TCP_CONTEXT, *PTCP_CONTEXT;
typedef struct _ADDRESS_FILE {
LIST_ENTRY ListEntry;
LONG RefCount;
volatile long ContextCount;
IPPROTO Protocol;
TDI_ADDRESS_IP Address;
struct netif *NetInterface;
TCPIP_INSTANCE Instance;
KSPIN_LOCK RequestLock;
LIST_ENTRY RequestListHead;
BOOLEAN HasListener;
union
{
struct raw_pcb* lwip_raw_pcb;
struct udp_pcb* lwip_udp_pcb;
PTCP_CONTEXT Listener;
};
} ADDRESS_FILE, *PADDRESS_FILE;
struct _TCP_CONTEXT {
ULONG TcpState;
PADDRESS_FILE AddressFile;
LIST_ENTRY RequestListHead;
struct tcp_pcb* lwip_tcp_pcb;
BOOLEAN ReferencedByUpperLayer;
KMUTEX Mutex;
};
typedef struct _TCP_REQUEST {
LIST_ENTRY ListEntry;
union
{
PIRP PendingIrp;
struct tcp_pcb *apcb;
struct pbuf *p;
} Payload;
UCHAR CancelMode;
UCHAR PendingMode;
UCHAR PayloadType;
} TCP_REQUEST, *PTCP_REQUEST;
void
TcpIpInitializeAddresses(void);
NTSTATUS
TcpIpCreateAddress(
_Inout_ PIRP Irp,
_In_ PTDI_ADDRESS_IP Address,
_In_ IPPROTO Protocol
);
NTSTATUS
TcpIpCreateContext(
_Inout_ PIRP Irp,
_In_ PTDI_ADDRESS_IP Address,
_In_ IPPROTO Protocol
);
NTSTATUS
TcpIpCloseAddress(
_Inout_ ADDRESS_FILE* AddressFile
);
NTSTATUS
TcpIpCloseContext(
_In_ PTCP_CONTEXT Context
);
NTSTATUS
TcpIpConnect(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpDisconnect(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpAssociateAddress(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpDisassociateAddress(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpListen(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpReceive(
_Inout_ PIRP Irp
);
NTSTATUS
TcpIpReceiveDatagram(
_Inout_ PIRP Irp);
NTSTATUS
TcpIpSend(
_Inout_ PIRP Irp);
NTSTATUS
TcpIpSendDatagram(
_Inout_ PIRP Irp);
NTSTATUS
AddressSetIpDontFragment(
_In_ TDIEntityID ID,
_In_ PVOID InBuffer,
_In_ ULONG BufferSize);
NTSTATUS
AddressSetTtl(
_In_ TDIEntityID ID,
_In_ PVOID InBuffer,
_In_ ULONG BufferSize);

View File

@@ -0,0 +1,12 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/address.c
* PURPOSE: tcpip.sys: addresses abstraction
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>

View File

@@ -1,13 +0,0 @@
TARGETNAME=datalink
TARGETPATH=..\objects
TARGETTYPE=LIBRARY
TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \
$(DDK_LIB_PATH)\ndis.lib
INCLUDES=..\include;$(BASEDIR)\INC;..\..\..\..\include\net
SOURCES= arp.c \
lan.c \
loopback.c
MSC_WARNING_LEVEL=/W3 /WX

View File

@@ -0,0 +1,324 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/address.c
* PURPOSE: tcpip.sys: entity list implementation
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
#define TAG_ENTITIES 'nIpI'
static const ULONG EntityList[] = {
AT_ENTITY,
CL_NL_ENTITY,
CO_NL_ENTITY,
CL_TL_ENTITY,
CO_TL_ENTITY,
ER_ENTITY,
IF_ENTITY
};
static LIST_ENTRY AtInstancesListHead;
static LIST_ENTRY ClNlInstancesListHead;
static LIST_ENTRY CoNlInstancesListHead;
static LIST_ENTRY ClTlInstancesListHead;
static LIST_ENTRY CoTlInstancesListHead;
static LIST_ENTRY ErInstancesListHead;
static LIST_ENTRY IfInstancesListHead;
/* The corresponding locks */
static KSPIN_LOCK AtInstanceLock;
static KSPIN_LOCK ClNlInstanceLock;
static KSPIN_LOCK CoNlInstanceLock;
static KSPIN_LOCK ClTlInstanceLock;
static KSPIN_LOCK CoTlInstanceLock;
static KSPIN_LOCK ErInstanceLock;
static KSPIN_LOCK IfInstanceLock;
/* We keep track of those just for the sake of speed,
* as our network stack thinks it's clever to get the entity list often */
static ULONG InstanceCount;
static
PLIST_ENTRY
GetInstanceListHeadAcquireLock(
_In_ ULONG Entity,
_Out_ PKIRQL OldIrql
)
{
switch (Entity)
{
case AT_ENTITY:
KeAcquireSpinLock(&AtInstanceLock, OldIrql);
return &AtInstancesListHead;
case CL_NL_ENTITY:
KeAcquireSpinLock(&ClNlInstanceLock, OldIrql);
return &ClNlInstancesListHead;
case CO_NL_ENTITY:
KeAcquireSpinLock(&CoNlInstanceLock, OldIrql);
return &CoNlInstancesListHead;
case CL_TL_ENTITY:
KeAcquireSpinLock(&ClTlInstanceLock, OldIrql);
return &ClTlInstancesListHead;
case CO_TL_ENTITY:
KeAcquireSpinLock(&CoTlInstanceLock, OldIrql);
return &CoTlInstancesListHead;
case ER_ENTITY:
KeAcquireSpinLock(&ErInstanceLock, OldIrql);
return &ErInstancesListHead;
case IF_ENTITY:
KeAcquireSpinLock(&IfInstanceLock, OldIrql);
return &IfInstancesListHead;
default:
DPRINT1("Got unknown entity ID %x\n", Entity);
return NULL;
}
}
static
void
AcquireEntityLock(
_In_ ULONG Entity,
_Out_ KIRQL* OldIrql)
{
switch (Entity)
{
case AT_ENTITY:
KeAcquireSpinLock(&AtInstanceLock, OldIrql);
return;
case CL_NL_ENTITY:
KeAcquireSpinLock(&ClNlInstanceLock, OldIrql);
return;
case CO_NL_ENTITY:
KeAcquireSpinLock(&CoNlInstanceLock, OldIrql);
return;
case CL_TL_ENTITY:
KeAcquireSpinLock(&ClTlInstanceLock, OldIrql);
return;
case CO_TL_ENTITY:
KeAcquireSpinLock(&CoTlInstanceLock, OldIrql);
return;
case ER_ENTITY:
KeAcquireSpinLock(&ErInstanceLock, OldIrql);
return;
case IF_ENTITY:
KeAcquireSpinLock(&IfInstanceLock, OldIrql);
return;
default:
DPRINT1("Got unknown entity ID %x\n", Entity);
ASSERT(FALSE);
}
}
static
void
ReleaseEntityLock(
_In_ ULONG Entity,
_In_ KIRQL OldIrql)
{
switch (Entity)
{
case AT_ENTITY:
KeReleaseSpinLock(&AtInstanceLock, OldIrql);
return;
case CL_NL_ENTITY:
KeReleaseSpinLock(&ClNlInstanceLock, OldIrql);
return;
case CO_NL_ENTITY:
KeReleaseSpinLock(&CoNlInstanceLock, OldIrql);
return;
case CL_TL_ENTITY:
KeReleaseSpinLock(&ClTlInstanceLock, OldIrql);
return;
case CO_TL_ENTITY:
KeReleaseSpinLock(&CoTlInstanceLock, OldIrql);
return;
case ER_ENTITY:
KeReleaseSpinLock(&ErInstanceLock, OldIrql);
return;
case IF_ENTITY:
KeReleaseSpinLock(&IfInstanceLock, OldIrql);
return;
default:
DPRINT1("Got unknown entity ID %x\n", Entity);
ASSERT(FALSE);
}
}
VOID
TcpIpInitializeEntities(void)
{
/* Initialize the locks */
KeInitializeSpinLock(&AtInstanceLock);
KeInitializeSpinLock(&ClNlInstanceLock);
KeInitializeSpinLock(&CoNlInstanceLock);
KeInitializeSpinLock(&ClTlInstanceLock);
KeInitializeSpinLock(&CoTlInstanceLock);
KeInitializeSpinLock(&ErInstanceLock);
KeInitializeSpinLock(&IfInstanceLock);
/* And the list heads */
InitializeListHead(&AtInstancesListHead);
InitializeListHead(&ClNlInstancesListHead);
InitializeListHead(&CoNlInstancesListHead);
InitializeListHead(&ClTlInstancesListHead);
InitializeListHead(&CoTlInstancesListHead);
InitializeListHead(&ErInstancesListHead);
InitializeListHead(&IfInstancesListHead);
/* We don't have anything for now */
InstanceCount = 0;
}
NTSTATUS
QueryEntityList(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize)
{
KIRQL OldIrql;
TDIEntityID* Entity = OutBuffer;
ULONG RemainingSize = *BufferSize, TotalSize = 0;
TCPIP_INSTANCE* Instance;
LIST_ENTRY* ListHead;
LIST_ENTRY* ListEntry;
ULONG i;
UNREFERENCED_PARAMETER(ID);
UNREFERENCED_PARAMETER(Context);
DPRINT("Gathering the entity list.\n");
if (!OutBuffer)
{
*BufferSize = InstanceCount * sizeof(TDIEntityID);
return STATUS_SUCCESS;
}
/* Go through the bitmaps */
for (i = 0; i < sizeof(EntityList)/sizeof(EntityList[0]); i++)
{
ListHead = GetInstanceListHeadAcquireLock(EntityList[i], &OldIrql);
ListEntry = ListHead->Flink;
while(ListEntry != ListHead)
{
if (RemainingSize < sizeof(TDIEntityID))
{
*BufferSize = InstanceCount * sizeof(TDIEntityID);
ReleaseEntityLock(EntityList[i], OldIrql);
return STATUS_BUFFER_OVERFLOW;
}
Instance = CONTAINING_RECORD(ListEntry, TCPIP_INSTANCE, ListEntry);
*Entity++ = Instance->InstanceId;
RemainingSize -= sizeof(*Entity);
TotalSize += sizeof(*Entity);
ListEntry = ListEntry->Flink;
}
ReleaseEntityLock(EntityList[i], OldIrql);
}
*BufferSize = TotalSize;
return STATUS_SUCCESS;
}
VOID
InsertEntityInstance(
_In_ ULONG Entity,
_Out_ TCPIP_INSTANCE* OutInstance)
{
KIRQL OldIrql;
LIST_ENTRY* ListHead;
LIST_ENTRY* ListEntry;
TCPIP_INSTANCE* Instance;
ULONG InstanceId = 1;
ListHead = GetInstanceListHeadAcquireLock(Entity, &OldIrql);
NT_ASSERT(ListHead);
ListEntry = ListHead->Flink;
/* Find an instance number for this guy */
while (ListEntry != ListHead)
{
Instance = CONTAINING_RECORD(ListEntry, TCPIP_INSTANCE, ListEntry);
if (Instance->InstanceId.tei_instance != InstanceId)
break;
InstanceId++;
ListEntry = ListEntry->Flink;
}
OutInstance->InstanceId.tei_entity = Entity;
OutInstance->InstanceId.tei_instance = InstanceId;
/* Keep this list sorted */
InsertHeadList(ListEntry, &OutInstance->ListEntry);
ReleaseEntityLock(Entity, OldIrql);
InterlockedIncrement((LONG*)&InstanceCount);
}
void
RemoveEntityInstance(
_In_ TCPIP_INSTANCE* Instance)
{
KIRQL OldIrql;
AcquireEntityLock(Instance->InstanceId.tei_entity, &OldIrql);
RemoveEntryList(&Instance->ListEntry);
ReleaseEntityLock(Instance->InstanceId.tei_entity, OldIrql);
InterlockedDecrement((LONG*)&InstanceCount);
}
NTSTATUS
GetInstance(
_In_ TDIEntityID ID,
_Out_ TCPIP_INSTANCE** OutInstance)
{
KIRQL OldIrql;
LIST_ENTRY *ListHead, *ListEntry;
TCPIP_INSTANCE* Instance;
ListHead = GetInstanceListHeadAcquireLock(ID.tei_entity, &OldIrql);
NT_ASSERT(ListHead != NULL);
ListEntry = ListHead->Flink;
while (ListEntry != ListHead)
{
Instance = CONTAINING_RECORD(ListEntry, TCPIP_INSTANCE, ListEntry);
NT_ASSERT(Instance->InstanceId.tei_entity == ID.tei_entity);
if (Instance->InstanceId.tei_instance == ID.tei_instance)
{
*OutInstance = Instance;
ReleaseEntityLock(ID.tei_entity, OldIrql);
return STATUS_SUCCESS;
}
#if 0
/* The list is sorted, so we can cut the loop a bit */
if (ID.tei_instance < Instance->InstanceId.tei_instance)
break;
#endif
ListEntry = ListEntry->Flink;
}
ReleaseEntityLock(ID.tei_entity, OldIrql);
/* Maybe we could find a more descriptive status */
return STATUS_INVALID_PARAMETER;
}

View File

@@ -0,0 +1,33 @@
#pragma once
typedef struct
{
TDIEntityID InstanceId;
LIST_ENTRY ListEntry;
} TCPIP_INSTANCE;
VOID
TcpIpInitializeEntities(void);
VOID
InsertEntityInstance(
_In_ ULONG Entity,
_Out_ TCPIP_INSTANCE* OutInstance);
void
RemoveEntityInstance(
_In_ TCPIP_INSTANCE* Instance);
NTSTATUS
GetInstance(
_In_ TDIEntityID,
_Out_ TCPIP_INSTANCE** Instance);
/* IOCTL_TCP_QUERY_INFORMATION_EX handler */
NTSTATUS
QueryEntityList(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize);

View File

@@ -1,78 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/address.h
* PURPOSE: Address manipulation prototypes
*/
#pragma once
/*
* Initialize an IPv4 style address
* VOID AddrInitIPv4(
* PIP_ADDRESS IPAddress,
* IPv4_RAW_ADDRESS RawAddress)
*/
#define AddrInitIPv4(IPAddress, RawAddress) \
{ \
(IPAddress)->Type = IP_ADDRESS_V4; \
(IPAddress)->Address.IPv4Address = (RawAddress); \
}
#if DBG
PCHAR A2S(
PIP_ADDRESS Address);
#endif /* DBG */
VOID IPAddressFree(
PVOID Object);
BOOLEAN AddrIsUnspecified(
PIP_ADDRESS Address);
NTSTATUS AddrGetAddress(
PTRANSPORT_ADDRESS AddrList,
PIP_ADDRESS Address,
PUSHORT Port);
NTSTATUS AddrBuildAddress(
PTRANSPORT_ADDRESS TdiAddress,
PIP_ADDRESS Address,
PUSHORT Port);
BOOLEAN AddrIsEqual(
PIP_ADDRESS Address1,
PIP_ADDRESS Address2);
INT AddrCompare(
PIP_ADDRESS Address1,
PIP_ADDRESS Address2);
BOOLEAN AddrIsEqualIPv4(
PIP_ADDRESS Address1,
IPv4_RAW_ADDRESS Address2);
PIP_INTERFACE AddrLocateInterface(
PIP_ADDRESS MatchAddress);
PADDRESS_FILE AddrSearchFirst(
PIP_ADDRESS Address,
USHORT Port,
USHORT Protocol,
PAF_SEARCH SearchContext);
PADDRESS_FILE AddrSearchNext(
PAF_SEARCH SearchContext);
unsigned long NTAPI inet_addr(const char*);
ULONG IPv4NToHl( ULONG Address );
UINT AddrCountPrefixBits( PIP_ADDRESS Netmask );
VOID AddrWidenAddress( PIP_ADDRESS Network, PIP_ADDRESS Source,
PIP_ADDRESS Netmask );
/* EOF */

View File

@@ -1,33 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/arp.h
* PURPOSE: Address Resolution Protocol definitions
*/
#pragma once
typedef struct ARP_HEADER {
USHORT HWType; /* Hardware Type */
USHORT ProtoType; /* Protocol Type */
UCHAR HWAddrLen; /* Hardware Address Length */
UCHAR ProtoAddrLen; /* Protocol Address Length */
USHORT Opcode; /* Opcode */
/* Sender's Hardware Address */
/* Sender's Protocol Address */
/* Target's Hardware Address */
/* Target's Protocol Address */
} ARP_HEADER, *PARP_HEADER;
/* We swap constants so we can compare values at runtime without swapping them */
#define ARP_OPCODE_REQUEST WH2N(0x0001) /* ARP request */
#define ARP_OPCODE_REPLY WH2N(0x0002) /* ARP reply */
BOOLEAN ARPTransmit(PIP_ADDRESS Address, PVOID LinkAddress, PIP_INTERFACE Interface);
VOID ARPReceive(
PVOID Context,
PIP_PACKET Packet);
/* EOF */

View File

@@ -1,49 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/checksum.h
* PURPOSE: Checksum routine definitions
*/
#pragma once
ULONG ChecksumFold(
ULONG Sum);
ULONG ChecksumCompute(
PVOID Data,
UINT Count,
ULONG Seed);
unsigned int
csum_partial(
const unsigned char * buff,
int len,
unsigned int sum);
ULONG
UDPv4ChecksumCalculate(
PIPv4_HEADER IPHeader,
PUCHAR PacketBuffer,
ULONG DataLength);
#define IPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(csum_partial(Data, Count, Seed)))
//#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
/*
* Macro to check for a correct checksum
* BOOLEAN IPv4CorrectChecksum(PVOID Data, UINT Count)
*/
#define IPv4CorrectChecksum(Data, Count) \
(BOOLEAN)(IPv4Checksum(Data, Count, 0) == DH2N(0x0000FFFF))
/*
* Macro to check for a correct checksum
* BOOLEAN TCPv4CorrectChecksum(PTCPv4_PSEUDO_HEADER TcpPseudoHeader,
* PVOID Data, UINT Count)
*/
#define TCPv4CorrectChecksum(TcpPseudoHeader, Data, Count) \
(BOOLEAN)(TCPv4Checksum(Data, Count, \
TCPv4Checksum(TcpPseudoHeader, sizeof(TCPv4_PSEUDO_HEADER), \
0)) == DH2N(0x0000FFFF))

View File

@@ -1,37 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/datagram.h
* PURPOSE: Datagram types and constants
*/
#pragma once
#include <titypes.h>
NTSTATUS DGReceiveDatagram(
PADDRESS_FILE AddrFile,
PTDI_CONNECTION_INFORMATION ConnInfo,
PCHAR Buffer,
ULONG ReceiveLength,
ULONG ReceiveFlags,
PTDI_CONNECTION_INFORMATION ReturnInfo,
PULONG BytesReceived,
PDATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PIRP Irp);
BOOLEAN DGRemoveIRP(
PADDRESS_FILE AddrFile,
PIRP Irp);
VOID DGDeliverData(
PADDRESS_FILE AddrFile,
PIP_ADDRESS SrcAddress,
PIP_ADDRESS DstAddress,
USHORT SrcPort,
USHORT DstPort,
PIP_PACKET IPPacket,
UINT DataSize);
/* EOF */

View File

@@ -1,78 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/debug.h
* PURPOSE: Debugging support macros
* DEFINES: DBG - Enable debug output
* NASSERT - Disable assertions
*/
#pragma once
#define MIN_TRACE ((1 << DPFLTR_WARNING_LEVEL))
#define MID_TRACE ((1 << DPFLTR_WARNING_LEVEL) | (1 << DPFLTR_TRACE_LEVEL))
#define MAX_TRACE ((1 << DPFLTR_WARNING_LEVEL) | (1 << DPFLTR_TRACE_LEVEL) | (1 << DPFLTR_INFO_LEVEL))
#define DEBUG_CHECK 0x00000100
#define DEBUG_MEMORY 0x00000200
#define DEBUG_PBUFFER 0x00000400
#define DEBUG_IRP 0x00000800
#define DEBUG_TCPIF 0x00001000
#define DEBUG_ADDRFILE 0x00002000
#define DEBUG_DATALINK 0x00004000
#define DEBUG_ARP 0x00008000
#define DEBUG_IP 0x00010000
#define DEBUG_UDP 0x00020000
#define DEBUG_TCP 0x00040000
#define DEBUG_ICMP 0x00080000
#define DEBUG_ROUTER 0x00100000
#define DEBUG_RCACHE 0x00200000
#define DEBUG_NCACHE 0x00400000
#define DEBUG_CPOINT 0x00800000
#define DEBUG_LOCK 0x01000000
#define DEBUG_INFO 0x02000000
#define DEBUG_ULTRA 0x7FFFFFFF
#if DBG
#define REMOVE_PARENS(...) __VA_ARGS__
#define TI_DbgPrint(_t_, _x_) \
DbgPrintEx(DPFLTR_TCPIP_ID, (_t_) | DPFLTR_MASK, "(%s:%d) ", __FILE__, __LINE__), \
DbgPrintEx(DPFLTR_TCPIP_ID, (_t_) | DPFLTR_MASK, REMOVE_PARENS _x_)
#else /* DBG */
#define TI_DbgPrint(_t_, _x_)
#endif /* DBG */
#define assert(x) ASSERT(x)
#define assert_irql(x) ASSERT_IRQL(x)
#ifdef _MSC_VER
#define UNIMPLEMENTED \
TI_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \
but come back another day.\n", __FILE__, __LINE__));
#else /* _MSC_VER */
#define UNIMPLEMENTED \
TI_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \
but come back another day.\n", __FILE__, __LINE__, __FUNCTION__));
#endif /* _MSC_VER */
#define CHECKPOINT \
do { TI_DbgPrint(DEBUG_CHECK, ("(%s:%d)\n", __FILE__, __LINE__)); } while(0);
#define CP CHECKPOINT
#define ASSERT_KM_POINTER(_x) \
ASSERT(((PVOID)_x) != (PVOID)0xcccccccc); \
ASSERT(((PVOID)_x) >= (PVOID)0x80000000);
/* EOF */

View File

@@ -1,40 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/fileobjs.h
* PURPOSE: File object routine prototypes
*/
#pragma once
extern LIST_ENTRY AddressFileListHead;
extern KSPIN_LOCK AddressFileListLock;
extern LIST_ENTRY ConnectionEndpointListHead;
extern KSPIN_LOCK ConnectionEndpointListLock;
NTSTATUS FileOpenAddress(
PTDI_REQUEST Request,
PTA_IP_ADDRESS AddrList,
USHORT Protocol,
BOOLEAN Shared,
PVOID Options);
NTSTATUS FileCloseAddress(
PTDI_REQUEST Request);
NTSTATUS FileOpenConnection(
PTDI_REQUEST Request,
PVOID ClientContext);
NTSTATUS FileCloseConnection(
PTDI_REQUEST Request);
NTSTATUS FileOpenControlChannel(
PTDI_REQUEST Request);
NTSTATUS FileCloseControlChannel(
PTDI_REQUEST Request);
VOID LogActiveObjects(VOID);
/* EOF */

View File

@@ -1,77 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/icmp.h
* PURPOSE: Internet Control Message Protocol definitions
*/
#pragma once
typedef struct ICMP_HEADER {
UCHAR Type; /* ICMP message type */
UCHAR Code; /* ICMP message code */
USHORT Checksum; /* ICMP message checksum */
ULONG Unused; /* ICMP unused */
} ICMP_HEADER, *PICMP_HEADER;
/* ICMP message types */
#define ICMP_TYPE_ECHO_REPLY 0 /* Echo reply */
#define ICMP_TYPE_DEST_UNREACH 3 /* Destination unreachable */
#define ICMP_TYPE_SOURCE_QUENCH 4 /* Source quench */
#define ICMP_TYPE_REDIRECT 5 /* Redirect */
#define ICMP_TYPE_ECHO_REQUEST 8 /* Echo request */
#define ICMP_TYPE_TIME_EXCEEDED 11 /* Time exceeded */
#define ICMP_TYPE_PARAMETER 12 /* Parameter problem */
#define ICMP_TYPE_TIMESTAMP_REQUEST 13 /* Timestamp request */
#define ICMP_TYPE_TIMESTAMP_REPLY 14 /* Timestamp reply */
#define ICMP_TYPE_INFO_REQUEST 15 /* Information request */
#define ICMP_TYPE_INFO_REPLY 16 /* Information reply */
/* ICMP codes for ICMP_TYPE_DEST_UNREACH */
#define ICMP_CODE_DU_NET_UNREACH 0 /* Network unreachable */
#define ICMP_CODE_DU_HOST_UNREACH 1 /* Host unreachable */
#define ICMP_CODE_DU_PROTOCOL_UNREACH 2 /* Protocol unreachable */
#define ICMP_CODE_DU_PORT_UNREACH 3 /* Port unreachable */
#define ICMP_CODE_DU_FRAG_DF_SET 4 /* Fragmentation needed and DF set */
#define ICMP_CODE_DU_SOURCE_ROUTE_FAILED 5 /* Source route failed */
/* ICMP codes for ICMP_TYPE_REDIRECT */
#define ICMP_CODE_RD_NET 0 /* Redirect datagrams for the network */
#define ICMP_CODE_RD_HOST 1 /* Redirect datagrams for the host */
#define ICMP_CODE_RD_TOS_NET 2 /* Redirect datagrams for the Type of Service and network */
#define ICMP_CODE_RD_TOS_HOST 3 /* Redirect datagrams for the Type of Service and host */
/* ICMP codes for ICMP_TYPE_TIME_EXCEEDED */
#define ICMP_CODE_TE_TTL 0 /* Time to live exceeded in transit */
#define ICMP_CODE_TE_REASSEMBLY 1 /* Fragment reassembly time exceeded */
/* ICMP codes for ICMP_TYPE_PARAMETER */
#define ICMP_CODE_TP_POINTER 1 /* Pointer indicates the error */
NTSTATUS ICMPSendDatagram(
PADDRESS_FILE AddrFile,
PTDI_CONNECTION_INFORMATION ConnInfo,
PCHAR BufferData,
ULONG DataSize,
PULONG DataUsed );
NTSTATUS ICMPStartup(VOID);
NTSTATUS ICMPShutdown(VOID);
VOID ICMPReceive(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);
VOID ICMPTransmit(
PIP_PACKET IPPacket,
PIP_TRANSMIT_COMPLETE Complete,
PVOID Context);
VOID ICMPReply(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket,
UCHAR Type,
UCHAR Code);
/* EOF */

View File

@@ -1,151 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/info.h
* PURPOSE: TdiQueryInformation definitions
*/
#pragma once
#include <tcpioctl.h>
#define MAX_PHYSADDR_LEN 8
#define MAX_IFDESCR_LEN 256
typedef struct IPADDR_ENTRY {
ULONG Addr;
ULONG Index;
ULONG Mask;
ULONG BcastAddr;
ULONG ReasmSize;
USHORT Context;
USHORT Pad;
} IPADDR_ENTRY, *PIPADDR_ENTRY;
#define ARP_ENTRY_STATIC 4
#define ARP_ENTRY_DYNAMIC 3
#define ARP_ENTRY_INVALID 2
#define ARP_ENTRY_OTHER 1
typedef struct IPARP_ENTRY {
ULONG Index;
ULONG AddrSize;
UCHAR PhysAddr[8];
ULONG LogAddr;
ULONG Type;
} IPARP_ENTRY, *PIPARP_ENTRY;
typedef struct IPROUTE_ENTRY {
ULONG Dest;
ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry
ULONG Metric1;
ULONG Metric2;
ULONG Metric3;
ULONG Metric4;
ULONG Gw;
ULONG Type;
ULONG Proto;
ULONG Age;
ULONG Mask;
ULONG Metric5;
ULONG Info;
} IPROUTE_ENTRY, *PIPROUTE_ENTRY;
/* Only UDP is supported */
#define TDI_SERVICE_FLAGS (TDI_SERVICE_CONNECTIONLESS_MODE | \
TDI_SERVICE_BROADCAST_SUPPORTED)
#define TCP_MIB_STAT_ID 1
#define UDP_MIB_STAT_ID 1
#define TCP_MIB_TABLE_ID 0x101
#define UDP_MIB_TABLE_ID 0x101
#define TL_INSTANCE 0
typedef struct ADDRESS_INFO {
ULONG LocalAddress;
ULONG LocalPort;
} ADDRESS_INFO, *PADDRESS_INFO;
typedef union TDI_INFO {
TDI_CONNECTION_INFO ConnInfo;
TDI_ADDRESS_INFO AddrInfo;
TDI_PROVIDER_INFO ProviderInfo;
TDI_PROVIDER_STATISTICS ProviderStats;
} TDI_INFO, *PTDI_INFO;
TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
PNDIS_BUFFER ClientBuf, PUINT ClientBufSize );
TDI_STATUS InfoTdiQueryInformationEx(
PTDI_REQUEST Request,
TDIObjectID *ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize,
PVOID Context);
TDI_STATUS InfoTdiSetInformationEx(
PTDI_REQUEST Request,
TDIObjectID *ID,
PVOID Buffer,
UINT BufferSize);
TDI_STATUS InfoTdiQueryGetAddrTable(TDIEntityID ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize);
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID ID,
PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer,
PUINT BufferSize);
TDI_STATUS InfoTdiQueryGetIPSnmpInfo( TDIEntityID ID,
PIP_INTERFACE IF,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTdiQueryGetRouteTable( PIP_INTERFACE IF,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTdiSetRoute(PIP_INTERFACE IF,
PVOID Buffer,
UINT BufferSize);
TDI_STATUS InfoTdiSetArptableMIB(PIP_INTERFACE IF,
PVOID Buffer,
UINT BufferSize);
TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID ID,
PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer,
PUINT BufferSize);
TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
PADDRESS_FILE AddrFile,
PVOID Buffer,
UINT BufferSize);
TDI_STATUS GetAddressFileInfo(TDIObjectID *ID,
PADDRESS_FILE AddrFile,
PVOID Buffer,
PUINT BufferSize);
TDI_STATUS SetConnectionInfo(TDIObjectID *ID,
PCONNECTION_ENDPOINT Connection,
PVOID Buffer,
UINT BufferSize);
/* Insert and remove entities */
VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface );
VOID RemoveTDIInterfaceEntity( PIP_INTERFACE Interface );
VOID AddEntity(ULONG EntityType,
PVOID Context,
ULONG Flags);
VOID RemoveEntityByContext(PVOID Context);
/* EOF */

View File

@@ -1,250 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/ip.h
* PURPOSE: Internet Protocol related definitions
*/
#pragma once
typedef VOID (*OBJECT_FREE_ROUTINE)(PVOID Object);
#define FOURCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
/* Raw IPv4 style address */
typedef ULONG IPv4_RAW_ADDRESS;
typedef IPv4_RAW_ADDRESS *PIPv4_RAW_ADDRESS;
/* Raw IPv6 style address */
typedef USHORT IPv6_RAW_ADDRESS[8];
typedef IPv6_RAW_ADDRESS *PIPv6_RAW_ADDRESS;
/* IP style address */
typedef struct IP_ADDRESS {
UCHAR Type; /* Type of IP address */
union {
IPv4_RAW_ADDRESS IPv4Address;/* IPv4 address (in network byte order) */
IPv6_RAW_ADDRESS IPv6Address;/* IPv6 address (in network byte order) */
} Address;
} IP_ADDRESS, *PIP_ADDRESS;
/* IP type constants */
#define IP_ADDRESS_V4 0x04 /* IPv4 style address */
#define IP_ADDRESS_V6 0x06 /* IPv6 style address */
/* IPv4 header format */
typedef struct IPv4_HEADER {
UCHAR VerIHL; /* 4-bit version, 4-bit Internet Header Length */
UCHAR Tos; /* Type of Service */
USHORT TotalLength; /* Total Length */
USHORT Id; /* Identification */
USHORT FlagsFragOfs; /* 3-bit Flags, 13-bit Fragment Offset */
UCHAR Ttl; /* Time to Live */
UCHAR Protocol; /* Protocol */
USHORT Checksum; /* Header Checksum */
IPv4_RAW_ADDRESS SrcAddr; /* Source Address */
IPv4_RAW_ADDRESS DstAddr; /* Destination Address */
} IPv4_HEADER, *PIPv4_HEADER;
/* IPv6 header format */
typedef struct IPv6_HEADER {
ULONG VTF; /* Version, Traffic Class, Flow Label */
USHORT PayloadLength;
UCHAR NextHeader; /* Same as Protocol in IPv4 */
UCHAR HopLimit; /* Same as Ttl in IPv4 */
IPv6_RAW_ADDRESS SrcAddr;
IPv6_RAW_ADDRESS DstAddr;
} IPv6_HEADER, *PIPv6_HEADER;
typedef union _IP_HEADER {
IPv4_HEADER v4;
IPv6_HEADER v6;
} IP_HEADER, *PIP_HEADER;
#define IPv4_FRAGOFS_MASK 0x1FFF /* Fragment offset mask (host byte order) */
#define IPv4_MF_MASK 0x2000 /* More fragments (host byte order) */
#define IPv4_DF_MASK 0x4000 /* Don't fragment (host byte order) */
#define IPv4_MAX_HEADER_SIZE 60
/* Packet completion handler prototype */
typedef VOID (*PACKET_COMPLETION_ROUTINE)(
PVOID Context,
PNDIS_PACKET NdisPacket,
NDIS_STATUS NdisStatus);
/* Structure for an IP packet */
typedef struct _IP_PACKET {
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */
UCHAR Type; /* Type of IP packet (see IP_ADDRESS_xx above) */
UCHAR Flags; /* Flags for packet (see IP_PACKET_FLAG_xx below)*/
BOOLEAN MappedHeader; /* States whether Header is from an MDL or allocated from pool */
BOOLEAN ReturnPacket; /* States whether NdisPacket should be passed to NdisReturnPackets */
PVOID Header; /* Pointer to IP header for this packet */
UINT HeaderSize; /* Size of IP header */
PVOID Data; /* Current pointer into packet data */
UINT TotalSize; /* Total amount of data in packet (IP header and data) */
UINT Position; /* Current logical offset into packet */
PNDIS_PACKET NdisPacket; /* Pointer to NDIS packet */
IP_ADDRESS SrcAddr; /* Source address */
IP_ADDRESS DstAddr; /* Destination address */
} IP_PACKET, *PIP_PACKET;
#define IP_PACKET_FLAG_RAW 0x01 /* Raw IP packet */
/* Packet context */
typedef struct _PACKET_CONTEXT {
PACKET_COMPLETION_ROUTINE DLComplete; /* Data link level completion handler
* Also used to link to next packet
* in a queue */
PVOID Context; /* Context information for handler */
UINT PacketType; /* Type of packet */
} PACKET_CONTEXT, *PPACKET_CONTEXT;
/* The ProtocolReserved field is structured as a PACKET_CONTEXT */
#define PC(Packet) ((PPACKET_CONTEXT)(&Packet->ProtocolReserved))
/* Values for address type -- also the interface flags */
/* These values are mean to overlap meaningfully with the BSD ones */
#define ADE_UNICAST 0x01
#define ADE_BROADCAST 0x02
#define ADE_ADDRMASK 0x04
#define ADE_POINTOPOINT 0x10
#define ADE_MULTICAST 0x8000
/* There is one NTE for each source (unicast) address assigned to an interface */
/* Link layer transmit prototype */
typedef VOID (*LL_TRANSMIT_ROUTINE)(
PVOID Context,
PNDIS_PACKET NdisPacket,
UINT Offset,
PVOID LinkAddress,
USHORT Type);
/* Link layer to IP binding information */
typedef struct _LLIP_BIND_INFO {
PVOID Context; /* Pointer to link layer context information */
UINT HeaderSize; /* Size of link level header */
UINT MinFrameSize; /* Minimum frame size in bytes */
PUCHAR Address; /* Pointer to interface address */
UINT AddressLength; /* Length of address in bytes */
LL_TRANSMIT_ROUTINE Transmit; /* Transmit function for this interface */
} LLIP_BIND_INFO, *PLLIP_BIND_INFO;
typedef struct _SEND_RECV_STATS {
UINT InBytes;
UINT InUnicast;
UINT InNUnicast;
UINT InDiscarded;
UINT InErrors;
UINT InDiscardedUnknownProto;
UINT OutBytes;
UINT OutUnicast;
UINT OutNUnicast;
UINT OutDiscarded;
UINT OutErrors;
} SEND_RECV_STATS, *PSEND_RECV_STATS;
/* Information about an IP interface */
typedef struct _IP_INTERFACE {
LIST_ENTRY ListEntry; /* Entry on list */
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources used by the object */
KSPIN_LOCK Lock; /* Spin lock for this object */
PVOID Context; /* Pointer to link layer context information */
UINT HeaderSize; /* Size of link level header */
UINT MinFrameSize; /* Minimum frame size in bytes */
UINT MTU; /* Maximum transmission unit */
UINT Speed; /* Link speed */
IP_ADDRESS Unicast; /* Unicast address */
IP_ADDRESS PointToPoint; /* Point to point address */
IP_ADDRESS Netmask; /* Netmask */
IP_ADDRESS Broadcast; /* Broadcast */
UNICODE_STRING Name; /* Adapter name (GUID) */
UNICODE_STRING Description; /* Adapter description (Human readable) */
PUCHAR Address; /* Pointer to interface address */
UINT AddressLength; /* Length of address in bytes */
UINT Index; /* Index of adapter (used to add ip addr) */
LL_TRANSMIT_ROUTINE Transmit; /* Pointer to transmit function */
PVOID TCPContext; /* TCP Content for this interface */
SEND_RECV_STATS Stats; /* Send/Receive statistics */
} IP_INTERFACE, *PIP_INTERFACE;
typedef struct _IP_SET_ADDRESS {
ULONG NteIndex;
IPv4_RAW_ADDRESS Address;
IPv4_RAW_ADDRESS Netmask;
} IP_SET_ADDRESS, *PIP_SET_ADDRESS;
#define IP_PROTOCOL_TABLE_SIZE 0x100
typedef VOID (*IP_PROTOCOL_HANDLER)(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);
/* Loopback adapter address information (network byte order) */
#define LOOPBACK_ADDRESS_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0x7F000001))
#define LOOPBACK_BCASTADDR_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0x7FFFFFFF))
#define LOOPBACK_ADDRMASK_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0xFF000000))
/* Protocol definitions */
#ifndef IPPROTO_RAW
#define IPPROTO_RAW 0 /* Raw IP */
#endif
#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
#define IPPROTO_IGMP 2 /* Internet Group Management Protocol */
#define IPPROTO_TCP 6 /* Transmission Control Protocol */
#define IPPROTO_UDP 17 /* User Datagram Protocol */
/* Timeout timer constants */
#define IP_TIMEOUT 1000 /* Timeout in milliseconds */
#define IP_DEFAULT_LINK_SPEED 10000
extern LIST_ENTRY InterfaceListHead;
extern KSPIN_LOCK InterfaceListLock;
extern LIST_ENTRY NetTableListHead;
extern KSPIN_LOCK NetTableListLock;
PIP_PACKET IPCreatePacket(
ULONG Type);
PIP_PACKET IPInitializePacket(
PIP_PACKET IPPacket,
ULONG Type);
PIP_INTERFACE IPCreateInterface(
PLLIP_BIND_INFO BindInfo);
VOID IPAddInterfaceRoute(
PIP_INTERFACE IF);
VOID IPRemoveInterfaceRoute(
PIP_INTERFACE IF);
VOID IPDestroyInterface(
PIP_INTERFACE IF);
BOOLEAN IPRegisterInterface(
PIP_INTERFACE IF);
VOID IPUnregisterInterface(
PIP_INTERFACE IF);
VOID NTAPI IPTimeoutDpcFn(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);
VOID IPDispatchProtocol(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);
VOID IPRegisterProtocol(
UINT ProtocolNumber,
IP_PROTOCOL_HANDLER Handler);
NTSTATUS IPStartup(PUNICODE_STRING RegistryPath);
NTSTATUS IPShutdown(VOID);
/* EOF */

View File

@@ -1,111 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/lan.h
* PURPOSE: LAN adapter definitions
*/
#pragma once
/* Media we support */
#define MEDIA_ETH 0
#define MAX_MEDIA 1
#define IEEE_802_ADDR_LENGTH 6
/* Ethernet header layout */
typedef struct ETH_HEADER {
UCHAR DstAddr[IEEE_802_ADDR_LENGTH]; /* Destination MAC address */
UCHAR SrcAddr[IEEE_802_ADDR_LENGTH]; /* Source MAC address */
USHORT EType; /* Ethernet protocol type */
} ETH_HEADER, *PETH_HEADER;
#define MAX_MEDIA_ETH sizeof(ETH_HEADER)
/* Broadcast masks */
#define BCAST_ETH_MASK 0x01
/* Broadcast values to check against */
#define BCAST_ETH_CHECK 0x01
/* Offset of broadcast address */
#define BCAST_ETH_OFFSET 0x00
/* Max packets queued for a single adapter */
#define IP_MAX_RECV_BACKLOG 0x20
/* Per adapter information */
typedef struct LAN_ADAPTER {
LIST_ENTRY ListEntry; /* Entry on list */
KSPIN_LOCK Lock; /* Lock for this structure */
UCHAR State, OldState; /* State of the adapter */
BOOLEAN CompletingReset; /* Reset is finishing */
KEVENT Event; /* Opening event */
PVOID Context; /* Upper layer context information */
NDIS_HANDLE NdisHandle; /* NDIS binding handle */
NDIS_STATUS NdisStatus; /* NDIS status of last request */
NDIS_MEDIUM Media; /* Media type */
UCHAR HWAddress[IEEE_802_ADDR_LENGTH]; /* Local HW address */
UINT HWAddressLength; /* Length of HW address */
UCHAR BCastMask; /* Mask for checking broadcast */
UCHAR BCastCheck; /* Value to check against */
UCHAR BCastOffset; /* Offset in frame to check against */
UCHAR HeaderSize; /* Size of link-level header */
USHORT MTU; /* Maximum Transfer Unit */
UINT MinFrameSize; /* Minimum frame size in bytes */
UINT MaxPacketSize; /* Maximum packet size when sending */
UINT MaxSendPackets; /* Maximum number of packets per send */
UINT MacOptions; /* MAC options for NIC driver/adapter */
UINT Speed; /* Link speed */
UINT PacketFilter; /* Packet filter for this adapter */
} LAN_ADAPTER, *PLAN_ADAPTER;
/* LAN adapter state constants */
#define LAN_STATE_OPENING 0
#define LAN_STATE_RESETTING 1
#define LAN_STATE_STARTED 2
#define LAN_STATE_STOPPED 3
/* Size of out lookahead buffer */
#define LOOKAHEAD_SIZE 128
/* Ethernet types. We swap constants so we can compare values at runtime
without swapping them there */
#define ETYPE_IPv4 WH2N(0x0800)
#define ETYPE_IPv6 WH2N(0x86DD)
#define ETYPE_ARP WH2N(0x0806)
/* Protocols */
#define LAN_PROTO_IPv4 0x0000 /* Internet Protocol version 4 */
#define LAN_PROTO_IPv6 0x0001 /* Internet Protocol version 6 */
#define LAN_PROTO_ARP 0x0002 /* Address Resolution Protocol */
NDIS_STATUS LANRegisterAdapter(
PNDIS_STRING AdapterName,
PNDIS_STRING RegistryPath);
NDIS_STATUS LANUnregisterAdapter(
PLAN_ADAPTER Adapter);
NTSTATUS LANRegisterProtocol(
PNDIS_STRING Name);
VOID NTAPI
LANUnregisterProtocol(VOID);
VOID LANStartup(VOID);
VOID LANShutdown(VOID);
NTSTATUS TcpipLanGetDwordOid( PIP_INTERFACE Interface, NDIS_OID Oid,
PULONG Result );
NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter,
NDIS_REQUEST_TYPE Type,
NDIS_OID OID,
PVOID Buffer,
UINT Length);
/* EOF */

View File

@@ -1,13 +0,0 @@
#pragma once
extern KIRQL TcpipGetCurrentIrql(VOID);
extern VOID TcpipInitializeSpinLock( PKSPIN_LOCK SpinLock );
extern VOID TcpipAcquireSpinLock( PKSPIN_LOCK SpinLock, PKIRQL Irql );
extern VOID TcpipReleaseSpinLock( PKSPIN_LOCK SpinLock, KIRQL Irql );
extern VOID TcpipAcquireSpinLockAtDpcLevel( PKSPIN_LOCK SpinLock );
extern VOID TcpipReleaseSpinLockFromDpcLevel( PKSPIN_LOCK SpinLock );
extern VOID TcpipInterlockedInsertTailList( PLIST_ENTRY ListHead,
PLIST_ENTRY Item,
PKSPIN_LOCK Lock );
extern VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex );
extern VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex );

View File

@@ -1,21 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/loopback.h
* PURPOSE: Loopback adapter definitions
*/
#pragma once
#include <lan.h>
extern PIP_INTERFACE Loopback;
NDIS_STATUS LoopRegisterAdapter(
PNDIS_STRING AdapterName,
PLAN_ADAPTER *Adapter);
NDIS_STATUS LoopUnregisterAdapter(
PLAN_ADAPTER Adapter);
/* EOF */

View File

@@ -1,112 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/neighbor.h
* PURPOSE: Neighbor definitions
*/
#pragma once
#define NB_HASHMASK 0xF /* Hash mask for neighbor cache */
typedef VOID (*PNEIGHBOR_PACKET_COMPLETE)
( PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status );
typedef struct _NEIGHBOR_PACKET {
LIST_ENTRY Next;
PNDIS_PACKET Packet;
PNEIGHBOR_PACKET_COMPLETE Complete;
PVOID Context;
} NEIGHBOR_PACKET, *PNEIGHBOR_PACKET;
typedef struct NEIGHBOR_CACHE_TABLE {
struct NEIGHBOR_CACHE_ENTRY *Cache; /* Pointer to cache */
KSPIN_LOCK Lock; /* Protecting lock */
} NEIGHBOR_CACHE_TABLE, *PNEIGHBOR_CACHE_TABLE;
/* Information about a neighbor */
typedef struct NEIGHBOR_CACHE_ENTRY {
struct NEIGHBOR_CACHE_ENTRY *Next; /* Pointer to next entry */
UCHAR State; /* State of NCE */
UINT EventTimer; /* Ticks since last event */
UINT EventCount; /* Number of events */
PIP_INTERFACE Interface; /* Pointer to interface */
UINT LinkAddressLength; /* Length of link address */
PVOID LinkAddress; /* Pointer to link address */
IP_ADDRESS Address; /* IP address of neighbor */
LIST_ENTRY PacketQueue; /* Packet queue */
} NEIGHBOR_CACHE_ENTRY, *PNEIGHBOR_CACHE_ENTRY;
/* NCE states */
#define NUD_INCOMPLETE 0x01
#define NUD_PERMANENT 0x02
#define NUD_STALE 0x04
/* Timeout for incomplete NCE ARP requests */
#define ARP_INCOMPLETE_TIMEOUT 3
/* Number of seconds between ARP transmissions */
#define ARP_RATE 900
/* Number of seconds before the NCE times out */
#define ARP_COMPLETE_TIMEOUT (ARP_RATE + 9)
/* Number of seconds before retransmission */
#define ARP_TIMEOUT_RETRANSMISSION 3
extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1];
VOID NBTimeout(
VOID);
VOID NBStartup(
VOID);
VOID NBShutdown(
VOID);
VOID NBSendSolicit(
PNEIGHBOR_CACHE_ENTRY NCE);
PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(
PIP_INTERFACE Interface,
PIP_ADDRESS Address,
PVOID LinkAddress,
UINT LinkAddressLength,
UCHAR Type,
UINT EventTimer);
VOID NBUpdateNeighbor(
PNEIGHBOR_CACHE_ENTRY NCE,
PVOID LinkAddress,
UCHAR State);
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
PIP_ADDRESS Address,
PIP_INTERFACE Interface);
PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
PIP_INTERFACE Interface,
PIP_ADDRESS Address,
BOOLEAN NoTimeout);
BOOLEAN NBQueuePacket(
PNEIGHBOR_CACHE_ENTRY NCE,
PNDIS_PACKET NdisPacket,
PNEIGHBOR_PACKET_COMPLETE PacketComplete,
PVOID PacketContext);
VOID NBRemoveNeighbor(
PNEIGHBOR_CACHE_ENTRY NCE);
ULONG NBCopyNeighbors(
PIP_INTERFACE Interface,
PIPARP_ENTRY ArpTable);
VOID NBResetNeighborTimeout(
PIP_ADDRESS Address);
VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface);
/* EOF */

View File

@@ -1,13 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/pool.h
* PURPOSE: Prototypes for memory pooling
*/
#pragma once
NDIS_STATUS PrependPacket( PNDIS_PACKET Packet, PCHAR Data, UINT Len,
BOOLEAN Copy );
/* EOF */

View File

@@ -1,28 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/ports.h
* PURPOSE: Port allocation
* PROGRAMMERS: arty (ayerkes@speakeasy.net)
* REVISIONS:
* arty 20041114 Created
*/
#pragma once
typedef struct _PORT_SET {
RTL_BITMAP ProtoBitmap;
PVOID ProtoBitBuffer;
UINT StartingPort;
UINT PortsToOversee;
KSPIN_LOCK Lock;
} PORT_SET, *PPORT_SET;
NTSTATUS PortsStartup( PPORT_SET PortSet,
UINT StartingPort,
UINT PortsToManage );
VOID PortsShutdown( PPORT_SET PortSet );
VOID DeallocatePort( PPORT_SET PortSet, ULONG Port );
BOOLEAN AllocatePort( PPORT_SET PortSet, ULONG Port );
ULONG AllocateAnyPort( PPORT_SET PortSet );
ULONG AllocatePortFromRange( PPORT_SET PortSet, ULONG Lowest, ULONG Highest );

View File

@@ -1,20 +0,0 @@
#ifndef _TCPIP_PCH_
#define _TCPIP_PCH_
#include <tags.h>
#include <tcpip.h>
#include <loopback.h>
#include <routines.h>
#include <info.h>
#include <route.h>
#include <transmit.h>
#include <rawip.h>
#include <icmp.h>
#include <udp.h>
#include <tcp.h>
#include <tilists.h>
#include <lock.h>
#include <interface.h>
#include <chew/chew.h>
#endif /* _TCPIP_PCH_ */

View File

@@ -1,39 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/rawip.h
* PURPOSE: Raw IP types and constants
*/
#pragma once
NTSTATUS RawIPSendDatagram(
PADDRESS_FILE AddrFile,
PTDI_CONNECTION_INFORMATION ConnInfo,
PCHAR Buffer,
ULONG DataSize,
PULONG DataUsed);
VOID RawIpReceive(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);
NTSTATUS RawIPStartup(
VOID);
NTSTATUS RawIPShutdown(
VOID);
NTSTATUS AddGenericHeaderIPv4(
PADDRESS_FILE AddrFile,
PIP_ADDRESS RemoteAddress,
USHORT RemotePort,
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
PIP_PACKET IPPacket,
UINT DataLength,
UINT Protocol,
UINT ExtraLength,
PVOID *NextHeader );
/* EOF */

View File

@@ -1,66 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/receive.h
* PURPOSE: Internet Protocol receive prototypes
*/
#pragma once
#include <ip.h>
/* Number of seconds before destroying the IPDR */
#define MAX_TIMEOUT_COUNT 3
/* IP datagram fragment descriptor. Used to store IP datagram fragments */
typedef struct IP_FRAGMENT {
LIST_ENTRY ListEntry; /* Entry on list */
PNDIS_PACKET Packet; /* NDIS packet containing fragment data */
BOOLEAN ReturnPacket; /* States whether to call NdisReturnPackets */
UINT PacketOffset; /* Offset into NDIS packet where data is */
UINT Offset; /* Offset into datagram where this fragment is */
UINT Size; /* Size of this fragment */
} IP_FRAGMENT, *PIP_FRAGMENT;
/* IP datagram hole descriptor. Used to reassemble IP datagrams */
typedef struct IPDATAGRAM_HOLE {
LIST_ENTRY ListEntry; /* Entry on list */
UINT First; /* Offset of first octet of the hole */
UINT Last; /* Offset of last octet of the hole */
} IPDATAGRAM_HOLE, *PIPDATAGRAM_HOLE;
/* IP datagram reassembly information */
typedef struct IPDATAGRAM_REASSEMBLY {
LIST_ENTRY ListEntry; /* Entry on list */
KSPIN_LOCK Lock; /* Protecting spin lock */
UINT DataSize; /* Size of datagram data area */
IP_ADDRESS SrcAddr; /* Source address */
IP_ADDRESS DstAddr; /* Destination address */
UCHAR Protocol; /* Internet Protocol number */
USHORT Id; /* Identification number */
PIP_HEADER IPv4Header; /* Pointer to IP header */
UINT HeaderSize; /* Length of IP header */
LIST_ENTRY FragmentListHead; /* IP fragment list */
LIST_ENTRY HoleListHead; /* IP datagram hole list */
UINT TimeoutCount; /* Timeout counter */
} IPDATAGRAM_REASSEMBLY, *PIPDATAGRAM_REASSEMBLY;
extern LIST_ENTRY ReassemblyListHead;
extern KSPIN_LOCK ReassemblyListLock;
extern NPAGED_LOOKASIDE_LIST IPDRList;
extern NPAGED_LOOKASIDE_LIST IPFragmentList;
extern NPAGED_LOOKASIDE_LIST IPHoleList;
VOID IPFreeReassemblyList(
VOID);
VOID IPDatagramReassemblyTimeout(
VOID);
VOID IPReceive(
PIP_INTERFACE IF,
PIP_PACKET IPPacket);
/* EOF */

View File

@@ -1,19 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/route.h
* PURPOSE: Routing cache definitions
*/
#pragma once
#include <neighbor.h>
#include <address.h>
#include <router.h>
#include <pool.h>
#include <info.h>
#include <arp.h>
PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination);
/* EOF */

View File

@@ -1,52 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/router.h
* PURPOSE: IP routing definitions
*/
#pragma once
#include <neighbor.h>
/* Forward Information Base Entry */
typedef struct _FIB_ENTRY {
LIST_ENTRY ListEntry; /* Entry on list */
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */
IP_ADDRESS NetworkAddress; /* Address of network */
IP_ADDRESS Netmask; /* Netmask of network */
PNEIGHBOR_CACHE_ENTRY Router; /* Pointer to NCE of router to use */
UINT Metric; /* Cost of this route */
} FIB_ENTRY, *PFIB_ENTRY;
PFIB_ENTRY RouterAddRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PNEIGHBOR_CACHE_ENTRY Router,
UINT Metric);
PNEIGHBOR_CACHE_ENTRY RouterGetRoute(PIP_ADDRESS Destination);
NTSTATUS RouterRemoveRoute(PIP_ADDRESS Target, PIP_ADDRESS Router);
PFIB_ENTRY RouterCreateRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PIP_ADDRESS RouterAddress,
PIP_INTERFACE Interface,
UINT Metric);
NTSTATUS RouterStartup(
VOID);
NTSTATUS RouterShutdown(
VOID);
VOID RouterRemoveRoutesForInterface(PIP_INTERFACE Interface);
UINT CountFIBs(PIP_INTERFACE IF);
UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target );
/* EOF */

View File

@@ -1,73 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/routines.h
* PURPOSE: Common routine prototypes
*/
#pragma once
UINT Random(VOID);
UINT CopyBufferToBufferChain(
PNDIS_BUFFER DstBuffer,
UINT DstOffset,
PCHAR SrcData,
UINT Length);
UINT CopyBufferChainToBuffer(
PCHAR DstData,
PNDIS_BUFFER SrcBuffer,
UINT SrcOffset,
UINT Length);
UINT CopyPacketToBuffer(
PCHAR DstData,
PNDIS_PACKET SrcPacket,
UINT SrcOffset,
UINT Length);
UINT CopyPacketToBufferChain(
PNDIS_BUFFER DstBuffer,
UINT DstOffset,
PNDIS_PACKET SrcPacket,
UINT SrcOffset,
UINT Length);
VOID FreeNdisPacketX(
PNDIS_PACKET Packet,
PCHAR File,
UINT Line);
PVOID AdjustPacket(
PNDIS_PACKET Packet,
UINT Available,
UINT Needed);
UINT ResizePacket(
PNDIS_PACKET Packet,
UINT Size);
NDIS_STATUS AllocatePacketWithBuffer( PNDIS_PACKET *NdisPacket,
PCHAR Data, UINT Len );
VOID FreeNdisPacket( PNDIS_PACKET Packet );
void GetDataPtr( PNDIS_PACKET Packet,
UINT Offset,
PCHAR *DataOut,
PUINT Size );
#if DBG
VOID DisplayIPPacket(
PIP_PACKET IPPacket);
#define DISPLAY_IP_PACKET(x) DisplayIPPacket(x)
VOID DisplayTCPPacket(
PIP_PACKET IPPacket);
#define DISPLAY_TCP_PACKET(x) DisplayTCPPacket(x)
#else
#define DISPLAY_IP_PACKET(x)
#define DISPLAY_TCP_PACKET(x)
#endif /* DBG */
/* EOF */

View File

@@ -1,218 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/tcp.h
* PURPOSE: Transmission Control Protocol definitions
*/
#pragma once
typedef VOID
(*PTCP_COMPLETION_ROUTINE)( PVOID Context, NTSTATUS Status, ULONG Count );
/* TCPv4 header structure */
#include <pshpack1.h>
typedef struct TCPv4_HEADER {
USHORT SourcePort; /* Source port */
USHORT DestinationPort; /* Destination port */
ULONG SequenceNumber; /* Sequence number */
ULONG AckNumber; /* Acknowledgement number */
UCHAR DataOffset; /* Data offset; 32-bit words (leftmost 4 bits) */
UCHAR Flags; /* Control bits (rightmost 6 bits) */
USHORT Window; /* Maximum acceptable receive window */
USHORT Checksum; /* Checksum of segment */
USHORT Urgent; /* Pointer to urgent data */
} TCPv4_HEADER, *PTCPv4_HEADER;
#define TCPOPT_END_OF_LIST 0x0
#define TCPOPT_NO_OPERATION 0x1
#define TCPOPT_MAX_SEG_SIZE 0x2
#define TCPOPTLEN_MAX_SEG_SIZE 0x4
/* Data offset; 32-bit words (leftmost 4 bits); convert to bytes */
#define TCP_DATA_OFFSET(DataOffset)(((DataOffset) & 0xF0) >> (4-2))
/* TCPv4 pseudo header */
typedef struct TCPv4_PSEUDO_HEADER {
ULONG SourceAddress; /* Source address */
ULONG DestinationAddress; /* Destination address */
UCHAR Zero; /* Reserved */
UCHAR Protocol; /* Protocol */
USHORT TCPLength; /* Size of TCP segment */
} TCPv4_PSEUDO_HEADER, *PTCPv4_PSEUDO_HEADER;
#include <poppack.h>
typedef struct _SLEEPING_THREAD {
LIST_ENTRY Entry;
PVOID SleepToken;
KEVENT Event;
} SLEEPING_THREAD, *PSLEEPING_THREAD;
typedef struct _CLIENT_DATA {
BOOLEAN Unlocked;
KSPIN_LOCK Lock;
KIRQL OldIrql;
} CLIENT_DATA, *PCLIENT_DATA;
/* Retransmission timeout constants */
/* Lower bound for retransmission timeout in TCP timer ticks */
#define TCP_MIN_RETRANSMISSION_TIMEOUT 1*1000 /* 1 tick */
/* Upper bound for retransmission timeout in TCP timer ticks */
#define TCP_MAX_RETRANSMISSION_TIMEOUT 1*60*1000 /* 1 tick */
/* Smoothing factor */
#define TCP_ALPHA_RETRANSMISSION_TIMEOUT(x)(((x)*8)/10) /* 0.8 */
/* Delay variance factor */
#define TCP_BETA_RETRANSMISSION_TIMEOUT(x)(((x)*16)/10) /* 1.6 */
#define SEL_CONNECT 1
#define SEL_FIN 2
#define SEL_RST 4
#define SEL_ABRT 8
#define SEL_READ 16
#define SEL_WRITE 32
#define SEL_ACCEPT 64
#define SEL_OOB 128
#define SEL_ERROR 256
#define SEL_FINOUT 512
#define FREAD 0x0001
#define FWRITE 0x0002
/* Datagram/segment send request flags */
#define SRF_URG TCP_URG
#define SRF_ACK TCP_ACK
#define SRF_PSH TCP_PSH
#define SRF_RST TCP_RST
#define SRF_SYN TCP_SYN
#define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification;
extern CLIENT_DATA ClientInfo;
/* accept.c */
NTSTATUS TCPCheckPeerForAccept(PVOID Context,
PTDI_REQUEST_KERNEL Request);
NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog );
BOOLEAN TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection );
NTSTATUS TCPAccept
( PTDI_REQUEST Request,
PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context );
/* tcp.c */
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext );
VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection );
NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
UINT Family, UINT Type, UINT Proto );
VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection);
PTCP_SEGMENT TCPCreateSegment(
PIP_PACKET IPPacket,
PTCPv4_HEADER TCPHeader,
ULONG SegmentLength);
VOID TCPFreeSegment(
PTCP_SEGMENT Segment);
VOID TCPAddSegment(
PCONNECTION_ENDPOINT Connection,
PTCP_SEGMENT Segment,
PULONG Acknowledged);
NTSTATUS TCPConnect(
PCONNECTION_ENDPOINT Connection,
PTDI_CONNECTION_INFORMATION ConnInfo,
PTDI_CONNECTION_INFORMATION ReturnInfo,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context);
NTSTATUS TCPDisconnect(
PCONNECTION_ENDPOINT Connection,
UINT Flags,
PLARGE_INTEGER Timeout,
PTDI_CONNECTION_INFORMATION ConnInfo,
PTDI_CONNECTION_INFORMATION ReturnInfo,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context);
NTSTATUS TCPReceiveData(
PCONNECTION_ENDPOINT Connection,
PNDIS_BUFFER Buffer,
ULONG ReceiveLength,
PULONG BytesReceived,
ULONG ReceiveFlags,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context);
NTSTATUS TCPSendData(
PCONNECTION_ENDPOINT Connection,
PCHAR Buffer,
ULONG DataSize,
PULONG DataUsed,
ULONG Flags,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context);
NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection );
NTSTATUS TCPTranslateError( const INT8 err );
UINT TCPAllocatePort( const UINT HintPort );
VOID TCPFreePort( const UINT Port );
NTSTATUS TCPGetSockAddress
( PCONNECTION_ENDPOINT Connection,
PTRANSPORT_ADDRESS TransportAddress,
BOOLEAN RemoteAddress );
NTSTATUS TCPStartup(
VOID);
NTSTATUS TCPShutdown(
VOID);
BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
NTSTATUS TCPSetNoDelay(PCONNECTION_ENDPOINT Connection, BOOLEAN Set);
VOID
TCPUpdateInterfaceLinkStatus(PIP_INTERFACE IF);
VOID
TCPUpdateInterfaceIPInformation(PIP_INTERFACE IF);
VOID
FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID
FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
VOID
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
VOID
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
VOID
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status);
VOID CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous);
void
LibTCPDumpPcb(PVOID SocketContext);

View File

@@ -1,175 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/tcpip.h
* PURPOSE: TCP/IP protocol driver definitions
* NOTES: Spin lock acquire order:
* - Net table list lock
* - Interface lock
* - Interface list lock
* - Prefix list lock
* - Neighbor cache lock
* - Route cache lock
*/
#pragma once
#ifdef _MSC_VER
#include <basetsd.h>
#include <ntddk.h>
#include <windef.h>
#include <ndis.h>
#include <tdikrnl.h>
#include <tdiinfo.h>
#else
#include <ntddk.h>
#include <ndis.h>
#include <tdikrnl.h>
#include <tdiinfo.h>
#endif
#include <debug.h>
#define TAG_STRING ' RTS' /* string */
/* Define _NTTEST_ to make test version. Device names are prefixed with
'NT' to allow the driver to run side by side with MS TCP/IP driver */
//#define _NTTEST_
/* FIXME: The following should be moved to ntddk.h or tdi headers */
#ifndef _MSC_VER
#ifndef IO_NETWORK_INCREMENT
#define IO_NETWORK_INCREMENT 2
#endif
#endif
#ifdef _MSC_VER
/* EXPORTED is already defined ddk/defines.h */
#define EXPORTED __declspec(dllexport)
#endif
#include <titypes.h>
#include <ticonsts.h>
/* Macros */
#define MIN(value1, value2) \
((value1 < value2)? value1 : value2)
#define MAX(value1, value2) \
((value1 > value2)? value1 : value2)
#define NDIS_BUFFER_TAG FOURCC('n','b','u','f')
#define NDIS_PACKET_TAG FOURCC('n','p','k','t')
#if defined(i386) || defined(_AMD64_) || defined(_ARM_)
/* DWORD network to host byte order conversion for i386 */
#define DN2H(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
/* DWORD host to network byte order conversion for i386 */
#define DH2N(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
/* WORD network to host order conversion for i386 */
#define WN2H(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
/* WORD host to network byte order conversion for i386 */
#define WH2N(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
#else /* defined(i386) || defined(_AMD64_) || defined(_ARM_) */
#error Unsupported architecture
/* DWORD network to host byte order conversion for other architectures */
#define DN2H(dw) \
(dw)
/* DWORD host to network byte order conversion for other architectures */
#define DH2N(dw) \
(dw)
/* WORD network to host order conversion for other architectures */
#define WN2H(w) \
(w)
/* WORD host to network byte order conversion for other architectures */
#define WH2N(w) \
(w)
#endif /* defined(i386) || defined(_AMD64_) || defined(_ARM_) */
/* AF_INET and other things Arty likes to use ;) */
#define AF_INET 2
#define SOCK_STREAM 1
/* Should use TDI structure, but Arty wants to keep BSD style */
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
struct in_addr
{
union
{
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
#define s_host S_un.S_un_b.s_b2
#define s_net S_un.S_un_b.s_b1
#define s_imp S_un.S_un_w.s_w2
#define s_impno S_un.S_un_b.s_b4
#define s_lh S_un.S_un_b.s_b3
};
#define __LWIP_INET_H__
#include "lwip/sockets.h"
/* Sufficient information to manage the entity list */
typedef struct {
UINT tei_entity;
UINT tei_instance;
PVOID context;
UINT flags;
} TDIEntityInfo;
#ifndef htons
#define htons(x) WH2N(x)
#endif
/* Global variable */
extern PDEVICE_OBJECT TCPDeviceObject;
extern PDEVICE_OBJECT UDPDeviceObject;
extern PDEVICE_OBJECT IPDeviceObject;
extern PDEVICE_OBJECT RawIPDeviceObject;
extern LIST_ENTRY InterfaceListHead;
extern KSPIN_LOCK InterfaceListLock;
extern LIST_ENTRY AddressFileListHead;
extern KSPIN_LOCK AddressFileListLock;
extern NDIS_HANDLE GlobalPacketPool;
extern NDIS_HANDLE GlobalBufferPool;
extern KSPIN_LOCK EntityListLock;
extern TDIEntityInfo *EntityList;
extern ULONG EntityCount;
extern ULONG EntityMax;
extern NTSTATUS TiGetProtocolNumber( PUNICODE_STRING FileName,
PULONG Protocol );
/* EOF */

View File

@@ -1,24 +0,0 @@
#pragma once
#define TIPASTE(x,y) x ## y
#define IF_LIST_ITER(n) \
PLIST_ENTRY TIPASTE(n,Entry); \
PIP_INTERFACE n;
#define ForEachInterface(n) \
TIPASTE(n,Entry) = InterfaceListHead.Flink; \
while (TIPASTE(n,Entry) != &InterfaceListHead) { \
TI_DbgPrint \
(MAX_TRACE,( # n ": %x\n", \
TIPASTE(n,Entry))); \
ASSERT(TIPASTE(n,Entry)); \
n = CONTAINING_RECORD(TIPASTE(n,Entry), IP_INTERFACE, \
ListEntry); \
ASSERT(n);
#define EndFor(n) \
TI_DbgPrint(MAX_TRACE,("Next " # n " %x\n", \
TIPASTE(n,Entry->Flink))); \
TIPASTE(n,Entry) = TIPASTE(n,Entry)->Flink; \
}

View File

@@ -1,35 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/transmit.h
* PURPOSE: Internet Protocol transmit prototypes
*/
#pragma once
typedef VOID (*PIP_TRANSMIT_COMPLETE)( PVOID Context,
PNDIS_PACKET Packet,
NDIS_STATUS Status );
/* IP fragment context information */
typedef struct IPFRAGMENT_CONTEXT {
struct IPFRAGMENT_CONTEXT *Next; /* Pointer to next in list */
PNDIS_PACKET Datagram; /* Pointer to original NDIS packet */
PVOID DatagramData; /* Pointer to datagram data */
UINT HeaderSize; /* IP datagram header size */
PNDIS_PACKET NdisPacket; /* Pointer to NDIS packet */
PNDIS_BUFFER NdisBuffer; /* Pointer to NDIS buffer */
PVOID Header; /* Pointer to IP header in fragment buffer */
PVOID Data; /* Pointer to fragment data */
UINT Position; /* Current fragment offset */
UINT BytesLeft; /* Number of bytes left to send */
UINT PathMTU; /* Path Maximum Transmission Unit */
PNEIGHBOR_CACHE_ENTRY NCE; /* Pointer to NCE to use */
KEVENT Event; /* Signalled when the transmission is complete */
NDIS_STATUS Status; /* Status of the transmission */
} IPFRAGMENT_CONTEXT, *PIPFRAGMENT_CONTEXT;
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE);
/* EOF */

View File

@@ -1,65 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/udp.h
* PURPOSE: User Datagram Protocol definitions
*/
#pragma once
#define UDP_STARTING_PORT 0x8000
#define UDP_DYNAMIC_PORTS 0x8000
/* UDPv4 header structure */
#include <pshpack1.h>
typedef struct UDP_HEADER {
USHORT SourcePort; /* Source port */
USHORT DestPort; /* Destination port */
USHORT Length; /* Size of header and data */
USHORT Checksum; /* Checksum of datagram */
} UDP_HEADER, *PUDP_HEADER;
/* UDPv4 pseudo header */
typedef struct UDP_PSEUDO_HEADER {
ULONG SourceAddress; /* Source address */
ULONG DestAddress; /* Destination address */
UCHAR Zero; /* Reserved */
UCHAR Protocol; /* Protocol */
USHORT UDPLength; /* Size of UDP datagram */
} UDP_PSEUDO_HEADER, *PUDP_PSEUDO_HEADER;
#include <poppack.h>
typedef struct UDP_STATISTICS {
ULONG InputDatagrams;
ULONG NumPorts;
ULONG InputErrors;
ULONG OutputDatagrams;
ULONG NumAddresses;
} UDP_STATISTICS, *PUDP_STATISTICS;
extern UDP_STATISTICS UDPStats;
VOID UDPSend(
PVOID Context,
PDATAGRAM_SEND_REQUEST SendRequest);
NTSTATUS UDPSendDatagram(
PADDRESS_FILE AddrFile,
PTDI_CONNECTION_INFORMATION ConnInfo,
PCHAR BufferData,
ULONG DataSize,
PULONG DataUsed );
VOID UDPReceive(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);
NTSTATUS UDPStartup(
VOID);
NTSTATUS UDPShutdown(
VOID);
UINT UDPAllocatePort( UINT HintPort );
VOID UDPFreePort( UINT Port );
/* EOF */

View File

@@ -1,7 +0,0 @@
#pragma once
NTSTATUS TcpipWaitForSingleObject( PVOID Object,
KWAIT_REASON Reason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout );

View File

@@ -0,0 +1,251 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/address.c
* PURPOSE: tcpip.sys: TCP_QUERY_INFORMATION_EX and TCP_SET_INFORMATION_EX ioctls implementation
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
typedef NTSTATUS (*QUERY_INFO_HANDLER)(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize);
typedef NTSTATUS (*SET_INFO_HANDLER)(
_In_ TDIEntityID ID,
_In_ PVOID InBuffer,
_In_ ULONG BufferSize);
static
struct
{
ULONG Entity, Class, Type, Id;
QUERY_INFO_HANDLER QueryHandler;
SET_INFO_HANDLER SetHandler;
} InfoHandlers[] =
{
{ GENERIC_ENTITY, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID, QueryEntityList, NULL },
{ IF_ENTITY, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER, IP_MIB_STATS_ID, QueryInterfaceEntry, NULL },
{ CL_NL_ENTITY, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER, IP_MIB_ADDRTABLE_ENTRY_ID, QueryInterfaceAddrTable, NULL },
{ ER_ENTITY, INFO_CLASS_PROTOCOL, INFO_TYPE_ADDRESS_OBJECT, AO_OPTION_TTL, NULL, AddressSetTtl },
{ ER_ENTITY, INFO_CLASS_PROTOCOL, INFO_TYPE_ADDRESS_OBJECT, AO_OPTION_IP_DONTFRAGMENT, NULL, AddressSetIpDontFragment },
{ (ULONG)-1, (ULONG)-1, (ULONG)-1, (ULONG)-1, NULL }
};
NTSTATUS
TcpIpQueryInformation(
_Inout_ PIRP Irp
)
{
PIO_STACK_LOCATION IrpSp;
TCP_REQUEST_QUERY_INFORMATION_EX* Query;
QUERY_INFO_HANDLER Handler = NULL;
PMDL QueryMdl = NULL, OutputMdl = NULL;
BOOL QueryLocked = FALSE, OutputLocked = FALSE;
ULONG OutputBufferLength;
PVOID OutputBuffer = NULL;
NTSTATUS Status;
ULONG i;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Check input buffer size */
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(TCP_REQUEST_QUERY_INFORMATION_EX))
return STATUS_INVALID_PARAMETER;
/* Get the input buffer */
Query = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
QueryMdl = IoAllocateMdl(Query, sizeof(*Query), FALSE, TRUE, NULL);
if (!QueryMdl)
return STATUS_INSUFFICIENT_RESOURCES;
_SEH2_TRY
{
MmProbeAndLockPages(QueryMdl, Irp->RequestorMode, IoReadAccess);
QueryLocked = TRUE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
goto Cleanup;
} _SEH2_END
/* Get the outputbuffer, if any */
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if (OutputBufferLength)
{
OutputBuffer = Irp->UserBuffer;
OutputMdl = IoAllocateMdl(OutputBuffer, OutputBufferLength, FALSE, TRUE, NULL);
if (!OutputMdl)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
_SEH2_TRY
{
MmProbeAndLockPages(OutputMdl, Irp->RequestorMode, IoWriteAccess);
OutputLocked = TRUE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
goto Cleanup;
}
_SEH2_END
}
/* Find the handler for this particular query */
for (i = 0; InfoHandlers[i].Entity != (ULONG)-1; i++)
{
if ((InfoHandlers[i].Entity == Query->ID.toi_entity.tei_entity) &&
(InfoHandlers[i].Class == Query->ID.toi_class) &&
(InfoHandlers[i].Type == Query->ID.toi_type) &&
(InfoHandlers[i].Id == Query->ID.toi_id))
{
Handler = InfoHandlers[i].QueryHandler;
break;
}
}
if (!Handler)
{
DPRINT1("TCPIP - Unknown query: entity 0x%x, class 0x%x, type 0x%x, Id 0x%x.\n",
Query->ID.toi_entity.tei_entity, Query->ID.toi_class, Query->ID.toi_type, Query->ID.toi_id);
Status = STATUS_NOT_IMPLEMENTED;
goto Cleanup;
}
Status = Handler(Query->ID.toi_entity, Query->Context, OutputBuffer, &OutputBufferLength);
Irp->IoStatus.Information = OutputBufferLength;
Cleanup:
if (QueryMdl)
{
if (QueryLocked)
MmUnlockPages(QueryMdl);
IoFreeMdl(QueryMdl);
}
if (OutputMdl)
{
if (OutputLocked)
MmUnlockPages(OutputMdl);
IoFreeMdl(OutputMdl);
}
return Status;
}
NTSTATUS
TcpIpQueryKernelInformation(
_Inout_ PIRP Irp
)
{
PIO_STACK_LOCATION IrpSp;
PTDI_REQUEST_KERNEL_QUERY_INFORMATION Query;
NTSTATUS Status;
PTDI_ADDRESS_INFO AddressInfo;
PADDRESS_FILE AddressFile;
PTA_ADDRESS TAAddress;
PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
/* See what we are queried */
switch (Query->QueryType)
{
case TDI_QUERY_ADDRESS_INFO :
if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*AddressInfo)) {
DPRINT1("MDL buffer too small.\n");
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
AddressFile = IrpSp->FileObject->FsContext;
AddressInfo = MmGetSystemAddressForMdl(Irp->MdlAddress);
AddressInfo->ActivityCount = AddressFile->RefCount;
AddressInfo->Address.TAAddressCount = 1;
TAAddress = AddressInfo->Address.Address;
TAAddress->AddressLength = TDI_ADDRESS_LENGTH_IP;
TAAddress->AddressType = TDI_ADDRESS_TYPE_IP;
RtlCopyMemory(&TAAddress->Address[0], &AddressFile->Address, TDI_ADDRESS_LENGTH_IP);
Status = STATUS_SUCCESS;
break;
case TDI_QUERY_MAX_DATAGRAM_INFO:
{
if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo))
{
DPRINT1("MDL buffer too small.\n");
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
MaxDatagramInfo = MmGetSystemAddressForMdl(Irp->MdlAddress);
MaxDatagramInfo->MaxDatagramSize = 0xFFFF;
Status = STATUS_SUCCESS;
break;
}
default:
DPRINT1("Unknown query: 0x%08x.\n", Query->QueryType);
return STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return Status;
}
NTSTATUS
TcpIpSetInformation(
_Inout_ PIRP Irp
)
{
TCP_REQUEST_SET_INFORMATION_EX* Query;
SET_INFO_HANDLER Handler = NULL;
NTSTATUS Status;
ULONG i;
/* Get the input buffer */
Query = Irp->AssociatedIrp.SystemBuffer;
/* Find the handler for this particular query */
for (i = 0; InfoHandlers[i].Entity != (ULONG)-1; i++)
{
if ((InfoHandlers[i].Entity == Query->ID.toi_entity.tei_entity) &&
(InfoHandlers[i].Class == Query->ID.toi_class) &&
(InfoHandlers[i].Type == Query->ID.toi_type) &&
(InfoHandlers[i].Id == Query->ID.toi_id))
{
Handler = InfoHandlers[i].SetHandler;
break;
}
}
if (!Handler)
{
DPRINT1("TCPIP - Unknown query: entity 0x%x, class 0x%x, type 0x%x, Id 0x%x.\n",
Query->ID.toi_entity.tei_entity, Query->ID.toi_class, Query->ID.toi_type, Query->ID.toi_id);
return STATUS_NOT_IMPLEMENTED;
}
Status = Handler(Query->ID.toi_entity, &Query->Buffer, Query->BufferSize);
if (NT_SUCCESS(Status))
Irp->IoStatus.Information = Query->BufferSize;
return Status;
}

View File

@@ -0,0 +1,17 @@
#pragma once
NTSTATUS
TcpIpQueryInformation(
_In_ PIRP Irp
);
NTSTATUS
TcpIpQueryKernelInformation(
_In_ PIRP Irp
);
NTSTATUS
TcpIpSetInformation(
_Inout_ PIRP Irp
);

View File

@@ -0,0 +1,233 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/interface.c
* PURPOSE: tcpip.sys: ndis <-> lwip bridge implementation
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
TCPIP_INTERFACE* LoopbackInterface;
static
VOID
GetInterfaceOperStatus(
_In_ TCPIP_INTERFACE* Interface,
_Out_ ULONG* OperStatus)
{
NDIS_STATUS Status;
NDIS_REQUEST Request;
NDIS_MEDIA_STATE MediaState;
if (Interface->NdisContext == NULL)
{
/* This is the looback interface */
*OperStatus = MIB_IF_OPER_STATUS_CONNECTED;
return;
}
/* Get the connection status from NDIS */
Request.RequestType = NdisRequestQueryInformation;
Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MEDIA_CONNECT_STATUS;
Request.DATA.QUERY_INFORMATION.InformationBuffer = &MediaState;
Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG);
NdisRequest(&Status, Interface->NdisContext, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get connection status from the NIC driver. Status 0x%08x\n", Status);
*OperStatus = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
return;
}
switch(MediaState)
{
case NdisMediaStateConnected:
*OperStatus = MIB_IF_OPER_STATUS_CONNECTED;
break;
case NdisMediaStateDisconnected:
*OperStatus = MIB_IF_OPER_STATUS_DISCONNECTED;
break;
default:
DPRINT1("Got unknown media state from NIC driver: %d.\n", MediaState);
*OperStatus = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
}
}
NTSTATUS
QueryInterfaceEntry(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize)
{
TCPIP_INSTANCE* Instance;
TCPIP_INTERFACE* Interface;
NTSTATUS Status;
IFEntry* IfEntry = OutBuffer;
ULONG NeededSize;
NT_ASSERT(ID.tei_entity == IF_ENTITY);
Status = GetInstance(ID, &Instance);
if (!NT_SUCCESS(Status))
return Status;
Interface = CONTAINING_RECORD(Instance, TCPIP_INTERFACE, IfInstance);
NeededSize = FIELD_OFFSET(IFEntry, if_descr) +
RTL_FIELD_SIZE(IFEntry, if_descr[0]) * (Interface->DeviceName.Length / 2 + 1);
if (!OutBuffer)
{
*BufferSize = NeededSize;
return STATUS_SUCCESS;
}
if (*BufferSize < NeededSize)
{
*BufferSize = NeededSize;
return STATUS_BUFFER_OVERFLOW;
}
/* Fill in the data from our interface */
IfEntry->if_index = Interface->lwip_netif.num;
IfEntry->if_type = (Interface->lwip_netif.flags & NETIF_FLAG_ETHARP) ?
IF_TYPE_ETHERNET_CSMACD : IF_TYPE_SOFTWARE_LOOPBACK;
IfEntry->if_mtu = Interface->lwip_netif.mtu;
IfEntry->if_speed = Interface->Speed;
IfEntry->if_physaddrlen = Interface->lwip_netif.hwaddr_len;
RtlCopyMemory(IfEntry->if_physaddr, Interface->lwip_netif.hwaddr, IfEntry->if_physaddrlen);
IfEntry->if_adminstatus = MIB_IF_ADMIN_STATUS_UP;
GetInterfaceOperStatus(Interface, &IfEntry->if_operstatus);
// FIXME: Fill those
IfEntry->if_lastchange = 0;
IfEntry->if_inoctets = 0;
IfEntry->if_inucastpkts = 0;
IfEntry->if_innucastpkts = 0;
IfEntry->if_inerrors = 0;
IfEntry->if_inunknownprotos = 0;
IfEntry->if_outoctets = 0;
IfEntry->if_outucastpkts = 0;
IfEntry->if_outnucastpkts = 0;
IfEntry->if_outdiscards = 0;
IfEntry->if_outerrors = 0;
IfEntry->if_outqlen = 0;
/* Set name */
RtlUnicodeToMultiByteN(
(PCHAR)&IfEntry->if_descr[0],
*BufferSize - FIELD_OFFSET(IFEntry, if_descr),
&IfEntry->if_descrlen,
Interface->DeviceName.Buffer,
Interface->DeviceName.Length);
*BufferSize = NeededSize;
return STATUS_SUCCESS;
}
NTSTATUS
QueryInterfaceAddrTable(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize)
{
TCPIP_INSTANCE* Instance;
TCPIP_INTERFACE* Interface;
NTSTATUS Status;
IPAddrEntry* AddrEntry = OutBuffer;
NT_ASSERT(ID.tei_entity == CL_NL_ENTITY);
Status = GetInstance(ID, &Instance);
if (!NT_SUCCESS(Status))
return Status;
Interface = CONTAINING_RECORD(Instance, TCPIP_INTERFACE, ClNlInstance);
// FIXME: return more than 'one' address
if (!OutBuffer)
{
*BufferSize = sizeof(IPAddrEntry);
return STATUS_SUCCESS;
}
if (*BufferSize < sizeof(IPAddrEntry))
{
*BufferSize = sizeof(IPAddrEntry);
return STATUS_BUFFER_OVERFLOW;
}
AddrEntry->iae_addr = Interface->lwip_netif.ip_addr.addr;
AddrEntry->iae_index = Interface->lwip_netif.num;
AddrEntry->iae_mask = Interface->lwip_netif.netmask.addr;
_BitScanReverse(&AddrEntry->iae_bcastaddr, AddrEntry->iae_addr | ~AddrEntry->iae_mask);
/* FIXME: set those */
AddrEntry->iae_reasmsize = 0;
AddrEntry->iae_context = 0;
AddrEntry->iae_pad = 0;
return STATUS_SUCCESS;
}
/* callback provided to lwip for initializing the loopback interface */
static
err_t
lwip_netif_loopback_init(struct netif *netif)
{
NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
netif->name[0] = 'l';
netif->name[1] = 'o';
netif->output = netif_loop_output;
return ERR_OK;
}
NTSTATUS
TcpIpCreateLoopbackInterface(void)
{
err_t lwip_error;
struct ip_addr IpAddr, SubnetMask, GatewayAddr;
LoopbackInterface = ExAllocatePoolWithTag(NonPagedPool, sizeof(*LoopbackInterface), TAG_INTERFACE);
if (!LoopbackInterface)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(LoopbackInterface, sizeof(*LoopbackInterface));
/* Add it to lwip stack */
IP4_ADDR(&GatewayAddr, 127,0,0,1);
IP4_ADDR(&IpAddr, 127,0,0,1);
IP4_ADDR(&SubnetMask, 255,0,0,0);
ACQUIRE_SERIAL_MUTEX_NO_TO();
lwip_error = netifapi_netif_add(
&LoopbackInterface->lwip_netif,
&IpAddr,
&SubnetMask,
&GatewayAddr,
LoopbackInterface,
lwip_netif_loopback_init,
tcpip_input);
if (lwip_error != ERR_OK)
{
ExFreePoolWithTag(LoopbackInterface, TAG_INTERFACE);
RELEASE_SERIAL_MUTEX();
return STATUS_INSUFFICIENT_RESOURCES;
}
netifapi_netif_set_up(&LoopbackInterface->lwip_netif);
RELEASE_SERIAL_MUTEX();
/* Add this interface into the entities DB */
InsertEntityInstance(CL_NL_ENTITY, &LoopbackInterface->ClNlInstance);
InsertEntityInstance(IF_ENTITY, &LoopbackInterface->IfInstance);
InsertEntityInstance(AT_ENTITY, &LoopbackInterface->AtInstance);
RtlInitUnicodeString(&LoopbackInterface->DeviceName, L"Loopback");
return STATUS_SUCCESS;
}

View File

@@ -0,0 +1,40 @@
#pragma once
#define TAG_INTERFACE 'fIpI'
#define TCPIP_PACKETPOOL_SIZE 200
#define TCPIP_BUFFERPOOL_SIZE 800
typedef struct
{
struct netif lwip_netif;
TCPIP_INSTANCE IfInstance;
TCPIP_INSTANCE AtInstance;
TCPIP_INSTANCE ClNlInstance;
UNICODE_STRING DeviceName;
NDIS_HANDLE NdisContext;
NDIS_HANDLE PacketPool;
NDIS_HANDLE BufferPool;
UINT MediumIndex;
ULONG Speed;
} TCPIP_INTERFACE;
extern TCPIP_INTERFACE* LoopbackInterface;
NTSTATUS
TcpIpCreateLoopbackInterface(void);
NTSTATUS
QueryInterfaceEntry(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize);
NTSTATUS
QueryInterfaceAddrTable(
_In_ TDIEntityID ID,
_In_ PVOID Context,
_Out_opt_ PVOID OutBuffer,
_Inout_ ULONG* BufferSize);

View File

@@ -0,0 +1,596 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/main.c
* PURPOSE: tcpip.sys driver entry
*/
#include "precomp.h"
#ifdef TCPIP_NDEBUG
#define NDEBUG
#endif
#include <debug.h>
/* DriverEntry, DriverUnload and dispatch routines declaration */
DRIVER_INITIALIZE DriverEntry;
static DRIVER_UNLOAD TcpIpUnload;
static DRIVER_DISPATCH TcpIpCreate;
static DRIVER_DISPATCH TcpIpClose;
static DRIVER_DISPATCH TcpIpDispatchInternal;
static DRIVER_DISPATCH TcpIpDispatch;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, TcpIpUnload)
#pragma alloc_text(PAGE, TcpIpCreate)
#pragma alloc_text(PAGE, TcpIpClose)
#pragma alloc_text(PAGE, TcpIpDispatchInternal)
#pragma alloc_text(PAGE, TcpIpDispatch)
#endif
/* Our device objects. TCP, UPD, IP, and RAW */
PDEVICE_OBJECT TcpDeviceObject = NULL;
PDEVICE_OBJECT UdpDeviceObject = NULL;
PDEVICE_OBJECT IpDeviceObject = NULL;
PDEVICE_OBJECT RawIpDeviceObject = NULL;
/* And the corresponding device names */
#define DD_TCP_DEVICE_NAME L"\\Device\\Tcp"
#define DD_UDP_DEVICE_NAME L"\\Device\\Udp"
#define DD_IP_DEVICE_NAME L"\\Device\\Ip"
#define DD_RAWIP_DEVICE_NAME L"\\Device\\RawIp"
/* This is a small utility which get the IPPROTO_* constant from the device object this driver was
* passed */
static
IPPROTO
ProtocolFromIrp(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIO_STACK_LOCATION IrpSp)
{
UNICODE_STRING ProtocolName;
PWCHAR Name;
ULONG Value;
NTSTATUS Status;
if (DeviceObject == TcpDeviceObject)
return IPPROTO_TCP;
if (DeviceObject == UdpDeviceObject)
return IPPROTO_UDP;
if (DeviceObject == IpDeviceObject)
return IPPROTO_RAW;
/* Get it from the IRP file object */
Name = IrpSp->FileObject->FileName.Buffer;
if (*Name++ != L'\\')
{
DPRINT1("Could not deduce protocol from file name %wZ.\n", &IrpSp->FileObject->FileName);
return (IPPROTO)-1;
}
RtlInitUnicodeString(&ProtocolName, Name);
Status = RtlUnicodeStringToInteger(&ProtocolName, 10, &Value);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not deduce protocol from file name %wZ.\n", &IrpSp->FileObject->FileName);
return (IPPROTO)-1;
}
if (Value >= IPPROTO_RESERVED_MAX)
{
DPRINT1("Could not deduce protocol from file name %wZ.\n", &IrpSp->FileObject->FileName);
return (IPPROTO)-1;
}
return (IPPROTO)Value;
}
NTSTATUS
NTAPI
DriverEntry(
_In_ struct _DRIVER_OBJECT *DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
UNICODE_STRING IpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
UNICODE_STRING RawIpDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
UNICODE_STRING UdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
NTSTATUS Status;
/* Initialize the lwip library */
tcpip_init(NULL, NULL);
RELEASE_SERIAL_MUTEX();
/* Create the device objects */
Status = IoCreateDevice(
DriverObject,
0,
&IpDeviceName,
FILE_DEVICE_NETWORK,
0,
FALSE,
&IpDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not create device object. Status: 0x%08x\n", Status);
goto Failure;
}
Status = IoCreateDevice(
DriverObject,
0,
&UdpDeviceName,
FILE_DEVICE_NETWORK,
0,
FALSE,
&UdpDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not create device object. Status: 0x%08x\n", Status);
goto Failure;
}
Status = IoCreateDevice(
DriverObject,
0,
&TcpDeviceName,
FILE_DEVICE_NETWORK,
0,
FALSE,
&TcpDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not create device object. Status: 0x%08x\n", Status);
goto Failure;
}
Status = IoCreateDevice(
DriverObject,
0,
&RawIpDeviceName,
FILE_DEVICE_NETWORK,
0,
FALSE,
&RawIpDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not create device object. Status: 0x%08x\n", Status);
goto Failure;
}
/* Use direct I/O with this devices */
IpDeviceObject->Flags |= DO_DIRECT_IO;
RawIpDeviceObject->Flags |= DO_DIRECT_IO;
UdpDeviceObject->Flags |= DO_DIRECT_IO;
TcpDeviceObject->Flags |= DO_DIRECT_IO;
/* Set driver object entry points */
DriverObject->MajorFunction[IRP_MJ_CREATE] = TcpIpCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = TcpIpClose;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TcpIpDispatchInternal;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TcpIpDispatch;
DriverObject->DriverUnload = TcpIpUnload;
/* Initialize various parts of the driver */
TcpIpInitializeAddresses();
TcpIpInitializeTcp();
TcpIpInitializeEntities();
Status = TcpIpRegisterNdisProtocol();
if (!NT_SUCCESS(Status))
goto Failure;
/* Create the loopback interface */
Status = TcpIpCreateLoopbackInterface();
if (!NT_SUCCESS(Status))
goto Failure;
return STATUS_SUCCESS;
Failure:
TcpIpUnregisterNdisProtocol();
if (IpDeviceObject)
IoDeleteDevice(IpDeviceObject);
if (TcpDeviceObject)
IoDeleteDevice(TcpDeviceObject);
if (UdpDeviceObject)
IoDeleteDevice(UdpDeviceObject);
if (RawIpDeviceObject)
IoDeleteDevice(RawIpDeviceObject);
return Status;
}
static
NTSTATUS
NTAPI
TcpIpCreate(
_Inout_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
NTSTATUS Status;
PFILE_FULL_EA_INFORMATION FileInfo;
IPPROTO Protocol;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Grab the info describing the file */
FileInfo = Irp->AssociatedIrp.SystemBuffer;
if (!FileInfo)
{
/* Caller just wants a control channel. We don't need any structure for this kind of "file" */
IrpSp->FileObject->FsContext = NULL;
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
Status = STATUS_SUCCESS;
goto Quickie;
}
/* Validate it */
switch (FileInfo->EaNameLength)
{
case TDI_TRANSPORT_ADDRESS_LENGTH:
{
PTA_IP_ADDRESS Address;
DPRINT1("TCPIP Create Transport Address\n");
if (strncmp(&FileInfo->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) != 0)
{
DPRINT1("TCPIP: Should maybe open file %*s.\n", FileInfo->EaNameLength, &FileInfo->EaName[0]);
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Get the address info right after the file name info */
Address = (PTA_IP_ADDRESS)(&FileInfo->EaName[FileInfo->EaNameLength + 1]);
/* Validate it */
if ((FileInfo->EaValueLength < sizeof(*Address)) ||
(Address->TAAddressCount != 1) ||
(Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
(Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP))
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Get the protocol this address will be created for. */
Protocol = ProtocolFromIrp(DeviceObject, IrpSp);
if (Protocol == (IPPROTO)-1)
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
Status = TcpIpCreateAddress(Irp, &Address->Address[0].Address[0], Protocol);
if (Status != STATUS_SUCCESS)
{
goto Quickie;
}
break;
}
case TDI_CONNECTION_CONTEXT_LENGTH:
{
PTA_IP_ADDRESS Address;
DPRINT1("TCPIP Create connection Context\n");
if (strncmp(&FileInfo->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) != 0)
{
DPRINT1("TCPIP: Should maybe open file %*s.\n", FileInfo->EaNameLength, &FileInfo->EaName[0]);
return STATUS_INVALID_PARAMETER;
}
Address = (PTA_IP_ADDRESS)(&FileInfo->EaName[FileInfo->EaNameLength + 1]);
/* Get the protocol this address will be created for. */
Protocol = ProtocolFromIrp(DeviceObject, IrpSp);
if (Protocol == (IPPROTO)-1)
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
Status = TcpIpCreateContext(Irp, &Address->Address[0].Address[0], Protocol);
break;
}
default:
DPRINT1("TCPIP: Should open file %*s.\n", FileInfo->EaNameLength, &FileInfo->EaName[0]);
Status = STATUS_INVALID_PARAMETER;
}
Quickie:
Irp->IoStatus.Status = Status;
if (Status == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
}
else
{
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
return Status;
}
static
NTSTATUS
NTAPI
TcpIpClose(
_Inout_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
ULONG_PTR FileType;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileType = (ULONG_PTR)IrpSp->FileObject->FsContext2;
switch (FileType)
{
case TDI_TRANSPORT_ADDRESS_FILE:
DPRINT1("TCPIP Close Transport Address\n");
if (!IrpSp->FileObject->FsContext)
{
DPRINT1("TCPIP: Got a close request without a file to close!\n");
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
Status = TcpIpCloseAddress(IrpSp->FileObject->FsContext);
break;
case TDI_CONNECTION_FILE:
if (!IrpSp->FileObject->FsContext)
{
DPRINT1("TCPIP: Got a close request without a file to close!\n");
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
DPRINT1("TCPIP Close Connection Context %p\n", IrpSp->FileObject->FsContext);
Status = TcpIpCloseContext(IrpSp->FileObject->FsContext);
break;
case TDI_CONTROL_CHANNEL_FILE:
/* We didn't allocate anything for this. */
Status = STATUS_SUCCESS;
break;
default:
DPRINT1("TCPIP: Should close file %Iu.\n", FileType);
Status = STATUS_INVALID_PARAMETER;
break;
}
Quickie:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return Status;
}
static
NTSTATUS
NTAPI
TcpIpDispatchInternal(
_Inout_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PTCP_CONTEXT Context;
PADDRESS_FILE AddressFile;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
DPRINT("TcpIpDispatchInternal on TDI object %p\n", IrpSp->FileObject->FsContext);
switch ((ULONG)IrpSp->FileObject->FsContext2)
{
case TDI_TRANSPORT_ADDRESS_FILE :
AddressFile = IrpSp->FileObject->FsContext;
break;
case TDI_CONNECTION_FILE :
Context = IrpSp->FileObject->FsContext;
AddressFile = Context->AddressFile;
break;
default :
DPRINT1("Unknown FileObject type\n");
break;
}
switch (IrpSp->MinorFunction)
{
case TDI_RECEIVE:
DPRINT1("TCPIP: TDI_RECEIVE!\n");
switch (AddressFile->Protocol)
{
case IPPROTO_TCP:
Status = TcpIpReceive(Irp);
break;
case IPPROTO_UDP:
Status = STATUS_NOT_IMPLEMENTED;
break;
case IPPROTO_RAW:
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
}
if (Status == STATUS_NOT_IMPLEMENTED)
{
DPRINT1("Received TDI_RECEIVE for non-TCP protocol\n");
}
break;
case TDI_RECEIVE_DATAGRAM:
DPRINT1("TCPIP: TDI_RECEIVE_DATAGRAM!\n");
return TcpIpReceiveDatagram(Irp);
case TDI_SEND:
DPRINT1("TCPIP: TDI_SEND!\n");
switch (AddressFile->Protocol)
{
case IPPROTO_TCP:
Status = TcpIpSend(Irp);
break;
case IPPROTO_UDP:
Status = STATUS_NOT_IMPLEMENTED;
break;
case IPPROTO_RAW:
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
}
if (Status == STATUS_NOT_IMPLEMENTED)
{
DPRINT1("Received TDI_SEND for non-TCP protocol\n");
}
break;
case TDI_SEND_DATAGRAM:
DPRINT1("TCPIP: TDI_SEND_DATAGRAM!\n");
return TcpIpSendDatagram(Irp);
case TDI_ACCEPT:
DPRINT1("TCPIP: TDI_ACCEPT!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case TDI_LISTEN:
DPRINT1("TCPIP: TDI_LISTEN!\n");
Status = TcpIpListen(Irp);
break;
case TDI_CONNECT:
DPRINT1("TCPIP: TDI_CONNECT!\n");
Status = TcpIpConnect(Irp);
break;
case TDI_DISCONNECT:
DPRINT1("TCPIP: TDI_DISCONNECT!\n");
Status = TcpIpDisconnect(Irp);
DPRINT("TcpIpDisconnect() Returned\n");
break;
case TDI_ASSOCIATE_ADDRESS:
DPRINT1("TCPIP: TDI_ASSOCIATE_ADDRESS\n");
Status = TcpIpAssociateAddress(Irp);
break;
case TDI_DISASSOCIATE_ADDRESS:
DPRINT1("TCPIP: TDI_DISASSOCIATE_ADDRESS!\n");
Status = TcpIpDisassociateAddress(Irp);
break;
case TDI_QUERY_INFORMATION:
DPRINT1("TCPIP: TDI_QUERY_INFORMATION\n");
return TcpIpQueryKernelInformation(Irp);
case TDI_SET_INFORMATION:
DPRINT1("TCPIP: TDI_SET_INFORMATION!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case TDI_SET_EVENT_HANDLER:
DPRINT1("TCPIP: TDI_SET_EVENT_HANDLER!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case TDI_ACTION:
DPRINT1("TDI_ACTION!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
/* An unsupported IOCTL code was submitted */
default:
DPRINT1("TCPIP: Unknown internal IOCTL: 0x%x.\n", IrpSp->MinorFunction);
Status = STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = Status;
if (Status == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
}
else
{
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
return Status;
}
static
NTSTATUS
NTAPI
TcpIpDispatch(
_Inout_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_TCP_QUERY_INFORMATION_EX:
Status = TcpIpQueryInformation(Irp);
break;
case IOCTL_TCP_SET_INFORMATION_EX:
Status = TcpIpSetInformation(Irp);
break;
case IOCTL_SET_IP_ADDRESS:
DPRINT1("TCPIP: Should handle IOCTL_SET_IP_ADDRESS.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case IOCTL_DELETE_IP_ADDRESS:
DPRINT1("TCPIP: Should handle IOCTL_DELETE_IP_ADDRESS.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
DPRINT1("TCPIP: Unknown IOCTL 0x%#x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
//DPRINT("TCPIP dispatched with status 0x%08x.\n", Status);
Irp->IoStatus.Status = Status;
if (Status == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
}
else
{
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
return Status;
}
static
VOID
NTAPI
TcpIpUnload(
_In_ struct _DRIVER_OBJECT *DriverObject
)
{
IoDeleteDevice(IpDeviceObject);
IoDeleteDevice(RawIpDeviceObject);
IoDeleteDevice(UdpDeviceObject);
IoDeleteDevice(TcpDeviceObject);
TcpIpUnregisterNdisProtocol();
}

View File

@@ -0,0 +1,458 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/ndis_proto.c
* PURPOSE: tcpip.sys: ndis protocol bindings
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
// FIXME: Maybe more in the future ?
static NDIS_MEDIUM NdisMediaArray[] = { NdisMedium802_3 };
/* The handle we got from NDIS for this protocol */
static NDIS_HANDLE NdisHandle;
/* Initializes the various values lwip will need */
static
NDIS_STATUS
InitializeInterface(
_Inout_ TCPIP_INTERFACE* Interface)
{
NDIS_STATUS Status;
NDIS_REQUEST Request;
UINT MTU, Speed;
NDIS_OID QueryAddrOid;
UINT PacketFilter;
/* Add this interface into the entities DB */
InsertEntityInstance(CL_NL_ENTITY, &Interface->ClNlInstance);
InsertEntityInstance(IF_ENTITY, &Interface->IfInstance);
InsertEntityInstance(AT_ENTITY, &Interface->AtInstance);
/* Get the MTU from the NIC */
Request.RequestType = NdisRequestQueryInformation;
Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
Request.DATA.QUERY_INFORMATION.InformationBuffer = &MTU;
Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(UINT);
NdisRequest(&Status, Interface->NdisContext, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get MTU from the NIC driver!\n");
return Status;
}
Interface->lwip_netif.mtu = MTU;
/* Setup media type related data. */
switch (NdisMediaArray[Interface->MediumIndex])
{
case NdisMedium802_3:
Interface->lwip_netif.hwaddr_len = ETHARP_HWADDR_LEN;
QueryAddrOid = OID_802_3_CURRENT_ADDRESS;
PacketFilter = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST;
break;
default:
/* This is currently impossible */
DPRINT1("Unknown medium!\n");
NT_ASSERT(FALSE);
return NDIS_STATUS_UNSUPPORTED_MEDIA;
}
/* Get the address */
Request.RequestType = NdisRequestQueryInformation;
Request.DATA.QUERY_INFORMATION.Oid = QueryAddrOid;
Request.DATA.QUERY_INFORMATION.InformationBuffer = &Interface->lwip_netif.hwaddr[0];
Request.DATA.QUERY_INFORMATION.InformationBufferLength = NETIF_MAX_HWADDR_LEN;
NdisRequest(&Status, Interface->NdisContext, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get HW address from the NIC driver!\n");
return Status;
}
/* Get the link speed */
Request.RequestType = NdisRequestQueryInformation;
Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
Request.DATA.QUERY_INFORMATION.InformationBuffer = &Speed;
Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(UINT);
NdisRequest(&Status, Interface->NdisContext, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get link speed NIC driver!\n");
/* Good old 10Mb/s as default */
Speed = 100000;
}
/* NDIS drivers give it in 100bps unit */
Speed *= 100;
/* Initialize lwip SNMP module */
NETIF_INIT_SNMP(&Interface->lwip_netif, snmp_ifType_ethernet_csmacd, Speed);
/* Set the packet filter */
Request.RequestType = NdisRequestSetInformation;
Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
Request.DATA.SET_INFORMATION.InformationBuffer = &PacketFilter;
Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(PacketFilter);
NdisRequest(&Status, Interface->NdisContext, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get HW address from the NIC driver!\n");
return Status;
}
/* Initialize the packet pool */
NdisAllocatePacketPool(&Status, &Interface->PacketPool, TCPIP_PACKETPOOL_SIZE, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not allocate a packet pool.\n");
return Status;
}
/* Initialize the buffer pool */
NdisAllocateBufferPool(&Status, &Interface->BufferPool, TCPIP_BUFFERPOOL_SIZE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not allocate a buffer pool.\n");
return Status;
}
return NDIS_STATUS_SUCCESS;
}
/* The various callbacks we will give to NDIS */
static
VOID
NTAPI
ProtocolOpenAdapterComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ NDIS_STATUS Status,
_In_ NDIS_STATUS OpenErrorStatus)
{
TCPIP_INTERFACE* Interface = (TCPIP_INTERFACE*)ProtocolBindingContext;
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Interface, TAG_INTERFACE);
return;
}
Status = InitializeInterface(Interface);
if (!NT_SUCCESS(Status))
{
/* Unbind the interface and that's all */
NdisCloseAdapter(&Status, Interface->NdisContext);
}
}
static
VOID
NTAPI
ProtocolCloseAdapterComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ NDIS_STATUS Status)
{
UNIMPLEMENTED;
}
static
VOID
NTAPI
ProtocolResetComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ NDIS_STATUS Status)
{
UNIMPLEMENTED;
}
static
VOID
NTAPI
ProtocolRequestComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNDIS_REQUEST NdisRequest,
_In_ NDIS_STATUS Status)
{
UNIMPLEMENTED;
}
static
NDIS_STATUS
NTAPI
ProtocolReceive(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ NDIS_HANDLE MacReceiveContext,
_In_ PVOID HeaderBuffer,
_In_ UINT HeaderBufferSize,
_In_ PVOID LookAheadBuffer,
_In_ UINT LookaheadBufferSize,
_In_ UINT PacketSize)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
static
VOID
NTAPI
ProtocolReceiveComplete(
_In_ NDIS_HANDLE ProtocolBindingContext)
{
UNIMPLEMENTED;
}
static
VOID
NTAPI
ProtocolStatusComplete(
_In_ NDIS_HANDLE ProtocolBindingContext)
{
UNIMPLEMENTED;
}
static
INT
NTAPI
ProtocolReceivePacket(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNDIS_PACKET Packet)
{
UNIMPLEMENTED;
return 0;
}
/* bridge between NDIS and lwip: send data to the adapter */
static
err_t
lwip_netif_linkoutput(
struct netif *netif,
struct pbuf *p)
{
TCPIP_INTERFACE* Interface = CONTAINING_RECORD(netif, TCPIP_INTERFACE, lwip_netif);
NDIS_STATUS Status;
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
PVOID PayloadCopy = NULL;
NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
/* Allocate a packet */
NdisAllocatePacket(&Status, &Packet, Interface->PacketPool);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not allocate a packet from packet pool!\n");
return ERR_MEM;
}
/* Map pbuf to a NDIS buffer chain, if possible (== allocated from non paged pool). */
if ((p->type == PBUF_POOL) || (p->type == PBUF_RAM))
{
while (p)
{
NdisAllocateBuffer(&Status, &Buffer, Interface->BufferPool, p->payload, p->len);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not allocate a buffer!\n");
return ERR_MEM;
}
NdisChainBufferAtBack(Packet, Buffer);
p = p->next;
}
}
else
{
PayloadCopy = ExAllocatePoolWithTag(NonPagedPool, p->tot_len, TAG_INTERFACE);
if (!PayloadCopy)
{
NdisFreePacket(Packet);
return ERR_MEM;
}
pbuf_copy_partial(p, PayloadCopy, p->tot_len, 0);
NdisAllocateBuffer(&Status, &Buffer, Interface->BufferPool, p->payload, p->len);
NdisChainBufferAtFront(Packet, Buffer);
}
/* Call ndis */
NdisSend(&Status, Interface->NdisContext, Packet);
DPRINT1("NdisSend: got status 0x%08x.\n", Status);
/* Free the buffer chain */
if (Status != NDIS_STATUS_PENDING)
{
NdisUnchainBufferAtFront(Packet, &Buffer);
while (Buffer)
{
NdisFreeBuffer(Buffer);
NdisUnchainBufferAtFront(Packet, &Buffer);
}
NdisFreePacket(Packet);
if (PayloadCopy)
ExFreePoolWithTag(PayloadCopy, TAG_INTERFACE);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("NdisSend returned status 0x%08x.\n", Status);
return ERR_CONN;
}
return ERR_OK;
}
/* lwip interface initialisation function */
static
err_t
lwip_netif_init(
struct netif* lwip_netif)
{
/* Set output callbacks */
lwip_netif->output = etharp_output;
lwip_netif->linkoutput = lwip_netif_linkoutput;
/* We use ARP and broadcasting */
lwip_netif->flags |= NETIF_FLAG_ETHARP | NETIF_FLAG_BROADCAST;
/* Let's say we're ethernet */
lwip_netif->name[0] = 'e';
lwip_netif->name[1] = 'n';
return ERR_OK;
}
static
VOID
NTAPI
ProtocolBindAdapter(
_Out_ PNDIS_STATUS Status,
_In_ NDIS_HANDLE BindContext,
_In_ PNDIS_STRING DeviceName,
_In_ PVOID SystemSpecific1,
_In_ PVOID SystemSpecific2)
{
TCPIP_INTERFACE* Interface;
NDIS_STATUS OpenErrorStatus;
UNICODE_STRING RealDeviceName;
struct ip_addr IpAddr, SubnetMask, GatewayAddr;
err_t lwip_error;
/* The device name comes in the \Device\AdapterName form */
RealDeviceName.Buffer = DeviceName->Buffer + 8;
RealDeviceName.Length = DeviceName->Length - (8 * sizeof(WCHAR));
RealDeviceName.MaximumLength = DeviceName->MaximumLength - (8 * sizeof(WCHAR));
/* Allocate an interface for this NIC */
Interface = ExAllocatePoolWithTag(PagedPool,
sizeof(*Interface) + RealDeviceName.MaximumLength,
TAG_INTERFACE);
if (!Interface)
{
DPRINT1("Could not allocate an interface structure!\n");
*Status = NDIS_STATUS_RESOURCES;
return;
}
/* Copy the device name */
RtlInitEmptyUnicodeString(&Interface->DeviceName, (PWSTR)(Interface + 1), RealDeviceName.MaximumLength);
RtlCopyUnicodeString(&Interface->DeviceName, &RealDeviceName);
/* Add the interface to the lwip list */
ip_addr_set_zero(&IpAddr);
ip_addr_set_zero(&SubnetMask);
ip_addr_set_zero(&GatewayAddr);
ACQUIRE_SERIAL_MUTEX_NO_TO();
lwip_error = netifapi_netif_add(
&Interface->lwip_netif,
&IpAddr,
&SubnetMask,
&GatewayAddr,
Interface,
lwip_netif_init,
ethernet_input);
RELEASE_SERIAL_MUTEX();
if (lwip_error != ERR_OK)
{
DPRINT1("netifapi_netif_add failed with error %d.\n", lwip_error);
*Status = NDIS_STATUS_RESOURCES;
return;
}
/* Get a adapter handle from NDIS */
NdisOpenAdapter(
Status,
&OpenErrorStatus,
&Interface->NdisContext,
&Interface->MediumIndex,
NdisMediaArray,
sizeof(NdisMediaArray) / sizeof(NdisMediaArray[0]),
NdisHandle,
Interface,
DeviceName,
0,
NULL);
if (*Status == NDIS_STATUS_PENDING)
{
/* Silently return, as the binding will be finished in the async call */
return;
}
if (*Status != NDIS_STATUS_SUCCESS)
{
DPRINT1("NdisOpenAdapter failed with status 0x%08x.\n", *Status);
ExFreePoolWithTag(Interface, TAG_INTERFACE);
return;
}
/* Finish the bind request in sync */
*Status = InitializeInterface(Interface);
}
static
VOID
NTAPI
ProtocolUnbindAdapter(
_Out_ PNDIS_STATUS Status,
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ NDIS_HANDLE UnbindContext)
{
UNIMPLEMENTED;
}
NTSTATUS
TcpIpRegisterNdisProtocol(void)
{
NDIS_STATUS Status;
NDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;
/* Simply fill in the structure and pass it to the NDIS driver. */
RtlZeroMemory(&ProtocolCharacteristics, sizeof(ProtocolCharacteristics));
ProtocolCharacteristics.MajorNdisVersion = NDIS_PROTOCOL_MAJOR_VERSION;
ProtocolCharacteristics.MinorNdisVersion = NDIS_PROTOCOL_MINOR_VERSION;
ProtocolCharacteristics.Reserved = 0;
ProtocolCharacteristics.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
ProtocolCharacteristics.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtocolCharacteristics.ResetCompleteHandler = ProtocolResetComplete;
ProtocolCharacteristics.RequestCompleteHandler = ProtocolRequestComplete;
ProtocolCharacteristics.ReceiveHandler = ProtocolReceive;
ProtocolCharacteristics.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtocolCharacteristics.StatusCompleteHandler = ProtocolStatusComplete;
ProtocolCharacteristics.ReceivePacketHandler = ProtocolReceivePacket;
ProtocolCharacteristics.BindAdapterHandler = ProtocolBindAdapter;
ProtocolCharacteristics.UnbindAdapterHandler = ProtocolUnbindAdapter;
RtlInitUnicodeString(&ProtocolCharacteristics.Name, L"TcpIp");
NdisRegisterProtocol(&Status, &NdisHandle, &ProtocolCharacteristics, sizeof(ProtocolCharacteristics));
return Status;
}
void
TcpIpUnregisterNdisProtocol(void)
{
NDIS_STATUS Status;
NdisDeregisterProtocol(&Status, NdisHandle);
}

View File

@@ -0,0 +1,8 @@
#pragma once
NTSTATUS
TcpIpRegisterNdisProtocol(void);
void
TcpIpUnregisterNdisProtocol(void);

View File

@@ -1,35 +0,0 @@
Ideas for optimizations:
* transmit.c (SendFragments, IPSendComplete):
Keep IPFRAGMENT_CONTEXT objects and PathMTU buffers in a pool
References:
RFC 791 - Internet Protocol
http://www.faqs.org/rfcs/rfc791.html
RFC 792 - Internet Control Message Protocol
http://www.faqs.org/rfcs/rfc792.html
RFC 793 - Transmission Control Protocol
http://www.faqs.org/rfcs/rfc793.html
RFC 826 - Ethernet Address Resolution Protocol
http://www.faqs.org/rfcs/rfc826.html
RFC 1122 - Requirements for Internet Hosts - Communication Layers
http://www.faqs.org/rfcs/rfc1122.html
RFC 1123 - Requirements for Internet Hosts - Application and Support
http://www.faqs.org/rfcs/rfc1123.html
RFC 2398 - Some Testing Tools for TCP Implementors
http://www.faqs.org/rfcs/rfc2398.html
RFC 2525 - Known TCP Implementation Problems
http://www.faqs.org/rfcs/rfc2525.html
RFC 2581 - TCP Congestion Control
http://www.faqs.org/rfcs/rfc2581.html

View File

@@ -0,0 +1,37 @@
#ifndef __TCPIP_PRECOMP_H__
#define __TCPIP_PRECOMP_H__
#include <ntifs.h>
#include <windef.h>
#include <tdi.h>
#include <tdiinfo.h>
#include <tdikrnl.h>
#include <tcpioctl.h>
#include <ndis.h>
#include <ipifcons.h>
typedef unsigned short u_short;
#include <ws2def.h>
#include <rtlfuncs.h>
#include <pseh/pseh2.h>
#include <lwip/icmp.h>
#include <lwip/ip.h>
#include <lwip/raw.h>
#include <lwip/snmp.h>
#include <lwip/tcpip.h>
#include <lwip/tcp.h>
#include <lwip/udp.h>
#include <netif/etharp.h>
#include "entities.h"
#include "address.h"
#include "information.h"
#include "interface.h"
#include "ndis_lwip.h"
#include "tcp.h"
#endif /* __TCPIP_PRECOMP_H__ */

View File

@@ -1,19 +0,0 @@
Build instructions for TCP/IP protocol driver
---------------------------------------------
Building with Visual C++ and Windows NT DDK:
Variables:
%BASEDIR% = path to NT4 DDK (e.g. c:\ntddk)
%DDKBUILDENV% = DDK build environment (free or checked)
DDK environment variables must be set! (run setenv.bat)
- Create the directory objects/i386/%DDKBUILDENV%
- Run "build" to build the driver
Building with Mingw32 and ReactOS include files:
- Build NDIS.SYS (i.e. "make ndis")
- Run "make tcpip" FROM THE ReactOS ROOT DIRECTORY to build the driver

View File

@@ -0,0 +1,42 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/main.c
* PURPOSE: tcpip.sys unimplemented functions
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
VOID
NTAPI
IPAddInterface(
ULONG Unknown0,
ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4)
{
UNIMPLEMENTED;
}
VOID
NTAPI
IPDelInterface(
ULONG Unknown0)
{
UNIMPLEMENTED;
}
VOID
NTAPI
LookupRoute(
ULONG Unknown0,
ULONG Unknown1)
{
UNIMPLEMENTED;
}

View File

@@ -0,0 +1,65 @@
/*
* PROJECT: ReactOS tcpip.sys
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: drivers/network/tcpip/main.c
* PURPOSE: tcpip.sys TCP functionality
*/
#include "precomp.h"
#include <intsafe.h>
#define NDEBUG
#include <debug.h>
static KSPIN_LOCK PortBitmapSpinlock;
static RTL_BITMAP PortBitmap;
static ULONG PortBitmapBuffer[(USHORT_MAX + 1) / 32];
static USHORT PortNumberHint = 1;
void
TcpIpInitializeTcp(void)
{
/* Initialize the port stuff */
KeInitializeSpinLock(&PortBitmapSpinlock);
RtlInitializeBitMap(&PortBitmap, PortBitmapBuffer, USHORT_MAX + 1);
RtlClearAllBits(&PortBitmap);
/* Reserve the port 0 */
RtlSetBit(&PortBitmap, 0);
}
BOOLEAN
AllocateTcpPort(
_Inout_ USHORT* PortNumber,
_In_ BOOLEAN Shared)
{
KIRQL OldIrql;
ULONG_PTR Bit;
KeAcquireSpinLock(&PortBitmapSpinlock, &OldIrql);
if (*PortNumber)
{
if (RtlCheckBit(&PortBitmap, *PortNumber))
{
if (!Shared)
*PortNumber = 0;
KeReleaseSpinLock(&PortBitmapSpinlock, OldIrql);
return TRUE;
}
RtlSetBit(&PortBitmap, *PortNumber);
KeReleaseSpinLock(&PortBitmapSpinlock, OldIrql);
return FALSE;
}
Bit = RtlFindClearBitsAndSet(&PortBitmap, 1, PortNumberHint);
if (Bit == ULONG_PTR_MAX)
*PortNumber = 0;
else
*PortNumber = Bit;
PortNumberHint = *PortNumber;
KeReleaseSpinLock(&PortBitmapSpinlock, OldIrql);
return FALSE;
}

View File

@@ -0,0 +1,10 @@
#pragma once
void
TcpIpInitializeTcp(void);
BOOLEAN
AllocateTcpPort(
_Inout_ USHORT* PortNumber,
_In_ BOOLEAN Shared);

View File

@@ -1,28 +0,0 @@
TARGETNAME=tcpip
TARGETPATH=..\objects
TARGETTYPE=EXPORT_DRIVER
TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \
$(DDK_LIB_PATH)\ndis.lib \
..\objects\*\free\datagram.lib \
..\objects\*\free\datalink.lib \
..\objects\*\free\network.lib \
..\objects\*\free\rawip.lib \
..\objects\*\free\tcp.lib \
..\objects\*\free\udp.lib
INCLUDES=..\include;$(BASEDIR)\INC;..\..\..\..\include\net
SOURCES= address.c \
checksum.c \
dispatch.c \
fileobjs.c \
info.c \
main.c \
pool.c \
routines.c \
RESOURCE.RC
MSC_WARNING_LEVEL=/W3 /WX

View File

@@ -1,32 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/cinfo.c
* PURPOSE: Per-socket connection information.
* PROGRAMMER: Jérôme Gardou
*/
#include "precomp.h"
TDI_STATUS SetConnectionInfo(TDIObjectID *ID,
PCONNECTION_ENDPOINT Connection,
PVOID Buffer,
UINT BufferSize)
{
ASSERT(ID->toi_type == INFO_TYPE_CONNECTION);
switch (ID->toi_id)
{
case TCP_SOCKET_NODELAY:
{
BOOLEAN Set;
if (BufferSize < sizeof(BOOLEAN))
return TDI_INVALID_PARAMETER;
Set = *(BOOLEAN*)Buffer;
return TCPSetNoDelay(Connection, Set);
}
default:
DbgPrint("TCPIP: Unknown connection info ID: %u.\n", ID->toi_id);
}
return TDI_INVALID_PARAMETER;
}

View File

@@ -1,722 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/fileobjs.c
* PURPOSE: Routines for handling file objects
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
/* Uncomment for logging of connections and address files every 10 seconds */
//#define LOG_OBJECTS
/* List of all address file objects managed by this driver */
LIST_ENTRY AddressFileListHead;
KSPIN_LOCK AddressFileListLock;
/* List of all connection endpoint file objects managed by this driver */
LIST_ENTRY ConnectionEndpointListHead;
KSPIN_LOCK ConnectionEndpointListLock;
/*
* FUNCTION: Searches through address file entries to find the first match
* ARGUMENTS:
* Address = IP address
* Port = Port number
* Protocol = Protocol number
* SearchContext = Pointer to search context
* RETURNS:
* Pointer to address file, NULL if none was found
*/
PADDRESS_FILE AddrSearchFirst(
PIP_ADDRESS Address,
USHORT Port,
USHORT Protocol,
PAF_SEARCH SearchContext)
{
KIRQL OldIrql;
SearchContext->Address = Address;
SearchContext->Port = Port;
SearchContext->Protocol = Protocol;
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
SearchContext->Next = AddressFileListHead.Flink;
if (!IsListEmpty(&AddressFileListHead))
ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry));
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
return AddrSearchNext(SearchContext);
}
BOOLEAN AddrIsBroadcastMatch(
PIP_ADDRESS UnicastAddress,
PIP_ADDRESS BroadcastAddress ) {
IF_LIST_ITER(IF);
ForEachInterface(IF) {
if ((AddrIsUnspecified(UnicastAddress) ||
AddrIsEqual(&IF->Unicast, UnicastAddress)) &&
(AddrIsEqual(&IF->Broadcast, BroadcastAddress)))
return TRUE;
} EndFor(IF);
return FALSE;
}
BOOLEAN AddrReceiveMatch(
PIP_ADDRESS LocalAddress,
PIP_ADDRESS RemoteAddress)
{
if (AddrIsEqual(LocalAddress, RemoteAddress))
{
/* Unicast address match */
return TRUE;
}
if (AddrIsBroadcastMatch(LocalAddress, RemoteAddress))
{
/* Broadcast address match */
return TRUE;
}
if (AddrIsUnspecified(LocalAddress))
{
/* Local address unspecified */
return TRUE;
}
if (AddrIsUnspecified(RemoteAddress))
{
/* Remote address unspecified */
return TRUE;
}
return FALSE;
}
VOID
LogActiveObjects(VOID)
{
#ifdef LOG_OBJECTS
PLIST_ENTRY CurrentEntry;
KIRQL OldIrql;
PADDRESS_FILE AddrFile;
PCONNECTION_ENDPOINT Conn;
DbgPrint("----------- TCP/IP Active Object Dump -------------\n");
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
CurrentEntry = AddressFileListHead.Flink;
while (CurrentEntry != &AddressFileListHead)
{
AddrFile = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
DbgPrint("Address File (%s, %d, %d) @ 0x%p | Ref count: %d | Sharers: %d\n",
A2S(&AddrFile->Address), WN2H(AddrFile->Port), AddrFile->Protocol,
AddrFile, AddrFile->RefCount, AddrFile->Sharers);
DbgPrint("\tListener: ");
if (AddrFile->Listener == NULL)
DbgPrint("<None>\n");
else
DbgPrint("0x%p\n", AddrFile->Listener);
DbgPrint("\tAssociated endpoints: ");
if (AddrFile->Connection == NULL)
DbgPrint("<None>\n");
else
{
Conn = AddrFile->Connection;
while (Conn)
{
DbgPrint("0x%p ", Conn);
Conn = Conn->Next;
}
DbgPrint("\n");
}
CurrentEntry = CurrentEntry->Flink;
}
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
CurrentEntry = ConnectionEndpointListHead.Flink;
while (CurrentEntry != &ConnectionEndpointListHead)
{
Conn = CONTAINING_RECORD(CurrentEntry, CONNECTION_ENDPOINT, ListEntry);
DbgPrint("Connection @ 0x%p | Ref count: %d\n", Conn, Conn->RefCount);
DbgPrint("\tPCB: ");
if (Conn->SocketContext == NULL)
DbgPrint("<None>\n");
else
{
DbgPrint("0x%p\n", Conn->SocketContext);
LibTCPDumpPcb(Conn->SocketContext);
}
DbgPrint("\tPacket queue status: %s\n", IsListEmpty(&Conn->PacketQueue) ? "Empty" : "Not Empty");
DbgPrint("\tRequest lists: Connect: %s | Recv: %s | Send: %s | Shutdown: %s | Listen: %s\n",
IsListEmpty(&Conn->ConnectRequest) ? "Empty" : "Not Empty",
IsListEmpty(&Conn->ReceiveRequest) ? "Empty" : "Not Empty",
IsListEmpty(&Conn->SendRequest) ? "Empty" : "Not Empty",
IsListEmpty(&Conn->ShutdownRequest) ? "Empty" : "Not Empty",
IsListEmpty(&Conn->ListenRequest) ? "Empty" : "Not Empty");
DbgPrint("\tSend shutdown: %s\n", Conn->SendShutdown ? "Yes" : "No");
DbgPrint("\tReceive shutdown: %s\n", Conn->ReceiveShutdown ? "Yes" : "No");
if (Conn->ReceiveShutdown) DbgPrint("\tReceive shutdown status: 0x%x\n", Conn->ReceiveShutdownStatus);
DbgPrint("\tClosing: %s\n", Conn->Closing ? "Yes" : "No");
CurrentEntry = CurrentEntry->Flink;
}
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
DbgPrint("---------------------------------------------------\n");
#endif
}
PADDRESS_FILE AddrFindShared(
PIP_ADDRESS BindAddress,
USHORT Port,
USHORT Protocol)
{
PLIST_ENTRY CurrentEntry;
KIRQL OldIrql;
PADDRESS_FILE Current = NULL;
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
CurrentEntry = AddressFileListHead.Flink;
while (CurrentEntry != &AddressFileListHead) {
Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
/* See if this address matches the search criteria */
if ((Current->Port == Port) &&
(Current->Protocol == Protocol))
{
/* Increase the sharer count */
ASSERT(Current->Sharers != 0);
InterlockedIncrement(&Current->Sharers);
break;
}
CurrentEntry = CurrentEntry->Flink;
Current = NULL;
}
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
return Current;
}
/*
* FUNCTION: Searches through address file entries to find next match
* ARGUMENTS:
* SearchContext = Pointer to search context
* RETURNS:
* Pointer to referenced address file, NULL if none was found
*/
PADDRESS_FILE AddrSearchNext(
PAF_SEARCH SearchContext)
{
PLIST_ENTRY CurrentEntry;
PIP_ADDRESS IPAddress;
KIRQL OldIrql;
PADDRESS_FILE Current = NULL;
BOOLEAN Found = FALSE;
PADDRESS_FILE StartingAddrFile;
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
if (SearchContext->Next == &AddressFileListHead)
{
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
return NULL;
}
/* Save this pointer so we can dereference it later */
StartingAddrFile = CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry);
CurrentEntry = SearchContext->Next;
while (CurrentEntry != &AddressFileListHead) {
Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
IPAddress = &Current->Address;
TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n",
WN2H(Current->Port),
Current->Protocol,
A2S(IPAddress),
WN2H(SearchContext->Port),
SearchContext->Protocol,
A2S(SearchContext->Address)));
/* See if this address matches the search criteria */
if ((Current->Port == SearchContext->Port) &&
(Current->Protocol == SearchContext->Protocol) &&
(AddrReceiveMatch(IPAddress, SearchContext->Address))) {
/* We've found a match */
Found = TRUE;
break;
}
CurrentEntry = CurrentEntry->Flink;
}
if (Found)
{
SearchContext->Next = CurrentEntry->Flink;
if (SearchContext->Next != &AddressFileListHead)
{
/* Reference the next address file to prevent the link from disappearing behind our back */
ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry));
}
/* Reference the returned address file before dereferencing the starting
* address file because it may be that Current == StartingAddrFile */
ReferenceObject(Current);
}
else
Current = NULL;
DereferenceObject(StartingAddrFile);
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
return Current;
}
VOID AddrFileFree(
PVOID Object)
/*
* FUNCTION: Frees an address file object
* ARGUMENTS:
* Object = Pointer to address file object to free
*/
{
PADDRESS_FILE AddrFile = Object;
KIRQL OldIrql;
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
PDATAGRAM_SEND_REQUEST SendRequest;
PLIST_ENTRY CurrentEntry;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
/* We should not be associated with a connection here */
ASSERT(!AddrFile->Connection);
/* Remove address file from the global list */
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
RemoveEntryList(&AddrFile->ListEntry);
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
/* FIXME: Kill TCP connections on this address file object */
/* Return pending requests with error */
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
/* Go through pending receive request list and cancel them all */
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
(*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
/* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
}
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
/* Go through pending send request list and cancel them all */
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
(*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
}
/* Protocol specific handling */
switch (AddrFile->Protocol) {
case IPPROTO_TCP:
if (AddrFile->Port)
{
TCPFreePort(AddrFile->Port);
}
break;
case IPPROTO_UDP:
UDPFreePort( AddrFile->Port );
break;
}
RemoveEntityByContext(AddrFile);
ExFreePoolWithTag(Object, ADDR_FILE_TAG);
}
VOID ControlChannelFree(
PVOID Object)
/*
* FUNCTION: Frees an address file object
* ARGUMENTS:
* Object = Pointer to address file object to free
*/
{
ExFreePoolWithTag(Object, CONTROL_CHANNEL_TAG);
}
/*
* FUNCTION: Open an address file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* Address = Pointer to address to be opened
* Protocol = Protocol on which to open the address
* Shared = Specifies if the address is opened for shared access
* Options = Pointer to option buffer
* RETURNS:
* Status of operation
*/
NTSTATUS FileOpenAddress(
PTDI_REQUEST Request,
PTA_IP_ADDRESS Address,
USHORT Protocol,
BOOLEAN Shared,
PVOID Options)
{
PADDRESS_FILE AddrFile;
TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol));
/* If it's shared and has a port specified, look for a match */
if ((Shared != FALSE) && (Address->Address[0].Address[0].sin_port != 0))
{
AddrFile = AddrFindShared(NULL, Address->Address[0].Address[0].sin_port, Protocol);
if (AddrFile != NULL)
{
Request->Handle.AddressHandle = AddrFile;
return STATUS_SUCCESS;
}
}
AddrFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADDRESS_FILE),
ADDR_FILE_TAG);
if (!AddrFile) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
AddrFile->RefCount = 1;
AddrFile->Free = AddrFileFree;
AddrFile->Sharers = 1;
/* Set our default options */
AddrFile->TTL = 128;
AddrFile->DF = 0;
AddrFile->BCast = 1;
AddrFile->HeaderIncl = 1;
/* Make sure address is a local unicast address or 0 */
/* FIXME: IPv4 only */
AddrFile->Family = Address->Address[0].AddressType;
AddrFile->Address.Address.IPv4Address = Address->Address[0].Address[0].in_addr;
AddrFile->Address.Type = IP_ADDRESS_V4;
if (!AddrIsUnspecified(&AddrFile->Address) &&
!AddrLocateInterface(&AddrFile->Address)) {
TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", A2S(&AddrFile->Address)));
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_INVALID_ADDRESS;
}
TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n",
A2S(&AddrFile->Address), Protocol, IPPROTO_UDP));
/* Protocol specific handling */
switch (Protocol) {
case IPPROTO_TCP:
if (Address->Address[0].Address[0].sin_port)
{
/* The client specified an explicit port so we force a bind to this */
AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port);
/* Check for bind success */
if (AddrFile->Port == 0xffff)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
/* Sanity check */
ASSERT(Address->Address[0].Address[0].sin_port == AddrFile->Port);
}
else if (!AddrIsUnspecified(&AddrFile->Address))
{
/* The client is trying to bind to a local address so allocate a port now too */
AddrFile->Port = TCPAllocatePort(0);
/* Check for bind success */
if (AddrFile->Port == 0xffff)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
}
else
{
/* The client wants an unspecified port with an unspecified address so we wait to see what the TCP library gives us */
AddrFile->Port = 0;
}
AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP);
AddrFile->Send = NULL; /* TCPSendData */
break;
case IPPROTO_UDP:
TI_DbgPrint(MID_TRACE,("Allocating udp port\n"));
AddrFile->Port =
UDPAllocatePort(Address->Address[0].Address[0].sin_port);
if ((Address->Address[0].Address[0].sin_port &&
AddrFile->Port != Address->Address[0].Address[0].sin_port) ||
AddrFile->Port == 0xffff)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n",
AddrFile->Port,
Address->Address[0].Address[0].sin_port));
AddEntity(CL_TL_ENTITY, AddrFile, CL_TL_UDP);
AddrFile->Send = UDPSendDatagram;
break;
case IPPROTO_ICMP:
AddrFile->Port = 0;
AddrFile->Send = ICMPSendDatagram;
/* FIXME: Verify this */
AddEntity(ER_ENTITY, AddrFile, ER_ICMP);
break;
default:
/* Use raw IP for all other protocols */
AddrFile->Port = 0;
AddrFile->Send = RawIPSendDatagram;
/* FIXME: Verify this */
AddEntity(CL_TL_ENTITY, AddrFile, 0);
break;
}
TI_DbgPrint(MID_TRACE, ("IP protocol number for address file object is %d.\n",
Protocol));
TI_DbgPrint(MID_TRACE, ("Port number for address file object is %d.\n",
WN2H(AddrFile->Port)));
/* Set protocol */
AddrFile->Protocol = Protocol;
/* Initialize receive and transmit queues */
InitializeListHead(&AddrFile->ReceiveQueue);
InitializeListHead(&AddrFile->TransmitQueue);
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&AddrFile->Lock);
/* Return address file object */
Request->Handle.AddressHandle = AddrFile;
/* Add address file to global list */
ExInterlockedInsertTailList(
&AddressFileListHead,
&AddrFile->ListEntry,
&AddressFileListLock);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Closes an address file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseAddress(
PTDI_REQUEST Request)
{
PADDRESS_FILE AddrFile = Request->Handle.AddressHandle;
KIRQL OldIrql;
if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
LockObject(AddrFile, &OldIrql);
if (InterlockedDecrement(&AddrFile->Sharers) != 0)
{
/* Still other guys have open handles to this, so keep it around */
UnlockObject(AddrFile, OldIrql);
return STATUS_SUCCESS;
}
/* We have to close this listener because we started it */
if( AddrFile->Listener )
{
TCPClose( AddrFile->Listener );
}
UnlockObject(AddrFile, OldIrql);
DereferenceObject(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Opens a connection file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* ClientContext = Pointer to client context information
* RETURNS:
* Status of operation
*/
NTSTATUS FileOpenConnection(
PTDI_REQUEST Request,
PVOID ClientContext)
{
NTSTATUS Status;
PCONNECTION_ENDPOINT Connection;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = TCPAllocateConnectionEndpoint( ClientContext );
if( !Connection ) return STATUS_NO_MEMORY;
Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( !NT_SUCCESS(Status) ) {
DereferenceObject( Connection );
return Status;
}
/* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection;
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Closes an connection file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseConnection(
PTDI_REQUEST Request)
{
PCONNECTION_ENDPOINT Connection;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = Request->Handle.ConnectionContext;
if (!Connection) return STATUS_INVALID_PARAMETER;
TCPClose( Connection );
Request->Handle.ConnectionContext = NULL;
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Opens a control channel file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileOpenControlChannel(
PTDI_REQUEST Request)
{
PCONTROL_CHANNEL ControlChannel;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
ControlChannel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ControlChannel),
CONTROL_CHANNEL_TAG);
if (!ControlChannel) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(ControlChannel, sizeof(CONTROL_CHANNEL));
/* Make sure address is a local unicast address or 0 */
/* Locate address entry. If specified address is 0, a random address is chosen */
/* Initialize receive and transmit queues */
InitializeListHead(&ControlChannel->ListEntry);
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&ControlChannel->Lock);
ControlChannel->RefCount = 1;
ControlChannel->Free = ControlChannelFree;
/* Return address file object */
Request->Handle.ControlChannel = ControlChannel;
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Closes a control channel file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseControlChannel(
PTDI_REQUEST Request)
{
if (!Request->Handle.ControlChannel) return STATUS_INVALID_PARAMETER;
DereferenceObject((PCONTROL_CHANNEL)Request->Handle.ControlChannel);
Request->Handle.ControlChannel = NULL;
return STATUS_SUCCESS;
}
/* EOF */

View File

@@ -1,383 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/info.c
* PURPOSE: TDI query and set information routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
#include <debug.h>
VOID AddEntity(ULONG EntityType, PVOID Context, ULONG Flags)
{
KIRQL OldIrql;
ULONG i, Instance = 0;
BOOLEAN ChoseIndex = FALSE;
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
while (!ChoseIndex)
{
ChoseIndex = TRUE;
for (i = 0; i < EntityCount; i++)
{
if (EntityList[i].tei_entity == EntityType &&
EntityList[i].tei_instance == Instance)
{
Instance++;
ChoseIndex = FALSE;
}
}
}
EntityList[EntityCount].tei_entity = EntityType;
EntityList[EntityCount].tei_instance = Instance;
EntityList[EntityCount].context = Context;
EntityList[EntityCount].flags = Flags;
EntityCount++;
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
}
VOID RemoveEntityByContext(PVOID Context)
{
ULONG i;
KIRQL OldIrql;
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
for (i = 0; i < EntityCount; i++) {
if( EntityList[i].context == Context ) {
if( i != EntityCount - 1 ) {
memcpy( &EntityList[i],
&EntityList[--EntityCount],
sizeof(EntityList[i]) );
} else {
EntityCount--;
}
}
}
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
}
PVOID GetContext(TDIEntityID ID)
{
UINT i;
KIRQL OldIrql;
PVOID Context;
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
for (i = 0; i < EntityCount; i++)
{
if (EntityList[i].tei_entity == ID.tei_entity &&
EntityList[i].tei_instance == ID.tei_instance)
break;
}
if (i == EntityCount)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
DbgPrint("WARNING: Unable to get context for %d %d\n", ID.tei_entity, ID.tei_instance);
return NULL;
}
Context = EntityList[i].context;
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return Context;
}
TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) {
UINT RememberedCBSize = *ClientBufSize;
*ClientBufSize = SizeOut;
/* The driver returns success even when it couldn't fit every available
* byte. */
if( RememberedCBSize < SizeOut || !ClientBuf )
return TDI_SUCCESS;
else {
CopyBufferToBufferChain( ClientBuf, 0, (PCHAR)DataOut, SizeOut );
return TDI_SUCCESS;
}
}
TDI_STATUS InfoTdiQueryEntityType(TDIEntityID ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize)
{
KIRQL OldIrql;
UINT i, Flags = 0;
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
for (i = 0; i < EntityCount; i++)
{
if (EntityList[i].tei_entity == ID.tei_entity &&
EntityList[i].tei_instance == ID.tei_instance)
break;
}
if (i == EntityCount)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_INVALID_PARAMETER;
}
Flags = EntityList[i].flags;
InfoCopyOut((PCHAR)&Flags,
sizeof(ULONG),
Buffer,
BufferSize);
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_SUCCESS;
}
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
PUINT BufferSize)
{
UINT Count, Size, BufSize = *BufferSize;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_INFO,("About to copy %d TDIEntityIDs to user\n",
EntityCount));
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
Size = EntityCount * sizeof(TDIEntityID);
*BufferSize = Size;
TI_DbgPrint(DEBUG_INFO,("BufSize: %d, NeededSize: %d\n", BufSize, Size));
if (BufSize < Size || !Buffer)
{
TcpipReleaseSpinLock( &EntityListLock, OldIrql );
/* The buffer is too small to contain requested data, but we return
* success anyway, as we did everything we wanted. */
return TDI_SUCCESS;
}
/* Return entity list -- Copy only the TDIEntityID parts. */
for( Count = 0; Count < EntityCount; Count++ ) {
CopyBufferToBufferChain(Buffer,
Count * sizeof(TDIEntityID),
(PCHAR)&EntityList[Count],
sizeof(TDIEntityID));
}
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_SUCCESS;
}
TDI_STATUS InfoTdiQueryInformationEx(
PTDI_REQUEST Request,
TDIObjectID *ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize,
PVOID Context)
/*
* FUNCTION: Returns extended information
* ARGUMENTS:
* Request = Pointer to TDI request structure for the request
* ID = TDI object ID
* Buffer = Pointer to buffer with data to use
* BufferSize = Pointer to buffer with size of Buffer. On return
* this is filled with number of bytes returned
* Context = Pointer to context buffer
* RETURNS:
* Status of operation
*/
{
PVOID EntityListContext;
TI_DbgPrint(DEBUG_INFO,
("InfoEx Req: %x %x %x!%04x:%d\n",
ID->toi_class,
ID->toi_type,
ID->toi_id,
ID->toi_entity.tei_entity,
ID->toi_entity.tei_instance));
switch (ID->toi_class)
{
case INFO_CLASS_GENERIC:
switch (ID->toi_id)
{
case ENTITY_LIST_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
return InfoTdiQueryListEntities(Buffer, BufferSize);
case ENTITY_TYPE_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
default:
return TDI_INVALID_REQUEST;
}
case INFO_CLASS_PROTOCOL:
if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
{
if ((EntityListContext = GetContext(ID->toi_entity)))
return GetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
}
switch (ID->toi_id)
{
case IF_MIB_STATS_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
if (ID->toi_entity.tei_entity == IF_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
ID->toi_entity.tei_entity == CO_NL_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else
return TDI_INVALID_PARAMETER;
case IP_MIB_ADDRTABLE_ENTRY_ID:
if (ID->toi_entity.tei_entity != CL_NL_ENTITY &&
ID->toi_entity.tei_entity != CO_NL_ENTITY)
return TDI_INVALID_PARAMETER;
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
case IP_MIB_ARPTABLE_ENTRY_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
if (ID->toi_entity.tei_entity == AT_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
ID->toi_entity.tei_entity == CL_NL_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetRouteTable(EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else
return TDI_INVALID_PARAMETER;
#if 0
case IP_INTFC_INFO_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
#endif
default:
return TDI_INVALID_REQUEST;
}
default:
return TDI_INVALID_REQUEST;
}
}
TDI_STATUS InfoTdiSetInformationEx
(PTDI_REQUEST Request,
TDIObjectID *ID,
PVOID Buffer,
UINT BufferSize)
/*
* FUNCTION: Sets extended information
* ARGUMENTS:
* Request = Pointer to TDI request structure for the request
* ID = Pointer to TDI object ID
* Buffer = Pointer to buffer with data to use
* BufferSize = Size of Buffer
* RETURNS:
* Status of operation
*/
{
PVOID EntityListContext;
switch (ID->toi_class)
{
case INFO_CLASS_PROTOCOL:
{
switch (ID->toi_type)
{
case INFO_TYPE_ADDRESS_OBJECT:
{
if ((EntityListContext = GetContext(ID->toi_entity)))
return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
}
case INFO_TYPE_CONNECTION:
{
PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
if (AddressFile == NULL)
return TDI_INVALID_PARAMETER;
return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
}
case INFO_TYPE_PROVIDER:
{
switch (ID->toi_id)
{
case IP_MIB_ARPTABLE_ENTRY_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
if (ID->toi_entity.tei_entity == AT_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiSetArptableMIB(EntityListContext, Buffer,
BufferSize);
else
return TDI_INVALID_PARAMETER;
else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
|| ID->toi_entity.tei_entity == CO_NL_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else
return TDI_INVALID_PARAMETER;
default:
return TDI_INVALID_REQUEST;
}
}
default:
DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
return TDI_INVALID_PARAMETER;
}
break;
}
default:
DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
return TDI_INVALID_REQUEST;
}
}

View File

@@ -1,46 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/lock.c
* PURPOSE: Locking and unlocking
* PROGRAMMERS: Art Yerkes
* REVISIONS:
*/
#include "precomp.h"
KIRQL TcpipGetCurrentIrql() { return KeGetCurrentIrql(); }
VOID TcpipInitializeSpinLock( PKSPIN_LOCK SpinLock ) {
KeInitializeSpinLock( SpinLock );
}
VOID TcpipAcquireSpinLock( PKSPIN_LOCK SpinLock, PKIRQL Irql ) {
KeAcquireSpinLock( SpinLock, Irql );
}
VOID TcpipAcquireSpinLockAtDpcLevel( PKSPIN_LOCK SpinLock ) {
KeAcquireSpinLockAtDpcLevel( SpinLock );
}
VOID TcpipReleaseSpinLock( PKSPIN_LOCK SpinLock, KIRQL Irql ) {
KeReleaseSpinLock( SpinLock, Irql );
}
VOID TcpipReleaseSpinLockFromDpcLevel( PKSPIN_LOCK SpinLock ) {
KeReleaseSpinLockFromDpcLevel( SpinLock );
}
VOID TcpipInterlockedInsertTailList( PLIST_ENTRY ListHead,
PLIST_ENTRY Item,
PKSPIN_LOCK Lock ) {
ExInterlockedInsertTailList( ListHead, Item, Lock );
}
VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex ) {
ExAcquireFastMutex( Mutex );
}
VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
ExReleaseFastMutex( Mutex );
}

View File

@@ -1,47 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/lock.c
* PURPOSE: Locking and unlocking
* PROGRAMMERS: Art Yerkes
* REVISIONS:
*/
#include "precomp.h"
KIRQL KernelIrql = PASSIVE_LEVEL;
KIRQL TcpipGetCurrentIrql() { return KernelIrql; }
VOID TcpipInitializeSpinLock( PKSPIN_LOCK SpinLock ) {
}
VOID TcpipAcquireSpinLock( PKSPIN_LOCK SpinLock, PKIRQL Irql ) {
*Irql = KernelIrql;
KernelIrql = DISPATCH_LEVEL;
}
VOID TcpipAcquireSpinLockAtDpcLevel( PKSPIN_LOCK SpinLock ) {
ASSERT(KernelIrql == DISPATCH_LEVEL);
}
VOID TcpipReleaseSpinLock( PKSPIN_LOCK SpinLock, KIRQL Irql ) {
ASSERT( Irql <= KernelIrql );
KernelIrql = Irql;
}
VOID TcpipReleaseSpinLockFromDpcLevel( PKSPIN_LOCK SpinLock ) {
ASSERT(KernelIrql == DISPATCH_LEVEL);
}
VOID TcpipInterlockedInsertTailList( PLIST_ENTRY ListHead,
PLIST_ENTRY Item,
PKSPIN_LOCK Lock ) {
InsertTailList( ListHead, Item );
}
VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex ) {
}
VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
}

View File

@@ -1,58 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/pool.c
* PURPOSE: Routines for controling pools
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
PVOID PoolAllocateBuffer(
ULONG Size)
/*
* FUNCTION: Returns a buffer from the free buffer pool
* RETURNS:
* Pointer to buffer, NULL if there was not enough
* free resources
*/
{
PVOID Buffer;
/* FIXME: Get buffer from a free buffer pool with enough room */
Buffer = malloc(Size);
TI_DbgPrint(DEBUG_MEMORY, ("Allocated (%i) bytes at (0x%X).\n", Size, Buffer));
return Buffer;
}
VOID PoolFreeBuffer(
PVOID Buffer)
/*
* FUNCTION: Returns a buffer to the free buffer pool
* ARGUMENTS:
* Buffer = Buffer to return to free buffer pool
*/
{
/* FIXME: Put buffer in free buffer pool */
TI_DbgPrint(DEBUG_MEMORY, ("Freeing buffer at (0x%X).\n", Buffer));
free(Buffer);
}
PVOID TcpipAllocateFromNPagedLookasideList( PNPAGED_LOOKASIDE_LIST List ) {
return PoolAllocateBuffer( List->Size );
}
VOID TcpipFreeToNPagedLookasideList( PNPAGED_LOOKASIDE_LIST List,
PVOID Thing ) {
PoolFreeBuffer( Thing );
}
/* EOF */

View File

@@ -1,18 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/lock.c
* PURPOSE: Waiting and signalling
* PROGRAMMERS: Art Yerkes
* REVISIONS:
*/
#include "precomp.h"
NTSTATUS TcpipWaitForSingleObject( PVOID Object,
KWAIT_REASON Reason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout ) {
return STATUS_SUCCESS;
}

View File

@@ -1,39 +0,0 @@
#include "precomp.h"
NTSTATUS TiGetProtocolNumber(
PUNICODE_STRING FileName,
PULONG Protocol)
/*
* FUNCTION: Returns the protocol number from a file name
* ARGUMENTS:
* FileName = Pointer to string with file name
* Protocol = Pointer to buffer to put protocol number in
* RETURNS:
* Status of operation
*/
{
UNICODE_STRING us;
NTSTATUS Status;
ULONG Value;
PWSTR Name;
TI_DbgPrint(MAX_TRACE, ("Called. FileName (%wZ).\n", FileName));
Name = FileName->Buffer;
if (*Name++ != (WCHAR)L'\\')
return STATUS_UNSUCCESSFUL;
if (*Name == L'\0')
return STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&us, Name);
Status = RtlUnicodeStringToInteger(&us, 10, &Value);
if (!NT_SUCCESS(Status) || ((Value > 255)))
return STATUS_UNSUCCESSFUL;
*Protocol = Value;
return STATUS_SUCCESS;
}

View File

@@ -1,10 +0,0 @@
#include <windows.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_NETWORK
#define VER_FILEDESCRIPTION_STR "TCP/IP protocol driver"
#define VER_INTERNALNAME_STR "TCPIP.SYS"
#define VER_ORIGINALFILENAME_STR "TCPIP.SYS"
#include "common.ver"

View File

@@ -1,32 +0,0 @@
; TCPIP.SYS - TCP/IP protocol driver
LIBRARY tcpip.sys
EXPORTS
;FreeIprBuff
;GetIFAndLink
IPAddInterface
;IPAllocBuff
IPDelInterface
;IPDelayedNdisReEnumerateBindings
;IPDeregisterARP
;IPDisableSniffer
;IPEnableSniffer
;IPFreeBuff
;IPGetAddrType
;IPGetBestInterface
;IPGetInfo
;IPInjectPkt
;IPProxyNdisRequest
;IPRegisterARP
;IPRegisterProtocol
;IPSetIPSecStatus
;IPTransmit
LookupRoute
;LookupRouteInformation
;SendICMPErr
;SetIPSecPtr
;UnSetIPSecPtr
;UnSetIPSecSendPtr
; EOF

View File

@@ -1,38 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/tinfo.c
* PURPOSE: Transport layer information
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
TDI_STATUS InfoTransportLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
if( InfoClass == INFO_CLASS_GENERIC &&
InfoType == INFO_TYPE_PROVIDER &&
InfoId == ENTITY_TYPE_ID ) {
ULONG Temp = CL_TL_UDP;
return InfoCopyOut( (PCHAR)&Temp, sizeof(Temp), Buffer, BufferSize );
}
return TDI_INVALID_REQUEST;
}
TDI_STATUS InfoTransportLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
return TDI_INVALID_REQUEST;
}

View File

@@ -1,19 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/lock.c
* PURPOSE: Waiting and signalling
* PROGRAMMERS: Art Yerkes
* REVISIONS:
*/
#include "precomp.h"
NTSTATUS TcpipWaitForSingleObject( PVOID Object,
KWAIT_REASON Reason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout ) {
return KeWaitForSingleObject
( Object, Reason, WaitMode, Alertable, Timeout );
}

View File

@@ -1,6 +0,0 @@
#include <windows.h>
#include "regtests.h"
_SetupOnce()
{
}

View File

@@ -1,52 +0,0 @@
# Automatically generated by stubgen
ndis.a _imp__NDIS_BUFFER_TO_SPAN_PAGES@4
ntoskrnl.a _imp__KeBugCheck@4
ntoskrnl.a _imp_@InterlockedPopEntrySList@4
ntoskrnl.a _imp_@InterlockedPushEntrySList@8
ntoskrnl.a _imp__ExDeleteNPagedLookasideList@4
ntoskrnl.a _imp__ExInitializeNPagedLookasideList@28
ndis.a _imp__NdisDeregisterProtocol@8
ndis.a _imp__NdisRegisterProtocol@16
ndis.a _imp__NdisCloseAdapter@8
ndis.a _imp__NdisOpenAdapter@44
ndis.a _imp__NdisSend@12
ndis.a _imp__NdisTransferData@28
ntoskrnl.a _imp__ExInterlockedRemoveHeadList@8
ndis.a _imp__NdisRequest@12
ndis.a _imp__NdisFreePacket@4
ndis.a _imp__NdisFreeBuffer@4
ndis.a _imp__NdisAllocatePacket@12
ndis.a _imp__NdisAllocateBuffer@20
ntoskrnl.a _imp__ExInterlockedInsertTailList@12
ntoskrnl.a _imp_@IofCompleteRequest@8
ntoskrnl.a _imp__MmProbeAndLockPages@12
ntoskrnl.a _imp__IoAllocateMdl@20
ntoskrnl.a _imp__ExFreePool@4
ntoskrnl.a _imp__IoFreeMdl@4
ntoskrnl.a _imp__MmUnlockPages@4
ntoskrnl.a _imp__MmMapLockedPages@8
ntoskrnl.a _imp_@ObfDereferenceObject@4
ntoskrnl.a _imp__ObReferenceObjectByHandle@24
ntoskrnl.a _imp__IoFileObjectType
ntoskrnl.a _imp_@InterlockedExchange@8
ntoskrnl.a _imp__KeSetTimerEx@20
ntoskrnl.a _imp__KeInitializeTimer@4
ntoskrnl.a _imp__KeInitializeDpc@12
ndis.a _imp__NdisAllocateBufferPool@12
ndis.a _imp__NdisAllocatePacketPool@16
ntoskrnl.a _imp__KeInitializeSpinLock@4
ntoskrnl.a _imp__IoCreateDevice@28
ntoskrnl.a _imp__ExQueueWorkItem@8
ntoskrnl.a _imp__IoDeleteDevice@4
ndis.a _imp__NdisFreePacketPool@4
ndis.a _imp__NdisFreeBufferPool@4
ntoskrnl.a _imp__KeCancelTimer@4
ntoskrnl.a _imp__KeWaitForSingleObject@20
ntoskrnl.a _imp__KeResetEvent@4
ntoskrnl.a _imp__IoReleaseCancelSpinLock@4
ntoskrnl.a _imp__KeSetEvent@12
ntoskrnl.a _imp__IoAcquireCancelSpinLock@4
ntoskrnl.a _imp__KeInitializeEvent@12
ntoskrnl.a _imp__ExAllocatePool@8
ntoskrnl.a _imp_@ExAcquireFastMutex@4
ntoskrnl.a _imp_@ExReleaseFastMutex@4

View File

@@ -1,12 +0,0 @@
#include "../../include/precomp.h"
#include "regtests.h"
static void RunTest() {
UNICODE_STRING Str;
int Proto;
RtlInitUnicodeString( &Str, L"1" );
TiGetProtocolNumber( &Str, (PULONG)&Proto );
_AssertEqualValue(1, Proto);
}
_Dispatcher(TigetprotocolnumberTest, "TiGetProtocolNumber");

View File

@@ -3,7 +3,7 @@ add_subdirectory(chew)
add_subdirectory(copysup)
add_subdirectory(csq)
add_subdirectory(hidparser)
add_subdirectory(ip)
#add_subdirectory(ip)
add_subdirectory(libusb)
add_subdirectory(lwip)
add_subdirectory(ntoskrnl_vista)

View File

@@ -10,8 +10,6 @@ include_directories(
src/include/ipv4)
list(APPEND SOURCE
src/rosip.c
src/rostcp.c
src/rosmem.c
src/sys_arch.c
src/api/api_lib.c
@@ -56,6 +54,7 @@ list(APPEND SOURCE
src/core/snmp/mib2.c
src/core/snmp/msg_in.c
src/core/snmp/msg_out.c
src/netif/etharp.c
precomp.h)
add_library(lwip ${SOURCE})
@@ -66,4 +65,5 @@ if(NOT MSVC)
if(LTCG)
add_compile_flags("-fno-builtin-malloc -fno-builtin-free")
endif()
add_compile_flags("-Wno-address")
endif()

View File

@@ -121,7 +121,6 @@ u8_t tcp_active_pcbs_changed;
/** Timer counter to handle calling slow-timer from tcp_tmr() */
static u8_t tcp_timer;
static u8_t tcp_timer_ctr;
static u16_t tcp_new_port(void);
/**
* Initialize this module.
@@ -643,7 +642,7 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
*
* @return a new (free) local TCP port number
*/
static u16_t
u16_t
tcp_new_port(void)
{
u8_t i;

View File

@@ -95,7 +95,7 @@ udp_init(void)
*
* @return a new (free) local UDP port number
*/
static u16_t
u16_t
udp_new_port(void)
{
u16_t n = 0;

View File

@@ -39,5 +39,4 @@ void
sys_arch_unprotect(sys_prot_t lev);
void
sys_shutdown(void);
sys_shutdown(void);

View File

@@ -1023,7 +1023,7 @@
* TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb.
*/
#ifndef TCP_LISTEN_BACKLOG
#define TCP_LISTEN_BACKLOG 0
#define TCP_LISTEN_BACKLOG 1
#endif
/**

View File

@@ -322,6 +322,8 @@ void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent);
void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
u16_t tcp_new_port(void);
#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
@@ -366,10 +368,48 @@ void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
err_t tcp_output (struct tcp_pcb *pcb);
/**
* REACT_OS Global Mutex
* Serializes all kernel network activity to circumvent lwIP core's lack of thread-safety.
**/
KMUTEX MTSerialMutex;
#define ACQUIRE_SERIAL_MUTEX(RelatedMutex,Timeout) \
while (KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, Timeout) \
== STATUS_TIMEOUT) \
{ \
KeReleaseMutex(RelatedMutex, TRUE); \
KeWaitForMutexObject(RelatedMutex, Executive, KernelMode, FALSE, NULL); \
} do {} while(0)
#define ACQUIRE_SERIAL_MUTEX_NO_TO() \
KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, NULL)
#define RELEASE_SERIAL_MUTEX() \
KeReleaseMutex(&MTSerialMutex, FALSE)
/*
#define ACQUIRE_SERIAL_MUTEX(RelatedMutex,Timeout) \
DPRINT("Acquiring MTSerialMutex on thread %p\n", KeGetCurrentThread()); \
while (KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, Timeout) \
== STATUS_TIMEOUT) \
{ \
KeReleaseMutex(RelatedMutex, TRUE); \
KeWaitForMutexObject(RelatedMutex, Executive, KernelMode, FALSE, NULL); \
} \
DPRINT("MTSerialMutex acquired on thread %p\n", KeGetCurrentThread())
#define ACQUIRE_SERIAL_MUTEX_NO_TO() \
DPRINT("Acquiring MTSerialMutex on thread %p\n", KeGetCurrentThread()); \
KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, NULL); \
DPRINT("MTSerialMutex acquired on thread %p\n", KeGetCurrentThread())
#define RELEASE_SERIAL_MUTEX() \
DPRINT("Releasing MTSerialMutex on thread %p\n", KeGetCurrentThread()); \
KeReleaseMutex(&MTSerialMutex, FALSE); \
DPRINT("MTSerialMutex released on thread %p\n", KeGetCurrentThread())
*/
const char* tcp_debug_state_str(enum tcp_state s);
#ifdef __cplusplus
}
#endif

View File

@@ -158,6 +158,8 @@ struct tcpip_msg {
} msg;
};
extern KMUTEX MTSerialMutex;
#ifdef __cplusplus
}
#endif

View File

@@ -136,6 +136,8 @@ err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p,
ip_addr_t *dst_ip, u16_t dst_port);
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
u16_t udp_new_port(void);
#if LWIP_CHECKSUM_ON_COPY
err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
ip_addr_t *dst_ip, u16_t dst_port,

View File

@@ -14,7 +14,7 @@
#define MEM_ALIGNMENT 4
#define LWIP_ARP 0
#define LWIP_ARP 1
#define ARP_QUEUEING 0
@@ -30,21 +30,21 @@
#define IP_SOF_BROADCAST_RECV 1
#define LWIP_ICMP 0
#define LWIP_ICMP 1
#define LWIP_RAW 0
#define LWIP_RAW 1
#define LWIP_DHCP 0
#define LWIP_AUTOIP 0
#define LWIP_SNMP 0
#define LWIP_SNMP 1
#define LWIP_IGMP 0
#define LWIP_DNS 0
#define LWIP_UDP 0
#define LWIP_UDP 1
#define LWIP_UDPLITE 0
@@ -96,6 +96,8 @@
#define PPPOS_SUPPORT 0
#define LWIP_NETIF_LOOPBACK 1
/*
---------------------------------------
---------- Debugging options ----------

View File

@@ -1,46 +0,0 @@
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "rosip.h"
#include <debug.h>
typedef struct netif* PNETIF;
void
LibIPInsertPacket(void *ifarg,
const void *const data,
const u32_t size)
{
struct pbuf *p;
ASSERT(ifarg);
ASSERT(data);
ASSERT(size > 0);
p = pbuf_alloc(PBUF_RAW, size, PBUF_RAM);
if (p)
{
ASSERT(p->tot_len == p->len);
ASSERT(p->len == size);
RtlCopyMemory(p->payload, data, p->len);
((PNETIF)ifarg)->input(p, (PNETIF)ifarg);
}
}
void
LibIPInitialize(void)
{
/* This completes asynchronously */
tcpip_init(NULL, NULL);
}
void
LibIPShutdown(void)
{
/* This is synchronous */
sys_shutdown();
}

View File

@@ -1,842 +0,0 @@
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "rosip.h"
#include <debug.h>
static const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
/* The way that lwIP does multi-threading is really not ideal for our purposes but
* we best go along with it unless we want another unstable TCP library. lwIP uses
* a thread called the "tcpip thread" which is the only one allowed to call raw API
* functions. Since this is the case, for each of our LibTCP* functions, we queue a request
* for a callback to "tcpip thread" which calls our LibTCP*Callback functions. Yes, this is
* a lot of unnecessary thread swapping and it could definitely be faster, but I don't want
* to going messing around in lwIP because I have no desire to create another mess like oskittcp */
extern KEVENT TerminationEvent;
extern NPAGED_LOOKASIDE_LIST MessageLookasideList;
extern NPAGED_LOOKASIDE_LIST QueueEntryLookasideList;
/* Required for ERR_T to NTSTATUS translation in receive error handling */
NTSTATUS TCPTranslateError(const err_t err);
void
LibTCPDumpPcb(PVOID SocketContext)
{
struct tcp_pcb *pcb = (struct tcp_pcb*)SocketContext;
unsigned int addr = ntohl(pcb->remote_ip.addr);
DbgPrint("\tState: %s\n", tcp_state_str[pcb->state]);
DbgPrint("\tRemote: (%d.%d.%d.%d, %d)\n",
(addr >> 24) & 0xFF,
(addr >> 16) & 0xFF,
(addr >> 8) & 0xFF,
addr & 0xFF,
pcb->remote_port);
}
static
void
LibTCPEmptyQueue(PCONNECTION_ENDPOINT Connection)
{
PLIST_ENTRY Entry;
PQUEUE_ENTRY qp = NULL;
ReferenceObject(Connection);
while (!IsListEmpty(&Connection->PacketQueue))
{
Entry = RemoveHeadList(&Connection->PacketQueue);
qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
/* We're in the tcpip thread here so this is safe */
pbuf_free(qp->p);
ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
}
DereferenceObject(Connection);
}
void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, struct pbuf *p)
{
PQUEUE_ENTRY qp;
qp = (PQUEUE_ENTRY)ExAllocateFromNPagedLookasideList(&QueueEntryLookasideList);
qp->p = p;
qp->Offset = 0;
ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry, &Connection->Lock);
}
PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection)
{
PLIST_ENTRY Entry;
PQUEUE_ENTRY qp = NULL;
if (IsListEmpty(&Connection->PacketQueue)) return NULL;
Entry = RemoveHeadList(&Connection->PacketQueue);
qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
return qp;
}
NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHAR RecvBuffer, UINT RecvLen, UINT *Received)
{
PQUEUE_ENTRY qp;
struct pbuf* p;
NTSTATUS Status;
UINT ReadLength, PayloadLength, Offset, Copied;
KIRQL OldIrql;
(*Received) = 0;
LockObject(Connection, &OldIrql);
if (!IsListEmpty(&Connection->PacketQueue))
{
while ((qp = LibTCPDequeuePacket(Connection)) != NULL)
{
p = qp->p;
/* Calculate the payload length first */
PayloadLength = p->tot_len;
PayloadLength -= qp->Offset;
Offset = qp->Offset;
/* Check if we're reading the whole buffer */
ReadLength = MIN(PayloadLength, RecvLen);
ASSERT(ReadLength != 0);
if (ReadLength != PayloadLength)
{
/* Save this one for later */
qp->Offset += ReadLength;
InsertHeadList(&Connection->PacketQueue, &qp->ListEntry);
qp = NULL;
}
UnlockObject(Connection, OldIrql);
Copied = pbuf_copy_partial(p, RecvBuffer, ReadLength, Offset);
ASSERT(Copied == ReadLength);
LockObject(Connection, &OldIrql);
/* Update trackers */
RecvLen -= ReadLength;
RecvBuffer += ReadLength;
(*Received) += ReadLength;
if (qp != NULL)
{
/* Use this special pbuf free callback function because we're outside tcpip thread */
pbuf_free_callback(qp->p);
ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
}
else
{
/* If we get here, it means we've filled the buffer */
ASSERT(RecvLen == 0);
}
ASSERT((*Received) != 0);
Status = STATUS_SUCCESS;
if (!RecvLen)
break;
}
}
else
{
if (Connection->ReceiveShutdown)
Status = Connection->ReceiveShutdownStatus;
else
Status = STATUS_PENDING;
}
UnlockObject(Connection, OldIrql);
return Status;
}
static
BOOLEAN
WaitForEventSafely(PRKEVENT Event)
{
PVOID WaitObjects[] = {Event, &TerminationEvent};
if (KeWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL) == STATUS_WAIT_0)
{
/* Signalled by the caller's event */
return TRUE;
}
else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */
{
/* Signalled by our termination event */
return FALSE;
}
}
static
err_t
InternalSendEventHandler(void *arg, PTCP_PCB pcb, const u16_t space)
{
/* Make sure the socket didn't get closed */
if (!arg) return ERR_OK;
TCPSendEventHandler(arg, space);
return ERR_OK;
}
static
err_t
InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err)
{
PCONNECTION_ENDPOINT Connection = arg;
/* Make sure the socket didn't get closed */
if (!arg)
{
if (p)
pbuf_free(p);
return ERR_OK;
}
if (p)
{
LibTCPEnqueuePacket(Connection, p);
tcp_recved(pcb, p->tot_len);
TCPRecvEventHandler(arg);
}
else if (err == ERR_OK)
{
/* Complete pending reads with 0 bytes to indicate a graceful closure,
* but note that send is still possible in this state so we don't close the
* whole socket here (by calling tcp_close()) as that would violate TCP specs
*/
Connection->ReceiveShutdown = TRUE;
Connection->ReceiveShutdownStatus = STATUS_SUCCESS;
/* If we already did a send shutdown, we're in TIME_WAIT so we can't use this PCB anymore */
if (Connection->SendShutdown)
{
Connection->SocketContext = NULL;
tcp_arg(pcb, NULL);
}
/* Indicate the graceful close event */
TCPRecvEventHandler(arg);
/* If the PCB is gone, clean up the connection */
if (Connection->SendShutdown)
{
TCPFinEventHandler(Connection, ERR_CLSD);
}
}
return ERR_OK;
}
/* This function MUST return an error value that is not ERR_ABRT or ERR_OK if the connection
* is not accepted to avoid leaking the new PCB */
static
err_t
InternalAcceptEventHandler(void *arg, PTCP_PCB newpcb, const err_t err)
{
/* Make sure the socket didn't get closed */
if (!arg)
return ERR_CLSD;
TCPAcceptEventHandler(arg, newpcb);
/* Set in LibTCPAccept (called from TCPAcceptEventHandler) */
if (newpcb->callback_arg)
return ERR_OK;
else
return ERR_CLSD;
}
static
err_t
InternalConnectEventHandler(void *arg, PTCP_PCB pcb, const err_t err)
{
/* Make sure the socket didn't get closed */
if (!arg)
return ERR_OK;
TCPConnectEventHandler(arg, err);
return ERR_OK;
}
static
void
InternalErrorEventHandler(void *arg, const err_t err)
{
PCONNECTION_ENDPOINT Connection = arg;
/* Make sure the socket didn't get closed */
if (!arg || Connection->SocketContext == NULL) return;
/* The PCB is dead now */
Connection->SocketContext = NULL;
/* Give them one shot to receive the remaining data */
Connection->ReceiveShutdown = TRUE;
Connection->ReceiveShutdownStatus = TCPTranslateError(err);
TCPRecvEventHandler(Connection);
/* Terminate the connection */
TCPFinEventHandler(Connection, err);
}
static
void
LibTCPSocketCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
ASSERT(msg);
msg->Output.Socket.NewPcb = tcp_new();
if (msg->Output.Socket.NewPcb)
{
tcp_arg(msg->Output.Socket.NewPcb, msg->Input.Socket.Arg);
tcp_err(msg->Output.Socket.NewPcb, InternalErrorEventHandler);
}
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
struct tcp_pcb *
LibTCPSocket(void *arg)
{
struct lwip_callback_msg *msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
struct tcp_pcb *ret;
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Socket.Arg = arg;
tcpip_callback_with_block(LibTCPSocketCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Socket.NewPcb;
else
ret = NULL;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return NULL;
}
static
void
LibTCPBindCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
PTCP_PCB pcb = msg->Input.Bind.Connection->SocketContext;
ASSERT(msg);
if (!msg->Input.Bind.Connection->SocketContext)
{
msg->Output.Bind.Error = ERR_CLSD;
goto done;
}
/* We're guaranteed that the local address is valid to bind at this point */
pcb->so_options |= SOF_REUSEADDR;
msg->Output.Bind.Error = tcp_bind(pcb,
msg->Input.Bind.IpAddress,
ntohs(msg->Input.Bind.Port));
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
err_t
LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
{
struct lwip_callback_msg *msg;
err_t ret;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Bind.Connection = Connection;
msg->Input.Bind.IpAddress = ipaddr;
msg->Input.Bind.Port = port;
tcpip_callback_with_block(LibTCPBindCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Bind.Error;
else
ret = ERR_CLSD;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return ERR_MEM;
}
static
void
LibTCPListenCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
ASSERT(msg);
if (!msg->Input.Listen.Connection->SocketContext)
{
msg->Output.Listen.NewPcb = NULL;
goto done;
}
msg->Output.Listen.NewPcb = tcp_listen_with_backlog((PTCP_PCB)msg->Input.Listen.Connection->SocketContext, msg->Input.Listen.Backlog);
if (msg->Output.Listen.NewPcb)
{
tcp_accept(msg->Output.Listen.NewPcb, InternalAcceptEventHandler);
}
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
PTCP_PCB
LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog)
{
struct lwip_callback_msg *msg;
PTCP_PCB ret;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Listen.Connection = Connection;
msg->Input.Listen.Backlog = backlog;
tcpip_callback_with_block(LibTCPListenCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Listen.NewPcb;
else
ret = NULL;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return NULL;
}
static
void
LibTCPSendCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
PTCP_PCB pcb = msg->Input.Send.Connection->SocketContext;
ULONG SendLength;
UCHAR SendFlags;
ASSERT(msg);
if (!msg->Input.Send.Connection->SocketContext)
{
msg->Output.Send.Error = ERR_CLSD;
goto done;
}
if (msg->Input.Send.Connection->SendShutdown)
{
msg->Output.Send.Error = ERR_CLSD;
goto done;
}
SendFlags = TCP_WRITE_FLAG_COPY;
SendLength = msg->Input.Send.DataLength;
if (tcp_sndbuf(pcb) == 0)
{
/* No buffer space so return pending */
msg->Output.Send.Error = ERR_INPROGRESS;
goto done;
}
else if (tcp_sndbuf(pcb) < SendLength)
{
/* We've got some room so let's send what we can */
SendLength = tcp_sndbuf(pcb);
/* Don't set the push flag */
SendFlags |= TCP_WRITE_FLAG_MORE;
}
msg->Output.Send.Error = tcp_write(pcb,
msg->Input.Send.Data,
SendLength,
SendFlags);
if (msg->Output.Send.Error == ERR_OK)
{
/* Queued successfully so try to send it */
tcp_output((PTCP_PCB)msg->Input.Send.Connection->SocketContext);
msg->Output.Send.Information = SendLength;
}
else if (msg->Output.Send.Error == ERR_MEM)
{
/* The queue is too long */
msg->Output.Send.Error = ERR_INPROGRESS;
}
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
err_t
LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe)
{
err_t ret;
struct lwip_callback_msg *msg;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Send.Connection = Connection;
msg->Input.Send.Data = dataptr;
msg->Input.Send.DataLength = len;
if (safe)
LibTCPSendCallback(msg);
else
tcpip_callback_with_block(LibTCPSendCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Send.Error;
else
ret = ERR_CLSD;
if (ret == ERR_OK)
*sent = msg->Output.Send.Information;
else
*sent = 0;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return ERR_MEM;
}
static
void
LibTCPConnectCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
err_t Error;
ASSERT(arg);
if (!msg->Input.Connect.Connection->SocketContext)
{
msg->Output.Connect.Error = ERR_CLSD;
goto done;
}
tcp_recv((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalRecvEventHandler);
tcp_sent((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalSendEventHandler);
Error = tcp_connect((PTCP_PCB)msg->Input.Connect.Connection->SocketContext,
msg->Input.Connect.IpAddress, ntohs(msg->Input.Connect.Port),
InternalConnectEventHandler);
msg->Output.Connect.Error = Error == ERR_OK ? ERR_INPROGRESS : Error;
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
err_t
LibTCPConnect(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
{
struct lwip_callback_msg *msg;
err_t ret;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Connect.Connection = Connection;
msg->Input.Connect.IpAddress = ipaddr;
msg->Input.Connect.Port = port;
tcpip_callback_with_block(LibTCPConnectCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
{
ret = msg->Output.Connect.Error;
}
else
ret = ERR_CLSD;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return ERR_MEM;
}
static
void
LibTCPShutdownCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
PTCP_PCB pcb = msg->Input.Shutdown.Connection->SocketContext;
if (!msg->Input.Shutdown.Connection->SocketContext)
{
msg->Output.Shutdown.Error = ERR_CLSD;
goto done;
}
/* LwIP makes the (questionable) assumption that SHUTDOWN_RDWR is equivalent to tcp_close().
* This assumption holds even if the shutdown calls are done separately (even through multiple
* WinSock shutdown() calls). This assumption means that lwIP has the right to deallocate our
* PCB without telling us if we shutdown TX and RX. To avoid these problems, we'll clear the
* socket context if we have called shutdown for TX and RX.
*/
if (msg->Input.Shutdown.shut_rx) {
msg->Output.Shutdown.Error = tcp_shutdown(pcb, TRUE, FALSE);
}
if (msg->Input.Shutdown.shut_tx) {
msg->Output.Shutdown.Error = tcp_shutdown(pcb, FALSE, TRUE);
}
if (!msg->Output.Shutdown.Error)
{
if (msg->Input.Shutdown.shut_rx)
{
msg->Input.Shutdown.Connection->ReceiveShutdown = TRUE;
msg->Input.Shutdown.Connection->ReceiveShutdownStatus = STATUS_FILE_CLOSED;
}
if (msg->Input.Shutdown.shut_tx)
msg->Input.Shutdown.Connection->SendShutdown = TRUE;
if (msg->Input.Shutdown.Connection->ReceiveShutdown &&
msg->Input.Shutdown.Connection->SendShutdown)
{
/* The PCB is not ours anymore */
msg->Input.Shutdown.Connection->SocketContext = NULL;
tcp_arg(pcb, NULL);
TCPFinEventHandler(msg->Input.Shutdown.Connection, ERR_CLSD);
}
}
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
err_t
LibTCPShutdown(PCONNECTION_ENDPOINT Connection, const int shut_rx, const int shut_tx)
{
struct lwip_callback_msg *msg;
err_t ret;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Shutdown.Connection = Connection;
msg->Input.Shutdown.shut_rx = shut_rx;
msg->Input.Shutdown.shut_tx = shut_tx;
tcpip_callback_with_block(LibTCPShutdownCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Shutdown.Error;
else
ret = ERR_CLSD;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return ERR_MEM;
}
static
void
LibTCPCloseCallback(void *arg)
{
struct lwip_callback_msg *msg = arg;
PTCP_PCB pcb = msg->Input.Close.Connection->SocketContext;
/* Empty the queue even if we're already "closed" */
LibTCPEmptyQueue(msg->Input.Close.Connection);
/* Check if we've already been closed */
if (msg->Input.Close.Connection->Closing)
{
msg->Output.Close.Error = ERR_OK;
goto done;
}
/* Enter "closing" mode if we're doing a normal close */
if (msg->Input.Close.Callback)
msg->Input.Close.Connection->Closing = TRUE;
/* Check if the PCB was already "closed" but the client doesn't know it yet */
if (!msg->Input.Close.Connection->SocketContext)
{
msg->Output.Close.Error = ERR_OK;
goto done;
}
/* Clear the PCB pointer and stop callbacks */
msg->Input.Close.Connection->SocketContext = NULL;
tcp_arg(pcb, NULL);
/* This may generate additional callbacks but we don't care,
* because they're too inconsistent to rely on */
msg->Output.Close.Error = tcp_close(pcb);
if (msg->Output.Close.Error)
{
/* Restore the PCB pointer */
msg->Input.Close.Connection->SocketContext = pcb;
msg->Input.Close.Connection->Closing = FALSE;
}
else if (msg->Input.Close.Callback)
{
TCPFinEventHandler(msg->Input.Close.Connection, ERR_CLSD);
}
done:
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
}
err_t
LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback)
{
err_t ret;
struct lwip_callback_msg *msg;
msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
if (msg)
{
KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
msg->Input.Close.Connection = Connection;
msg->Input.Close.Callback = callback;
if (safe)
LibTCPCloseCallback(msg);
else
tcpip_callback_with_block(LibTCPCloseCallback, msg, 1);
if (WaitForEventSafely(&msg->Event))
ret = msg->Output.Close.Error;
else
ret = ERR_CLSD;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;
}
return ERR_MEM;
}
void
LibTCPAccept(PTCP_PCB pcb, struct tcp_pcb *listen_pcb, void *arg)
{
ASSERT(arg);
tcp_arg(pcb, NULL);
tcp_recv(pcb, InternalRecvEventHandler);
tcp_sent(pcb, InternalSendEventHandler);
tcp_err(pcb, InternalErrorEventHandler);
tcp_arg(pcb, arg);
tcp_accepted(listen_pcb);
}
err_t
LibTCPGetHostName(PTCP_PCB pcb, struct ip_addr *const ipaddr, u16_t *const port)
{
if (!pcb)
return ERR_CLSD;
*ipaddr = pcb->local_ip;
*port = pcb->local_port;
return ERR_OK;
}
err_t
LibTCPGetPeerName(PTCP_PCB pcb, struct ip_addr * const ipaddr, u16_t * const port)
{
if (!pcb)
return ERR_CLSD;
*ipaddr = pcb->remote_ip;
*port = pcb->remote_port;
return ERR_OK;
}
void
LibTCPSetNoDelay(
PTCP_PCB pcb,
BOOLEAN Set)
{
if (Set)
pcb->flags |= TF_NODELAY;
else
pcb->flags &= ~TF_NODELAY;
}

View File

@@ -1,19 +1,17 @@
#include <ntifs.h>
#include "lwip/sys.h"
#include "lwip/tcp.h"
#include "lwip/pbuf.h"
#include "lwip/err.h"
#include "rosip.h"
#include <debug.h>
static LIST_ENTRY ThreadListHead;
static KSPIN_LOCK ThreadListLock;
KEVENT TerminationEvent;
NPAGED_LOOKASIDE_LIST MessageLookasideList;
NPAGED_LOOKASIDE_LIST QueueEntryLookasideList;
static LARGE_INTEGER StartTime;
@@ -99,6 +97,7 @@ sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
KeQuerySystemTime(&PreWaitTime);
RELEASE_SERIAL_MUTEX();
Status = KeWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
@@ -107,6 +106,7 @@ sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
FALSE,
timeout != 0 ? &LargeTimeout : NULL,
NULL);
ACQUIRE_SERIAL_MUTEX_NO_TO();
if (Status == STATUS_WAIT_0)
{
KeQuerySystemTime(&PostWaitTime);
@@ -118,6 +118,7 @@ sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
else if (Status == STATUS_WAIT_1)
{
/* DON'T remove ourselves from the thread list! */
RELEASE_SERIAL_MUTEX();
PsTerminateSystemThread(STATUS_SUCCESS);
/* We should never get here! */
@@ -194,6 +195,7 @@ sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
KeQuerySystemTime(&PreWaitTime);
RELEASE_SERIAL_MUTEX();
Status = KeWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
@@ -202,6 +204,7 @@ sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
FALSE,
timeout != 0 ? &LargeTimeout : NULL,
NULL);
ACQUIRE_SERIAL_MUTEX_NO_TO();
if (Status == STATUS_WAIT_0)
{
@@ -228,6 +231,7 @@ sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
else if (Status == STATUS_WAIT_1)
{
/* DON'T remove ourselves from the thread list! */
RELEASE_SERIAL_MUTEX();
PsTerminateSystemThread(STATUS_SUCCESS);
/* We should never get here! */
@@ -265,7 +269,9 @@ LwipThreadMain(PVOID Context)
ExInterlockedInsertHeadList(&ThreadListHead, &Container->ListEntry, &ThreadListLock);
ACQUIRE_SERIAL_MUTEX_NO_TO();
Container->ThreadFunction(Container->ThreadContext);
RELEASE_SERIAL_MUTEX();
KeAcquireSpinLock(&ThreadListLock, &OldIrql);
RemoveEntryList(&Container->ListEntry);
@@ -315,22 +321,9 @@ sys_init(void)
KeQuerySystemTime(&StartTime);
KeInitializeEvent(&TerminationEvent, NotificationEvent, FALSE);
KeInitializeMutex(&MTSerialMutex, 0);
ExInitializeNPagedLookasideList(&MessageLookasideList,
NULL,
NULL,
0,
sizeof(struct lwip_callback_msg),
LWIP_MESSAGE_TAG,
0);
ExInitializeNPagedLookasideList(&QueueEntryLookasideList,
NULL,
NULL,
0,
sizeof(QUEUE_ENTRY),
LWIP_QUEUE_TAG,
0);
ACQUIRE_SERIAL_MUTEX_NO_TO();
}
void
@@ -349,16 +342,17 @@ sys_shutdown(void)
if (Container->ThreadFunction)
{
RELEASE_SERIAL_MUTEX();
KeWaitForSingleObject(Container->Handle,
Executive,
KernelMode,
FALSE,
NULL);
ACQUIRE_SERIAL_MUTEX_NO_TO();
ZwClose(Container->Handle);
}
}
ExDeleteNPagedLookasideList(&MessageLookasideList);
ExDeleteNPagedLookasideList(&QueueEntryLookasideList);
}
RELEASE_SERIAL_MUTEX();
}