Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pcap-Net
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Pcap-Net
Commits
ce1f95a8
Commit
ce1f95a8
authored
Aug 26, 2011
by
Brickner_cp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DNS.
Improve PacketBuilder (calculate each Layer's length once).
parent
a31049c4
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
422 additions
and
65 deletions
+422
-65
IEnumerableExtensions.cs
PcapDotNet/src/PcapDotNet.Base/IEnumerableExtensions.cs
+5
-0
InlineEqualityComparer.cs
PcapDotNet/src/PcapDotNet.Base/InlineEqualityComparer.cs
+27
-0
PcapDotNet.Base.csproj
PcapDotNet/src/PcapDotNet.Base/PcapDotNet.Base.csproj
+1
-0
DnsTests.cs
PcapDotNet/src/PcapDotNet.Packets.Test/DnsTests.cs
+52
-0
RandomPacketsExtensions.cs
...c/PcapDotNet.Packets.TestUtils/RandomPacketsExtensions.cs
+63
-0
DnsDatagram.cs
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsDatagram.cs
+81
-9
DnsDomainName.cs
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsDomainName.cs
+34
-3
DnsDomainNameCompressionData.cs
...rc/PcapDotNet.Packets/Dns/DnsDomainNameCompressionData.cs
+56
-29
DnsLayer.cs
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsLayer.cs
+30
-9
DnsResourceRecord.cs
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsResourceRecord.cs
+66
-10
PacketBuilder.cs
PcapDotNet/src/PcapDotNet.Packets/PacketBuilder.cs
+7
-5
No files found.
PcapDotNet/src/PcapDotNet.Base/IEnumerableExtensions.cs
View file @
ce1f95a8
...
...
@@ -13,6 +13,11 @@ namespace PcapDotNet.Base
public
static
class
IEnumerableExtensions
// ReSharper restore InconsistentNaming
{
public
static
bool
IsNullOrEmpty
<
T
>(
this
IEnumerable
<
T
>
sequence
)
{
return
sequence
==
null
||
!
sequence
.
Any
();
}
/// <summary>
/// Concatenates a sequence with more values.
/// </summary>
...
...
PcapDotNet/src/PcapDotNet.Base/InlineEqualityComparer.cs
0 → 100644
View file @
ce1f95a8
using
System
;
using
System.Collections.Generic
;
namespace
PcapDotNet.Base
{
public
class
InlineEqualityComparer
<
T
>
:
IEqualityComparer
<
T
>
{
public
InlineEqualityComparer
(
Func
<
T
,
T
,
bool
>
equals
,
Func
<
T
,
int
>
getHashCode
)
{
Equals
=
equals
;
GetHashCode
=
getHashCode
;
}
bool
IEqualityComparer
<
T
>.
Equals
(
T
x
,
T
y
)
{
return
Equals
(
x
,
y
);
}
int
IEqualityComparer
<
T
>.
GetHashCode
(
T
obj
)
{
return
GetHashCode
(
obj
);
}
private
Func
<
T
,
T
,
bool
>
Equals
{
get
;
set
;
}
private
Func
<
T
,
int
>
GetHashCode
{
get
;
set
;
}
}
}
\ No newline at end of file
PcapDotNet/src/PcapDotNet.Base/PcapDotNet.Base.csproj
View file @
ce1f95a8
...
...
@@ -91,6 +91,7 @@
<Compile
Include=
"IDictionaryExtensions.cs"
/>
<Compile
Include=
"IEnumerableExtensions.cs"
/>
<Compile
Include=
"IListExtensions.cs"
/>
<Compile
Include=
"InlineEqualityComparer.cs"
/>
<Compile
Include=
"MatchExtensions.cs"
/>
<Compile
Include=
"PropertyInfoExtensions.cs"
/>
<Compile
Include=
"TimeSpanExtensions.cs"
/>
...
...
PcapDotNet/src/PcapDotNet.Packets.Test/DnsTests.cs
View file @
ce1f95a8
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
PcapDotNet.Base
;
using
PcapDotNet.Packets.Arp
;
...
...
@@ -73,5 +76,54 @@ namespace PcapDotNet.Packets.Test
Assert
.
AreEqual
(
dnsLayer
,
packet
.
Ethernet
.
IpV4
.
Udp
.
Dns
.
ExtractLayer
(),
"DNS Layer"
);
}
}
[
TestMethod
]
public
void
SimpleDnsTest
()
{
DnsLayer
dnsLayer
=
new
DnsLayer
{
//Queries = new[] {new DnsQueryResourceRecord(new DnsDomainName("abc.def."), DnsType.A, DnsClass.In)}.ToList(),
Answers
=
new
[]
{
// new DnsDataResourceRecord(new DnsDomainName("abc.def."), DnsType.A, DnsClass.In, 100,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("abcd")))),
// new DnsDataResourceRecord(new DnsDomainName("abc.def."), DnsType.A, DnsClass.In, 100,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("abce")))),
new
DnsDataResourceRecord
(
new
DnsDomainName
(
""
),
DnsType
.
A
,
DnsClass
.
Any
,
1
,
new
DnsResourceDataUnknown
(
new
DataSegment
(
new
byte
[
0
])))
}.
ToList
(),
// Authorities =
// new[]
// {
// new DnsDataResourceRecord(new DnsDomainName("def"), DnsType.Ns, DnsClass.In, 2222,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("123"))))
// }.ToList(),
// Additionals =
// new[]
// {
// new DnsDataResourceRecord(new DnsDomainName(""), DnsType.A, DnsClass.In, 2222,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("444")))),
// new DnsDataResourceRecord(new DnsDomainName("123"), DnsType.A, DnsClass.In, 2222,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("444")))),
// }.ToList(),
// DomainNameCompressionMode = DnsDomainNameCompressionMode.All,
// FutureUse = 6,
// Id = 16365,
// IsAuthoritiveAnswer = false,
// IsQuery = false,
// IsRecusionAvailable = true,
// IsRecusionDesired = true,
// Opcode = DnsOpcode.Query,
// ResponseCode = DnsResponseCode.ServerFailure,
};
Packet
packet
=
PacketBuilder
.
Build
(
DateTime
.
Now
,
new
EthernetLayer
(),
new
IpV4Layer
(),
new
UdpLayer
(),
dnsLayer
);
Assert
.
IsTrue
(
packet
.
IsValid
,
"IsValid"
);
// DNS
Assert
.
AreEqual
(
dnsLayer
,
packet
.
Ethernet
.
IpV4
.
Udp
.
Dns
.
ExtractLayer
(),
"DNS Layer"
);
}
}
}
\ No newline at end of file
PcapDotNet/src/PcapDotNet.Packets.TestUtils/RandomPacketsExtensions.cs
View file @
ce1f95a8
...
...
@@ -961,9 +961,72 @@ namespace PcapDotNet.Packets.TestUtils
public
static
DnsLayer
NextDnsLayer
(
this
Random
random
)
{
DnsLayer
dnsLayer
=
new
DnsLayer
();
dnsLayer
.
Id
=
random
.
NextUShort
();
dnsLayer
.
IsQuery
=
random
.
NextBool
();
dnsLayer
.
Opcode
=
random
.
NextEnum
<
DnsOpcode
>();
dnsLayer
.
IsAuthoritiveAnswer
=
random
.
NextBool
();
dnsLayer
.
IsTruncated
=
random
.
NextBool
();
dnsLayer
.
IsRecusionDesired
=
random
.
NextBool
();
dnsLayer
.
IsRecusionAvailable
=
random
.
NextBool
();
dnsLayer
.
FutureUse
=
random
.
NextByte
(
DnsDatagram
.
MaxFutureUse
+
1
);
dnsLayer
.
ResponseCode
=
random
.
NextEnum
<
DnsResponseCode
>();
dnsLayer
.
DomainNameCompressionMode
=
random
.
NextEnum
<
DnsDomainNameCompressionMode
>();
int
numQueries
=
random
.
Next
(
10
);
List
<
DnsQueryResourceRecord
>
queries
=
new
List
<
DnsQueryResourceRecord
>();
for
(
int
i
=
0
;
i
!=
numQueries
;
++
i
)
queries
.
Add
(
random
.
NextDnsQueryResourceRecord
());
dnsLayer
.
Queries
=
queries
;
int
numAnswers
=
random
.
Next
(
10
);
List
<
DnsDataResourceRecord
>
answers
=
new
List
<
DnsDataResourceRecord
>();
for
(
int
i
=
0
;
i
!=
numAnswers
;
++
i
)
answers
.
Add
(
random
.
NextDnsDataResourceRecord
());
dnsLayer
.
Answers
=
answers
;
int
numAuthorities
=
random
.
Next
(
10
);
List
<
DnsDataResourceRecord
>
authorities
=
new
List
<
DnsDataResourceRecord
>();
for
(
int
i
=
0
;
i
!=
numAuthorities
;
++
i
)
authorities
.
Add
(
random
.
NextDnsDataResourceRecord
());
dnsLayer
.
Authorities
=
authorities
;
int
numAdditionals
=
random
.
Next
(
10
);
List
<
DnsDataResourceRecord
>
additionals
=
new
List
<
DnsDataResourceRecord
>();
for
(
int
i
=
0
;
i
!=
numAdditionals
;
++
i
)
additionals
.
Add
(
random
.
NextDnsDataResourceRecord
());
dnsLayer
.
Additionals
=
additionals
;
return
dnsLayer
;
}
public
static
DnsQueryResourceRecord
NextDnsQueryResourceRecord
(
this
Random
random
)
{
DnsQueryResourceRecord
record
=
new
DnsQueryResourceRecord
(
random
.
NextDnsDomainName
(),
random
.
NextEnum
<
DnsType
>(),
random
.
NextEnum
<
DnsClass
>());
return
record
;
}
public
static
DnsDataResourceRecord
NextDnsDataResourceRecord
(
this
Random
random
)
{
DnsDataResourceRecord
record
=
new
DnsDataResourceRecord
(
random
.
NextDnsDomainName
(),
random
.
NextEnum
<
DnsType
>(),
random
.
NextEnum
<
DnsClass
>(),
random
.
Next
(),
random
.
NextDnsResourceData
());
return
record
;
}
public
static
DnsDomainName
NextDnsDomainName
(
this
Random
random
)
{
List
<
string
>
labels
=
new
List
<
string
>();
int
numLabels
=
random
.
Next
(
10
);
for
(
int
i
=
0
;
i
!=
numLabels
;
++
i
)
{
int
labelLength
=
random
.
Next
(
10
);
StringBuilder
label
=
new
StringBuilder
();
for
(
int
j
=
0
;
j
!=
labelLength
;
++
j
)
label
.
Append
(
random
.
NextChar
(
'a'
,
'z'
));
labels
.
Add
(
label
.
ToString
());
}
return
new
DnsDomainName
(
string
.
Join
(
"."
,
labels
));
}
public
static
DnsResourceData
NextDnsResourceData
(
this
Random
random
)
{
DnsResourceData
resourceData
=
new
DnsResourceDataUnknown
(
new
DataSegment
(
random
.
NextBytes
(
random
.
Next
(
100
))));
return
resourceData
;
}
// HTTP
public
static
HttpLayer
NextHttpLayer
(
this
Random
random
)
{
...
...
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsDatagram.cs
View file @
ce1f95a8
...
...
@@ -85,7 +85,9 @@ namespace PcapDotNet.Packets.Dns
/// <summary>
/// The number of bytes the DNS header takes.
/// </summary>
public
const
int
HeaderLength
=
10
;
public
const
int
HeaderLength
=
12
;
public
const
byte
MaxFutureUse
=
7
;
/// <summary>
/// A 16 bit identifier assigned by the program that generates any kind of query.
...
...
@@ -156,7 +158,7 @@ namespace PcapDotNet.Packets.Dns
{
get
{
return
ReadBool
(
Offset
.
IsRecusionAvailable
,
Mask
.
IsRecusionAvailable
);
}
}
/// <summary>
/// Reserved for future use.
/// Must be zero in all queries and responses.
...
...
@@ -202,8 +204,8 @@ namespace PcapDotNet.Packets.Dns
{
get
{
return
ReadUShort
(
Offset
.
AdditionalCount
,
Endianity
.
Big
);
}
}
public
ReadOnlyCollection
<
DnsQueryResouceRecord
>
Queries
public
ReadOnlyCollection
<
DnsQueryResou
r
ceRecord
>
Queries
{
get
{
...
...
@@ -246,8 +248,22 @@ namespace PcapDotNet.Packets.Dns
{
return
new
DnsLayer
{
Id
=
Id
,
IsQuery
=
IsQuery
,
Opcode
=
Opcode
,
IsAuthoritiveAnswer
=
IsAuthoritiveAnswer
,
IsTruncated
=
IsTruncated
,
IsRecusionDesired
=
IsRecusionDesired
,
IsRecusionAvailable
=
IsRecusionAvailable
,
FutureUse
=
FutureUse
,
ResponseCode
=
ResponseCode
,
Queries
=
Queries
.
ToList
(),
Answers
=
Answers
.
ToList
(),
Authorities
=
Authorities
.
ToList
(),
Additionals
=
Additionals
.
ToList
(),
};
}
/*
protected override bool CalculateIsValid()
{
...
...
@@ -263,12 +279,68 @@ namespace PcapDotNet.Packets.Dns
{
int
length
=
HeaderLength
;
DnsDomainNameCompressionData
compressionData
=
new
DnsDomainNameCompressionData
(
domainNameCompressionMode
);
foreach
(
DnsResourceRecord
record
in
resourceRecords
)
length
+=
record
.
GetLength
(
compressionData
,
length
);
if
(
resourceRecords
!=
null
)
{
foreach
(
DnsResourceRecord
record
in
resourceRecords
)
length
+=
record
.
GetLength
(
compressionData
,
length
);
}
return
length
;
}
internal
static
void
Write
(
byte
[]
buffer
,
int
offset
,
ushort
id
,
bool
isResponse
,
DnsOpcode
opcode
,
bool
isAuthoritiveAnswer
,
bool
isTruncated
,
bool
isRecursionDesired
,
bool
isRecursionAvailable
,
byte
futureUse
,
DnsResponseCode
responseCode
,
List
<
DnsQueryResourceRecord
>
queries
,
List
<
DnsDataResourceRecord
>
answers
,
List
<
DnsDataResourceRecord
>
authorities
,
List
<
DnsDataResourceRecord
>
additionals
,
DnsDomainNameCompressionMode
domainNameCompressionMode
)
{
buffer
.
Write
(
offset
+
Offset
.
Id
,
id
,
Endianity
.
Big
);
byte
flags0
=
0
;
if
(
isResponse
)
flags0
|=
Mask
.
IsResponse
;
flags0
|=
(
byte
)((((
byte
)
opcode
)
<<
Shift
.
Opcode
)
&
Mask
.
Opcode
);
if
(
isAuthoritiveAnswer
)
flags0
|=
Mask
.
IsAuthoritiveAnswer
;
if
(
isTruncated
)
flags0
|=
Mask
.
IsTruncated
;
if
(
isRecursionDesired
)
flags0
|=
Mask
.
IsRecusionDesired
;
buffer
.
Write
(
offset
+
Offset
.
IsResponse
,
flags0
);
byte
flags1
=
0
;
if
(
isRecursionAvailable
)
flags1
|=
Mask
.
IsRecusionAvailable
;
flags1
|=
(
byte
)((
futureUse
<<
Shift
.
FutureUse
)
&
Mask
.
FutureUse
);
flags1
|=
(
byte
)((
byte
)
responseCode
&
Mask
.
ResponseCode
);
buffer
.
Write
(
offset
+
Offset
.
IsRecusionAvailable
,
flags1
);
DnsDomainNameCompressionData
compressionData
=
new
DnsDomainNameCompressionData
(
domainNameCompressionMode
);
int
recordOffset
=
HeaderLength
;
if
(
queries
!=
null
)
{
buffer
.
Write
(
offset
+
Offset
.
QueryCount
,
(
ushort
)
queries
.
Count
,
Endianity
.
Big
);
foreach
(
DnsQueryResourceRecord
record
in
queries
)
recordOffset
+=
record
.
Write
(
buffer
,
offset
,
compressionData
,
recordOffset
);
}
if
(
answers
!=
null
)
{
buffer
.
Write
(
offset
+
Offset
.
AnswerCount
,
(
ushort
)
answers
.
Count
,
Endianity
.
Big
);
foreach
(
DnsDataResourceRecord
record
in
answers
)
recordOffset
+=
record
.
Write
(
buffer
,
offset
,
compressionData
,
recordOffset
);
}
if
(
authorities
!=
null
)
{
buffer
.
Write
(
offset
+
Offset
.
AuthorityCount
,
(
ushort
)
authorities
.
Count
,
Endianity
.
Big
);
foreach
(
DnsDataResourceRecord
record
in
authorities
)
recordOffset
+=
record
.
Write
(
buffer
,
offset
,
compressionData
,
recordOffset
);
}
if
(
additionals
!=
null
)
{
buffer
.
Write
(
offset
+
Offset
.
AdditionalCount
,
(
ushort
)
additionals
.
Count
,
Endianity
.
Big
);
foreach
(
DnsDataResourceRecord
record
in
additionals
)
recordOffset
+=
record
.
Write
(
buffer
,
offset
,
compressionData
,
recordOffset
);
}
}
private
int
QueriesOffset
{
get
{
return
HeaderLength
;
}
...
...
@@ -303,7 +375,7 @@ namespace PcapDotNet.Packets.Dns
private
void
ParseQueries
()
{
ParseRecords
(
QueriesOffset
,
()
=>
QueryCount
,
DnsQueryResouceRecord
.
Parse
,
ref
_queries
,
ref
_answersOffset
);
ParseRecords
(
QueriesOffset
,
()
=>
QueryCount
,
DnsQueryResou
r
ceRecord
.
Parse
,
ref
_queries
,
ref
_answersOffset
);
}
private
void
ParseAnswers
()
...
...
@@ -324,7 +396,7 @@ namespace PcapDotNet.Packets.Dns
private
delegate
TRecord
ParseRecord
<
out
TRecord
>(
DnsDatagram
dns
,
int
offset
,
out
int
numBytesRead
);
private
void
ParseRecords
<
TRecord
>(
int
offset
,
Func
<
ushort
>
countDelegate
,
ParseRecord
<
TRecord
>
parseRecord
,
private
void
ParseRecords
<
TRecord
>(
int
offset
,
Func
<
ushort
>
countDelegate
,
ParseRecord
<
TRecord
>
parseRecord
,
ref
ReadOnlyCollection
<
TRecord
>
parsedRecords
,
ref
int
nextOffset
)
{
if
(
parsedRecords
==
null
&&
Length
>=
offset
)
...
...
@@ -348,7 +420,7 @@ namespace PcapDotNet.Packets.Dns
}
}
private
ReadOnlyCollection
<
DnsQueryResouceRecord
>
_queries
;
private
ReadOnlyCollection
<
DnsQueryResou
r
ceRecord
>
_queries
;
private
ReadOnlyCollection
<
DnsDataResourceRecord
>
_answers
;
private
ReadOnlyCollection
<
DnsDataResourceRecord
>
_authorities
;
private
ReadOnlyCollection
<
DnsDataResourceRecord
>
_additionals
;
...
...
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsDomainName.cs
View file @
ce1f95a8
...
...
@@ -12,7 +12,15 @@ namespace PcapDotNet.Packets.Dns
public
class
DnsDomainName
{
private
const
byte
MaxLabelLength
=
63
;
private
const
ushort
OffsetMask
=
0xC000
;
private
const
ushort
CompressionMarker
=
0xC000
;
private
const
ushort
OffsetMask
=
0x3FFF
;
private
static
readonly
char
[]
Colon
=
new
[]
{
'.'
};
public
DnsDomainName
(
string
domainName
)
{
string
[]
labels
=
domainName
.
ToLowerInvariant
().
Split
(
Colon
,
StringSplitOptions
.
RemoveEmptyEntries
);
_labels
=
labels
.
Select
(
label
=>
new
DataSegment
(
Encoding
.
UTF8
.
GetBytes
(
label
))).
ToList
();
}
public
int
NumLabels
{
...
...
@@ -25,7 +33,7 @@ namespace PcapDotNet.Packets.Dns
public
override
string
ToString
()
{
if
(
_ascii
==
null
)
_ascii
=
_labels
.
Select
(
label
=>
label
.
ToString
(
Encoding
.
ASCII
)).
Concat
(
string
.
Empty
).
SequenceToString
(
'.'
)
;
_ascii
=
_labels
.
Select
(
label
=>
label
.
ToString
(
Encoding
.
UTF8
)).
SequenceToString
(
'.'
)
+
"."
;
return
_ascii
;
}
...
...
@@ -37,8 +45,8 @@ namespace PcapDotNet.Packets.Dns
ListSegment
<
DataSegment
>
labels
=
new
ListSegment
<
DataSegment
>(
_labels
,
i
);
if
(
compressionData
.
IsAvailable
(
labels
))
return
length
+
sizeof
(
ushort
);
length
+=
sizeof
(
byte
)
+
_labels
[
i
].
Length
;
compressionData
.
AddCompressionData
(
labels
,
offsetInDns
+
length
);
length
+=
sizeof
(
byte
)
+
labels
[
0
].
Length
;
}
return
length
+
sizeof
(
byte
);
}
...
...
@@ -50,6 +58,28 @@ namespace PcapDotNet.Packets.Dns
return
new
DnsDomainName
(
labels
);
}
internal
int
Write
(
byte
[]
buffer
,
int
dnsOffset
,
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
)
{
int
length
=
0
;
for
(
int
i
=
0
;
i
!=
NumLabels
;
++
i
)
{
ListSegment
<
DataSegment
>
labels
=
new
ListSegment
<
DataSegment
>(
_labels
,
i
);
int
pointerOffset
;
if
(
compressionData
.
TryGetOffset
(
labels
,
out
pointerOffset
))
{
buffer
.
Write
(
dnsOffset
+
offsetInDns
+
length
,
(
ushort
)(
CompressionMarker
|
(
ushort
)
pointerOffset
),
Endianity
.
Big
);
return
length
+
sizeof
(
ushort
);
}
DataSegment
currentLabel
=
labels
[
0
];
compressionData
.
AddCompressionData
(
labels
,
offsetInDns
+
length
);
buffer
.
Write
(
dnsOffset
+
offsetInDns
+
length
,
(
byte
)
currentLabel
.
Length
);
length
+=
sizeof
(
byte
);
currentLabel
.
Write
(
buffer
,
dnsOffset
+
offsetInDns
+
length
);
length
+=
currentLabel
.
Length
;
}
return
length
+
sizeof
(
byte
);
}
private
DnsDomainName
(
List
<
DataSegment
>
labels
)
{
_labels
=
labels
;
...
...
@@ -84,6 +114,7 @@ namespace PcapDotNet.Packets.Dns
return
;
labels
.
Add
(
dns
.
SubSegment
(
offsetInDns
,
labelLength
));
numBytesRead
+=
labelLength
;
offsetInDns
+=
labelLength
;
}
}
while
(
labelLength
!=
0
);
}
...
...
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsDomainNameCompressionData.cs
View file @
ce1f95a8
...
...
@@ -2,6 +2,7 @@
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Linq
;
using
PcapDotNet.Base
;
namespace
PcapDotNet.Packets.Dns
{
...
...
@@ -115,32 +116,47 @@ namespace PcapDotNet.Packets.Dns
internal
class
DnsDomainNameCompressionData
{
private
class
LabelNode
{
public
int
?
DnsOffset
{
get
;
private
set
;
}
public
bool
IsAvailable
(
ListSegment
<
DataSegment
>
labels
)
{
if
(
labels
.
Count
==
0
)
return
DnsOffset
!=
null
;
LabelNode
nextNode
;
if
(!
_nextLabels
.
TryGetValue
(
labels
[
0
],
out
nextNode
))
return
false
;
return
nextNode
.
IsAvailable
(
labels
.
SubSegment
(
1
));
}
public
void
AddLabels
(
ListSegment
<
DataSegment
>
labels
,
int
dnsOffset
)
{
if
(
labels
.
Count
==
0
)
{
DnsOffset
=
dnsOffset
;
return
;
}
_nextLabels
[
labels
[
0
]].
AddLabels
(
labels
.
SubSegment
(
1
),
dnsOffset
);
}
private
readonly
Dictionary
<
DataSegment
,
LabelNode
>
_nextLabels
=
new
Dictionary
<
DataSegment
,
LabelNode
>();
}
// private class LabelNode
// {
// public int? DnsOffset { get; private set; }
//
// public bool TryGetOffset(ListSegment<DataSegment> labels, out int offsetInDns)
// {
// if (labels.Count == 0)
// {
// offsetInDns = DnsOffset.GetValueOrDefault();
// return DnsOffset.HasValue;
// }
// LabelNode nextNode;
// if (!_nextLabels.TryGetValue(labels[0], out nextNode))
// {
// offsetInDns = 0;
// return false;
// }
// offsetInDns = nextNode.DnsOffset.Value;
// int nextNodeOffset;
// return nextNode.TryGetOffset(labels.SubSegment(1), out nextNodeOffset);
// }
//
// public void AddLabels(ListSegment<DataSegment> labels, int dnsOffset)
// {
// if (labels.Count == 0)
// {
// DnsOffset = dnsOffset;
// return;
// }
// DataSegment firstLabel = labels[0];
// LabelNode node;
// if (!_nextLabels.TryGetValue(firstLabel, out node))
// {
// node = new LabelNode();
// _nextLabels.Add(firstLabel, node);
// }
// node.AddLabels(labels.SubSegment(1), dnsOffset);
// }
//
// private readonly Dictionary<DataSegment, LabelNode> _nextLabels = new Dictionary<DataSegment, LabelNode>();
// }
public
DnsDomainNameCompressionData
(
DnsDomainNameCompressionMode
domainNameCompressionMode
)
{
...
...
@@ -150,12 +166,19 @@ namespace PcapDotNet.Packets.Dns
public
DnsDomainNameCompressionMode
DomainNameCompressionMode
{
get
;
private
set
;
}
public
bool
IsAvailable
(
ListSegment
<
DataSegment
>
labels
)
{
int
offsetInDns
;
return
TryGetOffset
(
labels
,
out
offsetInDns
);
}
public
bool
TryGetOffset
(
ListSegment
<
DataSegment
>
labels
,
out
int
offsetInDns
)
{
switch
(
DomainNameCompressionMode
)
{
case
DnsDomainNameCompressionMode
.
All
:
return
_
root
.
IsAvailable
(
label
s
);
return
_
data
.
TryGetValue
(
labels
,
out
offsetInDn
s
);
case
DnsDomainNameCompressionMode
.
Nothing
:
offsetInDns
=
0
;
return
false
;
default
:
throw
new
InvalidOperationException
(
string
.
Format
(
"Invalid DomainNameCompressionMode {0}"
,
DomainNameCompressionMode
));
...
...
@@ -167,7 +190,8 @@ namespace PcapDotNet.Packets.Dns
switch
(
DomainNameCompressionMode
)
{
case
DnsDomainNameCompressionMode
.
All
:
_root
.
AddLabels
(
labels
,
dnsOffset
);
if
(!
_data
.
ContainsKey
(
labels
))
_data
.
Add
(
labels
,
dnsOffset
);
return
;
case
DnsDomainNameCompressionMode
.
Nothing
:
return
;
...
...
@@ -176,6 +200,9 @@ namespace PcapDotNet.Packets.Dns
}
}
private
readonly
LabelNode
_root
=
new
LabelNode
();
private
static
readonly
InlineEqualityComparer
<
ListSegment
<
DataSegment
>>
_labelsComparer
=
new
InlineEqualityComparer
<
ListSegment
<
DataSegment
>>((
x
,
y
)
=>
x
.
SequenceEqual
(
y
),
obj
=>
obj
.
SequenceGetHashCode
());
private
readonly
Dictionary
<
ListSegment
<
DataSegment
>,
int
>
_data
=
new
Dictionary
<
ListSegment
<
DataSegment
>,
int
>(
_labelsComparer
);
}
}
\ No newline at end of file
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsLayer.cs
View file @
ce1f95a8
...
...
@@ -10,9 +10,8 @@ namespace PcapDotNet.Packets.Dns
/// Represents a DNS layer.
/// <seealso cref="DnsDatagram"/>
/// </summary>
public
class
DnsLayer
:
Layer
,
IEquatable
<
DnsLayer
>
public
class
DnsLayer
:
Simple
Layer
,
IEquatable
<
DnsLayer
>
{
public
ushort
Id
{
get
;
set
;
}
public
bool
IsResponse
{
get
;
set
;
}
public
bool
IsQuery
...
...
@@ -35,7 +34,7 @@ namespace PcapDotNet.Packets.Dns
public
DnsResponseCode
ResponseCode
{
get
;
set
;
}
public
List
<
DnsQueryResouceRecord
>
Queries
{
get
;
set
;
}
public
List
<
DnsQueryResou
r
ceRecord
>
Queries
{
get
;
set
;
}
public
List
<
DnsDataResourceRecord
>
Answers
{
get
;
set
;
}
...
...
@@ -45,7 +44,16 @@ namespace PcapDotNet.Packets.Dns
public
IEnumerable
<
DnsResourceRecord
>
Records
{
get
{
return
Queries
.
Concat
<
DnsResourceRecord
>(
Answers
).
Concat
(
Authorities
).
Concat
(
Additionals
);
}
get
{
IEnumerable
<
DnsResourceRecord
>
allRecords
=
null
;
foreach
(
IEnumerable
<
DnsResourceRecord
>
records
in
new
IEnumerable
<
DnsResourceRecord
>[]
{
Queries
,
Answers
,
Authorities
,
Additionals
})
{
if
(
records
!=
null
)
allRecords
=
allRecords
==
null
?
records
:
allRecords
.
Concat
(
records
);
}
return
allRecords
;
}
}
public
DnsDomainNameCompressionMode
DomainNameCompressionMode
{
get
;
set
;
}
...
...
@@ -66,11 +74,11 @@ namespace PcapDotNet.Packets.Dns
/// </summary>
/// <param name="buffer">The buffer to write the layer to.</param>
/// <param name="offset">The offset in the buffer to start writing the layer at.</param>
/// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param>
/// <param name="previousLayer">The layer that comes before this layer. null if this is the first layer.</param>
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public
override
void
Write
(
byte
[]
buffer
,
int
offset
,
int
payloadLength
,
ILayer
previousLayer
,
ILayer
nextLayer
)
protected
override
void
Write
(
byte
[]
buffer
,
int
offset
)
{
DnsDatagram
.
Write
(
buffer
,
offset
,
Id
,
IsResponse
,
Opcode
,
IsAuthoritiveAnswer
,
IsTruncated
,
IsRecusionDesired
,
IsRecusionAvailable
,
FutureUse
,
ResponseCode
,
Queries
,
Answers
,
Authorities
,
Additionals
,
DomainNameCompressionMode
);
}
/// <summary>
...
...
@@ -90,7 +98,20 @@ namespace PcapDotNet.Packets.Dns
/// </summary>
public
bool
Equals
(
DnsLayer
other
)
{
return
other
!=
null
;
return
other
!=
null
&&
Id
==
other
.
Id
&&
IsQuery
==
other
.
IsQuery
&&
Opcode
==
other
.
Opcode
&&
IsAuthoritiveAnswer
==
other
.
IsAuthoritiveAnswer
&&
IsTruncated
==
other
.
IsTruncated
&&
IsRecusionDesired
==
other
.
IsRecusionDesired
&&
IsRecusionAvailable
==
other
.
IsRecusionAvailable
&&
FutureUse
==
other
.
FutureUse
&&
ResponseCode
==
other
.
ResponseCode
&&
(
Queries
.
IsNullOrEmpty
()
==
other
.
Queries
.
IsNullOrEmpty
()
||
Queries
.
SequenceEqual
(
other
.
Queries
))
&&
(
Answers
.
IsNullOrEmpty
()
==
other
.
Answers
.
IsNullOrEmpty
()
||
Answers
.
SequenceEqual
(
other
.
Answers
))
&&
(
Authorities
.
IsNullOrEmpty
()
==
other
.
Authorities
.
IsNullOrEmpty
()
||
Authorities
.
SequenceEqual
(
other
.
Authorities
))
&&
(
Additionals
.
IsNullOrEmpty
()
==
other
.
Additionals
.
IsNullOrEmpty
()
||
Additionals
.
SequenceEqual
(
other
.
Additionals
));
}
/// <summary>
...
...
PcapDotNet/src/PcapDotNet.Packets/Dns/DnsResourceRecord.cs
View file @
ce1f95a8
...
...
@@ -3,6 +3,14 @@ using System.Collections.Generic;
namespace
PcapDotNet.Packets.Dns
{
// public enum DnsSection
// {
// Query,
// Answer,
// Authority,
// Additional,
// }
/// <summary>
/// RFC 1035.
/// All RRs have the same top level format shown below:
...
...
@@ -43,6 +51,8 @@ namespace PcapDotNet.Packets.Dns
DnsClass
=
dnsClass
;
}
// public abstract DnsSection Section { get; }
/// <summary>
/// An owner name, i.e., the name of the node to which this resource record pertains.
/// </summary>
...
...
@@ -72,6 +82,11 @@ namespace PcapDotNet.Packets.Dns
/// </summary>
public
abstract
DnsResourceData
Data
{
get
;
protected
set
;
}
public
override
string
ToString
()
{
return
DomainName
+
" "
+
Type
+
" "
+
DnsClass
;
}
internal
static
bool
TryParseBase
(
DnsDatagram
dns
,
int
offsetInDns
,
out
DnsDomainName
domainName
,
out
DnsType
type
,
out
DnsClass
dnsClass
,
out
int
numBytesRead
)
{
...
...
@@ -81,11 +96,11 @@ namespace PcapDotNet.Packets.Dns
if
(
domainName
==
null
)
return
false
;
if
(
offsetInDns
+
numBytesRead
+
MinimumLengthAfterDomainName
>
=
dns
.
Length
)
if
(
offsetInDns
+
numBytesRead
+
MinimumLengthAfterDomainName
>
dns
.
Length
)
return
false
;
type
=
(
DnsType
)
dns
.
ReadUShort
(
OffsetAfterDomainName
.
Type
,
Endianity
.
Big
);
dnsClass
=
(
DnsClass
)
dns
.
ReadUShort
(
OffsetAfterDomainName
.
DnsClass
,
Endianity
.
Big
);
type
=
(
DnsType
)
dns
.
ReadUShort
(
offsetInDns
+
numBytesRead
+
OffsetAfterDomainName
.
Type
,
Endianity
.
Big
);
dnsClass
=
(
DnsClass
)
dns
.
ReadUShort
(
offsetInDns
+
numBytesRead
+
OffsetAfterDomainName
.
DnsClass
,
Endianity
.
Big
);
numBytesRead
+=
MinimumLengthAfterDomainName
;
return
true
;
}
...
...
@@ -96,11 +111,22 @@ namespace PcapDotNet.Packets.Dns
}
internal
abstract
int
GetLengthAfterBase
(
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
);
internal
virtual
int
Write
(
byte
[]
buffer
,
int
dnsOffset
,
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
)
{
int
length
=
0
;
length
+=
DomainName
.
Write
(
buffer
,
dnsOffset
,
compressionData
,
offsetInDns
+
length
);
buffer
.
Write
(
dnsOffset
+
offsetInDns
+
length
,
(
ushort
)
Type
,
Endianity
.
Big
);
length
+=
sizeof
(
ushort
);
buffer
.
Write
(
dnsOffset
+
offsetInDns
+
length
,
(
ushort
)
DnsClass
,
Endianity
.
Big
);
length
+=
sizeof
(
ushort
);
return
length
;
}
}
public
class
DnsQueryResouceRecord
:
DnsResourceRecord
public
class
DnsQueryResou
r
ceRecord
:
DnsResourceRecord
{
public
DnsQueryResouceRecord
(
DnsDomainName
domainName
,
DnsType
type
,
DnsClass
dnsClass
)
public
DnsQueryResou
r
ceRecord
(
DnsDomainName
domainName
,
DnsType
type
,
DnsClass
dnsClass
)
:
base
(
domainName
,
type
,
dnsClass
)
{
}
...
...
@@ -117,7 +143,7 @@ namespace PcapDotNet.Packets.Dns
protected
set
{
throw
new
InvalidOperationException
(
"No Resource Data in queries"
);
}
}
internal
static
DnsQueryResouceRecord
Parse
(
DnsDatagram
dns
,
int
offsetInDns
,
out
int
numBytesRead
)
internal
static
DnsQueryResou
r
ceRecord
Parse
(
DnsDatagram
dns
,
int
offsetInDns
,
out
int
numBytesRead
)
{
DnsDomainName
domainName
;
DnsType
type
;
...
...
@@ -125,7 +151,7 @@ namespace PcapDotNet.Packets.Dns
if
(!
TryParseBase
(
dns
,
offsetInDns
,
out
domainName
,
out
type
,
out
dnsClass
,
out
numBytesRead
))
return
null
;
return
new
DnsQueryResouceRecord
(
domainName
,
type
,
dnsClass
);
return
new
DnsQueryResou
r
ceRecord
(
domainName
,
type
,
dnsClass
);
}
internal
override
int
GetLengthAfterBase
(
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
)
...
...
@@ -167,6 +193,11 @@ namespace PcapDotNet.Packets.Dns
/// </summary>
public
override
DnsResourceData
Data
{
get
;
protected
set
;
}
public
override
string
ToString
()
{
return
base
.
ToString
()
+
" "
+
Ttl
+
" "
+
Data
;
}
internal
static
DnsDataResourceRecord
Parse
(
DnsDatagram
dns
,
int
offsetInDns
,
out
int
numBytesRead
)
{
DnsDomainName
domainName
;
...
...
@@ -175,14 +206,14 @@ namespace PcapDotNet.Packets.Dns
if
(!
TryParseBase
(
dns
,
offsetInDns
,
out
domainName
,
out
type
,
out
dnsClass
,
out
numBytesRead
))
return
null
;
offsetInDns
+=
numBytesRead
;
if
(
offsetInDns
+
numBytesRead
+
MinimumLengthAfterBase
>=
dns
.
Length
)
if
(
offsetInDns
+
numBytesRead
+
MinimumLengthAfterBase
>
dns
.
Length
)
return
null
;
int
ttl
=
dns
.
ReadInt
(
offsetInDns
+
numBytesRead
+
OffsetAfterBase
.
Ttl
,
Endianity
.
Big
);
ushort
dataLength
=
dns
.
ReadUShort
(
offsetInDns
+
numBytesRead
+
OffsetAfterBase
.
DataLength
,
Endianity
.
Big
);
numBytesRead
+=
MinimumLengthAfterBase
;
if
(
offsetInDns
+
numBytesRead
+
dataLength
>
dns
.
Length
)
return
null
;
DnsResourceData
data
=
DnsResourceData
.
Read
(
dns
,
offsetInDns
+
numBytesRead
,
dataLength
);
if
(
data
==
null
)
return
null
;
...
...
@@ -195,6 +226,15 @@ namespace PcapDotNet.Packets.Dns
{
return
MinimumLengthAfterBase
+
Data
.
GetLength
(
compressionData
,
offsetInDns
);
}
internal
override
int
Write
(
byte
[]
buffer
,
int
dnsOffset
,
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
)
{
int
length
=
base
.
Write
(
buffer
,
dnsOffset
,
compressionData
,
offsetInDns
);
buffer
.
Write
(
dnsOffset
+
offsetInDns
+
length
,
Ttl
,
Endianity
.
Big
);
length
+=
sizeof
(
uint
);
length
+=
Data
.
Write
(
buffer
,
dnsOffset
,
offsetInDns
+
length
,
compressionData
);
return
length
;
}
}
public
abstract
class
DnsResourceData
...
...
@@ -205,6 +245,16 @@ namespace PcapDotNet.Packets.Dns
}
internal
abstract
int
GetLength
(
DnsDomainNameCompressionData
compressionData
,
int
offsetInDns
);
internal
int
Write
(
byte
[]
buffer
,
int
dnsOffset
,
int
offsetInDns
,
DnsDomainNameCompressionData
compressionData
)
{
int
length
=
WriteData
(
buffer
,
dnsOffset
,
offsetInDns
+
sizeof
(
ushort
),
compressionData
);
buffer
.
Write
(
dnsOffset
+
offsetInDns
,
(
ushort
)
length
,
Endianity
.
Big
);
length
+=
sizeof
(
ushort
);
return
length
;
}
internal
abstract
int
WriteData
(
byte
[]
buffer
,
int
dnsOffset
,
int
offsetInDns
,
DnsDomainNameCompressionData
compressionData
);
}
public
class
DnsResourceDataUnknown
:
DnsResourceData
...
...
@@ -220,5 +270,11 @@ namespace PcapDotNet.Packets.Dns
{
return
Data
.
Length
;
}
internal
override
int
WriteData
(
byte
[]
buffer
,
int
dnsOffset
,
int
offsetInDns
,
DnsDomainNameCompressionData
compressionData
)
{
Data
.
Write
(
buffer
,
dnsOffset
+
offsetInDns
);
return
Data
.
Length
;
}
}
}
\ No newline at end of file
PcapDotNet/src/PcapDotNet.Packets/PacketBuilder.cs
View file @
ce1f95a8
...
...
@@ -105,25 +105,27 @@ namespace PcapDotNet.Packets
/// <returns>A packet built from the builder's layers with the given timestamp.</returns>
public
Packet
Build
(
DateTime
timestamp
)
{
int
length
=
_layers
.
Select
(
layer
=>
layer
.
Length
).
Sum
();
int
[]
layersLength
=
_layers
.
Select
(
layer
=>
layer
.
Length
).
ToArray
();
int
length
=
layersLength
.
Sum
();
byte
[]
buffer
=
new
byte
[
length
];
WriteLayers
(
buffer
,
length
);
WriteLayers
(
layersLength
,
buffer
,
length
);
FinalizeLayers
(
buffer
,
length
);
return
new
Packet
(
buffer
,
timestamp
,
_dataLink
);
}
private
void
WriteLayers
(
byte
[]
buffer
,
int
length
)
private
void
WriteLayers
(
int
[]
layersLength
,
byte
[]
buffer
,
int
length
)
{
int
offset
=
0
;
for
(
int
i
=
0
;
i
!=
_layers
.
Length
;
++
i
)
{
ILayer
layer
=
_layers
[
i
];
int
layerLength
=
layersLength
[
i
];
ILayer
previousLayer
=
i
==
0
?
null
:
_layers
[
i
-
1
];
ILayer
nextLayer
=
i
==
_layers
.
Length
-
1
?
null
:
_layers
[
i
+
1
];
layer
.
Write
(
buffer
,
offset
,
length
-
offset
-
layer
.
Length
,
previousLayer
,
nextLayer
);
offset
+=
layer
.
Length
;
layer
.
Write
(
buffer
,
offset
,
length
-
offset
-
layerLength
,
previousLayer
,
nextLayer
);
offset
+=
layerLength
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment