doggo/cmd/output.go

224 lines
5.4 KiB
Go
Raw Normal View History

2020-12-12 11:57:13 +01:00
package main
2020-12-12 15:10:28 +01:00
import (
2020-12-13 05:04:53 +01:00
"encoding/json"
2020-12-12 15:10:28 +01:00
"fmt"
2020-12-13 04:17:07 +01:00
"os"
2020-12-12 15:10:28 +01:00
"strconv"
"github.com/fatih/color"
"github.com/miekg/dns"
"github.com/mr-karan/doggo/pkg/resolvers"
2020-12-13 04:17:07 +01:00
"github.com/olekukonko/tablewriter"
2020-12-12 15:10:28 +01:00
)
2020-12-13 05:04:53 +01:00
type Output struct {
2020-12-13 08:15:45 +01:00
Name string `json:"name"`
Type string `json:"type"`
Class string `json:"class"`
TTL string `json:"ttl"`
Address string `json:"address"`
TimeTaken string `json:"rtt"`
Nameserver string `json:"nameserver"`
2020-12-13 05:04:53 +01:00
}
type Query struct {
Name string `json:"name"`
Type string `json:"type"`
Class string `json:"class"`
}
type Response struct {
Output []Output `json:"answers"`
Queries []Query `json:"queries"`
}
type JSONResponse struct {
Response `json:"responses"`
}
func (hub *Hub) outputJSON(out []Output) {
2020-12-13 05:04:53 +01:00
// get the questions
queries := make([]Query, 0)
2020-12-13 09:26:38 +01:00
for _, ques := range hub.Questions {
q := Query{
Name: ques.Name,
2020-12-14 07:19:54 +01:00
Type: dns.TypeToString[ques.Qtype],
2020-12-13 09:26:38 +01:00
Class: dns.ClassToString[ques.Qclass],
2020-12-13 05:04:53 +01:00
}
2020-12-13 09:26:38 +01:00
queries = append(queries, q)
2020-12-13 05:04:53 +01:00
}
2020-12-13 09:26:38 +01:00
2020-12-13 05:04:53 +01:00
resp := JSONResponse{
Response{
Output: out,
Queries: queries,
},
}
res, err := json.Marshal(resp)
if err != nil {
hub.Logger.WithError(err).Error("unable to output data in JSON")
hub.Logger.Exit(-1)
}
fmt.Printf("%s", res)
}
func (hub *Hub) outputTerminal(out []Output) {
2020-12-13 16:33:44 +01:00
green := color.New(color.FgGreen, color.Bold).SprintFunc()
blue := color.New(color.FgBlue, color.Bold).SprintFunc()
yellow := color.New(color.FgYellow, color.Bold).SprintFunc()
cyan := color.New(color.FgCyan, color.Bold).SprintFunc()
red := color.New(color.FgRed, color.Bold).SprintFunc()
if !hub.QueryFlags.Color {
color.NoColor = true // disables colorized output
}
2020-12-13 04:17:07 +01:00
table := tablewriter.NewWriter(os.Stdout)
2020-12-13 09:42:24 +01:00
header := []string{"Name", "Type", "Class", "TTL", "Address", "Nameserver"}
2020-12-13 04:17:07 +01:00
if hub.QueryFlags.DisplayTimeTaken {
header = append(header, "Time Taken")
}
2020-12-13 09:42:24 +01:00
table.SetHeader(header)
2020-12-13 09:26:38 +01:00
table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
2020-12-13 09:42:24 +01:00
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetTablePadding("\t") // pad with tabs
table.SetNoWhiteSpace(true)
2020-12-13 04:17:07 +01:00
2020-12-13 05:04:53 +01:00
for _, o := range out {
2020-12-13 16:33:44 +01:00
var typOut string
switch typ := o.Type; typ {
case "A":
typOut = blue(o.Type)
case "AAAA":
typOut = blue(o.Type)
case "MX":
2020-12-14 07:19:54 +01:00
typOut = red(o.Type)
2020-12-13 16:33:44 +01:00
case "NS":
typOut = cyan(o.Type)
case "CNAME":
typOut = yellow(o.Type)
case "TXT":
typOut = yellow(o.Type)
2020-12-16 14:20:25 +01:00
case "SOA":
typOut = red(o.Type)
2020-12-13 16:33:44 +01:00
default:
2020-12-14 07:19:54 +01:00
typOut = blue(o.Type)
2020-12-13 16:33:44 +01:00
}
output := []string{green(o.Name), typOut, o.Class, o.TTL, o.Address, o.Nameserver}
2020-12-13 05:04:53 +01:00
// Print how long it took
if hub.QueryFlags.DisplayTimeTaken {
output = append(output, o.TimeTaken)
}
table.Append(output)
}
table.Render()
}
// Output takes a list of `dns.Answers` and based
// on the output format specified displays the information.
func (hub *Hub) Output(responses [][]resolvers.Response) {
2020-12-13 05:04:53 +01:00
out := collectOutput(responses)
if hub.QueryFlags.ShowJSON {
hub.outputJSON(out)
2020-12-13 05:04:53 +01:00
} else {
hub.outputTerminal(out)
}
}
func collectOutput(responses [][]resolvers.Response) []Output {
2020-12-13 09:26:38 +01:00
var out []Output
// for each resolver
for _, rslvr := range responses {
// get the response
for _, r := range rslvr {
var addr string
2020-12-17 12:27:44 +01:00
for _, ns := range r.Message.Ns {
// check for SOA record
soa, ok := ns.(*dns.SOA)
if !ok {
// skip this message
continue
2020-12-16 14:08:34 +01:00
}
2020-12-17 12:27:44 +01:00
addr = soa.Ns + " " + soa.Mbox +
" " + strconv.FormatInt(int64(soa.Serial), 10) +
" " + strconv.FormatInt(int64(soa.Refresh), 10) +
" " + strconv.FormatInt(int64(soa.Retry), 10) +
" " + strconv.FormatInt(int64(soa.Expire), 10) +
" " + strconv.FormatInt(int64(soa.Minttl), 10)
h := ns.Header()
name := h.Name
qclass := dns.Class(h.Class).String()
ttl := strconv.FormatInt(int64(h.Ttl), 10) + "s"
qtype := dns.Type(h.Rrtype).String()
rtt := fmt.Sprintf("%dms", r.RTT.Milliseconds())
o := Output{
Name: name,
Type: qtype,
TTL: ttl,
Class: qclass,
Address: addr,
TimeTaken: rtt,
Nameserver: r.Nameserver,
}
out = append(out, o)
2020-12-16 14:08:34 +01:00
}
for _, a := range r.Message.Answer {
switch t := a.(type) {
case *dns.A:
addr = t.A.String()
case *dns.AAAA:
addr = t.AAAA.String()
case *dns.CNAME:
addr = t.Target
case *dns.CAA:
addr = t.Tag + " " + t.Value
case *dns.HINFO:
addr = t.Cpu + " " + t.Os
case *dns.PTR:
addr = t.Ptr
case *dns.SRV:
addr = strconv.Itoa(int(t.Priority)) + " " +
strconv.Itoa(int(t.Weight)) + " " +
t.Target + ":" + strconv.Itoa(int(t.Port))
case *dns.TXT:
addr = t.String()
case *dns.NS:
addr = t.Ns
case *dns.MX:
addr = strconv.Itoa(int(t.Preference)) + " " + t.Mx
case *dns.SOA:
addr = t.String()
case *dns.NAPTR:
addr = t.String()
}
2020-12-13 09:26:38 +01:00
h := a.Header()
name := h.Name
qclass := dns.Class(h.Class).String()
ttl := strconv.FormatInt(int64(h.Ttl), 10) + "s"
qtype := dns.Type(h.Rrtype).String()
rtt := fmt.Sprintf("%dms", r.RTT.Milliseconds())
o := Output{
Name: name,
Type: qtype,
TTL: ttl,
Class: qclass,
Address: addr,
TimeTaken: rtt,
Nameserver: r.Nameserver,
}
out = append(out, o)
2020-12-13 04:17:07 +01:00
}
2020-12-12 15:10:28 +01:00
}
}
2020-12-13 05:04:53 +01:00
return out
2020-12-12 15:10:28 +01:00
}