Skip to content
Snippets Groups Projects
dyndnsd-client.go 2.54 KiB
Newer Older
Erick Hitter's avatar
Erick Hitter committed
package main

Erick Hitter's avatar
Erick Hitter committed
import (
	"fmt"
	"github.com/joshbetz/config"
	"io/ioutil"
Erick Hitter's avatar
Erick Hitter committed
	"log"
Erick Hitter's avatar
Erick Hitter committed
	"net/http"
	"net/url"
Erick Hitter's avatar
Erick Hitter committed
	"os"
Erick Hitter's avatar
Erick Hitter committed
)

var (
	cfg          *config.Config
	ipv4Endpoint string
	ipv6Endpoint string
Erick Hitter's avatar
Erick Hitter committed

	logger *log.Logger
Erick Hitter's avatar
Erick Hitter committed
// Preparations
Erick Hitter's avatar
Erick Hitter committed
func init() {
Erick Hitter's avatar
Erick Hitter committed
	// Logging
	logOpts := log.Ldate | log.Ltime | log.LUTC | log.Lshortfile
	logger = log.New(os.Stdout, "", logOpts)

	logger.Println("PINGING dyndnsd ENDPOINT")
Erick Hitter's avatar
Erick Hitter committed
	// Configuration
	cfg = config.New("config.json")
Erick Hitter's avatar
Erick Hitter committed
	cfg.Get("ipv4_endpoint", &ipv4Endpoint)
	cfg.Get("ipv6_endpoint", &ipv6Endpoint)
}

// Do the update!
Erick Hitter's avatar
Erick Hitter committed
func main() {
Erick Hitter's avatar
Erick Hitter committed
	// Base URL
	endpoint, err := buildEndpointUrl()
	if err != nil {
Erick Hitter's avatar
Erick Hitter committed
		logger.Println("Couldn't build endpoint URL")
		logger.Printf("%s", err)
Erick Hitter's avatar
Erick Hitter committed
		return
	}

	// IPv4 is required
	ipv4, err := getUrl(ipv4Endpoint)
	if err == nil {
		query := endpoint.Query()
		query.Set("myip", ipv4)
		endpoint.RawQuery = query.Encode()
	} else {
Erick Hitter's avatar
Erick Hitter committed
		logger.Println("Couldn't retrieve IPv4 address")
		logger.Printf("%s", err)
Erick Hitter's avatar
Erick Hitter committed
		return
	}

	// IPv6 is optional
	ipv6, err := getUrl(ipv6Endpoint)
	if err == nil {
		query := endpoint.Query()
		query.Set("myip6", ipv6)
		endpoint.RawQuery = query.Encode()
Erick Hitter's avatar
Erick Hitter committed
	} else {
		logger.Println("Couldn't retrieve IPv6 address")
		logger.Printf("%s", err)
Erick Hitter's avatar
Erick Hitter committed
	}

	// Send the update
	dyndns, err := getUrl(endpoint.String())
	if err != nil {
Erick Hitter's avatar
Erick Hitter committed
		logger.Println("Couldn't update dyndnsd endpoint")
		logger.Printf("%s", err)
Erick Hitter's avatar
Erick Hitter committed
	logger.Println("SUCCESS! Ping sent.")
	logger.Printf("%s", dyndns)
Erick Hitter's avatar
Erick Hitter committed
}

// Build endpoint URL from configuration
func buildEndpointUrl() (*url.URL, error) {
	var username string
	var password string
	var protocol string
	var host string
	var port int
	var path string
	var hostname string

	cfg.Get("username", &username)
	cfg.Get("password", &password)
	cfg.Get("protocol", &protocol)
	cfg.Get("host", &host)
	cfg.Get("port", &port)
	cfg.Get("path", &path)
	cfg.Get("dns_hostname", &hostname)

	daemonUrl, err := url.Parse("")
	if err != nil {
		return nil, err
	}

	daemonUrl.Scheme = protocol
	daemonUrl.Host = fmt.Sprintf("%s:%d", host, port)
	daemonUrl.Path = path

	userInfo := url.UserPassword(username, password)
	daemonUrl.User = userInfo

	query := daemonUrl.Query()
	query.Set("hostname", hostname)
	daemonUrl.RawQuery = query.Encode()

	return daemonUrl, nil
}

// Retrieve given URL
func getUrl(url string) (string, error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return "", err
	}

	respBodyString := string(respBody)
	return respBodyString, nil
Erick Hitter's avatar
Erick Hitter committed
}