summaryrefslogtreecommitdiff
path: root/internal/resolver/forward.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/resolver/forward.go')
-rw-r--r--internal/resolver/forward.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/internal/resolver/forward.go b/internal/resolver/forward.go
new file mode 100644
index 0000000..68edc5d
--- /dev/null
+++ b/internal/resolver/forward.go
@@ -0,0 +1,47 @@
+package resolver
+
+import (
+ "fmt"
+ "net"
+
+ "linum/internal/dns"
+)
+
+type Forwarder struct {
+ upstream string
+}
+
+func NewForwarder(upstream string) *Forwarder {
+ return &Forwarder{upstream: upstream}
+}
+
+func (f *Forwarder) Resolve(query *dns.Msg) (*dns.Msg, error) {
+ query.Header.SetRD(true)
+
+ wire, err := dns.Pack(query)
+ if err != nil {
+ return nil, fmt.Errorf("pack: %w", err)
+ }
+
+ conn, err := net.Dial("udp", f.upstream)
+ if err != nil {
+ return nil, fmt.Errorf("dial %s: %w", f.upstream, err)
+ }
+ defer conn.Close()
+
+ if _, err := conn.Write(wire); err != nil {
+ return nil, fmt.Errorf("write: %w", err)
+ }
+
+ buf := make([]byte, 4096)
+ n, err := conn.Read(buf)
+ if err != nil {
+ return nil, fmt.Errorf("read: %w", err)
+ }
+
+ resp, err := dns.Unpack(buf[:n])
+ if err != nil {
+ return nil, fmt.Errorf("unpack response: $w", err)
+ }
+ return resp, nil
+}