"encoding/base64"
"flag"
"fmt"
+ "github.com/miekg/dns"
"io"
"io/ioutil"
"log"
)
const (
- DefaultAccFile = "/usr/local/etc/ddnset/ddnset.acc"
- DefaultZoneFile = "/usr/local/etc/ddnset/ddnset.zon"
- DefaultLogFile = "/var/log/ddnset/default.log"
- DefaultListenPort = 1980
+ DefaultAccFile = "/usr/local/etc/ddnset/ddnset.acc"
+ DefaultZoneFile = "/usr/local/etc/ddnset/ddnset.zon"
+ DefaultLogFile = "/var/log/ddnset/default.log"
+ DefaultListenPort = 1980
+ DefaultAuthorityDNS = "localhost"
)
var AccFile = flag.String("a", DefaultAccFile, "Path to account file")
var ZoneFile = flag.String("z", DefaultZoneFile, "Path to zone file")
var LogFile = flag.String("l", DefaultLogFile, "Path to log file")
var ListenPort = flag.Uint("p", DefaultListenPort, "Port to listen on")
+var AuthorityDNS = flag.String("s", DefaultAuthorityDNS, "Authoritative name server")
var Help = flag.Bool("h", false, "Show usage")
return true
}
+func resolveWithAuthority(target, rectype string) string {
+ res := ""
+ c := dns.Client{}
+ m := dns.Msg{}
+
+ if rectype == "A" || rectype == "" {
+ m.SetQuestion(target+".", dns.TypeA)
+ r, _, err := c.Exchange(&m, *AuthorityDNS+":53")
+
+ if err == nil {
+ if len(r.Answer) == 0 {
+ log.Printf("%s. has no A record", target)
+ }
+
+ for _, ans := range r.Answer {
+ record := ans.(*dns.A)
+ log.Printf("%s. has IP %s", target, record.A)
+ res = res + record.A.String() + ","
+ }
+ } else {
+ log.Print(err)
+ }
+ }
+
+ if rectype == "AAAA" || rectype == "" {
+ m.SetQuestion(target+".", dns.TypeAAAA)
+ r, _, err := c.Exchange(&m, *AuthorityDNS+":53")
+
+ if err == nil {
+ if len(r.Answer) == 0 {
+ log.Print(target, ". has no AAAA record")
+ }
+ for _, ans := range r.Answer {
+ record := ans.(*dns.AAAA)
+ log.Printf("%s. has IPv6 %s", target, record.AAAA)
+ res = res + record.AAAA.String() + ","
+ }
+ } else {
+ log.Print(err)
+ }
+ }
+ return strings.TrimSuffix(res, ",")
+}
+
func myipHandle(w http.ResponseWriter, r *http.Request) {
log.Print(r.RemoteAddr, " ", r.Method, " ", r.URL.String())
clientIP, _, err := net.SplitHostPort(r.RemoteAddr)
//check auth
authok := false
hosts := ""
+ hostip := (r.URL.Path == "/hostip")
+
if hdr_auth, ok := r.Header["Authorization"]; ok {
log.Print("Authorization header present")
for _, auth := range hdr_auth {
log.Print("User hosts: ", hosts)
//check ip
q := r.URL.Query()
+
+ myip := "0.0.0.0"
+ ver := 4
+ valid := false
+ myip_count := len(q["myip"])
+ log.Print("myips: ", myip_count)
+ if !hostip {
+ if myip_count == 1 {
+ myip, ver, valid = checkIP(q["myip"][0]) //one IP to rule them all
+ }
+ log.Printf("IP: %s (valid:%v, ver:%d)", myip, valid, ver)
+ if !valid {
+ log.Print("StatusBadIP")
+ io.WriteString(w, StatusBadIP+"\n")
+ return
+ }
+ }
+ //update or reportip
hostnames := q["hostname"]
- myip, ver, valid := checkIP(q["myip"][0]) //one IP to rule them all
- log.Printf("IP: %s (valid:%v, ver:%d)", myip, valid, ver)
- if !valid {
- log.Print("StatusBadIP")
- io.WriteString(w, StatusBadIP+"\n")
- return
+ rectype := ""
+ if len(q["rectype"]) == 1 {
+ rectype = q["rectype"][0]
}
- //update
for _, host := range hostnames {
+ log.Print("Host:", host)
if !isDomainName(host) {
log.Print("StatusNotFQHN")
io.WriteString(w, StatusNotFQHN+"\n")
continue
}
if strings.Contains(hosts, host) {
- log.Printf("Updating %s to IP %s", host, myip)
- updated := knsupdate(host, myip, zone, ver)
- if updated {
- log.Print("StatusGood")
- io.WriteString(w, StatusGood+"\n")
+ if !hostip {
+ log.Printf("Updating %s to IP %s", host, myip)
+ updated := knsupdate(host, myip, zone, ver)
+ if updated {
+ log.Print("StatusGood")
+ io.WriteString(w, StatusGood+"\n")
+ } else {
+ log.Print("StatusBadDay")
+ io.WriteString(w, StatusBadDay+"\n")
+ }
} else {
- log.Print("StatusBadDay")
- io.WriteString(w, StatusBadDay+"\n")
+ io.WriteString(w, resolveWithAuthority(host, rectype)+"\n")
}
} else {
log.Print("StatusBadHost")
http.HandleFunc("/myip", myipHandle)
http.HandleFunc("/myip.php", myipHandle)
http.HandleFunc("/", rootHandle)
+ http.HandleFunc("/hostip", rootHandle)
logf, err := os.OpenFile(*LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if nil == err {
defer logf.Close()