1 #include <windows.h>
2 #include <net/lan.h>
3 #include <iostream>
4 #include <string>
5 #include <ddk/ntddk.h>
6 #include <rosrtl/string.h>
7 
8 using std::string;
9 using std::cin;
10 using std::cout;
11 using std::cerr;
12 using std::endl;
13 
14 void display_row( char *data, int off, int len ) {
15     int i;
16 
17     printf( "%08x:", off );
18     for( i = off; i < len && i < off + 16; i++ ) {
19 	printf( " %02x", data[i] & 0xff );
20     }
21 
22     for( ; i < off + 16; i++ )
23 	printf("   ");
24 
25     printf( " -- " );
26 
27     for( i = off; i < len && i < off + 16; i++ ) {
28 	printf( "%c", (data[i] >= ' ' && data[i] <= '~') ? data[i] : '.' );
29     }
30 
31     printf( "\n" );
32 }
33 
34 void display_buffer( char *Packet, int ReadLen ) {
35     UINT PktLen;
36     for( PktLen = 0; PktLen < ReadLen; PktLen += 16 )
37 	display_row( Packet, PktLen, ReadLen );
38 }
39 
40 int byte_till_end( char *Packet, int PktLen ) {
41     int byte;
42     std::string word;
43 
44     cin >> word;
45     while( word != "end" ) {
46 	byte = strtoul( (string("0x") + word).c_str(), 0, 0 );
47 	fprintf( stderr, "Byte[%d]: %x\n", PktLen, byte & 0xff );
48 	Packet[PktLen++] = byte;
49 	cin >> word;
50     }
51 
52     return PktLen;
53 }
54 
55 /* Ethernet types. We swap constants so we can compare values at runtime
56    without swapping them there */
57 #define ETYPE_IPv4 WH2N(0x0800)
58 #define ETYPE_IPv6 WH2N(0x86DD)
59 #define ETYPE_ARP  WH2N(0x0806)
60 
61 extern "C"
62 NTSTATUS NTAPI NtCreateFile(
63     PHANDLE FileHandle,
64     ACCESS_MASK DesiredAccess,
65     POBJECT_ATTRIBUTES ObjectAttributes,
66     PIO_STATUS_BLOCK IoStatusBlock,
67     PLARGE_INTEGER AllocationSize,
68     ULONG FileAttributes,
69     ULONG ShareAccess,
70     ULONG CreateDisposition,
71     ULONG CreateOptions,
72     PVOID EaBuffer,
73     ULONG EaLength);
74 
75 int main( int argc, char **argv ) {
76     string word;
77     HANDLE LanFile;
78     OBJECT_ATTRIBUTES Attributes;
79     UNICODE_STRING LanDevice;
80     IO_STATUS_BLOCK Iosb;
81     HANDLE Event;
82     PFILE_FULL_EA_INFORMATION EaBuffer;
83     NTSTATUS Status;
84     DWORD On = 1, PktLen;
85     CHAR Packet[1600];
86     PLAN_PACKET_HEADER Hdr = (PLAN_PACKET_HEADER)Packet;
87     PLAN_ADDRESS Addr = (PLAN_ADDRESS)Packet;
88     USHORT TypesToListen[] = { ETYPE_IPv4, ETYPE_IPv6, ETYPE_ARP };
89     UINT EaLength = LAN_EA_INFO_SIZE(sizeof(TypesToListen)/sizeof(USHORT));
90 
91     Status = NtCreateEvent(&Event,
92 			   EVENT_ALL_ACCESS,
93 			   NULL,
94 			   0,
95 			   0 );
96 
97     RtlInitUnicodeString( &LanDevice, L"\\Device\\Lan" );
98 
99     InitializeObjectAttributes( &Attributes,
100 				&LanDevice,
101 				OBJ_CASE_INSENSITIVE,
102 				NULL,
103 				NULL );
104 
105     EaBuffer = (PFILE_FULL_EA_INFORMATION)calloc( EaLength, 1 );
106     LAN_FILL_EA_INFO(EaBuffer,sizeof(TypesToListen)/sizeof(USHORT),
107 		     TypesToListen);
108 
109     Status = ZwCreateFile( &LanFile,
110 			   SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE |
111 			   GENERIC_EXECUTE,
112 			   &Attributes,
113 			   &Iosb,
114 			   NULL,
115 			   FILE_ATTRIBUTE_NORMAL,
116 			   FILE_SHARE_READ | FILE_SHARE_WRITE,
117 			   FILE_OPEN_IF,
118 			   FILE_SYNCHRONOUS_IO_NONALERT,
119 			   EaBuffer,
120 			   EaLength );
121 
122     if( !NT_SUCCESS(Status) ) {
123 	cerr << "Could not open lan device " << Status << "\n";
124 	return 1;
125     }
126 
127     Status = DeviceIoControl( LanFile,
128 			      IOCTL_IF_BUFFERED_MODE,
129 			      &On,
130 			      sizeof(On),
131 			      0,
132 			      0,
133 			      &PktLen,
134 			      NULL );
135 
136     if( !Status ) {
137 	cerr << "Could not turn on buffered mode " << Status << "\n";
138 	return 1;
139     }
140 
141     while( cin >> word ) {
142 	if( word == "end" ) {
143 	    NtClose( LanFile );
144 	    return 0;
145 	} else if( word == "enum" ) {
146 	    Status = DeviceIoControl( LanFile,
147 				      IOCTL_IF_ENUM_ADAPTERS,
148 				      NULL,
149 				      0,
150 				      Packet,
151 				      sizeof(Packet),
152 				      &PktLen,
153 				      NULL );
154 
155 	    cout << "EnumAdapters: " << Status << "\n";
156 	    if( Status )
157 		display_buffer( Packet, PktLen );
158 	} else if( word == "query" ) {
159 	    cin >> PktLen;
160 
161 	    Status = DeviceIoControl( LanFile,
162 				      IOCTL_IF_ADAPTER_INFO,
163 				      &PktLen,
164 				      sizeof(PktLen),
165 				      Packet,
166 				      sizeof(Packet),
167 				      &PktLen,
168 				      NULL );
169 
170 	    cout << "QueryAdapterInfo: " << Status << "\n";
171 	    if( Status )
172 		display_buffer( Packet, PktLen );
173 	} else if( word == "send" ) {
174 	    cin >> Hdr->Fixed.Adapter
175 		>> Hdr->Fixed.AddressType
176 		>> Hdr->Fixed.AddressLen
177 		>> Hdr->Fixed.PacketType;
178 	    Hdr->Fixed.Mdl = NULL;
179 	    PktLen = byte_till_end( Packet, Hdr->Address - (PCHAR)Hdr );
180 	    Status = NtWriteFile( LanFile,
181 				  NULL,
182 				  NULL,
183 				  NULL,
184 				  &Iosb,
185 				  Packet,
186 				  PktLen,
187 				  NULL,
188 				  NULL );
189 
190 	    cout << "NtWriteFile: " << Status << "\n";
191 	} else if( word == "recv" ) {
192 	    ULONG ReadLen;
193 	    Status = NtReadFile( LanFile,
194 				 Event,
195 				 NULL,
196 				 NULL,
197 				 &Iosb,
198 				 Packet,
199 				 sizeof(Packet),
200 				 NULL,
201 				 NULL );
202 	    cout << "NtReadFile: " << Status << "\n";
203 	    if( Status == STATUS_PENDING ) {
204 		LARGE_INTEGER Timeout = { 0 };
205 		Status = NtWaitForSingleObject( Event, 1, &Timeout );
206 	    }
207 
208 	    ReadLen = Iosb.Information;
209 
210 	    if( Status == STATUS_SUCCESS ) {
211 		cout << "Read " << ReadLen << " bytes\n";
212 		display_buffer( Packet, ReadLen );
213 	    }
214 	}
215     }
216 
217     return 0;
218 }
219