mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
First shot at ip lib test app.
svn path=/trunk/; revision=11178
This commit is contained in:
parent
4e21459b33
commit
184c8d80f1
2 changed files with 502 additions and 0 deletions
476
reactos/apps/tests/iptest/iptest.cpp
Normal file
476
reactos/apps/tests/iptest/iptest.cpp
Normal file
|
@ -0,0 +1,476 @@
|
|||
#include <iostream>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
extern "C" {
|
||||
typedef unsigned short u_short;
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ddk/tdi.h>
|
||||
#include <ddk/tdikrnl.h>
|
||||
#include <ddk/tdiinfo.h>
|
||||
#include <ddk/ndis.h>
|
||||
#include <titypes.h>
|
||||
#include <ip.h>
|
||||
#include <tcp.h>
|
||||
#include <receive.h>
|
||||
#include <lan.h>
|
||||
#include <routines.h>
|
||||
};
|
||||
|
||||
/* Undis */
|
||||
extern "C" VOID ExpInitLookasideLists();
|
||||
|
||||
std::list<std::string> output_packets;
|
||||
DWORD DebugTraceLevel = 0x7fffffff;
|
||||
PVOID GlobalBufferPool, GlobalPacketPool;
|
||||
|
||||
#define MAX_DG_SIZE 16384
|
||||
|
||||
char hwaddr[6] = { 0x08, 0x00, 0x20, 0x0b, 0xb7, 0xbb };
|
||||
|
||||
char hdr[14] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00 };
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
|
||||
void display_row( char *data, int off, int len ) {
|
||||
int i;
|
||||
|
||||
printf( "%08x:", off );
|
||||
for( i = off; i < len && i < off + 16; i++ ) {
|
||||
printf( " %02x", data[i] & 0xff );
|
||||
}
|
||||
|
||||
printf( " -- " );
|
||||
|
||||
for( i = off; i < len && i < off + 16; i++ ) {
|
||||
printf( "%c", (data[i] >= ' ') ? data[i] : '.' );
|
||||
}
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
void connect_complete( void *context, NTSTATUS status, unsigned long count ) {
|
||||
printf( "Connection: status %x\n", status );
|
||||
}
|
||||
|
||||
void receive_complete( void *context, NTSTATUS status, unsigned long count ) {
|
||||
printf( "Receive: status %s (bytes %d)\n", status, count );
|
||||
if( !status && count ) {
|
||||
for( int off = 0; off < count; off += 16 ) {
|
||||
display_row( (char *)context, off, count );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
class SocketObject {
|
||||
public:
|
||||
virtual ~SocketObject() { }
|
||||
virtual int send( char *buf, int len, int *bytes,
|
||||
struct sockaddr_in *si ) = 0;
|
||||
virtual int recv( char *buf, int len, int *bytes,
|
||||
struct sockaddr_in *si ) = 0;
|
||||
};
|
||||
|
||||
UINT TdiAddressSizeFromType( UINT AddressType ) {
|
||||
switch( AddressType ) {
|
||||
case TDI_ADDRESS_TYPE_IP:
|
||||
return sizeof(TA_IP_ADDRESS);
|
||||
default:
|
||||
KeBugCheck( 0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS TdiBuildNullConnectionInfoInPlace
|
||||
( PTDI_CONNECTION_INFORMATION ConnInfo,
|
||||
ULONG Type )
|
||||
/*
|
||||
* FUNCTION: Builds a NULL TDI connection information structure
|
||||
* ARGUMENTS:
|
||||
* ConnectionInfo = Address of buffer to place connection information
|
||||
* Type = TDI style address type (TDI_ADDRESS_TYPE_XXX).
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
ULONG TdiAddressSize;
|
||||
|
||||
TdiAddressSize = TdiAddressSizeFromType(Type);
|
||||
|
||||
RtlZeroMemory(ConnInfo,
|
||||
sizeof(TDI_CONNECTION_INFORMATION) +
|
||||
TdiAddressSize);
|
||||
|
||||
ConnInfo->OptionsLength = sizeof(ULONG);
|
||||
ConnInfo->RemoteAddressLength = 0;
|
||||
ConnInfo->RemoteAddress = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS TdiBuildNullConnectionInfo
|
||||
( PTDI_CONNECTION_INFORMATION *ConnectionInfo,
|
||||
ULONG Type )
|
||||
/*
|
||||
* FUNCTION: Builds a NULL TDI connection information structure
|
||||
* ARGUMENTS:
|
||||
* ConnectionInfo = Address of buffer pointer to allocate connection
|
||||
* information in
|
||||
* Type = TDI style address type (TDI_ADDRESS_TYPE_XXX).
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
PTDI_CONNECTION_INFORMATION ConnInfo;
|
||||
ULONG TdiAddressSize;
|
||||
NTSTATUS Status;
|
||||
|
||||
TdiAddressSize = TdiAddressSizeFromType(Type);
|
||||
|
||||
ConnInfo = (PTDI_CONNECTION_INFORMATION)
|
||||
ExAllocatePool(NonPagedPool,
|
||||
sizeof(TDI_CONNECTION_INFORMATION) +
|
||||
TdiAddressSize);
|
||||
if (!ConnInfo)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Status = TdiBuildNullConnectionInfoInPlace( ConnInfo, Type );
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
ExFreePool( ConnInfo );
|
||||
else
|
||||
*ConnectionInfo = ConnInfo;
|
||||
|
||||
ConnInfo->RemoteAddress = (PTA_ADDRESS)&ConnInfo[1];
|
||||
ConnInfo->RemoteAddressLength = TdiAddressSize;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) {
|
||||
UINT AddrLen = 2 * sizeof( ULONG ) + Addr->Address[0].AddressLength;
|
||||
printf("AddrLen %x\n", AddrLen);
|
||||
return AddrLen;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TdiBuildConnectionInfoInPlace
|
||||
( PTDI_CONNECTION_INFORMATION ConnectionInfo,
|
||||
PTA_ADDRESS Address ) {
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
RtlCopyMemory( ConnectionInfo->RemoteAddress,
|
||||
Address,
|
||||
ConnectionInfo->RemoteAddressLength );
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TdiBuildConnectionInfo
|
||||
( PTDI_CONNECTION_INFORMATION *ConnectionInfo,
|
||||
PTA_ADDRESS Address ) {
|
||||
NTSTATUS Status = TdiBuildNullConnectionInfo( ConnectionInfo,
|
||||
Address->AddressType );
|
||||
|
||||
if( NT_SUCCESS(Status) )
|
||||
TdiBuildConnectionInfoInPlace( *ConnectionInfo, Address );
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
class TCPSocketObject : public SocketObject {
|
||||
public:
|
||||
TCPSocketObject( std::string host, int port, NTSTATUS *status ) {
|
||||
TA_IP_ADDRESS ConnectTo;
|
||||
PTDI_CONNECTION_INFORMATION ConnInfo;
|
||||
|
||||
ConnectTo.TAAddressCount = 1;
|
||||
ConnectTo.Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
|
||||
ConnectTo.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
||||
ConnectTo.Address[0].Address[0].sin_port = htons(port);
|
||||
ConnectTo.Address[0].Address[0].in_addr = 0x6a020a0a;
|
||||
|
||||
TdiBuildConnectionInfo( &ConnInfo, (PTA_ADDRESS)&ConnectTo );
|
||||
|
||||
Connection = TCPAllocateConnectionEndpoint( NULL );
|
||||
*status = TCPSocket( Connection,
|
||||
AF_INET,
|
||||
SOCK_STREAM, IPPROTO_TCP );
|
||||
if( !*status )
|
||||
*status = TCPConnect( Connection,
|
||||
ConnInfo,
|
||||
NULL,
|
||||
connect_complete,
|
||||
NULL );
|
||||
}
|
||||
|
||||
~TCPSocketObject() {
|
||||
TCPClose( Connection );
|
||||
if( Connection ) TCPFreeConnectionEndpoint( Connection );
|
||||
}
|
||||
|
||||
int send( char *buf, int len, int *bytes, struct sockaddr_in *si ) {
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if( Connection )
|
||||
Status = TCPSendData( Connection,
|
||||
buf,
|
||||
len,
|
||||
(PULONG)bytes,
|
||||
0 );
|
||||
return Status;
|
||||
}
|
||||
|
||||
int recv( char *buf, int len, int *bytes, struct sockaddr_in *si ) {
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if( Connection )
|
||||
Status = TCPSendData( Connection,
|
||||
buf,
|
||||
len,
|
||||
(PULONG)bytes,
|
||||
0 );
|
||||
return Status;
|
||||
}
|
||||
|
||||
private:
|
||||
PCONNECTION_ENDPOINT Connection;
|
||||
};
|
||||
|
||||
VOID SendPacket( PVOID Context,
|
||||
PNDIS_PACKET NdisPacket,
|
||||
UINT Offset,
|
||||
PVOID LinkAddress,
|
||||
USHORT Type ) {
|
||||
PCHAR DataOut;
|
||||
PUCHAR Addr = (PUCHAR)LinkAddress;
|
||||
UINT Size;
|
||||
std::string output_packet;
|
||||
|
||||
printf( "Sending packet: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5] );
|
||||
|
||||
GetDataPtr( NdisPacket, Offset, &DataOut, &Size );
|
||||
for( int off = 0; off < Size; off += 16 ) {
|
||||
display_row( DataOut, off, Size );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
output_packet += std::string( hwaddr, sizeof(hwaddr) );
|
||||
output_packet += std::string( (char *)LinkAddress, sizeof(hwaddr) );
|
||||
output_packet += (char)(Type >> 8);
|
||||
output_packet += (char)Type;
|
||||
output_packet += std::string( DataOut + Offset, Size - Offset );
|
||||
|
||||
output_packets.push_back( output_packet );
|
||||
}
|
||||
|
||||
#if 0
|
||||
UINT CopyBufferToBufferChain
|
||||
( PNDIS_BUFFER DstBuffer, UINT DstOffset, PCHAR SrcData, UINT Length ) {
|
||||
assert( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
int asock = INVALID_SOCKET, selret, dgrecv, fromsize, err, port = 5001;
|
||||
int bytes, adapter_id, mtu, speed;
|
||||
char datagram[MAX_DG_SIZE];
|
||||
struct fd_set readf;
|
||||
struct timeval tv;
|
||||
struct sockaddr_in addr_from = { AF_INET }, addr_to;
|
||||
std::string word, cmdin, host;
|
||||
std::list<std::string>::iterator i;
|
||||
WSADATA wsadata;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING RegistryUnicodePath;
|
||||
PCONNECTION_ENDPOINT Connection;
|
||||
PIP_INTERFACE Interface;
|
||||
IP_PACKET IPPacket;
|
||||
LLIP_BIND_INFO BindInfo;
|
||||
SocketObject *S = NULL;
|
||||
|
||||
RtlInitUnicodeString
|
||||
( &RegistryUnicodePath,
|
||||
L"\\SYSTEM\\CurrentControlSet\\Services"
|
||||
L"\\Tcpip" );
|
||||
|
||||
ExpInitLookasideLists();
|
||||
|
||||
WSAStartup( 0x101, &wsadata );
|
||||
|
||||
if( argc > 1 ) port = atoi(argv[1]);
|
||||
|
||||
IPStartup( &RegistryUnicodePath );
|
||||
|
||||
BindInfo.Context = NULL;
|
||||
BindInfo.HeaderSize = sizeof(ETH_HEADER);
|
||||
BindInfo.MTU = 1500; /* MTU for ethernet */
|
||||
BindInfo.Address = (PUCHAR)hwaddr;
|
||||
BindInfo.AddressLength = sizeof(hwaddr);
|
||||
BindInfo.Transmit = SendPacket;
|
||||
|
||||
IPCreateInterface( &BindInfo );
|
||||
|
||||
asock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
|
||||
addr_from.sin_port = htons( port );
|
||||
|
||||
if( bind( asock, (struct sockaddr *)&addr_from, sizeof( addr_from ) ) ) {
|
||||
printf( "Bind error\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( true ) {
|
||||
FD_ZERO( &readf );
|
||||
FD_SET( asock, &readf );
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
selret = select( asock + 1, &readf, NULL, NULL, &tv );
|
||||
|
||||
if( FD_ISSET( asock, &readf ) ) {
|
||||
fromsize = sizeof( addr_from );
|
||||
dgrecv = recvfrom( asock, datagram, sizeof(datagram), 0,
|
||||
(struct sockaddr *)&addr_from, &fromsize );
|
||||
|
||||
if( datagram[0] == 'C' && datagram[1] == 'M' &&
|
||||
datagram[2] == 'D' && datagram[3] == ' ' ) {
|
||||
int theport, bytes, recvret, off, bytin;
|
||||
struct sockaddr_in nam;
|
||||
std::string faddr, word;
|
||||
std::istringstream
|
||||
cmdin( std::string( datagram + 4, dgrecv - 4 ) );
|
||||
|
||||
cmdin >> word;
|
||||
|
||||
/* UDP Section */
|
||||
if( word == "udpsocket" ) {
|
||||
/* TCP Section */
|
||||
} else if( word == "tcpsocket" ) {
|
||||
cmdin >> host >> port;
|
||||
S = new TCPSocketObject( host, port, &Status );
|
||||
fprintf( stderr, "Socket: Result %x\n", Status );
|
||||
} else if( word == "close" ) {
|
||||
TCPClose( Connection );
|
||||
TCPFreeConnectionEndpoint( Connection );
|
||||
} else if( word == "type" ) {
|
||||
std::string therest = &cmdin.str()[word.size()];
|
||||
char* p = &therest[0];
|
||||
p += strspn ( p, " \t" );
|
||||
char* src = p;
|
||||
char* dst = p;
|
||||
while ( *src )
|
||||
{
|
||||
char c = *src++;
|
||||
if ( c == '\r' || c == '\n' ) break;
|
||||
if ( c == '\\' )
|
||||
{
|
||||
c = *src++;
|
||||
switch ( c )
|
||||
{
|
||||
case 'b': c = '\b'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
}
|
||||
}
|
||||
*dst++ = c;
|
||||
}
|
||||
*dst = '\0';
|
||||
if( S )
|
||||
err = S->send( p, strlen(p), &bytes, NULL );
|
||||
if( err > 0 ) { bytin = err; err = 0; }
|
||||
|
||||
if( err )
|
||||
fprintf ( stderr, "OskitTCPConnect: error %d\n",
|
||||
err );
|
||||
else {
|
||||
printf ( "wrote %d bytes\n", bytin );
|
||||
}
|
||||
} else if( word == "send" ) {
|
||||
off = 0;
|
||||
while( cmdin >> word ) {
|
||||
datagram[off++] =
|
||||
atoi( (std::string("0x") + word).c_str() );
|
||||
}
|
||||
|
||||
if( (err = S->send( datagram, off, &bytin, NULL )) != 0 ) {
|
||||
fprintf( stderr, "OskitTCPConnect: error %d\n", err );
|
||||
} else {
|
||||
printf( "wrote %d bytes\n", bytin );
|
||||
}
|
||||
} else if( word == "recv" ) {
|
||||
cmdin >> bytes;
|
||||
|
||||
if( (err = S->recv( datagram,
|
||||
sizeof(datagram),
|
||||
&bytes,
|
||||
NULL )) != 0 ) {
|
||||
fprintf( stderr, "OskitTCPRecv: error %d\n", err );
|
||||
}
|
||||
|
||||
/* Misc section */
|
||||
} else if( word == "end" ) {
|
||||
return 0;
|
||||
}
|
||||
} else if( dgrecv > 14 ) {
|
||||
addr_to = addr_from;
|
||||
|
||||
if( datagram[12] == 8 && datagram[13] == 6 ) {
|
||||
/* Answer arp query */
|
||||
char laddr[4];
|
||||
/* Mark patch as to the previous sender */
|
||||
memcpy( datagram + 32, datagram + 6, 6 );
|
||||
memcpy( datagram, datagram + 6, 6 );
|
||||
/* Mark packet as from us */
|
||||
memcpy( datagram + 22, hwaddr, 6 );
|
||||
memcpy( datagram + 6, hwaddr, 6 );
|
||||
/* Swap inet addresses */
|
||||
memcpy( laddr, datagram + 28, 4 );
|
||||
memcpy( datagram + 28, datagram + 38, 4 );
|
||||
memcpy( datagram + 38, laddr, 4 );
|
||||
/* Set reply opcode */
|
||||
datagram[21] = 2;
|
||||
|
||||
err = sendto( asock, datagram, dgrecv, 0,
|
||||
(struct sockaddr *)&addr_to,
|
||||
sizeof(addr_to) );
|
||||
|
||||
if( err != 0 )
|
||||
printf( "sendto: %d\n", err );
|
||||
} else {
|
||||
memcpy( hdr, datagram + 6, 6 );
|
||||
memcpy( hdr + 6, datagram, 6 );
|
||||
memcpy( hdr + 12, datagram + 12, 2 );
|
||||
IPPacket.Header = datagram;
|
||||
IPPacket.Data = datagram + 14;
|
||||
IPPacket.TotalSize = dgrecv;
|
||||
IPReceive( Interface, &IPPacket );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPTimeout(NULL, NULL, NULL, NULL);
|
||||
|
||||
for( i = output_packets.begin(); i != output_packets.end(); i++ ) {
|
||||
err = sendto( asock, i->c_str(), i->size(), 0,
|
||||
(struct sockaddr *)&addr_to, sizeof(addr_to) );
|
||||
|
||||
fprintf( stderr, "** SENDING PACKET %d bytes **\n", i->size() );
|
||||
|
||||
if( err != 0 )
|
||||
printf( "sendto: %d\n", err );
|
||||
}
|
||||
|
||||
output_packets.clear();
|
||||
}
|
||||
}
|
||||
|
26
reactos/apps/tests/iptest/makefile
Normal file
26
reactos/apps/tests/iptest/makefile
Normal file
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# $Id: makefile,v 1.1 2004/10/04 04:26:00 arty Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET_NORC = yes
|
||||
|
||||
TARGET_TYPE = program
|
||||
|
||||
TARGET_APPTYPE = console
|
||||
|
||||
TARGET_NAME = iptest
|
||||
|
||||
TARGET_SDKLIBS = ws2_32.a ip.a oskittcp.a undis.a ntdll.a
|
||||
|
||||
TARGET_OBJECTS = iptest.o
|
||||
|
||||
TARGET_CPPFLAGS = -I$(PATH_TO_TOP)/drivers/lib/oskittcp/include -I$(PATH_TO_TOP)/w32api/include -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/drivers/net/tcpip/include -g
|
||||
|
||||
TARGET_GCCLIBS = stdc++
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# EOF
|
Loading…
Reference in a new issue