package dns import ( "bytes" "encoding/binary" osm "git.loafle.net/overflow/service_matcher-go" ) type Dns_frame_header struct { Transaction_id uint16 Flags uint16 Questions uint16 Answer_rrs uint16 Authority_rrs uint16 Additional_rrs uint16 } type Dns_query_section struct { Name uint8 Query_type uint16 Class_type uint16 } type Dns_authority_section struct { Name uint8 Auth_type uint16 Class_type uint16 Time_to_live uint32 Data_length uint16 Primary_name_server [20]uint8 Responsible_authority_mailbox [24]uint8 Serial_number uint32 Refresh_interval uint32 Retry_interval uint32 Expire_limit uint32 Minium_ttl uint32 } type DNSMatcher struct { osm.Matchers } func (m *DNSMatcher) Key() string { return "DNS" } func (m *DNSMatcher) Name(matchCtx *osm.MatchCtx) string { return "DNS" } func (m *DNSMatcher) IsPrePacket() bool { return false } func (m *DNSMatcher) HasResponse(matchCtx *osm.MatchCtx, index int) bool { return true } func (m *DNSMatcher) IsError(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) bool { return false } func (m *DNSMatcher) Match(matchCtx *osm.MatchCtx, index int, packet *osm.Packet) error { if packet == nil || !packet.Valid() { return osm.NoPacketReceivedError() } reader := new(bytes.Buffer) reader.Write(packet.Buffer) h := Dns_frame_header{} if err := binary.Read(reader, binary.BigEndian, &h); err != nil { return err } if h.Transaction_id != 0x2a88 { return osm.NotMatchedError() } if h.Flags != 0x8180 && h.Flags != 0x8182 { return osm.NotMatchedError() } if h.Questions != 1 { return osm.NotMatchedError() } if h.Answer_rrs != 0 { return osm.NotMatchedError() } if h.Authority_rrs != 0 && h.Authority_rrs != 1 { return osm.NotMatchedError() } if h.Additional_rrs != 0 && h.Additional_rrs != 1 { return osm.NotMatchedError() } q := Dns_query_section{} if err := binary.Read(reader, binary.BigEndian, &q); err != nil { return osm.NotMatchedError() } if q.Name != 0 { return osm.NotMatchedError() } if q.Query_type != 1 { return osm.NotMatchedError() } if q.Class_type != 1 { return osm.NotMatchedError() } return nil } func (m *DNSMatcher) IsSend(port int) bool { if 53 == port { return true } return false } func NewMatcher() osm.UDPMatcher { m := &DNSMatcher{} header := Dns_frame_header{ Transaction_id: 0x2a88, Flags: 0x0100, Questions: 1, Answer_rrs: 0, Authority_rrs: 0, Additional_rrs: 0, } query := Dns_query_section{ Name: 0, Query_type: 1, Class_type: 1, } buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, header) binary.Write(buf, binary.BigEndian, query) m.AddPacket(osm.NewPacket(buf.Bytes(), buf.Len())) return m }