Figured out a way to split the "address" part of the buffer from the packet
data itself. This makes for a much cleaner interface. sys/divert.c dll/divert.c include/*.h DivertRecv and DivertSend now use IOCTLs instead of reads/writes. The 'address' parameter is passed by pointer to the driver, which writes directly to it (after sanity checks). This means that the data buffer now only contains the packet, which help to avoid some messy code. examples/*/*.c Update the examples to reflect the new API. doc/divert.html Update the documentation to reflect the new API.
This commit is contained in:
+39
-51
@@ -439,24 +439,21 @@ DivertDriverInstallExit:
|
||||
*/
|
||||
extern HANDLE DivertOpen(const char *filter)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct divert_message_s header;
|
||||
struct divert_ioctl_filter_s filter[DIVERT_FILTER_MAXLEN];
|
||||
} ioctl;
|
||||
struct divert_ioctl_s ioctl;
|
||||
struct divert_ioctl_filter_s ioctl_filter[DIVERT_FILTER_MAXLEN];
|
||||
UINT8 filter_len;
|
||||
DWORD err, iolen;
|
||||
HANDLE handle;
|
||||
|
||||
// Parse the filter:
|
||||
if (!DivertCompileFilter(filter, ioctl.filter, &filter_len))
|
||||
if (!DivertCompileFilter(filter, ioctl_filter, &filter_len))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#ifdef DIVERT_DEBUG
|
||||
DivertFilterDump(ioctl.filter, filter_len);
|
||||
DivertFilterDump(ioctl_filter, filter_len);
|
||||
#endif
|
||||
|
||||
// Attempt to open the Divert device:
|
||||
@@ -485,13 +482,13 @@ extern HANDLE DivertOpen(const char *filter)
|
||||
}
|
||||
|
||||
// Set the filter:
|
||||
ioctl.header.version = DIVERT_VERSION;
|
||||
ioctl.header.magic = DIVERT_MAGIC;
|
||||
ioctl.header.reserved = 0x0;
|
||||
ioctl.version = DIVERT_VERSION;
|
||||
ioctl.magic = DIVERT_MAGIC;
|
||||
ioctl.reserved = 0x0;
|
||||
ioctl.arg = NULL;
|
||||
if (!DeviceIoControl(handle, IOCTL_DIVERT_SET_FILTER, &ioctl,
|
||||
sizeof(struct divert_message_s) +
|
||||
filter_len*sizeof(struct divert_ioctl_filter_s), NULL, 0, &iolen,
|
||||
NULL))
|
||||
sizeof(ioctl), ioctl_filter,
|
||||
filter_len*sizeof(struct divert_ioctl_filter_s), &iolen, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -504,31 +501,24 @@ extern HANDLE DivertOpen(const char *filter)
|
||||
/*
|
||||
* Receive a packet from the Divert device.
|
||||
*/
|
||||
extern BOOL DivertRecv(HANDLE handle, PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
UINT *readlen)
|
||||
extern BOOL DivertRecv(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
PDIVERT_ADDRESS addr, UINT *readlen)
|
||||
{
|
||||
divert_message_t message;
|
||||
struct divert_ioctl_s ioctl;
|
||||
DWORD readlen0;
|
||||
|
||||
if (!ReadFile(handle, (PVOID)pPacket, (DWORD)packetLen, &readlen0, NULL))
|
||||
|
||||
ioctl.version = DIVERT_VERSION;
|
||||
ioctl.magic = DIVERT_MAGIC;
|
||||
ioctl.reserved = 0x0;
|
||||
ioctl.arg = (PVOID)addr;
|
||||
if (!DeviceIoControl(handle, IOCTL_DIVERT_RECV, &ioctl, sizeof(ioctl),
|
||||
pPacket, packetLen, &readlen0, NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (readlen0 <= sizeof(DIVERT_PACKET))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
message = (divert_message_t)pPacket->Reserved;
|
||||
if (message->magic != DIVERT_MAGIC ||
|
||||
message->version != DIVERT_VERSION)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
if (readlen != NULL)
|
||||
{
|
||||
*readlen = readlen0;
|
||||
*readlen = (UINT)readlen0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -536,27 +526,26 @@ extern BOOL DivertRecv(HANDLE handle, PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
/*
|
||||
* Send (inject) a packet to the Divert device.
|
||||
*/
|
||||
extern BOOL DivertSend(HANDLE handle, PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
UINT *writelen)
|
||||
extern BOOL DivertSend(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
PDIVERT_ADDRESS addr, UINT *writelen)
|
||||
{
|
||||
divert_message_t message;
|
||||
struct divert_ioctl_s ioctl;
|
||||
DWORD writelen0;
|
||||
|
||||
if (packetLen <= sizeof(DIVERT_PACKET))
|
||||
|
||||
ioctl.version = DIVERT_VERSION;
|
||||
ioctl.magic = DIVERT_MAGIC;
|
||||
ioctl.reserved = 0x0;
|
||||
ioctl.arg = (PVOID)addr;
|
||||
if (!DeviceIoControl(handle, IOCTL_DIVERT_SEND, &ioctl, sizeof(ioctl),
|
||||
pPacket, packetLen, &writelen0, NULL))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
message = (divert_message_t)pPacket->Reserved;
|
||||
message->magic = DIVERT_MAGIC;
|
||||
message->version = DIVERT_VERSION;
|
||||
message->reserved = 0x0;
|
||||
if (writelen == NULL)
|
||||
if (writelen != NULL)
|
||||
{
|
||||
writelen = &writelen0;
|
||||
*writelen = writelen0;
|
||||
}
|
||||
return WriteFile(handle, (PVOID)pPacket, (DWORD)packetLen,
|
||||
(DWORD *)writelen, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1564,7 +1553,7 @@ static void DivertFilterDump(divert_ioctl_filter_t filter, UINT8 len)
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
extern BOOL DivertHelperParse(PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
extern BOOL DivertHelperParse(PVOID pPacket, UINT packetLen,
|
||||
PDIVERT_IPHDR *ppIpHdr, PDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
PDIVERT_ICMPHDR *ppIcmpHdr, PDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
PDIVERT_TCPHDR *ppTcpHdr, PDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
|
||||
@@ -1582,13 +1571,12 @@ extern BOOL DivertHelperParse(PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
UINT data_len = 0;
|
||||
BOOL success;
|
||||
|
||||
if (pPacket == NULL ||
|
||||
packetLen < sizeof(DIVERT_PACKET) + sizeof(UINT8))
|
||||
if (pPacket == NULL || packetLen < sizeof(UINT8))
|
||||
{
|
||||
goto DivertHelperParseExit;
|
||||
}
|
||||
data = DIVERT_PACKET_DATA(pPacket);
|
||||
data_len = packetLen - sizeof(DIVERT_PACKET);
|
||||
data = pPacket;
|
||||
data_len = packetLen;
|
||||
|
||||
ip_header = (PDIVERT_IPHDR)data;
|
||||
switch (ip_header->Version)
|
||||
@@ -1730,7 +1718,7 @@ DivertHelperParseExit:
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern UINT DivertHelperCalcChecksums(PDIVERT_PACKET pPacket, UINT packetLen,
|
||||
extern UINT DivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
UINT64 flags)
|
||||
{
|
||||
DIVERT_PSEUDOHDR pseudo_header;
|
||||
|
||||
+69
-52
@@ -33,7 +33,7 @@
|
||||
<li><a href="#uninstalling">4. Uninstalling</a></li>
|
||||
<li><a href="#programming_api">5. Programming API</a></li>
|
||||
<ul>
|
||||
<li><a href="#divert_packet">5.1 DIVERT_PACKET</a></li>
|
||||
<li><a href="#divert_address">5.1 DIVERT_ADDRESS</a></li>
|
||||
<li><a href="#divert_open">5.2 DivertOpen</a></li>
|
||||
<li><a href="#divert_recv">5.3 DivertRecv</a></li>
|
||||
<li><a href="#divert_send">5.4 DivertSend</a></li>
|
||||
@@ -175,24 +175,24 @@ To use the <tt>divert</tt> package, a program/application must:
|
||||
<li> Link or dynamically load the <tt>divert.dll</tt> dynamic link library.
|
||||
</ol>
|
||||
|
||||
<a name="divert_packet"><h3>5.1 DIVERT_PACKET</h3></a>
|
||||
<a name="divert_address"><h3>5.1 DIVERT_ADDRESS</h3></a>
|
||||
<table border="1" cellpadding="5"><tr><td>
|
||||
<pre>
|
||||
typedef struct
|
||||
{
|
||||
UINT8 Reserved[7];
|
||||
UINT8 Direction;
|
||||
UINT32 IfIdx;
|
||||
UINT32 SubIfIdx;
|
||||
} <b>DIVERT_PACKET</b>, *<b>PDIVERT_PACKET</b>;
|
||||
UINT8 Direction;
|
||||
} <b>DIVERT_ADDRESS</b>, *<b>PDIVERT_ADDRESS</b>;
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
<dl><dd>
|
||||
<p>
|
||||
<b>Fields</b>
|
||||
<ul>
|
||||
<li> <tt>Reserved</tt>: Reserved for internal use. This field may be
|
||||
left uninitialized.</li>
|
||||
<li> <tt>IfIdx</tt>: The interface index on which the packet arrived
|
||||
(for inbound packets), or is to be sent (for outbound packets).</li>
|
||||
<li> <tt>SubIfIdx</tt>: The sub-interface index for <tt>IfIdx</tt>.</li>
|
||||
<li> <tt>Direction</tt>: The packet's direction.
|
||||
The possible values are
|
||||
<ul>
|
||||
@@ -201,15 +201,12 @@ packets.</li>
|
||||
<li> <tt>DIVERT_PACKET_DIRECTION_INBOUND</tt> with value 1 for inbound
|
||||
packets.</li>
|
||||
</ul></li>
|
||||
<li> <tt>IfIdx</tt>: The interface index on which the packet arrived
|
||||
(for inbound packets), or is to be sent (for outbound packets).</li>
|
||||
<li> <tt>SubIfIdx</tt>: The sub-interface index for <tt>IfIdx</tt>.</li>
|
||||
</ul>
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
The <tt>DIVERT_PACKET</tt> structure represents a captured or injected packet.
|
||||
The packet's contents, i.e., IP/TCP/UDP headers and data, immediately follow
|
||||
a DIVERT_PACKET header in memory.
|
||||
The <tt>DIVERT_ADDRESS</tt> structure represents where a captured or injected
|
||||
packet is being sent.
|
||||
This includes the packets network interfaces, and the packet's direction.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -264,8 +261,9 @@ This model helps ensure the driver is not loaded unless it is required to be.
|
||||
<pre>
|
||||
BOOL <b>DivertRecv</b>(
|
||||
__in HANDLE handle,
|
||||
__out PDIVERT_PACKET pPacket,
|
||||
__out PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out PDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *recvLen
|
||||
);
|
||||
</pre>
|
||||
@@ -276,12 +274,9 @@ BOOL <b>DivertRecv</b>(
|
||||
<ul>
|
||||
<li> <tt>handle</tt>: A valid <tt>divert</tt> handle created by
|
||||
<tt>DivertOpen()</tt>.</li>
|
||||
<li> <tt>pPacket</tt>: A pointer to a <tt>DIVERT_PACKET</tt> header and free
|
||||
space to write the captured packet to.
|
||||
The free space is assumed to immediately follow the
|
||||
<tt>DIVERT_PACKET</tt> header.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the <tt>DIVERT_PACKET</tt>
|
||||
header and the free space.</li>
|
||||
<li> <tt>pPacket</tt>: A buffer for the captured packet.</li>
|
||||
<li> <tt>packetLen</tt>: The length of the buffer <tt>pPacket</tt>.</li>
|
||||
<li> <tt>pAddr</tt>: The <tt>DIVERT_ADDRESS</tt> of the captured packet.</li>
|
||||
<li> <tt>recvLen</tt>: The total number of bytes written to <tt>pPacket</tt>.
|
||||
Can be <tt>NULL</tt> if this information is not required.</li>
|
||||
</ul>
|
||||
@@ -295,24 +290,14 @@ Use <tt>GetLastError()</tt> to get the reason for the error.
|
||||
Receives a diverted packet that matches the filter passed to
|
||||
<tt>DivertOpen()</tt>.
|
||||
The received packet is guaranteed to match the filter.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>pPacket</tt> parameter is intended to be a buffer large enough to
|
||||
store a <tt>DIVERT_PACKET</tt> header, and enough space to store the diverted
|
||||
packet.
|
||||
This would typically be achieved by the following declarations:
|
||||
<pre>
|
||||
char packet[MAX_SIZE]; // packet buffer space
|
||||
PDIVERT_PACKET pPacket = (PDIVERT_PACKET)packet; // cast packet to a PDIVERT_PACKET
|
||||
...
|
||||
if (!DivertRecv(handle, pPacket, sizeof(packet), &recvLen))
|
||||
{
|
||||
// Recv error
|
||||
}
|
||||
...
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
</p><p>
|
||||
The contents of the captured packet are written to <tt>pPacket</tt>.
|
||||
If the captured packet is larger than the <tt>pPacket</tt> buffer length,
|
||||
then the packet will be truncated.
|
||||
If <tt>recvLen</tt> is non-<tt>NULL</tt>, then the total number of bytes
|
||||
written to <tt>pPacket</tt> is placed there.
|
||||
The address of the captured packet is written to <tt>pAddr</tt>.
|
||||
</p><p>
|
||||
An application should call <tt>DivertRecv()</tt> <i>as soon as possible</i>
|
||||
after a successful call to <tt>DivertOpen()</tt>.
|
||||
When a <tt>divert</tt> handle is open, any packet that matches the filter will
|
||||
@@ -332,8 +317,9 @@ as possible.
|
||||
<pre>
|
||||
BOOL <b>DivertSend</b>(
|
||||
__in HANDLE handle,
|
||||
__in PDIVERT_PACKET pPacket,
|
||||
__in PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__in PDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *sendLen
|
||||
);
|
||||
</pre>
|
||||
@@ -344,12 +330,9 @@ BOOL <b>DivertSend</b>(
|
||||
<ul>
|
||||
<li> <tt>handle</tt>: A valid <tt>divert</tt> handle created by
|
||||
<tt>DivertOpen()</tt>.</li>
|
||||
<li> <tt>pPacket</tt>: A pointer to a <tt>DIVERT_PACKET</tt> header and the
|
||||
packet to be injected.
|
||||
The packet is assumed to immediately follow the
|
||||
<tt>DIVERT_PACKET</tt> header.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the <tt>DIVERT_PACKET</tt>
|
||||
header and packet to be injected.</li>
|
||||
<li> <tt>pPacket</tt>: A buffer containing the packet to be injected.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the buffer <tt>pPacket</tt>.</li>
|
||||
<li> <tt>pAddr</tt>: The <tt>DIVERT_ADDRESS</tt> for the injected packet.</li>
|
||||
<li> <tt>sendLen</tt>: The total number of bytes injected.
|
||||
Can be <tt>NULL</tt> if this information is not required.</li>
|
||||
</ul>
|
||||
@@ -365,7 +348,7 @@ The injected packet may be one received from <tt>DivertRecv()</tt>, or a
|
||||
modified version, or a completely new packet.
|
||||
Injected packets cannot be read again by <tt>DivertRecv()</tt>.
|
||||
</p><p>
|
||||
The <tt>DIVERT_PACKET</tt> header determines how the packet is injected.
|
||||
The <tt>pAddr</tt> parameter determines how the packet is injected.
|
||||
If the <tt>Direction</tt> field is <tt>DIVERT_PACKET_DIRECTION_OUTBOUND</tt>,
|
||||
the packet is injected into the <i>outbound</i> path (i.e. a packet leaving
|
||||
this computer).
|
||||
@@ -602,7 +585,7 @@ UDP header definition.
|
||||
<table border="1" cellpadding="5"><tr><td>
|
||||
<pre>
|
||||
BOOL <b>DivertHelperParse</b>(
|
||||
__in PDIVERT_PACKET pPacket,
|
||||
__in PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt PDIVERT_IPHDR *ppIpHdr,
|
||||
__out_opt PDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
@@ -620,8 +603,7 @@ BOOL <b>DivertHelperParse</b>(
|
||||
<b>Parameters</b><br>
|
||||
<ul>
|
||||
<li> <tt>pPacket</tt>: The packet to be parsed.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the packet and the
|
||||
<tt>DIVERT_PACKET</tt> header.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the packet <tt>pPacket</tt>.</li>
|
||||
<li> <tt>ppIpHdr</tt>: Output pointer to a <tt>DIVERT_IPHDR</tt>.</li>
|
||||
<li> <tt>ppIpv6Hdr</tt>: Output pointer to a <tt>DIVERT_IPV6HDR</tt>.</li>
|
||||
<li> <tt>ppIcmpHdr</tt>: Output pointer to a <tt>DIVERT_ICMPHDR</tt>.</li>
|
||||
@@ -662,7 +644,7 @@ themselves.
|
||||
<table border="1" cellpadding="5"><tr><td>
|
||||
<pre>
|
||||
UINT <b>DivertHelperCalcChecksums</b>(
|
||||
__inout PDIVERT_PACKET pPacket,
|
||||
__inout PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__in UINT64 flags
|
||||
);
|
||||
@@ -673,8 +655,7 @@ UINT <b>DivertHelperCalcChecksums</b>(
|
||||
<b>Parameters</b><br>
|
||||
<ul>
|
||||
<li> <tt>pPacket</tt>: The packet to be modified.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the packet and the
|
||||
<tt>DIVERT_PACKET</tt> header.</li>
|
||||
<li> <tt>packetLen</tt>: The total length of the packet <tt>pPacket</tt>.</li>
|
||||
<li> <tt>flags</tt>: One or more of the following flags:
|
||||
<ul>
|
||||
<li> <tt>DIVERT_HELPER_NO_IP_CHECKSUM</tt>: Do not calculate the IPv4
|
||||
@@ -902,6 +883,42 @@ They are
|
||||
efficient as it could be.
|
||||
In the future we plan to rectify this.
|
||||
</ul>
|
||||
</p><p>
|
||||
All of the samples use some variant of the following basic template for
|
||||
<tt>divert</tt> applications.
|
||||
The basic idea is to open a <tt>divert</tt> handle, then enter a
|
||||
capture-modify-reinject loop:
|
||||
<pre>
|
||||
HANDLE handle; // Divert handle
|
||||
DIVERT_ADDRESS addr; // Packet address
|
||||
char packet[MAXBUF]; // Packet buffer
|
||||
UINT packetLen;
|
||||
|
||||
handle = DivertOpen("..."); // Open some filter
|
||||
if (handle == INVALID_HANDLE_VALUE);
|
||||
{
|
||||
// Handle error
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Main capture-modify-inject loop:
|
||||
while (TRUE)
|
||||
{
|
||||
if (!DivertRecv(handle, packet, sizeof(packet), &addr, &packetLen))
|
||||
{
|
||||
// Handle recv error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Modify packet.
|
||||
|
||||
if (!DivertSend(handle, packet, packetLen, &addr, NULL))
|
||||
{
|
||||
// Handle send error
|
||||
continue;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
+11
-15
@@ -47,16 +47,14 @@ int main(int argc, char **argv)
|
||||
UINT i;
|
||||
char filter[MAXBUF];
|
||||
char packet[MAXBUF];
|
||||
PDIVERT_PACKET ppacket = (PDIVERT_PACKET)packet;
|
||||
UINT ppacket_len;
|
||||
UINT packet_len;
|
||||
DIVERT_ADDRESS addr;
|
||||
PDIVERT_IPHDR ip_header;
|
||||
PDIVERT_IPV6HDR ipv6_header;
|
||||
PDIVERT_ICMPHDR icmp_header;
|
||||
PDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PDIVERT_TCPHDR tcp_header;
|
||||
PDIVERT_UDPHDR udp_header;
|
||||
UINT8 *data;
|
||||
UINT data_len;
|
||||
|
||||
// Concat all command line args into a filter string.
|
||||
flen = 0;
|
||||
@@ -96,7 +94,7 @@ int main(int argc, char **argv)
|
||||
while (TRUE)
|
||||
{
|
||||
// Read a matching packet.
|
||||
if (!DivertRecv(handle, ppacket, sizeof(packet), &ppacket_len))
|
||||
if (!DivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -104,14 +102,14 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// Re-inject the matching packet.
|
||||
if (!DivertSend(handle, ppacket, ppacket_len, NULL))
|
||||
if (!DivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
// Print info about the matching packet.
|
||||
DivertHelperParse(ppacket, ppacket_len, &ip_header, &ipv6_header,
|
||||
DivertHelperParse(packet, packet_len, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
|
||||
NULL);
|
||||
if (ip_header == NULL && ipv6_header == NULL)
|
||||
@@ -123,7 +121,7 @@ int main(int argc, char **argv)
|
||||
putchar('\n');
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("Packet [Direction=%u IfIdx=%u SubIfIdx=%u]\n",
|
||||
ppacket->Direction, ppacket->IfIdx, ppacket->SubIfIdx);
|
||||
addr.Direction, addr.IfIdx, addr.SubIfIdx);
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr;
|
||||
@@ -208,26 +206,24 @@ int main(int argc, char **argv)
|
||||
ntohs(udp_header->Length), ntohs(udp_header->Checksum));
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
data = DIVERT_PACKET_DATA(ppacket);
|
||||
data_len = ppacket_len - sizeof(DIVERT_PACKET);
|
||||
for (i = 0; i < data_len; i++)
|
||||
for (i = 0; i < packet_len; i++)
|
||||
{
|
||||
if (i % 20 == 0)
|
||||
{
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("%.2X", (unsigned)data[i]);
|
||||
printf("%.2X", (UINT8)packet[i]);
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_BLUE);
|
||||
for (i = 0; i < data_len; i++)
|
||||
for (i = 0; i < packet_len; i++)
|
||||
{
|
||||
if (i % 40 == 0)
|
||||
{
|
||||
printf("\n\t");
|
||||
}
|
||||
if (isprint(data[i]))
|
||||
if (isprint(packet[i]))
|
||||
{
|
||||
putchar(data[i]);
|
||||
putchar(packet[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -46,38 +46,26 @@
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
DIVERT_PACKET divert;
|
||||
DIVERT_IPHDR ip;
|
||||
} PACKET, *PPACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DIVERT_PACKET divert;
|
||||
DIVERT_IPV6HDR ipv6;
|
||||
} PACKETV6, *PPACKETV6;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PACKET header;
|
||||
DIVERT_IPHDR ip;
|
||||
DIVERT_TCPHDR tcp;
|
||||
} TCPPACKET, *PTCPPACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PACKETV6 header;
|
||||
DIVERT_IPV6HDR ipv6;
|
||||
DIVERT_TCPHDR tcp;
|
||||
} TCPV6PACKET, *PTCPV6PACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PACKET header;
|
||||
DIVERT_IPHDR ip;
|
||||
DIVERT_ICMPHDR icmp;
|
||||
UINT8 data[];
|
||||
} ICMPPACKET, *PICMPPACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PACKETV6 header;
|
||||
DIVERT_IPV6HDR ipv6;
|
||||
DIVERT_ICMPV6HDR icmpv6;
|
||||
UINT8 data[];
|
||||
} ICMPV6PACKET, *PICMPV6PACKET;
|
||||
@@ -85,10 +73,10 @@ typedef struct
|
||||
/*
|
||||
* Prototypes.
|
||||
*/
|
||||
static void PacketIpInit(PPACKET packet);
|
||||
static void PacketIpInit(PDIVERT_IPHDR packet);
|
||||
static void PacketIpTcpInit(PTCPPACKET packet);
|
||||
static void PacketIpIcmpInit(PICMPPACKET packet);
|
||||
static void PacketIpv6Init(PPACKETV6 packet);
|
||||
static void PacketIpv6Init(PDIVERT_IPV6HDR packet);
|
||||
static void PacketIpv6TcpInit(PTCPV6PACKET packet);
|
||||
static void PacketIpv6Icmpv6Init(PICMPV6PACKET packet);
|
||||
|
||||
@@ -102,8 +90,8 @@ int main(int argc, char **argv)
|
||||
UINT i;
|
||||
char filter[MAXBUF];
|
||||
char packet[MAXBUF];
|
||||
PDIVERT_PACKET ppacket = (PDIVERT_PACKET)packet;
|
||||
UINT ppacket_len;
|
||||
UINT packet_len;
|
||||
DIVERT_ADDRESS recv_addr, send_addr;
|
||||
PDIVERT_IPHDR ip_header;
|
||||
PDIVERT_IPV6HDR ipv6_header;
|
||||
PDIVERT_ICMPHDR icmp_header;
|
||||
@@ -151,7 +139,7 @@ int main(int argc, char **argv)
|
||||
resetv6->tcp.Rst = 1;
|
||||
resetv6->tcp.Ack = 1;
|
||||
PacketIpv6Icmpv6Init(dnrv6);
|
||||
dnrv6->header.ipv6.Length = htons(sizeof(DIVERT_ICMPV6HDR) + 4 +
|
||||
dnrv6->ipv6.Length = htons(sizeof(DIVERT_ICMPV6HDR) + 4 +
|
||||
sizeof(DIVERT_IPV6HDR) + sizeof(DIVERT_TCPHDR));
|
||||
dnrv6->icmpv6.Type = 1; // Destination not reachable.
|
||||
dnrv6->icmpv6.Code = 4; // Port not reachable.
|
||||
@@ -177,14 +165,15 @@ int main(int argc, char **argv)
|
||||
while (TRUE)
|
||||
{
|
||||
// Read a matching packet.
|
||||
if (!DivertRecv(handle, ppacket, sizeof(packet), &ppacket_len))
|
||||
if (!DivertRecv(handle, packet, sizeof(packet), &recv_addr,
|
||||
&packet_len))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Print info about the matching packet.
|
||||
DivertHelperParse(ppacket, ppacket_len, &ip_header, &ipv6_header,
|
||||
DivertHelperParse(packet, packet_len, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
|
||||
&payload_len);
|
||||
if (ip_header == NULL && ipv6_header == NULL)
|
||||
@@ -266,11 +255,8 @@ int main(int argc, char **argv)
|
||||
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
reset->header.divert.IfIdx = ppacket->IfIdx;
|
||||
reset->header.divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
reset->header.divert.Direction = !ppacket->Direction;
|
||||
reset->header.ip.SrcAddr = ip_header->DstAddr;
|
||||
reset->header.ip.DstAddr = ip_header->SrcAddr;
|
||||
reset->ip.SrcAddr = ip_header->DstAddr;
|
||||
reset->ip.DstAddr = ip_header->SrcAddr;
|
||||
reset->tcp.SrcPort = tcp_header->DstPort;
|
||||
reset->tcp.DstPort = tcp_header->SrcPort;
|
||||
reset->tcp.SeqNum =
|
||||
@@ -280,10 +266,12 @@ int main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + 1):
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)reset,
|
||||
sizeof(TCPPACKET), 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)reset,
|
||||
sizeof(TCPPACKET), NULL))
|
||||
DivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET), 0);
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
if (!DivertSend(handle, (PVOID)reset, sizeof(TCPPACKET),
|
||||
&send_addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send TCP reset (%d)\n",
|
||||
GetLastError());
|
||||
@@ -292,13 +280,10 @@ int main(int argc, char **argv)
|
||||
|
||||
if (ipv6_header != NULL)
|
||||
{
|
||||
resetv6->header.divert.IfIdx = ppacket->IfIdx;
|
||||
resetv6->header.divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
resetv6->header.divert.Direction = !ppacket->Direction;
|
||||
memcpy(resetv6->header.ipv6.SrcAddr, ipv6_header->DstAddr,
|
||||
sizeof(resetv6->header.ipv6.SrcAddr));
|
||||
memcpy(resetv6->header.ipv6.DstAddr, ipv6_header->SrcAddr,
|
||||
sizeof(resetv6->header.ipv6.DstAddr));
|
||||
memcpy(resetv6->ipv6.SrcAddr, ipv6_header->DstAddr,
|
||||
sizeof(resetv6->ipv6.SrcAddr));
|
||||
memcpy(resetv6->ipv6.DstAddr, ipv6_header->SrcAddr,
|
||||
sizeof(resetv6->ipv6.DstAddr));
|
||||
resetv6->tcp.SrcPort = tcp_header->DstPort;
|
||||
resetv6->tcp.DstPort = tcp_header->SrcPort;
|
||||
resetv6->tcp.SeqNum =
|
||||
@@ -308,10 +293,13 @@ int main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + 1):
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)resetv6,
|
||||
sizeof(TCPV6PACKET), 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)resetv6,
|
||||
sizeof(TCPV6PACKET), NULL))
|
||||
DivertHelperCalcChecksums((PVOID)resetv6, sizeof(TCPV6PACKET),
|
||||
0);
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
if (!DivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET),
|
||||
&send_addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send TCP (IPV6) "
|
||||
"reset (%d)\n", GetLastError());
|
||||
@@ -331,16 +319,15 @@ int main(int argc, char **argv)
|
||||
UINT icmp_length = ip_header->HdrLength*sizeof(UINT32) + 8;
|
||||
memcpy(dnr->data, ip_header, icmp_length);
|
||||
icmp_length += sizeof(ICMPPACKET);
|
||||
dnr->header.divert.IfIdx = ppacket->IfIdx;
|
||||
dnr->header.divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
dnr->header.divert.Direction =
|
||||
DIVERT_PACKET_DIRECTION_OUTBOUND;
|
||||
dnr->header.ip.Length =
|
||||
htons(icmp_length - sizeof(DIVERT_PACKET));
|
||||
dnr->header.ip.SrcAddr = ip_header->DstAddr;
|
||||
dnr->header.ip.DstAddr = ip_header->SrcAddr;
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)dnr, icmp_length, 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)dnr, icmp_length,
|
||||
dnr->ip.Length = htons((UINT16)icmp_length);
|
||||
dnr->ip.SrcAddr = ip_header->DstAddr;
|
||||
dnr->ip.DstAddr = ip_header->SrcAddr;
|
||||
|
||||
DivertHelperCalcChecksums((PVOID)dnr, icmp_length, 0);
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = DIVERT_PACKET_DIRECTION_OUTBOUND;
|
||||
if (!DivertSend(handle, (PVOID)dnr, icmp_length, &send_addr,
|
||||
NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send ICMP message "
|
||||
@@ -354,18 +341,17 @@ int main(int argc, char **argv)
|
||||
sizeof(DIVERT_TCPHDR);
|
||||
memcpy(dnrv6->data, ipv6_header, icmpv6_length);
|
||||
icmpv6_length += sizeof(ICMPV6PACKET);
|
||||
dnrv6->header.divert.IfIdx = ppacket->IfIdx;
|
||||
dnrv6->header.divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
dnrv6->header.divert.Direction =
|
||||
DIVERT_PACKET_DIRECTION_OUTBOUND;
|
||||
memcpy(dnrv6->header.ipv6.SrcAddr, ipv6_header->DstAddr,
|
||||
sizeof(dnrv6->header.ipv6.SrcAddr));
|
||||
memcpy(dnrv6->header.ipv6.DstAddr, ipv6_header->SrcAddr,
|
||||
sizeof(dnrv6->header.ipv6.DstAddr));
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)dnrv6, icmpv6_length,
|
||||
0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)dnrv6, icmpv6_length,
|
||||
NULL))
|
||||
memcpy(dnrv6->ipv6.SrcAddr, ipv6_header->DstAddr,
|
||||
sizeof(dnrv6->ipv6.SrcAddr));
|
||||
memcpy(dnrv6->ipv6.DstAddr, ipv6_header->SrcAddr,
|
||||
sizeof(dnrv6->ipv6.DstAddr));
|
||||
|
||||
DivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length, 0);
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = DIVERT_PACKET_DIRECTION_OUTBOUND;
|
||||
if (!DivertSend(handle, (PVOID)dnrv6, icmpv6_length,
|
||||
&send_addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send ICMPv6 message "
|
||||
"(%d)\n", GetLastError());
|
||||
@@ -379,13 +365,13 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Initialize a PACKET.
|
||||
*/
|
||||
static void PacketIpInit(PPACKET packet)
|
||||
static void PacketIpInit(PDIVERT_IPHDR packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(PACKET));
|
||||
packet->ip.Version = 4;
|
||||
packet->ip.HdrLength = sizeof(DIVERT_IPHDR) / sizeof(UINT32);
|
||||
packet->ip.Id = ntohs(0xDEAD);
|
||||
packet->ip.TTL = 64;
|
||||
memset(packet, 0, sizeof(DIVERT_IPHDR));
|
||||
packet->Version = 4;
|
||||
packet->HdrLength = sizeof(DIVERT_IPHDR) / sizeof(UINT32);
|
||||
packet->Id = ntohs(0xDEAD);
|
||||
packet->TTL = 64;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -394,10 +380,9 @@ static void PacketIpInit(PPACKET packet)
|
||||
static void PacketIpTcpInit(PTCPPACKET packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(TCPPACKET));
|
||||
PacketIpInit(&packet->header);
|
||||
packet->header.ip.Length = htons(sizeof(TCPPACKET) -
|
||||
sizeof(DIVERT_PACKET));
|
||||
packet->header.ip.Protocol = IPPROTO_TCP;
|
||||
PacketIpInit(&packet->ip);
|
||||
packet->ip.Length = htons(sizeof(TCPPACKET));
|
||||
packet->ip.Protocol = IPPROTO_TCP;
|
||||
packet->tcp.HdrLength = sizeof(DIVERT_TCPHDR) / sizeof(UINT32);
|
||||
}
|
||||
|
||||
@@ -407,18 +392,18 @@ static void PacketIpTcpInit(PTCPPACKET packet)
|
||||
static void PacketIpIcmpInit(PICMPPACKET packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(ICMPPACKET));
|
||||
PacketIpInit(&packet->header);
|
||||
packet->header.ip.Protocol = IPPROTO_ICMP;
|
||||
PacketIpInit(&packet->ip);
|
||||
packet->ip.Protocol = IPPROTO_ICMP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a PACKETV6.
|
||||
*/
|
||||
static void PacketIpv6Init(PPACKETV6 packet)
|
||||
static void PacketIpv6Init(PDIVERT_IPV6HDR packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(PACKETV6));
|
||||
packet->ipv6.Version = 6;
|
||||
packet->ipv6.HopLimit = 64;
|
||||
memset(packet, 0, sizeof(DIVERT_IPV6HDR));
|
||||
packet->Version = 6;
|
||||
packet->HopLimit = 64;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -427,9 +412,9 @@ static void PacketIpv6Init(PPACKETV6 packet)
|
||||
static void PacketIpv6TcpInit(PTCPV6PACKET packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(TCPV6PACKET));
|
||||
PacketIpv6Init(&packet->header);
|
||||
packet->header.ipv6.Length = htons(sizeof(DIVERT_TCPHDR));
|
||||
packet->header.ipv6.NextHdr = IPPROTO_TCP;
|
||||
PacketIpv6Init(&packet->ipv6);
|
||||
packet->ipv6.Length = htons(sizeof(DIVERT_TCPHDR));
|
||||
packet->ipv6.NextHdr = IPPROTO_TCP;
|
||||
packet->tcp.HdrLength = sizeof(DIVERT_TCPHDR) / sizeof(UINT32);
|
||||
}
|
||||
|
||||
@@ -439,7 +424,7 @@ static void PacketIpv6TcpInit(PTCPV6PACKET packet)
|
||||
static void PacketIpv6Icmpv6Init(PICMPV6PACKET packet)
|
||||
{
|
||||
memset(packet, 0, sizeof(ICMPV6PACKET));
|
||||
PacketIpv6Init(&packet->header);
|
||||
packet->header.ipv6.NextHdr = IPPROTO_ICMPV6;
|
||||
PacketIpv6Init(&packet->ipv6);
|
||||
packet->ipv6.NextHdr = IPPROTO_ICMPV6;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ typedef struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
DIVERT_PACKET divert;
|
||||
DIVERT_IPHDR ip;
|
||||
DIVERT_TCPHDR tcp;
|
||||
} PACKET, *PPACKET;
|
||||
@@ -105,9 +104,9 @@ static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data,
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle;
|
||||
DIVERT_ADDRESS addr;
|
||||
UINT8 packet[MAXBUF];
|
||||
PDIVERT_PACKET ppacket = (PDIVERT_PACKET)packet;
|
||||
UINT ppacket_len;
|
||||
UINT packet_len;
|
||||
PDIVERT_IPHDR ip_header;
|
||||
PDIVERT_TCPHDR tcp_header;
|
||||
PVOID payload;
|
||||
@@ -142,8 +141,7 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
PacketInit(&blockpage->header);
|
||||
blockpage->header.ip.Length =
|
||||
htons(blockpage_len - sizeof(DIVERT_PACKET));
|
||||
blockpage->header.ip.Length = htons(blockpage_len);
|
||||
blockpage->header.tcp.SrcPort = htons(80);
|
||||
blockpage->header.tcp.Psh = 1;
|
||||
blockpage->header.tcp.Ack = 1;
|
||||
@@ -170,19 +168,19 @@ int main(int argc, char **argv)
|
||||
// Main loop:
|
||||
while (TRUE)
|
||||
{
|
||||
if (!DivertRecv(handle, ppacket, sizeof(packet), &ppacket_len))
|
||||
if (!DivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet (%d)\n",
|
||||
GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DivertHelperParse(ppacket, ppacket_len, &ip_header, NULL, NULL,
|
||||
if (!DivertHelperParse(packet, packet_len, &ip_header, NULL, NULL,
|
||||
NULL, &tcp_header, NULL, &payload, &payload_len) ||
|
||||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
|
||||
{
|
||||
// Packet does not match the blacklist; simply reinject it.
|
||||
if (!DivertSend(handle, ppacket, ppacket_len, NULL))
|
||||
if (!DivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -195,35 +193,29 @@ int main(int argc, char **argv)
|
||||
|
||||
// (1) Send a TCP RST to the server; immediately closing the
|
||||
// connection at the server's end.
|
||||
reset->divert.IfIdx = ppacket->IfIdx;
|
||||
reset->divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
reset->divert.Direction = ppacket->Direction;
|
||||
reset->ip.SrcAddr = ip_header->SrcAddr;
|
||||
reset->ip.DstAddr = ip_header->DstAddr;
|
||||
reset->tcp.SrcPort = tcp_header->SrcPort;
|
||||
reset->tcp.DstPort = htons(80);
|
||||
reset->tcp.SeqNum = tcp_header->SeqNum;
|
||||
reset->tcp.AckNum = tcp_header->AckNum;
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)reset, sizeof(PACKET), 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)reset, sizeof(PACKET), NULL))
|
||||
DivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
|
||||
if (!DivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
// (2) Send the blockpage to the browser:
|
||||
blockpage->header.divert.IfIdx = ppacket->IfIdx;
|
||||
blockpage->header.divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
blockpage->header.divert.Direction = !ppacket->Direction;
|
||||
blockpage->header.ip.SrcAddr = ip_header->DstAddr;
|
||||
blockpage->header.ip.DstAddr = ip_header->SrcAddr;
|
||||
blockpage->header.tcp.DstPort = tcp_header->SrcPort;
|
||||
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
|
||||
blockpage->header.tcp.AckNum =
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len);
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)blockpage, blockpage_len, 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)blockpage, blockpage_len,
|
||||
NULL))
|
||||
DivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, 0);
|
||||
addr.Direction = !addr.Direction; // Reverse direction.
|
||||
if (!DivertSend(handle, (PVOID)blockpage, blockpage_len, &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -231,9 +223,6 @@ int main(int argc, char **argv)
|
||||
|
||||
// (3) Send a TCP RST to the browser; closing the connection at the
|
||||
// browser's end.
|
||||
reset->divert.IfIdx = ppacket->IfIdx;
|
||||
reset->divert.SubIfIdx = ppacket->SubIfIdx;
|
||||
reset->divert.Direction = !ppacket->Direction;
|
||||
reset->ip.SrcAddr = ip_header->DstAddr;
|
||||
reset->ip.DstAddr = ip_header->SrcAddr;
|
||||
reset->tcp.SrcPort = htons(80);
|
||||
@@ -242,8 +231,8 @@ int main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
|
||||
reset->tcp.AckNum =
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len);
|
||||
DivertHelperCalcChecksums((PDIVERT_PACKET)reset, sizeof(PACKET), 0);
|
||||
if (!DivertSend(handle, (PDIVERT_PACKET)reset, sizeof(PACKET), NULL))
|
||||
DivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
|
||||
if (!DivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -259,7 +248,7 @@ static void PacketInit(PPACKET packet)
|
||||
memset(packet, 0, sizeof(PACKET));
|
||||
packet->ip.Version = 4;
|
||||
packet->ip.HdrLength = sizeof(DIVERT_IPHDR) / sizeof(UINT32);
|
||||
packet->ip.Length = htons(sizeof(PACKET) - sizeof(DIVERT_PACKET));
|
||||
packet->ip.Length = htons(sizeof(PACKET));
|
||||
packet->ip.TTL = 64;
|
||||
packet->ip.Protocol = IPPROTO_TCP;
|
||||
packet->tcp.HdrLength = sizeof(DIVERT_TCPHDR) / sizeof(UINT32);
|
||||
|
||||
+8
-13
@@ -38,23 +38,16 @@ extern "C" {
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT8 Reserved[7]; // Reserved for internal use.
|
||||
UINT8 Direction; // Packet's direction.
|
||||
UINT32 IfIdx; // Packet's interface index.
|
||||
UINT32 SubIfIdx; // Packet's sub-interface index.
|
||||
} DIVERT_PACKET, *PDIVERT_PACKET;
|
||||
UINT8 Direction; // Packet's direction.
|
||||
} DIVERT_ADDRESS, *PDIVERT_ADDRESS;
|
||||
|
||||
#ifndef DIVERT_PACKET_DIRECTION_OUTBOUND
|
||||
#define DIVERT_PACKET_DIRECTION_OUTBOUND 0
|
||||
#define DIVERT_PACKET_DIRECTION_INBOUND 1
|
||||
#endif /* DIVERT_PACKET_DIRECTION_OUTBOUND */
|
||||
|
||||
#define DIVERT_PACKET_DIRECTION(pPacket) (pPacket->Direction)
|
||||
#define DIVERT_PACKET_INTERFACE_INDEX(pPacket) (pPacket->IfIdx)
|
||||
#define DIVERT_PACKET_SUB_INTERFACE_INDEX(pPacket) (pPacket->SubIfIdx)
|
||||
#define DIVERT_PACKET_DATA(pPacket) \
|
||||
((PVOID)(pPacket+1))
|
||||
|
||||
/*
|
||||
* Open a handle to the divert device with the given filter.
|
||||
*/
|
||||
@@ -66,8 +59,9 @@ extern DIVERTEXPORT HANDLE DivertOpen(
|
||||
*/
|
||||
extern DIVERTEXPORT BOOL DivertRecv(
|
||||
__in HANDLE handle,
|
||||
__inout PDIVERT_PACKET pPacket,
|
||||
__out PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out PDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *readLen);
|
||||
|
||||
/*
|
||||
@@ -75,8 +69,9 @@ extern DIVERTEXPORT BOOL DivertRecv(
|
||||
*/
|
||||
extern DIVERTEXPORT BOOL DivertSend(
|
||||
__in HANDLE handle,
|
||||
__in PDIVERT_PACKET pPacket,
|
||||
__in PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__in PDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *writeLen);
|
||||
|
||||
/*
|
||||
@@ -238,7 +233,7 @@ typedef struct
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
extern DIVERTEXPORT BOOL DivertHelperParse(
|
||||
__in PDIVERT_PACKET pPacket,
|
||||
__in PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt PDIVERT_IPHDR *ppIpHdr,
|
||||
__out_opt PDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
@@ -253,7 +248,7 @@ extern DIVERTEXPORT BOOL DivertHelperParse(
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern DIVERTEXPORT UINT DivertHelperCalcChecksums(
|
||||
__inout PDIVERT_PACKET pPacket,
|
||||
__inout PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__in UINT64 flags);
|
||||
|
||||
|
||||
@@ -16,18 +16,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: This file is NOT part of the divert API. For the divert API, include
|
||||
* "divert.h" instead.
|
||||
*/
|
||||
|
||||
#ifndef __DIVERT_DEVICE_H
|
||||
#define __DIVERT_DEVICE_H
|
||||
|
||||
#define DIVERT_DEVICE_NAME L"\\Device\\Divert"
|
||||
#define DIVERT_DOS_DEVICE_NAME L"\\??\\Divert"
|
||||
|
||||
#define DIVERT_VERSION 0
|
||||
#define DIVERT_VERSION 1
|
||||
#define DIVERT_MAGIC 0xF8D3
|
||||
|
||||
#define DIVERT_FILTER_FIELD_ZERO 0
|
||||
@@ -115,13 +110,14 @@
|
||||
/*
|
||||
* Message definitions.
|
||||
*/
|
||||
struct divert_message_s
|
||||
struct divert_ioctl_s
|
||||
{
|
||||
UINT16 magic; // DIVERT_MAGIC
|
||||
UINT8 version; // DIVERT_VERSION
|
||||
UINT8 reserved; // Reserved (set to 0x0)
|
||||
PVOID arg; // Pointer to buffer
|
||||
};
|
||||
typedef struct divert_message_s *divert_message_t;
|
||||
typedef struct divert_ioctl_s *divert_ioctl_t;
|
||||
|
||||
/*
|
||||
* IOCTL structures.
|
||||
@@ -139,7 +135,11 @@ typedef struct divert_ioctl_filter_s *divert_ioctl_filter_t;
|
||||
/*
|
||||
* IOCTL codes.
|
||||
*/
|
||||
#define IOCTL_DIVERT_RECV \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x908, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_DIVERT_SEND \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x909, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_DIVERT_SET_FILTER \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90A, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90A, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#endif // __DIVERT_DEVICE_H
|
||||
|
||||
+150
-124
@@ -30,8 +30,6 @@
|
||||
*/
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
EVT_WDF_DRIVER_UNLOAD divert_unload;
|
||||
EVT_WDF_IO_QUEUE_IO_READ divert_read;
|
||||
EVT_WDF_IO_QUEUE_IO_WRITE divert_write;
|
||||
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL divert_ioctl;
|
||||
EVT_WDF_DEVICE_FILE_CREATE divert_create;
|
||||
EVT_WDF_TIMER divert_timer;
|
||||
@@ -133,6 +131,17 @@ typedef struct context_s context_s;
|
||||
typedef struct context_s *context_t;
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(context_s, divert_context_get);
|
||||
|
||||
/*
|
||||
* Request context.
|
||||
*/
|
||||
struct req_context_s
|
||||
{
|
||||
struct divert_addr_s *addr; // Pointer to address structure.
|
||||
};
|
||||
typedef struct req_context_s req_context_s;
|
||||
typedef struct req_context_s *req_context_t;
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(req_context_s, divert_req_context_get);
|
||||
|
||||
/*
|
||||
* Packets
|
||||
*/
|
||||
@@ -156,15 +165,19 @@ typedef struct packet_s *packet_t;
|
||||
#define DIVERT_NET_BUFFER_LIST_TAG 'Lvid'
|
||||
|
||||
/*
|
||||
* Header definitions.
|
||||
* Address definition.
|
||||
*/
|
||||
struct hdr // Warning: must match DIVERT_PACKET in divert.h
|
||||
struct divert_addr_s
|
||||
{
|
||||
UINT8 Reserved[7];
|
||||
UINT8 Direction;
|
||||
UINT32 IfIdx;
|
||||
UINT32 SubIfIdx;
|
||||
UINT8 Direction;
|
||||
};
|
||||
typedef struct divert_addr_s *divert_addr_t;
|
||||
|
||||
/*
|
||||
* Header definitions.
|
||||
*/
|
||||
struct iphdr
|
||||
{
|
||||
UINT8 HdrLength:4;
|
||||
@@ -267,8 +280,7 @@ HANDLE injectv6_handle;
|
||||
*/
|
||||
extern VOID divert_ioctl(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t in_length, IN size_t out_len, IN ULONG code);
|
||||
extern VOID divert_read(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t length);
|
||||
extern NTSTATUS divert_read(context_t context, WDFREQUEST request);
|
||||
static void divert_read_service(context_t context);
|
||||
static BOOLEAN divert_context_verify(context_t context, context_state_t state);
|
||||
extern VOID divert_create(IN WDFDEVICE device, IN WDFREQUEST request,
|
||||
@@ -280,8 +292,8 @@ extern NTSTATUS divert_register_callout(context_t context, UINT idx,
|
||||
extern VOID divert_timer(IN WDFTIMER timer);
|
||||
extern VOID divert_cleanup(IN WDFFILEOBJECT object);
|
||||
extern VOID divert_close(IN WDFFILEOBJECT object);
|
||||
extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t length);
|
||||
extern NTSTATUS divert_write(context_t context, WDFREQUEST request,
|
||||
divert_addr_t addr);
|
||||
extern void NTAPI divert_inject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *packets, BOOLEAN dispatch_level);
|
||||
static NTSTATUS divert_notify_callout(IN FWPS_CALLOUT_NOTIFY_TYPE type,
|
||||
@@ -391,8 +403,8 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
|
||||
}
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config,
|
||||
WdfIoQueueDispatchSequential);
|
||||
queue_config.EvtIoRead = divert_read;
|
||||
queue_config.EvtIoWrite = divert_write;
|
||||
queue_config.EvtIoRead = NULL;
|
||||
queue_config.EvtIoWrite = NULL;
|
||||
queue_config.EvtIoDeviceControl = divert_ioctl;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&obj_attrs);
|
||||
status = WdfIoQueueCreate(device, &queue_config, &obj_attrs, &queue);
|
||||
@@ -867,38 +879,25 @@ extern VOID divert_close(IN WDFFILEOBJECT object)
|
||||
/*
|
||||
* Divert read routine.
|
||||
*/
|
||||
extern VOID divert_read(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t length)
|
||||
static NTSTATUS divert_read(context_t context, WDFREQUEST request)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
context_t context = divert_context_get(WdfRequestGetFileObject(request));
|
||||
|
||||
DEBUG("READ: reading diverted packet (context=%p, request=%p)", context,
|
||||
request);
|
||||
|
||||
if (!divert_context_verify(context, DIVERT_CONTEXT_STATE_OPEN))
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
goto divert_read_exit;
|
||||
}
|
||||
|
||||
// Forward the request to the pending read queue:
|
||||
status = WdfRequestForwardToIoQueue(request, context->read_queue);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to forward I/O request to read queue", status);
|
||||
goto divert_read_exit;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Service the read request:
|
||||
divert_read_service(context);
|
||||
|
||||
divert_read_exit:
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
WdfRequestCompleteWithInformation(request, status, 0);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -914,8 +913,8 @@ static void divert_read_service(context_t context)
|
||||
ULONG dst_len, src_len;
|
||||
NTSTATUS status;
|
||||
packet_t packet;
|
||||
divert_message_t message;
|
||||
struct hdr *header;
|
||||
req_context_t req_context;
|
||||
divert_addr_t addr;
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
while (context->state == DIVERT_CONTEXT_STATE_OPEN &&
|
||||
@@ -950,23 +949,6 @@ static void divert_read_service(context_t context)
|
||||
goto divert_read_service_complete;
|
||||
}
|
||||
dst_len = MmGetMdlByteCount(dst_mdl);
|
||||
if (dst_len < sizeof(struct hdr))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
DEBUG_ERROR("failed to write to output buffer; buffer too small - "
|
||||
"cannot fit packet header", status);
|
||||
goto divert_read_service_complete;
|
||||
}
|
||||
header = (struct hdr *)dst;
|
||||
header->Direction = packet->direction;
|
||||
header->IfIdx = packet->if_idx;
|
||||
header->SubIfIdx = packet->sub_if_idx;
|
||||
message = (divert_message_t)header->Reserved;
|
||||
message->magic = DIVERT_MAGIC;
|
||||
message->version = DIVERT_VERSION;
|
||||
message->reserved = 0x0;
|
||||
dst = (PVOID)((UINT8 *)dst + sizeof(struct hdr));
|
||||
dst_len -= sizeof(struct hdr);
|
||||
src_len = NET_BUFFER_DATA_LENGTH(packet->buffer);
|
||||
dst_len = (src_len < dst_len? src_len: dst_len);
|
||||
src = NdisGetDataBuffer(packet->buffer, dst_len, NULL, 1, 0);
|
||||
@@ -978,6 +960,13 @@ static void divert_read_service(context_t context)
|
||||
{
|
||||
RtlCopyMemory(dst, src, dst_len);
|
||||
}
|
||||
|
||||
// Write the address information.
|
||||
req_context = divert_req_context_get(request);
|
||||
addr = req_context->addr;
|
||||
addr->IfIdx = packet->if_idx;
|
||||
addr->SubIfIdx = packet->sub_if_idx;
|
||||
addr->Direction = packet->direction;
|
||||
|
||||
// Compute the IP/TCP/UDP checksums here if required.
|
||||
divert_update_checksums(dst, dst_len, packet->ip_checksum,
|
||||
@@ -990,8 +979,7 @@ divert_read_service_complete:
|
||||
ExFreePoolWithTag(packet, DIVERT_PACKET_TAG);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
WdfRequestCompleteWithInformation(request, status,
|
||||
src_len + sizeof(struct hdr));
|
||||
WdfRequestCompleteWithInformation(request, status, dst_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1005,19 +993,16 @@ divert_read_service_complete:
|
||||
/*
|
||||
* Divert write routine.
|
||||
*/
|
||||
extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t length)
|
||||
static NTSTATUS divert_write(context_t context, WDFREQUEST request,
|
||||
divert_addr_t addr)
|
||||
{
|
||||
PMDL mdl, sub_mdl = NULL;
|
||||
UINT8 *sub_addr;
|
||||
UINT sub_len;
|
||||
PNET_BUFFER_LIST buffers = NULL;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
divert_message_t message;
|
||||
struct hdr *header;
|
||||
PMDL mdl = NULL;
|
||||
PVOID data;
|
||||
UINT data_len;
|
||||
struct iphdr *ip_header;
|
||||
BOOL isipv4;
|
||||
context_t context = divert_context_get(WdfRequestGetFileObject(request));
|
||||
PNET_BUFFER_LIST buffers = NULL;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
DEBUG("WRITE: writing/injecting a packet (context=%p, request=%p)",
|
||||
context, request);
|
||||
@@ -1028,44 +1013,30 @@ extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveInputWdmMdl(request, &mdl);
|
||||
status = WdfRequestRetrieveOutputWdmMdl(request, &mdl);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to retrieve input MDL", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
if (MmGetMdlByteCount(mdl) != length)
|
||||
{
|
||||
status = STATUS_INVALID_BUFFER_SIZE;
|
||||
DEBUG_ERROR("failed to validate MDL buffer size", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
if (length <= sizeof(struct hdr))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
DEBUG_ERROR("failed to read packet header; buffer too small", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
header = (struct hdr *)MmGetSystemAddressForMdlSafe(mdl,
|
||||
NormalPagePriority);
|
||||
if (header == NULL)
|
||||
data = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
|
||||
if (data == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DEBUG_ERROR("failed to get MDL address", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
message = (divert_message_t)header->Reserved;
|
||||
if (message->magic != DIVERT_MAGIC ||
|
||||
message->version != DIVERT_VERSION)
|
||||
|
||||
data_len = MmGetMdlByteCount(mdl);
|
||||
if (data_len < sizeof(struct iphdr))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DEBUG_ERROR("failed to validate packet header", status);
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
DEBUG_ERROR("write buffer too small, cannot read ip header", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
ip_header = (struct iphdr *)(header + 1);
|
||||
ip_header = (struct iphdr *)data;
|
||||
switch (ip_header->Version)
|
||||
{
|
||||
case 4:
|
||||
@@ -1080,19 +1051,8 @@ extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
sub_addr = (UINT8 *)MmGetMdlVirtualAddress(mdl) + sizeof(struct hdr);
|
||||
sub_len = length - sizeof(struct hdr);
|
||||
sub_mdl = IoAllocateMdl(sub_addr, sub_len, FALSE, FALSE, NULL);
|
||||
if (sub_mdl == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DEBUG_ERROR("failed to allocate sub-mdl", status);
|
||||
goto divert_write_exit;
|
||||
}
|
||||
IoBuildPartialMdl(mdl, sub_mdl, sub_addr, sub_len);
|
||||
|
||||
status = FwpsAllocateNetBufferAndNetBufferList0(context->pool_handle,
|
||||
0, 0, sub_mdl, 0, sub_len, &buffers);
|
||||
0, 0, mdl, 0, data_len, &buffers);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to create NET_BUFFER_LIST for injected packet",
|
||||
@@ -1100,7 +1060,7 @@ extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
goto divert_write_exit;
|
||||
}
|
||||
|
||||
switch (header->Direction)
|
||||
switch (addr->Direction)
|
||||
{
|
||||
case DIVERT_PACKET_DIRECTION_OUTBOUND:
|
||||
if (isipv4)
|
||||
@@ -1121,14 +1081,14 @@ extern VOID divert_write(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
{
|
||||
status = FwpsInjectNetworkReceiveAsync0(inject_handle,
|
||||
DIVERT_PACKET_INJECTED, 0, UNSPECIFIED_COMPARTMENT_ID,
|
||||
header->IfIdx, header->SubIfIdx, buffers,
|
||||
addr->IfIdx, addr->SubIfIdx, buffers,
|
||||
divert_inject_complete, (HANDLE)request);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FwpsInjectNetworkReceiveAsync0(injectv6_handle,
|
||||
DIVERT_PACKET_INJECTED, 0, UNSPECIFIED_COMPARTMENT_ID,
|
||||
header->IfIdx, header->SubIfIdx, buffers,
|
||||
addr->IfIdx, addr->SubIfIdx, buffers,
|
||||
divert_inject_complete, (HANDLE)request);
|
||||
}
|
||||
break;
|
||||
@@ -1147,12 +1107,9 @@ divert_write_exit:
|
||||
{
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
}
|
||||
if (sub_mdl != NULL)
|
||||
{
|
||||
IoFreeMdl(sub_mdl);
|
||||
}
|
||||
WdfRequestComplete(request, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1161,7 +1118,6 @@ divert_write_exit:
|
||||
static void NTAPI divert_inject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *buffers, BOOLEAN dispatch_level)
|
||||
{
|
||||
PMDL sub_mdl;
|
||||
WDFREQUEST request = (WDFREQUEST)context;
|
||||
PNET_BUFFER buffer;
|
||||
size_t length = 0;
|
||||
@@ -1171,7 +1127,6 @@ static void NTAPI divert_inject_complete(VOID *context,
|
||||
DEBUG("COMPLETE: write/inject packet complete (request=%p)", request);
|
||||
|
||||
buffer = NET_BUFFER_LIST_FIRST_NB(buffers);
|
||||
sub_mdl = NET_BUFFER_FIRST_MDL(buffer);
|
||||
status = NET_BUFFER_LIST_STATUS(buffers);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
@@ -1181,10 +1136,8 @@ static void NTAPI divert_inject_complete(VOID *context,
|
||||
{
|
||||
DEBUG_ERROR("failed to inject packet", status);
|
||||
}
|
||||
IoFreeMdl(sub_mdl);
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
WdfRequestCompleteWithInformation(request, status,
|
||||
(ULONG_PTR)(length + sizeof(struct hdr)));
|
||||
WdfRequestCompleteWithInformation(request, status, length);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1193,10 +1146,14 @@ static void NTAPI divert_inject_complete(VOID *context,
|
||||
extern VOID divert_ioctl(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
IN size_t out_length, IN size_t in_length, IN ULONG code)
|
||||
{
|
||||
PCHAR buf;
|
||||
size_t buflen, filter_len;
|
||||
divert_message_t message;
|
||||
PCHAR inbuf, outbuf;
|
||||
size_t inbuflen, outbuflen, filter_len;
|
||||
divert_ioctl_t ioctl;
|
||||
divert_ioctl_filter_t filter;
|
||||
WDFMEMORY memobj;
|
||||
divert_addr_t addr;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
req_context_t req_context = NULL;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
context_t context = divert_context_get(WdfRequestGetFileObject(request));
|
||||
UNREFERENCED_PARAMETER(queue);
|
||||
@@ -1209,34 +1166,102 @@ extern VOID divert_ioctl(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
|
||||
// Get the buffers and do sanity checks.
|
||||
status = WdfRequestRetrieveInputBuffer(request, 0, &inbuf, &inbuflen);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to retrieve input buffer", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
|
||||
if (inbuflen != sizeof(struct divert_ioctl_s) || inbuflen != in_length)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DEBUG_ERROR("input buffer not an ioctl message header", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
|
||||
ioctl = (divert_ioctl_t)inbuf;
|
||||
if (ioctl->version != DIVERT_VERSION || ioctl->magic != DIVERT_MAGIC ||
|
||||
ioctl->reserved != 0x0)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DEBUG_ERROR("input buffer contained a bad ioctl message header",
|
||||
status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveOutputBuffer(request, 0, &outbuf, &outbuflen);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to retrieve output buffer", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
if (outbuflen != out_length)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DEBUG_ERROR("output buffer length mismatch", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
|
||||
// Handle the ioctl:
|
||||
switch (code)
|
||||
{
|
||||
case IOCTL_DIVERT_SET_FILTER:
|
||||
status = WdfRequestRetrieveInputBuffer(request, 0, &buf, &buflen);
|
||||
case IOCTL_DIVERT_RECV:
|
||||
status = WdfRequestProbeAndLockUserBufferForWrite(request,
|
||||
ioctl->arg, sizeof(struct divert_addr_s), &memobj);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to retrieve input buffer", status);
|
||||
DEBUG_ERROR("invalid arg pointer for RECV ioctl", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
if (buflen != in_length ||
|
||||
buflen < sizeof(struct divert_message_s))
|
||||
addr = (divert_addr_t)WdfMemoryGetBuffer(memobj, NULL);
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
|
||||
req_context_s);
|
||||
status = WdfObjectAllocateContext(request, &attributes,
|
||||
&req_context);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
DEBUG_ERROR("input buffer has an invalid length %u bytes",
|
||||
status, buflen);
|
||||
DEBUG_ERROR("failed to allocate request context for RECV "
|
||||
"ioctl", status);
|
||||
goto divert_ioctl_exit;
|
||||
|
||||
}
|
||||
req_context->addr = addr;
|
||||
status = divert_read(context, request);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_DIVERT_SEND:
|
||||
status = WdfRequestProbeAndLockUserBufferForRead(request,
|
||||
ioctl->arg, sizeof(struct divert_addr_s), &memobj);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("invalid arg pointer for SEND ioctl", status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
message = (divert_message_t)buf;
|
||||
if (message->version != DIVERT_VERSION ||
|
||||
message->magic != DIVERT_MAGIC)
|
||||
addr = (divert_addr_t)WdfMemoryGetBuffer(memobj, NULL);
|
||||
status = divert_write(context, request, addr);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_DIVERT_SET_FILTER:
|
||||
if (ioctl->arg != NULL)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DEBUG_ERROR("input buffer contains an invalid request header",
|
||||
DEBUG_ERROR("arg pointer is non-NULL for SET_FILTER ioctl",
|
||||
status);
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
filter = (divert_ioctl_filter_t)(message+1);
|
||||
filter_len = buflen - sizeof(struct divert_message_s);
|
||||
filter = (divert_ioctl_filter_t)outbuf;
|
||||
filter_len = outbuflen;
|
||||
if (!divert_filter_compile(filter, filter_len, context->filter))
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
@@ -1244,6 +1269,7 @@ extern VOID divert_ioctl(IN WDFQUEUE queue, IN WDFREQUEST request,
|
||||
goto divert_ioctl_exit;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DEBUG_ERROR("failed to complete I/O control; invalid request",
|
||||
|
||||
Reference in New Issue
Block a user