package main import ( "errors" "fmt" "log" "net" "net/http" "os" "time" ) type conf struct { zone string token string server string } func main() { conf, err := readConfigVars() if err != nil { log.Fatal(err) } lastIPv6 := "" for { time.Sleep(1 * time.Second) if newIPv6, ok := checkForNewV6(lastIPv6); ok { lastIPv6 = newIPv6 sendNewIP(conf) } } } // Checks if the newest IPv6 on the first Interface is not equal to the provided one // Returns the new IPv6 if it changed func checkForNewV6(lastIPv6 string) (string, bool) { interfaces, err := net.Interfaces() if err != nil { log.Println(err) return lastIPv6, false } currentIPv6 := "" for _, inter := range interfaces { addresses, err := inter.Addrs() if err != nil { log.Println(err) return lastIPv6, false } for _, addr := range addresses { if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() { if ip.IP.To4() == nil { currentIPv6 = ip.IP.String() } } } } if currentIPv6 != lastIPv6 { return currentIPv6, true } return lastIPv6, false } // Updates the Prefix on the Server func sendNewIP(config conf) error { _, err := http.Get(fmt.Sprintf("https://ipv6.dynv6.com/api/update?ipv6prefix=auto&token=%s&zone=%s", config.token, config.zone)) if err != nil { return err } return nil } // Reads all ENVIRONMENT variables func readConfigVars() (conf, error) { var zone, token, server string var present bool if zone, present = os.LookupEnv("ZONE"); !present { return conf{}, errors.New("No Zone Specified") } if token, present = os.LookupEnv("TOKEN"); !present { return conf{}, errors.New("No Token Specified") } if server, present = os.LookupEnv("SERVER"); !present { server = "ipv6.dynv6.com" } return conf{ zone: zone, token: token, server: server, }, nil }