diff --git a/querylog/qlog.go b/querylog/qlog.go index 151b16ff..713a2849 100644 --- a/querylog/qlog.go +++ b/querylog/qlog.go @@ -373,9 +373,9 @@ func answerToMap(a *dns.Msg) []map[string]interface{} { // try most common record types switch v := k.(type) { case *dns.A: - answer["value"] = v.A + answer["value"] = v.A.String() case *dns.AAAA: - answer["value"] = v.AAAA + answer["value"] = v.AAAA.String() case *dns.MX: answer["value"] = fmt.Sprintf("%v %v", v.Preference, v.Mx) case *dns.CNAME: diff --git a/querylog/querylog_test.go b/querylog/querylog_test.go index 91dc405b..63bcbfd8 100644 --- a/querylog/querylog_test.go +++ b/querylog/querylog_test.go @@ -2,6 +2,7 @@ package querylog import ( "net" + "os" "testing" "time" @@ -10,16 +11,94 @@ import ( "github.com/stretchr/testify/assert" ) +func prepareTestDir() string { + const dir = "./agh-test" + _ = os.RemoveAll(dir) + _ = os.MkdirAll(dir, 0755) + return dir +} + +// Check adding and loading (with filtering) entries from disk and memory func TestQueryLog(t *testing.T) { conf := Config{ Enabled: true, Interval: 1, } + conf.BaseDir = prepareTestDir() + defer func() { _ = os.RemoveAll(conf.BaseDir) }() l := newQueryLog(conf) + // add disk entries + addEntry(l, "example.org", "1.2.3.4", "0.1.2.3") + addEntry(l, "example.org", "1.2.3.4", "0.1.2.3") + + // write to disk + l.flushLogBuffer(true) + + // add memory entries + addEntry(l, "test.example.org", "2.2.3.4", "0.1.2.4") + + // get all entries + params := getDataParams{ + OlderThan: time.Time{}, + } + d := l.getData(params) + mdata := d["data"].([]map[string]interface{}) + assert.True(t, len(mdata) == 2) + assert.True(t, checkEntry(t, mdata[0], "test.example.org", "2.2.3.4", "0.1.2.4")) + assert.True(t, checkEntry(t, mdata[1], "example.org", "1.2.3.4", "0.1.2.3")) + + // search by domain (strict) + params = getDataParams{ + OlderThan: time.Time{}, + Domain: "test.example.org", + StrictMatchDomain: true, + } + d = l.getData(params) + mdata = d["data"].([]map[string]interface{}) + assert.True(t, len(mdata) == 1) + assert.True(t, checkEntry(t, mdata[0], "test.example.org", "2.2.3.4", "0.1.2.4")) + + // search by domain + params = getDataParams{ + OlderThan: time.Time{}, + Domain: "example.org", + StrictMatchDomain: false, + } + d = l.getData(params) + mdata = d["data"].([]map[string]interface{}) + assert.True(t, len(mdata) == 2) + assert.True(t, checkEntry(t, mdata[0], "test.example.org", "2.2.3.4", "0.1.2.4")) + assert.True(t, checkEntry(t, mdata[1], "example.org", "1.2.3.4", "0.1.2.3")) + + // search by client IP (strict) + params = getDataParams{ + OlderThan: time.Time{}, + Client: "0.1.2.3", + StrictMatchClient: true, + } + d = l.getData(params) + mdata = d["data"].([]map[string]interface{}) + assert.True(t, len(mdata) == 1) + assert.True(t, checkEntry(t, mdata[0], "example.org", "1.2.3.4", "0.1.2.3")) + + // search by client IP + params = getDataParams{ + OlderThan: time.Time{}, + Client: "0.1.2", + StrictMatchClient: false, + } + d = l.getData(params) + mdata = d["data"].([]map[string]interface{}) + assert.True(t, len(mdata) == 2) + assert.True(t, checkEntry(t, mdata[0], "test.example.org", "2.2.3.4", "0.1.2.4")) + assert.True(t, checkEntry(t, mdata[1], "example.org", "1.2.3.4", "0.1.2.3")) +} + +func addEntry(l *queryLog, host, answerStr, client string) { q := dns.Msg{} q.Question = append(q.Question, dns.Question{ - Name: "example.org.", + Name: host + ".", Qtype: dns.TypeA, Qclass: dns.ClassINET, }) @@ -32,20 +111,24 @@ func TestQueryLog(t *testing.T) { Rrtype: dns.TypeA, Class: dns.ClassINET, } - answer.A = net.IP{1, 2, 3, 4} + answer.A = net.ParseIP(answerStr) a.Answer = append(a.Answer, answer) - res := dnsfilter.Result{} - l.Add(&q, &a, &res, 0, nil, "upstream") + l.Add(&q, &a, &res, 0, net.ParseIP(client), "upstream") +} - params := getDataParams{ - OlderThan: time.Now(), - } - d := l.getData(params) - mdata := d["data"].([]map[string]interface{}) - m := mdata[0] +func checkEntry(t *testing.T, m map[string]interface{}, host, answer, client string) bool { mq := m["question"].(map[string]interface{}) - assert.True(t, mq["host"].(string) == "example.org") + ma := m["answer"].([]map[string]interface{}) + ma0 := ma[0] + if !assert.True(t, mq["host"].(string) == host) || + !assert.True(t, mq["class"].(string) == "IN") || + !assert.True(t, mq["type"].(string) == "A") || + !assert.True(t, ma0["value"].(string) == answer) || + !assert.True(t, m["client"].(string) == client) { + return false + } + return true } func TestJSON(t *testing.T) {