doggo/cmd/doggo-v1/cli.go

167 lines
5.3 KiB
Go
Raw Normal View History

2020-12-09 18:11:09 +01:00
package main
import (
"fmt"
2020-12-09 18:11:09 +01:00
"os"
"time"
2020-12-09 18:11:09 +01:00
2020-12-13 13:19:10 +01:00
"github.com/knadh/koanf"
"github.com/knadh/koanf/providers/posflag"
"github.com/mr-karan/doggo/internal/app"
2022-07-06 18:22:59 +02:00
"github.com/mr-karan/doggo/internal/resolvers"
"github.com/mr-karan/doggo/internal/utils"
"github.com/mr-karan/logf"
2020-12-13 13:19:10 +01:00
flag "github.com/spf13/pflag"
2020-12-09 18:11:09 +01:00
)
var (
2022-07-01 04:15:46 +02:00
// Version of the build. This is injected at build-time.
buildString = "unknown"
logger = utils.InitLogger()
k = koanf.New(".")
2020-12-09 18:11:09 +01:00
)
func main() {
// Initialize app.
2022-07-01 04:15:46 +02:00
app := app.New(logger, buildString)
2020-12-10 17:14:04 +01:00
2020-12-17 12:27:44 +01:00
// Configure Flags.
2020-12-13 13:19:10 +01:00
f := flag.NewFlagSet("config", flag.ContinueOnError)
2020-12-17 12:27:44 +01:00
// Custom Help Text.
2020-12-13 16:33:44 +01:00
f.Usage = renderCustomHelp
2020-12-17 12:27:44 +01:00
// Query Options.
2020-12-13 13:19:10 +01:00
f.StringSliceP("query", "q", []string{}, "Domain name to query")
f.StringSliceP("type", "t", []string{}, "Type of DNS record to be queried (A, AAAA, MX etc)")
f.StringSliceP("class", "c", []string{}, "Network class of the DNS record to be queried (IN, CH, HS etc)")
f.StringSliceP("nameservers", "n", []string{}, "Address of the nameserver to send packets to")
f.BoolP("reverse", "x", false, "Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively.")
2020-12-13 13:19:10 +01:00
// Resolver Options
2022-07-02 07:49:47 +02:00
f.Int("timeout", 2, "Sets the timeout for a query to T seconds. The default timeout is 2 seconds.")
f.Int("retry", 3, "Number of times to retry DNS lookup")
2020-12-18 16:37:02 +01:00
f.Bool("search", true, "Use the search list provided in resolv.conf. It sets the `ndots` parameter as well unless overridden by `ndots` flag.")
f.Int("ndots", -1, "Specify the ndots parameter. Default value is taken from resolv.conf and fallbacks to 1 if ndots statement is missing in resolv.conf")
2020-12-16 15:10:01 +01:00
f.BoolP("ipv4", "4", false, "Use IPv4 only")
f.BoolP("ipv6", "6", false, "Use IPv6 only")
f.String("strategy", "all", "Strategy to query nameservers in resolv.conf file (`all`, `random`, `first`)")
f.String("tls-hostname", "", "Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP")
f.Bool("skip-hostname-verification", false, "Skip TLS Hostname Verification")
f.StringSliceP("tweaks", "Z", []string{}, "Specify protocol tweaks. Set flags like aa,ad,cd")
2020-12-13 13:19:10 +01:00
// Output Options
f.BoolP("json", "J", false, "Set the output format as JSON")
f.Bool("short", false, "Short output format")
2020-12-13 13:19:10 +01:00
f.Bool("time", false, "Display how long it took for the response to arrive")
2020-12-13 16:33:44 +01:00
f.Bool("color", true, "Show colored output")
2020-12-13 13:19:10 +01:00
f.Bool("debug", false, "Enable debug mode")
f.Bool("version", false, "Show version of doggo")
2020-12-17 17:38:23 +01:00
// Parse and Load Flags.
2020-12-17 12:27:44 +01:00
err := f.Parse(os.Args[1:])
if err != nil {
app.Logger.WithError(err).Fatal("error parsing flags")
2020-12-17 12:27:44 +01:00
}
if err = k.Load(posflag.Provider(f, ".", k), nil); err != nil {
2020-12-13 16:33:44 +01:00
f.Usage()
app.Logger.WithError(err).Fatal("error loading flags")
2020-12-13 16:33:44 +01:00
}
2020-12-13 17:00:54 +01:00
// If version flag is set, output version and quit.
if k.Bool("version") {
2022-07-01 04:15:46 +02:00
fmt.Println(buildString)
os.Exit(0)
}
2020-12-17 12:27:44 +01:00
// Set log level.
2020-12-13 16:33:44 +01:00
if k.Bool("debug") {
app.Logger.SetLevel(logf.DebugLevel)
2020-12-09 18:11:09 +01:00
}
// Unmarshall flags to the app.
err = k.Unmarshal("", &app.QueryFlags)
2020-12-17 12:27:44 +01:00
if err != nil {
app.Logger.WithError(err).Fatal("error loading args")
2020-12-17 12:27:44 +01:00
}
// Load all `non-flag` arguments
// which will be parsed separately.
nsvrs, qt, qc, qn := loadUnparsedArgs(f.Args())
app.QueryFlags.Nameservers = append(app.QueryFlags.Nameservers, nsvrs...)
app.QueryFlags.QTypes = append(app.QueryFlags.QTypes, qt...)
app.QueryFlags.QClasses = append(app.QueryFlags.QClasses, qc...)
app.QueryFlags.QNames = append(app.QueryFlags.QNames, qn...)
2020-12-13 13:19:10 +01:00
// Check if reverse flag is passed. If it is, then set
// query type as PTR and query class as IN.
// Modify query name like 94.2.0.192.in-addr.arpa if it's an IPv4 address.
// Use IP6.ARPA nibble format otherwise.
if app.QueryFlags.ReverseLookup {
app.ReverseLookup()
}
// Load fallbacks.
app.LoadFallbacks()
2020-12-16 14:08:34 +01:00
2020-12-24 17:25:20 +01:00
// Load Questions.
app.PrepareQuestions()
2020-12-24 17:25:20 +01:00
2020-12-17 17:38:23 +01:00
// Load Nameservers.
err = app.LoadNameservers()
2020-12-17 12:27:44 +01:00
if err != nil {
app.Logger.WithError(err).Fatal("error loading nameservers")
2020-12-16 14:08:34 +01:00
}
ropts := resolvers.Options{
Nameservers: app.Nameservers,
UseIPv4: app.QueryFlags.UseIPv4,
UseIPv6: app.QueryFlags.UseIPv6,
SearchList: app.ResolverOpts.SearchList,
Ndots: app.ResolverOpts.Ndots,
Timeout: app.QueryFlags.Timeout * time.Second,
Logger: logger,
Strategy: app.QueryFlags.Strategy,
InsecureSkipVerify: app.QueryFlags.InsecureSkipVerify,
TLSHostname: app.QueryFlags.TLSHostname,
}
if contains(app.QueryFlags.Tweaks, "aa") {
ropts.Authoritative = true
}
if contains(app.QueryFlags.Tweaks, "ad") {
ropts.AuthenticatedData = true
}
if contains(app.QueryFlags.Tweaks, "cd") {
ropts.CheckingDisabled = true
}
// Load Resolvers.
rslvrs, err := resolvers.LoadResolvers(ropts)
2020-12-16 14:08:34 +01:00
if err != nil {
app.Logger.WithError(err).Fatal("error loading resolver")
2020-12-16 14:08:34 +01:00
}
app.Resolvers = rslvrs
2020-12-17 12:27:44 +01:00
app.Logger.Debug("Starting doggo 🐶")
if len(app.QueryFlags.QNames) == 0 {
2020-12-13 16:33:44 +01:00
f.Usage()
os.Exit(0)
}
2020-12-17 12:27:44 +01:00
// Resolve Queries.
2020-12-24 17:25:20 +01:00
var responses []resolvers.Response
for _, q := range app.Questions {
for _, rslv := range app.Resolvers {
2022-07-02 07:49:47 +02:00
resp, err := app.LookupWithRetry(app.QueryFlags.RetryCount, rslv, q)
2020-12-24 17:25:20 +01:00
if err != nil {
app.Logger.WithError(err).Error("error looking up DNS records")
2020-12-24 17:25:20 +01:00
}
responses = append(responses, resp)
}
2020-12-09 18:11:09 +01:00
}
app.Output(responses)
2020-12-17 17:38:23 +01:00
// Quitting.
os.Exit(0)
2020-12-09 18:11:09 +01:00
}