* properly set extended rcode when packing
When calling `SetExtendedRcode`, we expect to get the full extended
rcode, not the rcode after we shift 4 bytes right.
* fix extended rcode
* fix TestOPTTtl test
* set error messages in TestPackExtendedBadCookie
* Set Rcode with extended rcode
* |=
* Set extended RCODE field to 0 when RCODE is not an extended one.
+ unittests
* Force setting extended rcode if we have an OPT available.
* go fmt + @tmthrgd comments
* comments and nits
* reformat comment
* Simplify appendByte
* Add test case and benchmark for sprintName
* Add test case and benchmark for sprintTxtOctet
* Add test case and benchmark for sprintTxt
* Use strings.Builder for sprint* functions in types.go
* Use writeByte helper in unpackString
* Rename writeByte to writeEscapedByte
This better captures the purpose of this function.
These two functions were identical (sans-variable names) before I
optimized unpackString in 5debfeec63.
This will improve the performance of it's only caller unpackTxt and is
covered by the test and benchmark added in 5debfeec63.
* Remove redundant parenthesis
These were caught with:
gofmt -r '(a) -> a' -w *.go
This commit only includes the changes where the formatting makes the
ordering of operations clear.
* Remove more redundant parenthesis
These were caught with:
gofmt -r '(a) -> a' -w *.go
This commit includes the remaining changes where the formatting does not
make the ordering of operations as clear as the previous commit.
* Fixed len computation when size just goes beyond 14 bits
* Added bouds checks around 14bits
* Len() always right including when around 14bits boudaries
* Avoid splitting into labels when not applicable
* Fixed comments
* Added comments in code
* Added new test cases
* Fixed computation of Len() for SRV and all kind of records
* Fixed Sign that was relying on non-copy for Unit tests
* Removed unused padding
* Fixed typo in PackBuffer() function
* Added comment about packBufferWithCompressionMap() for testing purposes
* do not modify dns.Rcode when packing to wire format
When the message has an EDNS0 option in the additional section and
dns.Msg.Rcode is set to an extended rcode, dns.Msg.PackBuffer() modifies
dns.Msg.Rcode.
If you were to `Pack` the message and log it after, the Rcode would show
NOERROR.
Running the test before the change would error with:
```
=== RUN TestPackNoSideEffect
--- FAIL: TestPackNoSideEffect (0.00s)
msg_test.go:51: after pack: Rcode is expected to be BADVERS
```
after fixing dns.Msg.PackBuffer(), all tests are still passing.
Fixes#674
* address comments from PR#675
This offset max was not taking into account leading Len() to emit a
smaller value that could not be matched by Pack(), i.e all names can
be fully compressed or used as a target for compression.
Split length tests off in seperate file length_test.go to clean up
dns_test.og a bit.
We currently use information from a potential attacker to pre-allocate slices for the Question, Answer, etc. sections. This allows an attacker to force allocation of several MiB per parsed Msg.
Instead, don't pre-allocate those slices. append() always allocates in powers of two, which is probably the best we can do.
Fixes#609.
* limiting domain names to 255/63 octets/labels (#463)
(cherry picked from commit 0b729df06c)
* account for \ and \xxx in presentation format
(cherry picked from commit a094f774892fb4305051d185c2488cb43200c4d9)
* go fmt
* Add tests for UnpackDomainName
Domain names must not exceed 255 octets in wire format.
Ref gh-463
Ref gh-469
* Fix UnpackDomainName
* Introduce a long-domain sentinel error
A typed error would be better, but inconsistent with this library.
cf. https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully
* Generate the compressionHelper functions and fix compression.
This was a long standing TODO: generate the compression helper
functions. This now automatically picks up new names that can be
used for compression.
When packing add names to compression map:
When packing a message we should only compress when compress is true.
But whenever the compression map is not nil we should still add names
to it that can be *used* for future compression. The packing
inadvertently only added those names when compress would be true.
* Removed unused functions
* Work around golang/go#11833 predictable random issue.
In certain circumstances crypto/rand.Reader will return non-random
bytes. The most likely case is near boot, and as init is run when
the go program is started, it's possible that a non-random seed
could be used. While this is very unlikely to ever be an issue,
it is a very easy fix and it is preferable to be resilient.
Instead of seeding the global math/rand rng during init, a separate
math/rand.Rand is seeded upon the first call to Id. This also avoids
polluting the global math/rand rng which might be seeded elsewhere.
If crypto/rand.Reader fails, math/rand.Int63 will be called to
provide a seed. This is better than the current fallback to a seed
of 1.
This change introduces no noticeable performance overhead as the
global math/rand rng already uses a sync.Mutex internally.
* Document lack of performance overhead from mutex in `func id()`
* Test for proper parsing of whitespace-separated (TXT) character-strings
* Properly parse whitespace-separated (TXT) character-strings
* Remove non-RFC treatment of backslash sequences in character-strings
Fixes gh-420
* For tests, remove non-RFC treatment of backslashes in domain names
* Cleanup and removals
Gut rawmsg.go as most functions are not used. Reword some documentation.
Add more types to be checked for name compression.
* Yeah, we do use these
* Remove this function as well - only used one
Update the size-xxx-member tags to point to another field in the struct
that should be used for the length in that field. Fix NSEC3/HIP and TSIG
to use to this and generate the correct pack/unpack functions for them.
Remove IPSECKEY from the lib and handle it as an unknown record - it is
such a horrible RR, needed kludges before - now just handle it as an
unknown RR.
All types now use generated pack and unpack functions. The blacklist is
removed.
Make the reflection types a black list (these types use (or should use)
the tag 'size-xxx' in their struct definition.s
HIP, IPSECKEY, NSEC3, TSIG
All other types don't use reflection anymore.
* Return a pointer to the header when there is no rdata, this restores old
behavior. The rest of the conversion mostly hangs on getting size-hex
right, but then packStruct and packStructValue and the unpack variant
can be killed.
* Generate pack and unpack for all embedded types as well.
* Fix PrivateRRs, register an unpack function as well, when you register
a new PrivateRR.
* Add the tag octet, nsec, []domains and more to msg_helper.go
* Make the error variable always named err.
Sometimes the error variable was named 'err' sometimes 'e'. Sometimes
'e' refered to an EDNS or string and not an error type.
* Use t.Errorf instead of t.Logf & t.Fail.
* Remove {un,}packUint{16,32}Msg functions.
unpackUint16Msg unpackUint32Msg packUint16Msg packUint32Msg implemented
functionality that is part of the encoding/binary package.
* Use encoding/binary's encoding in more places.
Add dns:txt parsing helper to prevent compile errors. This allows
us to generate all unpack/pack function.
Add pack to the RR interface definition and add this method to
PrivateRR.
We still use typeToUnpack to select which types don't use reflection.
* Use crypto/rand to seed math/rand instead of using the default seed
* Better seeding+generation and fallback on crypto/rand.Read failure
* Remove user warning
Remove the use of reflection when packing and unpacking, instead
generate all the pack and unpack functions using msg_generate.
This will generate zmsg.go which in turn calls the helper functions from
msg_helper.go.
This increases the speed by about ~30% while cutting back on memory
usage. Not all RRs are using it, but that will be rectified in upcoming
PR.
Most of the speed increase is in the header/question section parsing.
These functions *are* not generated, but straight forward enough. The
implementation can be found in msg.go.
The new code has been fuzzed by go-fuzz, which turned up some issues.
All files that started with 'z', and not autogenerated were renamed,
i.e. zscan.go is now scan.go.
Reflection is still used, in subsequent PRs it will be removed entirely.
This process probably fixes a bug in NSAPPTR.len(), after a similar one was
found in HINFO.len().
This should also make it easier to make changes to these functions, and
check their correctness.
Generate the code by running "go generate".
Add function that dedups a list of RRs. Work on strings, which
adds garbage, but seems to be the least intrusive and takes the
last amount of memory.
Some fmt changes snook in as well.
When a pointer points to a empty name, the "return '.'" special case used to
kick in which is not pointer-aware so it would reset the parsing offset to
the pointer target
This was independently found and fixed in c13d4ee, I'm submitting this patch
anyway as it seems a bit more robust and DRY [citation needed].
If the root label is compressed (which is 2 bytes, the root label
itself is only 1 byte, so why do it?), go dns incorrectly set the
offset when encountering such a name.
Fixes#234
A handful of EDNS options have been standardized, and they each have a type defined in GoDNS. However there is currently no way a development team can use GoDNS with internally defined options, or with new options that may be proposed in the future.
This change solves the problem by giving users an EDNS0_CUSTOM type to allow clients to send, and servers to receive, custom EDNS options.
If you have a system with large amounts of copies, these slice
allocations start stacking up. Use a shared slice and then subslice
them with a cap limit so that append works properly.
Also, add a benchmark and test for Msg.Copy
Benchcmp:
benchmark old ns/op new ns/op delta
BenchmarkCopy 1880 1672 -11.06%
benchmark old allocs new allocs delta
BenchmarkCopy 13 11 -15.38%
benchmark old bytes new bytes delta
BenchmarkCopy 528 528 +0.00%
IPSECKEY is kinda strange because it has a type selector which tells
what type a later rdata field has. The type can be a domainname, address
or v6 address. You sort of wish Go would have a union type for this, but
alas.
Currently this is implemented as:
GatewayA net.IP `dns:"a"`
GatewayAAAA net.IP `dns:"aaaa"`
GatewayName string `dns:"domain-name"`
In the IPSECKEY. Only one of these is active at any one time. When
parsing/packing and unpacking the value of GatewayType is checked
to see what to do.
Parsing from strings is also implemented properly and tested. The Unpack
function still needs work.
ECDSA public keys consist of a single value, called "Q" in FIPS
186-3. In DNSSEC keys, Q is a simple bit string that represents the
uncompressed form of a curve point, "x | y".
The ECDSA signature is the combination of two non-negative integers,
called "r" and "s" in FIPS 186-3. The two integers, each of which is
formatted as a simple octet string, are combined into a single longer
octet string for DNSSEC as the concatenation "r | s". (Conversion of
the integers to bit strings is described in Section C.2 of FIPS
186-3.) For P-256, each integer MUST be encoded as 32 octets; for
P-384, each integer MUST be encoded as 48 octets.
Instead of going through the fmt package, we can use append int,
which saves an allocation.
benchmark old ns/op new ns/op delta
BenchmarkUnpackDomainNameUnprintable 2147 506 -76.43%
This is based on @miekg's sig0 branch. That branch diverged from master
and I didn't want to wander off on a rebase.
As implemented there's no allowance for multi-envelope (TCP) support.
TODO:
* unpackUint32() could be moved out and used elsewhere
* tests
* multi-envelope support (if useful)