From bf609a4cf8b0946331be0de9922dcd75ea22530c Mon Sep 17 00:00:00 2001 From: David Fifield Date: Fri, 20 Mar 2020 23:25:07 -0600 Subject: [PATCH] Set MTU based on domain length. --- dnstt-client/dns_test.go | 27 +++++++++++++++++++++++++++ dnstt-client/main.go | 26 +++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 dnstt-client/dns_test.go diff --git a/dnstt-client/dns_test.go b/dnstt-client/dns_test.go new file mode 100644 index 0000000..071fc50 --- /dev/null +++ b/dnstt-client/dns_test.go @@ -0,0 +1,27 @@ +package main + +import ( + "bytes" + "testing" + + "www.bamsoftware.com/git/dnstt.git/dns" +) + +func TestDNSNameCapacity(t *testing.T) { + for domainLen := 0; domainLen < 255; domainLen++ { + domain, err := dns.NewName(chunks(bytes.Repeat([]byte{'x'}, domainLen), 63)) + if err != nil { + continue + } + capacity := dnsNameCapacity(domain) + if capacity <= 0 { + continue + } + prefix := []byte(base32Encoding.EncodeToString(bytes.Repeat([]byte{'y'}, capacity))) + labels := append(chunks(prefix, 63), domain...) + _, err = dns.NewName(labels) + if err != nil { + t.Errorf("length %v capacity %v %v", domainLen, capacity, err) + } + } +} diff --git a/dnstt-client/main.go b/dnstt-client/main.go index a098b7f..45abe11 100644 --- a/dnstt-client/main.go +++ b/dnstt-client/main.go @@ -239,6 +239,25 @@ func handle(local *net.TCPConn, sess *smux.Session) error { return err } +// dnsNameCapacity returns the number of bytes remaining for encoded data after +// including domain in a DNS name. +func dnsNameCapacity(domain dns.Name) int { + // https://tools.ietf.org/html/rfc1035#section-2.3.4 + // Names must be 255 octets or shorter in total length. + capacity := 255 + // Subtract the length of the null terminator. + capacity -= 1 + for _, label := range domain { + // Subtract the length of the label and the length octet. + capacity -= len(label) + 1 + } + // Each label may be up to 63 bytes long and requires 64 + capacity = capacity * 63 / 64 + // Base32 expands every 5 bytes to 8. + capacity = capacity * 5 / 8 + return capacity +} + func run(domain dns.Name, localAddr, udpAddr string) error { var sess *smux.Session @@ -272,7 +291,12 @@ func run(domain dns.Name, localAddr, udpAddr string) error { 0, // default resend 1, // nc=1 => congestion window off ) - conn.SetMtu(100) // TODO: MTU appropriate for length of domain + mtu := dnsNameCapacity(domain) - 8 // clientid + if mtu < 80 { + return fmt.Errorf("domain %s leaves only %d bytes for payload", domain, mtu) + } + fmt.Printf("MTU %d\n", mtu) + conn.SetMtu(mtu) // Start a smux session on the KCP conn. smuxConfig := smux.DefaultConfig()