dnsutils.go 2.41 KB
Newer Older
1 2 3
package main

import (
4
	"encoding/binary"
5
	"strings"
6 7
	"time"

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
	"github.com/miekg/dns"
)

func TruncatedResponse(packet []byte) ([]byte, error) {
	srcMsg := new(dns.Msg)
	if err := srcMsg.Unpack(packet); err != nil {
		return nil, err
	}
	dstMsg := srcMsg
	dstMsg.Response = true
	dstMsg.Answer = make([]dns.RR, 0)
	dstMsg.Ns = make([]dns.RR, 0)
	dstMsg.Extra = make([]dns.RR, 0)
	dstMsg.Truncated = true
	return dstMsg.Pack()
}

25 26 27 28 29 30 31 32 33
func EmptyResponseFromMessage(srcMsg *dns.Msg) (*dns.Msg, error) {
	dstMsg := srcMsg
	dstMsg.Response = true
	dstMsg.Answer = make([]dns.RR, 0)
	dstMsg.Ns = make([]dns.RR, 0)
	dstMsg.Extra = make([]dns.RR, 0)
	return dstMsg, nil
}

34 35 36 37 38 39 40 41 42
func RefusedResponseFromMessage(srcMsg *dns.Msg) (*dns.Msg, error) {
	dstMsg, err := EmptyResponseFromMessage(srcMsg)
	if err != nil {
		return dstMsg, err
	}
	dstMsg.Rcode = dns.RcodeRefused
	return dstMsg, nil
}

43 44 45
func HasTCFlag(packet []byte) bool {
	return packet[2]&2 == 2
}
46

47 48 49 50 51 52 53 54
func TransactionID(packet []byte) uint16 {
	return binary.BigEndian.Uint16(packet[0:2])
}

func SetTransactionID(packet []byte, tid uint16) {
	binary.BigEndian.PutUint16(packet[0:2], tid)
}

55 56 57 58
func Rcode(packet []byte) uint8 {
	return packet[3] & 0xf
}

59 60 61 62 63 64 65 66
func NormalizeName(name *[]byte) {
	for i, c := range *name {
		if c >= 65 && c <= 90 {
			(*name)[i] = c + 32
		}
	}
}

67
func StripTrailingDot(str string) string {
68
	if len(str) > 1 && strings.HasSuffix(str, ".") {
69 70 71 72 73
		str = str[:len(str)-1]
	}
	return str
}

74
func getMinTTL(msg *dns.Msg, minTTL uint32, maxTTL uint32, negCacheMinTTL uint32) time.Duration {
75
	if msg.Rcode != dns.RcodeSuccess || len(msg.Answer) <= 0 {
76 77 78 79 80 81 82 83 84 85 86 87 88
		return time.Duration(negCacheMinTTL) * time.Second
	}
	ttl := uint32(maxTTL)
	for _, rr := range msg.Answer {
		if rr.Header().Ttl < ttl {
			ttl = rr.Header().Ttl
		}
	}
	if ttl < minTTL {
		ttl = minTTL
	}
	return time.Duration(ttl) * time.Second
}
Frank Denis's avatar
Frank Denis committed
89

90
func setMaxTTL(msg *dns.Msg, ttl uint32) {
Frank Denis's avatar
Frank Denis committed
91
	for _, rr := range msg.Answer {
92
		if ttl < rr.Header().Ttl {
Frank Denis's avatar
Frank Denis committed
93 94 95 96
			rr.Header().Ttl = ttl
		}
	}
	for _, rr := range msg.Ns {
Frank Denis's avatar
Frank Denis committed
97
		if ttl < rr.Header().Ttl {
Frank Denis's avatar
Frank Denis committed
98 99 100 101
			rr.Header().Ttl = ttl
		}
	}
	for _, rr := range msg.Extra {
Frank Denis's avatar
Frank Denis committed
102
		if ttl < rr.Header().Ttl {
Frank Denis's avatar
Frank Denis committed
103 104 105 106
			rr.Header().Ttl = ttl
		}
	}
}
107 108

func updateTTL(msg *dns.Msg, expiration time.Time) {
109 110 111
	ttl := uint32(time.Until(expiration) / time.Second)

	for _, rr := range msg.Answer {
Frank Denis's avatar
Frank Denis committed
112
		rr.Header().Ttl = ttl
113 114
	}
	for _, rr := range msg.Ns {
Frank Denis's avatar
Frank Denis committed
115
		rr.Header().Ttl = ttl
116 117
	}
	for _, rr := range msg.Extra {
Frank Denis's avatar
Frank Denis committed
118
		rr.Header().Ttl = ttl
119
	}
120
}