Yes :4 :2 :1 do represents bit lengths. Odd why PB don't yet support bit values in Structures.
Windows Filtering Platform
Re: Windows Filtering Platform
Nice!
Yes :4 :2 :1 do represents bit lengths. Odd why PB don't yet support bit values in Structures.
Yes :4 :2 :1 do represents bit lengths. Odd why PB don't yet support bit values in Structures.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
Using PureBasic 5.20 LTS (x64) and even tested on x86. Lot of the returned values are null. And the limited few that returns are still gibberish. There shouldn't be anything fancy to get the right ports information?
I don't know what is going on here.
I don't know what is going on here.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
My returned values - is this similar to your results?
---------------
DivertOpen
---------------
hWndDivert: 320
filter: outbound && ip && tcp.DstPort == 80 && tcp.PayloadLength > 0
---------------
DivertRecv
---------------
pAddr\IfIdx: 11
pAddr\SubIfIdx: 0
pAddr\Direction: 0
---------------
DivertHelperParsePacket
---------------
ppIpHdr\HdrLength: 128
ppIpHdr\Version: 0
ppIpHdr\TOS: 208
ppIpHdr\Length: 4
ppIpHdr\Id: 0
ppIpHdr\FragOff0: 0
ppIpHdr\TTL: 0
ppIpHdr\Protocol: 0
ppIpHdr\Checksum: 0
ppIpHdr\SrcAddr: 0
ppIpHdr\DstAddr: 0
---------------
ppIcmpHdr\Type: 0
ppIcmpHdr\Code: 0
---------------
ppTcpHdr\SrcPort: 148
ppTcpHdr\DstPort: 1232
---------------
ppUdpHdr\SrcPort: 0
ppUdpHdr\DstPort: 0
---------------
*ppData
---------------
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)
Accept-Encoding: gzip, deflate
Host: duckduckgo.com
DNT: 1
Connection: Keep-Alive
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: Windows Filtering Platform
Indeed.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
For the outgoing www-HTTP (80tcp) packets the destination port should be showing 80. The source which be using dynamic port range 49152-65535 or 1025-5000 for systems earlier than Vista.
DIVERT_ADDRESS gets correct information that is properly read.
DIVERT_IPHDR and DIVERT_TCPHDR (the two that we are using for our HTTP outgoing packets) doesn't seem to be returning much of anything.
IP Header - Version should be returning 4 or 6, 4 for Ipv4. Not be returning a 0.
The ICMP Info like type and code is understandably returning 0, we aren't working with ICMP and the same for UDP.
IP_Header containing the source and destination IP information, where is that? Only 0 being returned nothing that we can change over to aaa.bbb.ccc.ddd
The protocol info shouldn't be 0, it should be showing 6 for TCP, 17 for UDP for when we do use.
Other information that should be there ... or returned, but only with 0 here.
DIVERT_ADDRESS gets correct information that is properly read.
DIVERT_IPHDR and DIVERT_TCPHDR (the two that we are using for our HTTP outgoing packets) doesn't seem to be returning much of anything.
IP Header - Version should be returning 4 or 6, 4 for Ipv4. Not be returning a 0.
The ICMP Info like type and code is understandably returning 0, we aren't working with ICMP and the same for UDP.
IP_Header containing the source and destination IP information, where is that? Only 0 being returned nothing that we can change over to aaa.bbb.ccc.ddd
The protocol info shouldn't be 0, it should be showing 6 for TCP, 17 for UDP for when we do use.
Other information that should be there ... or returned, but only with 0 here.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
First step would be to setup and use arrays in our structures. lol
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
Good information, thanks.
I see what you mean with the "0" values being returned, but I was just happy that the *ppData parameter returning successfully, which meant that DivertHelperParsePacket() is being called correctly, which in turn narrows our problem to the Structures... baby steps.
Here is how I decided on the Structure's data types: https://github.com/ToniPB/PureBasic_Win ... aseTsd.pbi
I also updated the link to include the resources I've downloaded from the WinDivert website... you probably already have them.
I have to get back to the weekend
but I thought it was important to post the small changes after hearing back from -basil (WinDivert).
Later,
I see what you mean with the "0" values being returned, but I was just happy that the *ppData parameter returning successfully, which meant that DivertHelperParsePacket() is being called correctly, which in turn narrows our problem to the Structures... baby steps.
Here is how I decided on the Structure's data types: https://github.com/ToniPB/PureBasic_Win ... aseTsd.pbi
I also updated the link to include the resources I've downloaded from the WinDivert website... you probably already have them.
I have to get back to the weekend
Later,
Last edited by JHPJHP on Sun Sep 22, 2013 5:10 am, edited 2 times in total.
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: Windows Filtering Platform
Thanks JHPJHP!
I'll take it all in and report back if I make any progress.
I'll take it all in and report back if I make any progress.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
Using the new Structure configuration from your other post (great catch Josh & Danilo):
Code: Select all
Structure DIVERT_IPHDR
StructureUnion
HdrLength.a
Version.a
EndStructureUnion
TOS.a
Length.u
Id.u
FragOff0.u
TTL.a
Protocol.a
Checksum.u
SrcAddr.l
DstAddr.l
EndStructure
*ppIpHdr.DIVERT_IPHDR
DivertHelperParsePacket(*pPacket, recvLen, @*ppIpHdr, #Null, @ppIcmpHdr, #Null, @ppTcpHdr, @ppUdpHdr, @ppData, @pDataLen)
Debug "---------------"
Debug "DivertHelperParsePacket"
Debug "---------------"
Debug "ppIpHdr\HdrLength: " + PeekA(@*ppIpHdr\HdrLength)
Debug "ppIpHdr\Version: " + PeekA(@*ppIpHdr\Version)
Debug "ppIpHdr\TOS: " + PeekA(@*ppIpHdr\TOS)
Debug "ppIpHdr\Length: " + PeekU(@*ppIpHdr\Length)
Debug "ppIpHdr\Id: " + PeekU(@*ppIpHdr\Id)
Debug "ppIpHdr\FragOff0: " + PeekU(@*ppIpHdr\FragOff0)
Debug "ppIpHdr\TTL: " + PeekA(@*ppIpHdr\TTL)
Debug "ppIpHdr\Protocol: " + PeekA(@*ppIpHdr\Protocol)
Debug "ppIpHdr\Checksum: " + PeekU(@*ppIpHdr\Checksum)
Debug "ppIpHdr\SrcAddr: " + PeekL(@*ppIpHdr\SrcAddr)
Debug "ppIpHdr\DstAddr: " + PeekL(@*ppIpHdr\DstAddr)
Last edited by JHPJHP on Mon Sep 23, 2013 1:04 pm, edited 1 time in total.
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: Windows Filtering Platform
LOL.
The source IP address is there.... but it is just been put in backwards LOL!
I mean.... instead of it 192.168.x.y it is y.x.168.192
The source IP address is there.... but it is just been put in backwards LOL!
I mean.... instead of it 192.168.x.y it is y.x.168.192
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
I knew we would eventually get there. 
Also (for Long),
I bet the other Structures need some support as well.
Also (for Long),
Code: Select all
htonl_(PeekL(@*ppIpHdr\SrcAddr))
Last edited by JHPJHP on Mon Sep 23, 2013 12:42 am, edited 1 time in total.
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: Windows Filtering Platform
Looking good so far. 
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
Code: Select all
ipHdr_Length = PeekA(@*ppIpHdr\HdrLength) & %1111
ipHdr_Version = (PeekA(@*ppIpHdr\Version) >> 4)
ipHdr_TOS = htons_(PeekA(@*ppIpHdr\TOS))
ipHdr_TotalLength = htons_(PeekU(@*ppIpHdr\Length))
ipHdr_Id = htons_(PeekU(@*ppIpHdr\Id))
ipHdr_FragsOff = PeekU(@*ppIpHdr\FragOff0)
ipHdr_TTL = PeekA(@*ppIpHdr\TTL)
ipHdr_Protocol = PeekA(@*ppIpHdr\Protocol)
ipHdr_Checksum = PeekU(@*ppIpHdr\Checksum)
ipHdr_SrcAddr.s = IPString(PeekL(@*ppIpHdr\SrcAddr)) ;Dropped htonl_(), Native PB command sufficient.
ipHdr_DstAddr.s = IPString(PeekL(@*ppIpHdr\DstAddr)) ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Windows Filtering Platform
That's a great update - now using IPString, and you beat me to the (post) punch.
I added StructureUnion to the other datatypes with bit references.
(split StructureUnion by bit length - DIVERT_TCPHDR)
Other stuff added and fixed (updated original link as well).
I added StructureUnion to the other datatypes with bit references.
(split StructureUnion by bit length - DIVERT_TCPHDR)
Other stuff added and fixed (updated original link as well).
Code: Select all
Structure DIVERT_ADDRESS
IfIdx.l
SubIfIdx.l
Direction.a
EndStructure
Structure DIVERT_IPHDR
StructureUnion
HdrLength.a
Version.a
EndStructureUnion
TOS.a
Length.u
Id.u
FragOff0.u
TTL.a
Protocol.a
Checksum.u
SrcAddr.l
DstAddr.l
EndStructure
Structure DIVERT_IPV6HDR
StructureUnion
TrafficClass0.a
Version.a
FlowLabel0.a
TrafficClass1.a
EndStructureUnion
FlowLabel1.u
Length.u
NextHdr.u
HopLimit.u
SrcAddr.l[4]
DstAddr.l[4]
EndStructure
Structure DIVERT_ICMPHDR
Type.a
Code.a
Checksum.u
Body.l
EndStructure
Structure DIVERT_ICMPV6HDR
Type.a
Code.a
Checksum.u
Body.l
EndStructure
Structure DIVERT_TCPHDR
SrcPort.u
DstPort.u
SeqNum.l
AckNum.l
StructureUnion
Reserved1.u
HdrLength.u
EndStructureUnion
StructureUnion
Fin.u
Syn.u
Rst.u
Psh.u
Ack.u
Urg.u
EndStructureUnion
StructureUnion
Reserved2.u
EndStructureUnion
Window.u
Checksum.u
UrgPtr.u
EndStructure
Structure DIVERT_UDPHDR
SrcPort.u
DstPort.u
Length.u
Checksum.u
EndStructure
Prototype protoDivertOpen(filter.s, layer, priority.u, flags.q)
Global DivertOpen.protoDivertOpen
Prototype.b protoDivertSetParam(handle, param, value.q)
Global DivertSetParam.protoDivertSetParam
Prototype.b protoDivertRecv(handle, *pPacket, packetLen, pAddr, recvLen)
Global DivertRecv.protoDivertRecv
Prototype.b protoDivertHelperParsePacket(*pPacket, packetLen, *ppIpHdr, *ppIpv6Hdr, *ppIcmpHdr, *ppIcmpv6Hdr, *ppTcpHdr, *ppUdpHdr, *ppData, pDataLen)
Global DivertHelperParsePacket.protoDivertHelperParsePacket
Prototype.b protoDivertClose(handle)
Global DivertClose.protoDivertClose
Procedure.s TestForError()
Result.s = ""
dwMessageId = GetLastError_()
*lpBuffer = AllocateMemory(255)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, dwMessageId, #Null, *lpBuffer, MemorySize(*lpBuffer), #Null)
dwDescription.s = PeekS(*lpBuffer)
Result = "Error: " + Str(dwMessageId) + " - " + Left(dwDescription, Len(dwDescription) - 1)
FreeMemory(*lpBuffer)
ProcedureReturn Result
EndProcedure
WinDivert = OpenLibrary(#PB_Any, "WinDivert.dll")
If IsLibrary(WinDivert)
#DIVERT_LAYER_NETWORK = 0
#DIVERT_PRIORITY_DEFAULT = 0
#DIVERT_FLAG_SNIFF = 1
DivertOpen = GetFunction(WinDivert, "DivertOpen")
filter.s = "outbound && ip && tcp.DstPort == 80 && tcp.PayloadLength > 0"
hWndDivert = DivertOpen(filter, #DIVERT_LAYER_NETWORK, #DIVERT_PRIORITY_DEFAULT, #DIVERT_FLAG_SNIFF)
If hWndDivert <> #INVALID_HANDLE_VALUE
Debug "---------------"
Debug "DivertOpen"
Debug "---------------"
Debug "hWndDivert: " + Str(hWndDivert)
Debug "filter: " + filter
#DIVERT_PARAM_QUEUE_LEN = 0
#DIVERT_PARAM_QUEUE_TIME = 1
DivertSetParam = GetFunction(WinDivert, "DivertSetParam")
DivertSetParam(hWndDivert, #DIVERT_PARAM_QUEUE_LEN, 8192)
DivertSetParam(hWndDivert, #DIVERT_PARAM_QUEUE_TIME, 1024)
*pPacket = AllocateMemory($FFFF)
pAddr.DIVERT_ADDRESS
DivertRecv = GetFunction(WinDivert, "DivertRecv")
If DivertRecv(hWndDivert, *pPacket, MemorySize(*pPacket), @pAddr, @recvLen)
Debug "---------------"
Debug "DivertRecv"
Debug "---------------"
Debug "pAddr\IfIdx: " + PeekL(@pAddr\IfIdx)
Debug "pAddr\SubIfIdx: " + PeekL(@pAddr\SubIfIdx)
Debug "pAddr\Direction: " + PeekA(@pAddr\Direction)
*ppIpHdr.DIVERT_IPHDR
*ppIpv6Hdr.DIVERT_IPV6HDR
*ppIcmpHdr.DIVERT_ICMPHDR
*ppIcmpv6Hdr.DIVERT_ICMPV6HDR
*ppTcpHdr.DIVERT_TCPHDR
*ppUdpHdr.DIVERT_UDPHDR
DivertHelperParsePacket = GetFunction(WinDivert, "DivertHelperParsePacket")
DivertHelperParsePacket(*pPacket, recvLen, @*ppIpHdr, @*ppIpv6Hdr, @*ppIcmpHdr, @*ppIcmpv6Hdr, @*ppTcpHdr, @*ppUdpHdr, @*ppData, @pDataLen)
Debug "---------------"
Debug "DivertHelperParsePacket"
Debug "---------------"
If *ppIpHdr
Debug "ppIpHdr\HdrLength: " + Str(PeekA(@*ppIpHdr\HdrLength) & %1111)
Debug "ppIpHdr\Version: " + Str(PeekA(@*ppIpHdr\Version) >> 4)
Debug "ppIpHdr\TOS: " + PeekA(@*ppIpHdr\TOS)
Debug "ppIpHdr\Length: " + htons_(PeekU(@*ppIpHdr\Length))
Debug "ppIpHdr\Id: " + htons_(PeekU(@*ppIpHdr\Id))
Debug "ppIpHdr\FragOff0: " + htons_(PeekU(@*ppIpHdr\FragOff0))
Debug "ppIpHdr\TTL: " + PeekA(@*ppIpHdr\TTL)
Debug "ppIpHdr\Protocol: " + PeekA(@*ppIpHdr\Protocol)
Debug "ppIpHdr\Checksum: " + htons_(PeekU(@*ppIpHdr\Checksum))
Debug "ppIpHdr\SrcAddr: " + IPString(PeekL(@*ppIpHdr\SrcAddr))
Debug "ppIpHdr\DstAddr: " + IPString(PeekL(@*ppIpHdr\DstAddr))
EndIf
Debug "---------------"
If *ppIpv6Hdr
Debug "ppIpv6Hdr\TrafficClass0: " + PeekA(@*ppIpv6Hdr\TrafficClass0)
Debug "ppIpv6Hdr\Version: " + PeekA(@*ppIpv6Hdr\Version)
Debug "ppIpv6Hdr\FlowLabel0: " + PeekA(@*ppIpv6Hdr\FlowLabel0)
Debug "ppIpv6Hdr\TrafficClass1: " + PeekA(@*ppIpv6Hdr\TrafficClass1)
Debug "ppIpv6Hdr\FlowLabel1: " + PeekU(@*ppIpv6Hdr\FlowLabel1)
Debug "ppIpv6Hdr\Length: " + PeekU(@*ppIpv6Hdr\Length)
Debug "ppIpv6Hdr\NextHdr: " + PeekU(@*ppIpv6Hdr\NextHdr)
Debug "ppIpv6Hdr\HopLimit: " + PeekU(@*ppIpv6Hdr\HopLimit)
Debug "ppIpv6Hdr\SrcAddr[1]: " + PeekL(@*ppIpv6Hdr\SrcAddr[0])
Debug "ppIpv6Hdr\SrcAddr[2]: " + PeekL(@*ppIpv6Hdr\SrcAddr[1])
Debug "ppIpv6Hdr\SrcAddr[3]: " + PeekL(@*ppIpv6Hdr\SrcAddr[2])
Debug "ppIpv6Hdr\SrcAddr[4]: " + PeekL(@*ppIpv6Hdr\SrcAddr[3])
Debug "ppIpv6Hdr\DstAddr[1]: " + PeekL(@*ppIpv6Hdr\DstAddr[0])
Debug "ppIpv6Hdr\DstAddr[2]: " + PeekL(@*ppIpv6Hdr\DstAddr[1])
Debug "ppIpv6Hdr\DstAddr[3]: " + PeekL(@*ppIpv6Hdr\DstAddr[2])
Debug "ppIpv6Hdr\DstAddr[4]: " + PeekL(@*ppIpv6Hdr\DstAddr[3])
EndIf
Debug "---------------"
If *ppIcmpHdr
Debug "ppIcmpHdr\Type: " + PeekA(@*ppIcmpHdr\Type)
Debug "ppIcmpHdr\Code: " + PeekA(@*ppIcmpHdr\Code)
Debug "ppIcmpHdr\Checksum: " + PeekU(@*ppIcmpHdr\Checksum)
Debug "ppIcmpHdr\Body: " + PeekL(@*ppIcmpHdr\Body)
EndIf
Debug "---------------"
If *ppIcmpv6Hdr
Debug "ppIcmpv6Hdr\Type: " + PeekA(@*ppIcmpv6Hdr\Type)
Debug "ppIcmpv6Hdr\Code: " + PeekA(@*ppIcmpv6Hdr\Code)
Debug "ppIcmpv6Hdr\Checksum: " + PeekU(@*ppIcmpv6Hdr\Checksum)
Debug "ppIcmpv6Hdr\Body: " + PeekL(@*ppIcmpv6Hdr\Body)
EndIf
Debug "---------------"
If *ppTcpHdr
Debug "ppTcpHdr\SrcPort: " + PeekU(@*ppTcpHdr\SrcPort)
Debug "ppTcpHdr\DstPort: " + PeekU(@*ppTcpHdr\DstPort)
Debug "ppTcpHdr\SeqNum: " + PeekL(@*ppTcpHdr\SeqNum)
Debug "ppTcpHdr\AckNum: " + PeekL(@*ppTcpHdr\AckNum)
Debug "ppTcpHdr\Reserved1: " + PeekU(@*ppTcpHdr\Reserved1)
Debug "ppTcpHdr\HdrLength: " + PeekU(@*ppTcpHdr\HdrLength)
Debug "ppTcpHdr\Fin: " + PeekU(@*ppTcpHdr\Fin)
Debug "ppTcpHdr\Syn: " + PeekU(@*ppTcpHdr\Syn)
Debug "ppTcpHdr\Rst: " + PeekU(@*ppTcpHdr\Rst)
Debug "ppTcpHdr\Psh: " + PeekU(@*ppTcpHdr\Psh)
Debug "ppTcpHdr\Ack: " + PeekU(@*ppTcpHdr\Ack)
Debug "ppTcpHdr\Urg: " + PeekU(@*ppTcpHdr\Urg)
Debug "ppTcpHdr\Reserved2: " + PeekU(@*ppTcpHdr\Reserved2)
Debug "ppTcpHdr\Window: " + PeekU(@*ppTcpHdr\Window)
Debug "ppTcpHdr\Checksum: " + PeekU(@*ppTcpHdr\Checksum)
Debug "ppTcpHdr\UrgPtr: " + PeekU(@*ppTcpHdr\UrgPtr)
EndIf
Debug "---------------"
If *ppUdpHdr
Debug "ppUdpHdr\SrcPort: " + PeekU(@*ppUdpHdr\SrcPort)
Debug "ppUdpHdr\DstPort: " + PeekU(@*ppUdpHdr\DstPort)
Debug "ppUdpHdr\Length: " + PeekU(@*ppUdpHdr\Length)
Debug "ppUdpHdr\Checksum: " + PeekU(@*ppUdpHdr\Checksum)
EndIf
If *ppData
Debug "---------------"
Debug "*ppData"
Debug "---------------"
Debug PeekS(*ppData, pDataLen)
EndIf
FreeMemory(*pPacket)
Else
Debug "---------------"
Debug "DivertRecv"
Debug TestForError()
Debug "---------------"
EndIf
DivertClose = GetFunction(WinDivert, "DivertClose")
DivertClose(hWndDivert)
Else
Debug "---------------"
Debug "DivertOpen"
Debug TestForError()
Debug "---------------"
EndIf
CloseLibrary(WinDivert)
RunProgram("sc", "stop WinDivert1.0", "")
RunProgram("sc", "delete WinDivert1.0", "")
EndIf
Last edited by JHPJHP on Mon Sep 23, 2013 1:21 pm, edited 2 times in total.
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: Windows Filtering Platform
Looking good!
I was trying to figure how to have PB handle the first three-bit fields in \FragOff0.
#define DIVERT_IPHDR_GET_FRAGOFF(hdr) \
(((hdr)->FragOff0) & 0xFF1F)
#define DIVERT_IPHDR_GET_MF(hdr) \
((((hdr)->FragOff0) & 0x0020) != 0)
#define DIVERT_IPHDR_GET_DF(hdr) \
((((hdr)->FragOff0) & 0x0040) != 0)
#define DIVERT_IPHDR_GET_RESERVED(hdr) \
((((hdr)->FragOff0) & 0x0080) != 0)
I was trying to figure how to have PB handle the first three-bit fields in \FragOff0.
#define DIVERT_IPHDR_GET_FRAGOFF(hdr) \
(((hdr)->FragOff0) & 0xFF1F)
#define DIVERT_IPHDR_GET_MF(hdr) \
((((hdr)->FragOff0) & 0x0020) != 0)
#define DIVERT_IPHDR_GET_DF(hdr) \
((((hdr)->FragOff0) & 0x0040) != 0)
#define DIVERT_IPHDR_GET_RESERVED(hdr) \
((((hdr)->FragOff0) & 0x0080) != 0)
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
