chore: Very very rough impl

pull/2/head
Karan Sharma 2020-12-09 22:41:09 +05:30
parent bae72607bf
commit f888bd220f
10 changed files with 319 additions and 0 deletions

21
.gitignore vendored 100644
View File

@ -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

29
Makefile 100644
View File

@ -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);)

BIN
bin/doggo.bin 100755

Binary file not shown.

91
cmd/cli.go 100644
View File

@ -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)
}
}

33
cmd/hub.go 100644
View File

@ -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)
}
}

32
cmd/resolve.go 100644
View File

@ -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)
}
}

35
cmd/utils.go 100644
View File

@ -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
}

9
go.mod 100644
View File

@ -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
)

36
go.sum 100644
View File

@ -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=

View File

@ -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
}