mirror of
https://github.com/reactos/reactos
synced 2025-10-06 08:22:58 +02:00
Compare commits
29 Commits
taskmgr_ac
...
GSoC_2016/
Author | SHA1 | Date | |
---|---|---|---|
|
d9fceab325 | ||
|
5c170dba4a | ||
|
cafd261b58 | ||
|
53d6c153c1 | ||
|
5c00746715 | ||
|
0e5f1a8172 | ||
|
b307304597 | ||
|
5b8f12afd5 | ||
|
ae49055b2d | ||
|
fa552bc182 | ||
|
fe828c7869 | ||
|
9152dcd395 | ||
|
0419b23db6 | ||
|
1ff4744677 | ||
|
ee238ae9a7 | ||
|
7c78e13710 | ||
|
f4ffbd00d1 | ||
|
6b24b98072 | ||
|
04571e1dbb | ||
|
24ee5b3396 | ||
|
606af0c099 | ||
|
b9556ea719 | ||
|
3ef725b96b | ||
|
55c372b2c3 | ||
|
b26dc390cc | ||
|
19adc74ebd | ||
|
3411247830 | ||
|
11059493a3 | ||
|
67ff49b0a5 |
@@ -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)
|
||||
|
11
base/applications/network/tcpclient/CMakeLists.txt
Normal file
11
base/applications/network/tcpclient/CMakeLists.txt
Normal 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)
|
122
base/applications/network/tcpclient/main.c
Normal file
122
base/applications/network/tcpclient/main.c
Normal 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;
|
||||
}
|
11
base/applications/network/tcpserver/CMakeLists.txt
Normal file
11
base/applications/network/tcpserver/CMakeLists.txt
Normal 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)
|
147
base/applications/network/tcpserver/main.c
Normal file
147
base/applications/network/tcpserver/main.c
Normal 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;
|
||||
}
|
@@ -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)
|
||||
|
@@ -1,5 +0,0 @@
|
||||
DIRS= datalink \
|
||||
network \
|
||||
transport \
|
||||
tcpip
|
||||
|
2622
drivers/network/tcpip/address.c
Normal file
2622
drivers/network/tcpip/address.c
Normal file
File diff suppressed because it is too large
Load Diff
157
drivers/network/tcpip/address.h
Normal file
157
drivers/network/tcpip/address.h
Normal 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);
|
12
drivers/network/tcpip/connection.c
Normal file
12
drivers/network/tcpip/connection.c
Normal 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>
|
||||
|
@@ -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
|
324
drivers/network/tcpip/entities.c
Normal file
324
drivers/network/tcpip/entities.c
Normal 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;
|
||||
}
|
33
drivers/network/tcpip/entities.h
Normal file
33
drivers/network/tcpip/entities.h
Normal 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);
|
@@ -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 */
|
@@ -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 */
|
@@ -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))
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 );
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 );
|
@@ -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_ */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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 */
|
@@ -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);
|
@@ -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 */
|
@@ -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; \
|
||||
}
|
@@ -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 */
|
@@ -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 */
|
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
NTSTATUS TcpipWaitForSingleObject( PVOID Object,
|
||||
KWAIT_REASON Reason,
|
||||
KPROCESSOR_MODE WaitMode,
|
||||
BOOLEAN Alertable,
|
||||
PLARGE_INTEGER Timeout );
|
251
drivers/network/tcpip/information.c
Normal file
251
drivers/network/tcpip/information.c
Normal 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;
|
||||
}
|
17
drivers/network/tcpip/information.h
Normal file
17
drivers/network/tcpip/information.h
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
NTSTATUS
|
||||
TcpIpQueryInformation(
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
TcpIpQueryKernelInformation(
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
TcpIpSetInformation(
|
||||
_Inout_ PIRP Irp
|
||||
);
|
233
drivers/network/tcpip/interface.c
Normal file
233
drivers/network/tcpip/interface.c
Normal 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;
|
||||
}
|
40
drivers/network/tcpip/interface.h
Normal file
40
drivers/network/tcpip/interface.h
Normal 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);
|
596
drivers/network/tcpip/main.c
Normal file
596
drivers/network/tcpip/main.c
Normal 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();
|
||||
}
|
458
drivers/network/tcpip/ndis_lwip.c
Normal file
458
drivers/network/tcpip/ndis_lwip.c
Normal 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);
|
||||
}
|
8
drivers/network/tcpip/ndis_lwip.h
Normal file
8
drivers/network/tcpip/ndis_lwip.h
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
NTSTATUS
|
||||
TcpIpRegisterNdisProtocol(void);
|
||||
|
||||
void
|
||||
TcpIpUnregisterNdisProtocol(void);
|
@@ -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
|
37
drivers/network/tcpip/precomp.h
Normal file
37
drivers/network/tcpip/precomp.h
Normal 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__ */
|
@@ -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
|
42
drivers/network/tcpip/stubs.c
Normal file
42
drivers/network/tcpip/stubs.c
Normal 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;
|
||||
}
|
65
drivers/network/tcpip/tcp.c
Normal file
65
drivers/network/tcpip/tcp.c
Normal 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;
|
||||
}
|
||||
|
10
drivers/network/tcpip/tcp.h
Normal file
10
drivers/network/tcpip/tcp.h
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
void
|
||||
TcpIpInitializeTcp(void);
|
||||
|
||||
BOOLEAN
|
||||
AllocateTcpPort(
|
||||
_Inout_ USHORT* PortNumber,
|
||||
_In_ BOOLEAN Shared);
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
@@ -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 */
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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 );
|
||||
}
|
@@ -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 ) {
|
||||
}
|
@@ -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 */
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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"
|
@@ -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
|
@@ -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;
|
||||
}
|
@@ -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 );
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "regtests.h"
|
||||
|
||||
_SetupOnce()
|
||||
{
|
||||
}
|
@@ -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
|
@@ -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");
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -39,5 +39,4 @@ void
|
||||
sys_arch_unprotect(sys_prot_t lev);
|
||||
|
||||
void
|
||||
sys_shutdown(void);
|
||||
|
||||
sys_shutdown(void);
|
@@ -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
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -158,6 +158,8 @@ struct tcpip_msg {
|
||||
} msg;
|
||||
};
|
||||
|
||||
extern KMUTEX MTSerialMutex;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -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,
|
||||
|
@@ -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 ----------
|
||||
|
@@ -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();
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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();
|
||||
}
|
Reference in New Issue
Block a user