chore: Very very rough impl
parent
bae72607bf
commit
f888bd220f
|
@ -0,0 +1,21 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
dist/
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
vendor/
|
||||
|
||||
# App Specific
|
||||
.env
|
||||
config.yml
|
||||
.DS_Store
|
|
@ -0,0 +1,29 @@
|
|||
DOGGO-BIN := doggo.bin
|
||||
|
||||
HASH := $(shell git rev-parse --short HEAD)
|
||||
COMMIT_DATE := $(shell git show -s --format=%ci ${HASH})
|
||||
BUILD_DATE := $(shell date '+%Y-%m-%d %H:%M:%S')
|
||||
VERSION := ${HASH} (${COMMIT_DATE})
|
||||
|
||||
.PHONY: build
|
||||
build: ## Build the doggo binary
|
||||
mkdir -p bin/; \
|
||||
cd cmd/; \
|
||||
go build -ldflags="-X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}'" -o ${DOGGO-BIN} ./... && \
|
||||
mv ${DOGGO-BIN} ../bin/${DOGGO-BIN}
|
||||
|
||||
.PHONY: run
|
||||
run: build ## Build and Execute the binary after the build step
|
||||
./bin/${DOGGO-BIN}
|
||||
|
||||
fresh: clean build
|
||||
|
||||
clean:
|
||||
go clean
|
||||
- rm -f ./bin/${BIN}
|
||||
|
||||
# pack-releases runns stuffbin packing on a given list of
|
||||
# binaries. This is used with goreleaser for packing
|
||||
# release builds for cross-build targets.
|
||||
pack-releases:
|
||||
$(foreach var,$(RELEASE_BUILDS),stuffbin -a stuff -in ${var} -out ${var} ${STATIC} $(var);)
|
Binary file not shown.
|
@ -0,0 +1,91 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mr-karan/doggo/pkg/resolver"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
// Version and date of the build. This is injected at build-time.
|
||||
buildVersion = "unknown"
|
||||
buildDate = "unknown"
|
||||
)
|
||||
|
||||
// initLogger initializes logger
|
||||
func initLogger(verbose bool) *logrus.Logger {
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&logrus.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
})
|
||||
// Set logger level
|
||||
if verbose {
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
logger.Debug("verbose logging enabled")
|
||||
} else {
|
||||
logger.SetLevel(logrus.InfoLevel)
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Intialize new CLI app
|
||||
app := cli.NewApp()
|
||||
app.Name = "doggo"
|
||||
app.Usage = "Command-line DNS Client"
|
||||
app.Version = buildVersion
|
||||
app.Author = "Karan Sharma @mrkaran"
|
||||
// Register command line args.
|
||||
app.Flags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Usage: "Enable verbose logging",
|
||||
},
|
||||
}
|
||||
var (
|
||||
logger = initLogger(true)
|
||||
)
|
||||
// Initialize hub.
|
||||
hub := NewHub(logger, buildVersion)
|
||||
|
||||
app.Action = func(c *cli.Context) error {
|
||||
// parse arguments
|
||||
for _, arg := range c.Args() {
|
||||
if strings.HasPrefix(arg, "@") {
|
||||
hub.Nameservers = append(hub.Nameservers, arg)
|
||||
} else if isUpper(arg) {
|
||||
if parseQueryType(arg) {
|
||||
hub.QTypes = append(hub.QTypes, arg)
|
||||
} else if parseQueryClass(arg) {
|
||||
hub.QClass = append(hub.QClass, arg)
|
||||
}
|
||||
} else {
|
||||
hub.Domains = append(hub.Domains, arg)
|
||||
}
|
||||
}
|
||||
// load defaults
|
||||
if len(hub.QTypes) == 0 {
|
||||
hub.QTypes = append(hub.QTypes, "A")
|
||||
}
|
||||
if len(hub.Nameservers) == 0 {
|
||||
ns, err := resolver.GetDefaultNameserver()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
hub.Nameservers = append(hub.Nameservers, ns)
|
||||
}
|
||||
// resolve query
|
||||
hub.Resolve()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the app.
|
||||
hub.Logger.Info("Starting doggo...")
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
logger.Errorf("Something terrbily went wrong: %s", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// Hub represents the structure for all app wide functions and structs.
|
||||
type Hub struct {
|
||||
Logger *logrus.Logger
|
||||
Version string
|
||||
Domains []string
|
||||
QTypes []string
|
||||
QClass []string
|
||||
Nameservers []string
|
||||
}
|
||||
|
||||
// NewHub initializes an instance of Hub which holds app wide configuration.
|
||||
func NewHub(logger *logrus.Logger, buildVersion string) *Hub {
|
||||
hub := &Hub{
|
||||
Logger: logger,
|
||||
Version: buildVersion,
|
||||
}
|
||||
return hub
|
||||
}
|
||||
|
||||
// initApp acts like a middleware to load app managers with Hub before running any command.
|
||||
// Use this middleware to perform any action before the command is run.
|
||||
func (hub *Hub) initApp(fn cli.ActionFunc) cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
return fn(c)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Resolve resolves the domain name
|
||||
func (hub *Hub) Resolve() {
|
||||
var messages = make([]dns.Msg, 0, len(hub.Domains))
|
||||
for _, d := range hub.Domains {
|
||||
msg := dns.Msg{}
|
||||
msg.Id = dns.Id()
|
||||
msg.RecursionDesired = true
|
||||
msg.Question = []dns.Question{(dns.Question{d, dns.TypeA, dns.ClassINET})}
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
c := new(dns.Client)
|
||||
for _, msg := range messages {
|
||||
in, rtt, err := c.Exchange(&msg, "127.0.0.1:53")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, ans := range in.Answer {
|
||||
if t, ok := ans.(*dns.A); ok {
|
||||
fmt.Println(t.String())
|
||||
}
|
||||
}
|
||||
fmt.Println("rtt is", rtt, msg.Question)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import "unicode"
|
||||
|
||||
var (
|
||||
QTYPES = []string{"A", "AAAA", "MX"}
|
||||
QCLASS = []string{"CN", "AAAA", "MX"}
|
||||
)
|
||||
|
||||
func isUpper(s string) bool {
|
||||
for _, r := range s {
|
||||
if !unicode.IsUpper(r) && unicode.IsLetter(r) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseQueryType(s string) bool {
|
||||
for _, b := range QTYPES {
|
||||
if b == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseQueryClass(s string) bool {
|
||||
for _, b := range QCLASS {
|
||||
if b == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module github.com/mr-karan/doggo
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/urfave/cli v1.22.5
|
||||
)
|
|
@ -0,0 +1,36 @@
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,33 @@
|
|||
package resolver
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetDefaultNameserver reads `/etc/resolv.conf` to determine the default
|
||||
// nameserver configured. Returns an error if unable to parse or
|
||||
// no nameserver specified. It returns as soon as it finds a line
|
||||
// with `nameserver` prefix.
|
||||
// An example format:
|
||||
// `nameserver 127.0.0.1`
|
||||
|
||||
func GetDefaultNameserver() (string, error) {
|
||||
file, err := os.Open("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
if strings.HasPrefix(scanner.Text(), "nameserver") {
|
||||
return strings.Fields(scanner.Text())[1], nil
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "", err
|
||||
}
|
Loading…
Reference in New Issue