diff --git a/dns/client.go b/dns/client.go index 77cdbb0..c143112 100644 --- a/dns/client.go +++ b/dns/client.go @@ -65,12 +65,12 @@ func (c *Client) Encapsulate(carrierData []byte, frameOffset int) (int, error) { } c.state = dnsAwaitResponse // Unset don't frag since DNS requests go through LOTS of nodes. - if frameOffset >= 28 { - version := carrierData[0] >> 4 - if version == 4 { - carrierData[6], carrierData[7] = 0, 0 // unset IP Flags. - } - } + // if frameOffset >= 28 { + // version := carrierData[0] >> 4 + // if version == 4 { + // carrierData[6], carrierData[7] = 0, 0 // unset IP Flags. + // } + // } return len(data), nil } diff --git a/dns/dns.go b/dns/dns.go index 105eb70..cb88297 100644 --- a/dns/dns.go +++ b/dns/dns.go @@ -626,10 +626,10 @@ func (dst *Message) CopyFrom(m Message) { for i := range dst.Answers { dst.Answers[i].CopyFrom(m.Answers[i]) } - for i := range dst.Answers { + for i := range dst.Authorities { dst.Authorities[i].CopyFrom(m.Authorities[i]) } - for i := range dst.Answers { + for i := range dst.Additionals { dst.Additionals[i].CopyFrom(m.Additionals[i]) } } diff --git a/dns/dns_test.go b/dns/dns_test.go index 6ddaa97..5914922 100644 --- a/dns/dns_test.go +++ b/dns/dns_test.go @@ -221,3 +221,18 @@ func (m *Message) String() string { } return s } + +func TestDecodeMessage(t *testing.T) { + var data = []byte{ + 0x84, 0x05, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x77, 0x68, 0x69, + 0x74, 0x74, 0x69, 0x6c, 0x65, 0x61, 0x6b, 0x73, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, + 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x1e, 0xaf, 0x00, 0x04, 0xc6, 0x31, 0x17, + 0x91, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } + var msg Message + msg.LimitResourceDecoding(5, 5, 5, 5) + off, incomplete, err := msg.Decode(data) + if incomplete || err != nil { + t.Fatal(incomplete, err, off) + } +} diff --git a/examples/bridge/main.go b/examples/bridge/main.go index f8e1d43..f246937 100644 --- a/examples/bridge/main.go +++ b/examples/bridge/main.go @@ -137,10 +137,12 @@ func run() (err error) { } case stateDNS: - addrs, err := stack.ResultLookupIP() + addrs, done, err := stack.ResultLookupIP() if err == nil { fmt.Println(flagHostToResolve, "resolved to", addrs) return nil + } else if done { + return err } } @@ -197,7 +199,7 @@ func (s *Stack) Demux(b []byte, _ int) (err error) { s.aux, err = s.shark.CaptureEthernet(s.aux[:0], b, 0) topFrame := s.aux[len(s.aux)-1] isOK := topFrame.Protocol == "DHCPv4" || // Allow DHCP responses. - (topFrame.Protocol == lneto.IPProtoUDP && getField(topFrame, b, pcap.FieldClassSrc) == 53) || // Allow DNS responses. + topFrame.Protocol == "DNS" || topFrame.Protocol == ethernet.TypeARP // Allow ARP responses. if !isOK { return nil @@ -308,12 +310,12 @@ func (s *Stack) StartLookupIP(host string) error { return nil } -func (s *Stack) ResultLookupIP() ([]netip.Addr, error) { +func (s *Stack) ResultLookupIP() ([]netip.Addr, bool, error) { done, err := s.dns.MessageCopyTo(&s.lookup) if err != nil { - return nil, err + return nil, done, err } else if !done { - return nil, errors.New("DNS not done") + return nil, done, errors.New("DNS not done") } var addrs []netip.Addr ans := s.lookup.Answers @@ -325,7 +327,7 @@ func (s *Stack) ResultLookupIP() ([]netip.Addr, error) { addrs = append(addrs, netip.AddrFrom16([16]byte(data))) } } - return addrs, nil + return addrs, done, nil } func (s *Stack) BeginDHCPRequest(request [4]byte) error { diff --git a/internet/pcap/capture.go b/internet/pcap/capture.go index 083c5d7..937e61d 100644 --- a/internet/pcap/capture.go +++ b/internet/pcap/capture.go @@ -10,6 +10,7 @@ import ( "github.com/soypat/lneto" "github.com/soypat/lneto/arp" "github.com/soypat/lneto/dhcpv4" + "github.com/soypat/lneto/dns" "github.com/soypat/lneto/ethernet" "github.com/soypat/lneto/http/httpraw" "github.com/soypat/lneto/ipv4" @@ -21,8 +22,9 @@ import ( const unknownPayloadProto = "payload?" type PacketBreakdown struct { - hdr httpraw.Header - vld lneto.Validator + hdr httpraw.Header + dmsg dns.Message + vld lneto.Validator } func (pc *PacketBreakdown) CaptureEthernet(dst []Frame, pkt []byte, bitOffset int) ([]Frame, error) { @@ -323,13 +325,42 @@ func (pc *PacketBreakdown) CaptureUDP(dst []Frame, pkt []byte, bitOffset int) ([ end := bitOffset + 8*octet payload := ufrm.Payload() if dhcpv4.PayloadIsDHCPv4(payload) { - return pc.CaptureDHCPv4(dst, pkt, end) - } else { + dst, err = pc.CaptureDHCPv4(dst, pkt, end) + } else if ufrm.DestinationPort() == 53 || ufrm.SourcePort() == 53 { + dst, err = pc.CaptureDNS(dst, pkt, end) + } + if err != nil { dst = append(dst, remainingFrameInfo(unknownPayloadProto, FieldClassPayload, end, octet*len(pkt))) } return dst, nil } +func (pc *PacketBreakdown) CaptureDNS(dst []Frame, pkt []byte, bitOffset int) ([]Frame, error) { + if bitOffset%8 != 0 { + return nil, errors.New("DNS must be parsed at byte boundary") + } + dnsData := pkt[bitOffset/8:] + pc.dmsg.LimitResourceDecoding(20, 20, 20, 20) + off, incomplete, err := pc.dmsg.Decode(dnsData) + if err != nil && !incomplete { + return dst, err + } + finfo := Frame{ + Protocol: "DNS", + PacketBitOffset: bitOffset, + } + if incomplete { + finfo.Errors = append(finfo.Errors, errors.New("pcap: could not parse all DNS resources; add higher limit")) + } + finfo.Fields = append(finfo.Fields, FrameField{ + Name: "Data", + FrameBitOffset: 0, + BitLength: int(off) * octet, + }) + dst = append(dst, finfo) + return dst, nil +} + func (pc *PacketBreakdown) CaptureDHCPv4(dst []Frame, pkt []byte, bitOffset int) ([]Frame, error) { if bitOffset%8 != 0 { return nil, errors.New("DHCP must be parsed at byte boundary")