diff --git a/dns/client.go b/dns/client.go index aa96bfd..f49513c 100644 --- a/dns/client.go +++ b/dns/client.go @@ -91,6 +91,18 @@ func (c *Client) isClosed() bool { return c.state == dnsClosed || c.state == dnsAborted } +func (c *Client) MessageCopyTo(dst *Message) (done bool, err error) { + if !c.respFlags.IsResponse() { + return false, nil + } + dst.CopyFrom(c.msg) + rcode := c.respFlags.ResponseCode() + if rcode != 0 { + return true, rcode + } + return true, nil +} + func (c *Client) Answers() []Resource { if c.state != dnsDone { return nil diff --git a/dns/definitions.go b/dns/definitions.go index ed8e6cf..080fc8e 100644 --- a/dns/definitions.go +++ b/dns/definitions.go @@ -9,6 +9,7 @@ import ( // common errors. Taken from golang.org/x/net/dns/dnsmessage module. var ( + errNoResponse = errors.New("no DNS response") errNameTooLong = errors.New("DNS name exceeds maximum length") errNoNullTerm = errors.New("DNS name missing null terminator") errCalcLen = errors.New("DNS calculated name label length exceeds remaining buffer length") @@ -141,6 +142,10 @@ func (flags HeaderFlags) String() string { return string(flags.appendF(buf)) } +func (flags RCode) Error() string { + return flags.String() +} + func (flags HeaderFlags) appendF(buf []byte) []byte { writeBit := func(b bool, s string) { if b { diff --git a/dns/dns.go b/dns/dns.go index 12a3069..318149e 100644 --- a/dns/dns.go +++ b/dns/dns.go @@ -245,7 +245,7 @@ func (m *Message) AddQuestions(questions []Question) { m.Questions = slices.Grow(m.Questions, len(questions)) m.Questions = m.Questions[:qoff+len(questions)] for i := range questions { - m.Questions[qoff+i].Name.CloneFrom(questions[i].Name) + m.Questions[qoff+i].Name.CopyFrom(questions[i].Name) m.Questions[qoff+i].Type = questions[i].Type m.Questions[qoff+i].Class = questions[i].Class } @@ -418,7 +418,7 @@ func (n *Name) Len() uint16 { return uint16(len(n.data)) } -func (n *Name) CloneFrom(ex Name) { +func (n *Name) CopyFrom(ex Name) { n.data = append(n.data[:0], ex.data...) } @@ -573,3 +573,48 @@ LOOP: } return newOff, nil } + +func (dst *Message) CopyFrom(m Message) { + reuseGrowSlice(&dst.Questions, len(m.Questions)) + reuseGrowSlice(&dst.Answers, len(m.Answers)) + reuseGrowSlice(&dst.Authorities, len(m.Authorities)) + reuseGrowSlice(&dst.Additionals, len(m.Additionals)) + for i := range dst.Questions { + dst.Questions[i].CopyFrom(m.Questions[i]) + } + for i := range dst.Answers { + dst.Answers[i].CopyFrom(m.Answers[i]) + } + for i := range dst.Answers { + dst.Authorities[i].CopyFrom(m.Authorities[i]) + } + for i := range dst.Answers { + dst.Additionals[i].CopyFrom(m.Additionals[i]) + } +} + +func (dst *Question) CopyFrom(q Question) { + dst.Name.CopyFrom(q.Name) + dst.Class = q.Class + dst.Type = q.Type +} + +func (dst *Resource) CopyFrom(r Resource) { + dst.Header.CopyFrom(r.Header) + dst.data = append(dst.data[:0], r.data...) +} + +func (dst *ResourceHeader) CopyFrom(rh ResourceHeader) { + dst.Name.CopyFrom(rh.Name) + dst.Type = rh.Type + dst.Class = rh.Class + dst.TTL = rh.TTL + dst.Length = rh.Length +} + +func reuseGrowSlice[T any](dst *[]T, n int) { + if n == 0 { + return + } + *dst = slices.Grow(*dst, n)[:n] +} diff --git a/examples/bridge/main.go b/examples/bridge/main.go index 74c7129..9fd879e 100644 --- a/examples/bridge/main.go +++ b/examples/bridge/main.go @@ -134,12 +134,13 @@ func run() (err error) { } type Stack struct { - link internet.StackEthernet - ip internet.StackIP - arp internet.NodeARP - udps internet.StackPorts - dhcp dhcpv4.Client - dns dns.Client + link internet.StackEthernet + ip internet.StackIP + arp internet.NodeARP + udps internet.StackPorts + dhcp dhcpv4.Client + dns dns.Client + lookup dns.Message } func (s *Stack) Demux(b []byte, _ int) error { @@ -196,7 +197,7 @@ func (s *Stack) Reset(mac [6]byte, addr netip.Addr, mtu uint16) error { return nil } -func (s *Stack) StartLookupNetIP(host string) error { +func (s *Stack) StartLookupIP(host string) error { name, err := dns.NewName(host) if err != nil { return err @@ -224,6 +225,12 @@ func (s *Stack) StartLookupNetIP(host string) error { return nil } +func (s *Stack) ResultLookupIP() ([]netip.Addr, error) { + s.dns.MessageCopyTo() + // s.dns.Answers() + return nil, nil +} + func (s *Stack) BeginDHCPRequest() error { addr4 := s.ip.Addr().As4() var buf [4]byte diff --git a/http/httpraw/cookie.go b/http/httpraw/cookie.go index f303e20..c4e4742 100644 --- a/http/httpraw/cookie.go +++ b/http/httpraw/cookie.go @@ -46,8 +46,8 @@ func (c *Cookie) ParseBytes(cookie []byte) error { return c.Parse() } -// CopyTo makes a copy of the cookie in dst argument. No memory is shared between cookies. -func (c *Cookie) CopyTo(dst *Cookie) { +// CopyFrom makes a copy of the argument cookie to the receiver dst argument. No memory is shared between cookies. +func (dst *Cookie) CopyFrom(c Cookie) { dst.buf = append(dst.buf[:0], c.buf...) dst.kvs = append(dst.kvs[:0], c.kvs...) } diff --git a/internal/tap.go b/internal/tap.go index ca92c47..a49037f 100644 --- a/internal/tap.go +++ b/internal/tap.go @@ -209,7 +209,7 @@ func NewBridge(name string) (*Bridge, error) { if err != nil { return nil, err } - proto := htons(syscall.ETH_P_IP) + proto := htons(syscall.ETH_P_ALL) fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(proto)) if err != nil { return nil, err