split off the questions

This commit is contained in:
Miek Gieben 2011-09-20 14:59:28 +02:00
parent 1a81ac9c85
commit 9e2bec0041
4 changed files with 78 additions and 58 deletions

View File

@ -3,6 +3,6 @@
# license that can be found in the LICENSE file.
include $(GOROOT)/src/Make.inc
TARG=q
GOFILES=q.go fp.go lex.go
GOFILES=q.go fp.go lex.go dns.go
DEPS=../../
include $(GOROOT)/src/Make.cmd

36
_examples/q/dns.go Normal file
View File

@ -0,0 +1,36 @@
package main
import (
"dns"
)
// Check if the server responds at all
func dnsAlive(l *lexer) stateFn {
l.verbose("Alive")
l.setString("QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,1,0,0,0,do,0")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
f := l.probe()
if f.ok() {
return dnsDoBitMirror
}
l.emit(&item{itemError, f.error()})
return nil
}
// Check if the server returns the DO-bit when set in the request.
func dnsDoBitMirror(l *lexer) stateFn {
l.verbose("DoBitMirror")
// The important part here is that the DO bit is on in the reply
l.setString("QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,0")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
f := l.probe()
if !f.Do {
l.emit(&item{itemSoftware, NSD})
return nil
}
l.emit(&item{itemSoftware, BIND})
return nil
}

View File

@ -17,7 +17,7 @@ const (
// Vendors
ISC = "ISC"
NLNETLABS = "NLnet Labs"
MICROSOFT = "Microsoft"
MICROSOFT = "Microsoft"
)
func startParse(addr string) {
@ -27,6 +27,7 @@ func startParse(addr string) {
fp: new(fingerprint),
items: make(chan item),
state: dnsAlive,
debug: true,
}
l.run()
@ -54,22 +55,23 @@ func sendProbe(c *dns.Client, addr string, f *fingerprint, q dns.Question) *fing
// This leads to strings like: "QUERY,NOERROR,qr,aa,tc,RD,ad,cd,z,1,0,0,1,DO,4096"
type fingerprint struct {
Error os.Error
Opcode int
Rcode int
Response bool
Authoritative bool
Truncated bool
RecursionDesired bool
AuthenticatedData bool
CheckingDisabled bool
Zero bool
Question int
Answer int
Ns int
Extra int
Do bool
UDPSize int
Error os.Error
Opcode int
Rcode int
Response bool
Authoritative bool
Truncated bool
RecursionDesired bool
RecursionAvailable bool
AuthenticatedData bool
CheckingDisabled bool
Zero bool
Question int
Answer int
Ns int
Extra int
Do bool
UDPSize int
}
// String creates a (short) string representation of a dns message.
@ -86,6 +88,7 @@ func (f *fingerprint) String() string {
s += valueOfBool(f.Authoritative, ",aa")
s += valueOfBool(f.Truncated, ",tc")
s += valueOfBool(f.RecursionDesired, ",rd")
s += valueOfBool(f.RecursionAvailable, ",ra")
s += valueOfBool(f.AuthenticatedData, ",ad")
s += valueOfBool(f.CheckingDisabled, ",cd")
s += valueOfBool(f.Zero, ",z")
@ -129,28 +132,33 @@ func (f *fingerprint) setString(str string) {
f.RecursionDesired = true
}
case 6:
f.RecursionAvailable = false
if s == strings.ToUpper("ra") {
f.RecursionAvailable = true
}
case 7:
f.AuthenticatedData = false
if s == strings.ToUpper("ad") {
f.AuthenticatedData = true
}
case 7:
case 8:
f.CheckingDisabled = false
if s == strings.ToUpper("cd") {
f.CheckingDisabled = true
}
case 8:
case 9:
f.Zero = false
if s == strings.ToUpper("z") {
f.Zero = true
}
case 9, 10, 11, 12:
case 10, 11, 12, 13:
// Can not set content of the message
case 13:
case 14:
f.Do = false
if s == strings.ToUpper("do") {
f.Do = true
}
case 14:
case 15:
f.UDPSize = 0
f.UDPSize = valueOfString(s)
default:
@ -190,6 +198,7 @@ func msgToFingerprint(m *dns.Msg) *fingerprint {
f.Authoritative = h.Authoritative
f.Truncated = h.Truncated
f.RecursionDesired = h.RecursionDesired
f.RecursionAvailable = h.RecursionAvailable
f.AuthenticatedData = h.AuthenticatedData
f.CheckingDisabled = h.CheckingDisabled
f.Zero = h.Zero

View File

@ -34,10 +34,15 @@ type lexer struct {
q dns.Question // question to ask.
items chan item // channel of scanned items.
state stateFn // the next function to enter.
debug bool // if true, the fingerprints are printed.
}
func (l *lexer) probe() *fingerprint {
return sendProbe(l.client, l.addr, l.fp, l.q)
f := sendProbe(l.client, l.addr, l.fp, l.q)
if l.debug {
fmt.Printf(" QR fp: %s\n", f)
}
return f
}
func (l *lexer) emit(i *item) {
@ -46,6 +51,9 @@ func (l *lexer) emit(i *item) {
func (l *lexer) setString(s string) {
l.fp.setString(s)
if l.debug {
fmt.Printf(" Q fp: %s\n", s)
}
}
func (l *lexer) setQuestion(name string, t uint16, c uint16) {
@ -62,38 +70,5 @@ func (l *lexer) run() {
}
func (l *lexer) verbose(s string) {
fmt.Printf("running: dns%s\n", s)
}
// "Lexer" functions, prefixed with dns
// Check if the server responds at all
func dnsAlive(l *lexer) stateFn {
l.verbose("Alive")
l.setString("QUERY,NOERROR,qr,aa,tc,rd,ad,cd,z,1,0,0,0,do,0")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
f := l.probe()
if f.ok() {
return dnsDoBitMirror
}
l.emit(&item{itemError, f.error()})
return nil
}
// Check if the server returns the DO-bit when set in the request.
func dnsDoBitMirror(l *lexer) stateFn {
l.verbose("DoBitMirror")
// The important part here is that the DO bit is on in the reply
l.setString("QUERY,NOERROR,qr,aa,tc,RD,ad,cd,z,1,0,0,0,DO,0")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
f := l.probe()
if !f.Do {
l.emit(&item{itemSoftware, NSD})
return nil
}
l.emit(&item{itemSoftware, BIND})
return nil
fmt.Printf("running: dns%s\n", s)
}