split up modules
This commit is contained in:
parent
adab1510c9
commit
9026b24cc1
56
addr.go
56
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
63
main.go
63
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
88
update.go
88
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)
|
||||
|
|
Loading…
Reference in New Issue