From 9026b24cc14cbf8806b1d706e3768169dcc4d0c8 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 19 Jun 2016 19:46:23 +0300 Subject: [PATCH] split up modules --- addr.go | 56 +++++++++++++++++++++++++--------- dns.go | 26 ++++++++++++++++ main.go | 63 +++++++------------------------------- netlink.go | 24 +++++++++++++++ update.go | 88 +++++++++++++++++++++--------------------------------- 5 files changed, 137 insertions(+), 120 deletions(-) create mode 100644 dns.go create mode 100644 netlink.go diff --git a/addr.go b/addr.go index 080f11b..dc8c237 100644 --- a/addr.go +++ b/addr.go @@ -2,28 +2,56 @@ package main import ( "net" - "github.com/miekg/dns" + "github.com/vishvananda/netlink" + "fmt" + "log" ) -type Addr struct { - IP net.IP +type AddrSet struct { + addrs map[string]net.IP } -func (addr Addr) buildRR(name string, ttl int) dns.RR { - if ip4 := addr.IP.To4(); ip4 != nil { - return &dns.A{ - Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: uint32(ttl)}, - A: ip4, - } +func (as *AddrSet) ScanInterface(iface string, family Family) error { + link, err := netlink.LinkByName(iface) + if err != nil { + return fmt.Errorf("netlink.LinkByName %v: %v", iface, err) } - if ip6 := addr.IP.To16(); ip6 != nil { - return &dns.AAAA{ - Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: uint32(ttl)}, - AAAA: ip6, - } + addrList, err := netlink.AddrList(link, int(family)) + if err != nil { + return fmt.Errorf("netlink.AddrList %v: %v", link, err) + } + + // set + as.addrs = make(map[string]net.IP) + + for _, addr := range addrList { + as.applyLinkAddr(link, addr) } return nil } +func (as *AddrSet) applyLinkAddr(link netlink.Link, addr netlink.Addr) { + linkUp := link.Attrs().Flags & net.FlagUp != 0 + + if addr.Scope >= int(netlink.SCOPE_LINK) { + return + } + + as.applyAddr(addr.IP, linkUp) +} + +// Update state for address +func (as *AddrSet) applyAddr(ip net.IP, up bool) { + if up { + log.Printf("update: up %v", ip) + + as.addrs[ip.String()] = ip + + } else { + log.Printf("update: down %v", ip) + + delete(as.addrs, ip.String()) + } +} diff --git a/dns.go b/dns.go new file mode 100644 index 0000000..4822012 --- /dev/null +++ b/dns.go @@ -0,0 +1,26 @@ +package main + +import ( + "github.com/miekg/dns" + "fmt" +) + +const TSIG_FUDGE_SECONDS = 300 +type TSIGAlgorithm string + +func (t *TSIGAlgorithm) UnmarshalFlag(value string) error { + switch (value) { + case "hmac-md5", "md5": + *t = dns.HmacMD5 + case "hmac-sha1", "sha1": + *t = dns.HmacSHA1 + case "hmac-sha256", "sha256": + *t = dns.HmacSHA256 + case "hmac-sha512", "sha512": + *t = dns.HmacSHA512 + default: + return fmt.Errorf("Invalid --tsig-algorithm=%v", value) + } + + return nil +} diff --git a/main.go b/main.go index fe7cd64..20ee05b 100644 --- a/main.go +++ b/main.go @@ -2,51 +2,11 @@ package main import ( "github.com/jessevdk/go-flags" - "github.com/vishvananda/netlink" - "github.com/miekg/dns" - "net" - "fmt" "log" "os" "time" ) -// zero value is unspec=all -type Family int - -func (f *Family) UnmarshalFlag(value string) error { - switch (value) { - case "inet", "ipv4": - *f = netlink.FAMILY_V4 - case "inet6", "ipv6": - *f = netlink.FAMILY_V6 - default: - return fmt.Errorf("Invalid --family=%v", value) - } - - return nil -} - -const TSIG_FUDGE_SECONDS = 300 -type TSIGAlgorithm string - -func (t *TSIGAlgorithm) UnmarshalFlag(value string) error { - switch (value) { - case "hmac-md5", "md5": - *t = dns.HmacMD5 - case "hmac-sha1", "sha1": - *t = dns.HmacSHA1 - case "hmac-sha256", "sha256": - *t = dns.HmacSHA256 - case "hmac-sha512", "sha512": - *t = dns.HmacSHA512 - default: - return fmt.Errorf("Invalid --tsig-algorithm=%v", value) - } - - return nil -} - type Options struct { Verbose bool `long:"verbose" short:"v"` @@ -75,33 +35,32 @@ func main() { os.Exit(1) } - var update = &Update{ - zone: dns.Fqdn(options.Zone), - name: dns.Fqdn(options.Name), + var update = Update{ ttl: options.TTL, timeout: options.Timeout, } - if _, _, err := net.SplitHostPort(options.Server); err == nil { - update.server = options.Server - } else { - update.server = net.JoinHostPort(options.Server, "53") + if err := update.Init(options.Name, options.Zone, options.Server); err != nil { + log.Fatalf("init: %v", err) } if options.TSIGName != "" { log.Printf("using TSIG: %v (algo=%v)", options.TSIGName, options.TSIGAlgorithm) - update.initTSIG(dns.Fqdn(options.TSIGName), options.TSIGSecret, string(options.TSIGAlgorithm)) + update.InitTSIG(options.TSIGName, options.TSIGSecret, options.TSIGAlgorithm) } - // run + // addrs + var addrs = new(AddrSet) + if options.Interface == "" { - } else if err := update.scan(options.Interface, int(options.InterfaceFamily)); err != nil { - log.Fatalf("scan: %v", err) + } else if err := addrs.ScanInterface(options.Interface, options.InterfaceFamily); err != nil { + log.Fatalf("addrs scan: %v", err) } - if err := update.update(options.Verbose); err != nil { + // update + if err := update.Update(addrs, options.Verbose); err != nil { log.Fatalf("update: %v", err) } } diff --git a/netlink.go b/netlink.go new file mode 100644 index 0000000..e701dd3 --- /dev/null +++ b/netlink.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/vishvananda/netlink" + "fmt" +) + +// zero value is unspec=all +type Family int + +func (f *Family) UnmarshalFlag(value string) error { + switch (value) { + case "inet", "ipv4": + *f = netlink.FAMILY_V4 + case "inet6", "ipv6": + *f = netlink.FAMILY_V6 + default: + return fmt.Errorf("Invalid --family=%v", value) + } + + return nil +} + + diff --git a/update.go b/update.go index c0a0c00..edb84a9 100644 --- a/update.go +++ b/update.go @@ -1,7 +1,6 @@ package main import ( - "github.com/vishvananda/netlink" "github.com/miekg/dns" "time" "fmt" @@ -15,83 +14,64 @@ type Update struct { ttl int tsig map[string]string - tsigAlgo string + tsigAlgo TSIGAlgorithm server string timeout time.Duration - - link netlink.Link - addrs map[string]Addr } -func (u *Update) initTSIG(name string, secret string, algo string) { - u.tsig = map[string]string{name: secret} - u.tsigAlgo = algo -} +func (u *Update) Init(name string, zone string, server string) error { + u.name = dns.Fqdn(name) + u.zone = dns.Fqdn(zone) -// Update state for link -func (u *Update) scan(iface string, family int) error { - link, err := netlink.LinkByName(iface) - if err != nil { - return fmt.Errorf("netlink.LinkByName %v: %v", iface, err) - } - - addrs, err := netlink.AddrList(link, family) - if err != nil { - return fmt.Errorf("netlink.AddrList %v: %v", link, err) - } - - // set - u.addrs = make(map[string]Addr) - - for _, addr := range addrs { - u.applyLinkAddr(link, addr) + if _, _, err := net.SplitHostPort(server); err == nil { + u.server = server + } else { + u.server = net.JoinHostPort(server, "53") } return nil } -func (u *Update) applyLinkAddr(link netlink.Link, addr netlink.Addr) { - linkUp := link.Attrs().Flags & net.FlagUp != 0 - - if addr.Scope >= int(netlink.SCOPE_LINK) { - return - } - - u.apply(addr.IP, linkUp) +func (u *Update) InitTSIG(name string, secret string, algo TSIGAlgorithm) { + u.tsig = map[string]string{dns.Fqdn(name): secret} + u.tsigAlgo = algo } -// Update state for address -func (u *Update) apply(ip net.IP, up bool) { - if up { - log.Printf("update: up %v", ip) - - u.addrs[ip.String()] = Addr{IP: ip} - - } else { - log.Printf("update: down %v", ip) - - delete(u.addrs, ip.String()) +func (u *Update) buildAddr(ip net.IP) dns.RR { + if ip4 := ip.To4(); ip4 != nil { + return &dns.A{ + Hdr: dns.RR_Header{Name: u.name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: uint32(u.ttl)}, + A: ip4, + } } -} -func (u *Update) buildRR() (rs []dns.RR) { - for _, addr := range u.addrs { - rs = append(rs, addr.buildRR(u.name, u.ttl)) + if ip6 := ip.To16(); ip6 != nil { + return &dns.AAAA{ + Hdr: dns.RR_Header{Name: u.name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: uint32(u.ttl)}, + AAAA: ip6, + } + } + + return nil +} +func (u *Update) buildAddrs(addrs *AddrSet) (rs []dns.RR) { + for _, ip := range addrs.addrs { + rs = append(rs, u.buildAddr(ip)) } return rs } -func (u *Update) buildMsg() *dns.Msg { +func (u *Update) buildMsg(addrs *AddrSet) *dns.Msg { var msg = new(dns.Msg) msg.SetUpdate(u.zone) msg.RemoveName([]dns.RR{&dns.RR_Header{Name:u.name}}) - msg.Insert(u.buildRR()) + msg.Insert(u.buildAddrs(addrs)) if u.tsig != nil { for keyName, _ := range u.tsig { - msg.SetTsig(keyName, u.tsigAlgo, TSIG_FUDGE_SECONDS, time.Now().Unix()) + msg.SetTsig(keyName, string(u.tsigAlgo), TSIG_FUDGE_SECONDS, time.Now().Unix()) } } @@ -122,8 +102,8 @@ func (u *Update) query(msg *dns.Msg) (*dns.Msg, error) { } } -func (u *Update) update(verbose bool) error { - q := u.buildMsg() +func (u *Update) Update(addrs *AddrSet, verbose bool) error { + q := u.buildMsg(addrs) if verbose { log.Printf("query:\n%v", q)