diff --git a/service/userconfig.go b/service/userconfig.go index 2c9464b..019a5e9 100644 --- a/service/userconfig.go +++ b/service/userconfig.go @@ -24,17 +24,18 @@ type UserConfig struct { UserName string PassWord string + Domain string Router UserConfigRouter Others []UserConfigOther } type UserConfigRouter struct { - DNS string - NFT UserConfigNFT + Hostname string + NFT UserConfigNFT } type UserConfigOther struct { - DNS string + Hostname string V6IID string RegisterV4 bool NFT UserConfigNFT @@ -119,44 +120,51 @@ func (uco *UserConfigOther) ConvertIIDToAddress(localNet *net.IPNet) net.IP { return out } -func (ucn *UserConfigNFT) ValidateSetNames() bool { +func (ucn *UserConfigNFT) ValidateSetNames() error { if ucn.Set4 == "" && ucn.Set6 == "" { - return true + return nil } - return ucn.Set4 != ucn.Set6 + if ucn.Table == "" { + return errors.New("NFT table name undefined") + } + if ucn.Set4 == ucn.Set6 { + return errors.New("set4 and set6 are identical") + } + + return nil } func (uc *UserConfig) Validate() error { - if !uc.Router.NFT.ValidateSetNames() { - return errors.New("router NFT set names invalid (probably identical for v4 and v6)") + if err := uc.Router.NFT.ValidateSetNames(); err != nil { + return fmt.Errorf("router NFT validation failed: %v", err) } - if uc.Router.DNS == "" { - return errors.New("router record has no DNS") + if uc.Router.Hostname == "" { + return errors.New("router record has no Hostname") } dnsnames := make(map[string]bool) - dnsnames[uc.Router.DNS] = true + dnsnames[uc.Router.Hostname] = true for i, other := range uc.Others { - if other.DNS == "" { - return fmt.Errorf("other record #%d has no DNS", i) + if other.Hostname == "" { + return fmt.Errorf("other record #%d has no Hostname", i) } - if dnsnames[other.DNS] { - return fmt.Errorf("the DNS FQDN %s is used twice", other.DNS) + if dnsnames[other.Hostname] { + return fmt.Errorf("the Hostname %s is used twice", other.Hostname) } - dnsnames[other.DNS] = true - if !other.NFT.ValidateSetNames() { - return fmt.Errorf("other %s NFT set names invalid (probably identical for v4 and v6)", other.DNS) + dnsnames[other.Hostname] = true + if err := other.NFT.ValidateSetNames(); err != nil { + return fmt.Errorf("other %s NFT validation failed: %v", other.Hostname, err) } if other.V6IID == "" { - return fmt.Errorf("other record %s has no V6IID", other.DNS) + return fmt.Errorf("other record %s has no V6IID", other.Hostname) } iidIP := net.ParseIP(other.V6IID) if iidIP == nil { - return fmt.Errorf("other record %s has invalid V6IID %s", other.DNS, other.V6IID) + return fmt.Errorf("other record %s has invalid V6IID %s", other.Hostname, other.V6IID) } if iidIP.To4() != nil { - return fmt.Errorf("other record %s IID looks like an IPv4 Address", other.DNS) + return fmt.Errorf("other record %s IID looks like an IPv4 Address", other.Hostname) } } diff --git a/users/example.yml b/users/example.yml index 86a20a2..a88c2c8 100644 --- a/users/example.yml +++ b/users/example.yml @@ -1,19 +1,20 @@ password: $2a$10$ymHFfGjKINWsUKwEo5xp.efN6DR6NkiRCXsbH4VWo0Nnzma8Yc.82 +domain: dyn.local router: - DNS: brandfeld.dyn.local + Hostname: mainhost NFT: table: sshguard set4: blackhole set6: blackhole6 others: - - DNS: atlantis.dyn.local + - Hostname: atlantis v6iid: ::dead:beef:dead:beef registerv4: true NFT: table: sshguard set4: blackhole set6: blackhole6 - - DNS: troya.dyn.local + - Hostname: troya v6iid: ::cafe:babe:deca:fbad registerv4: false NFT: diff --git a/webapi/update.go b/webapi/update.go index 2130226..1e17cf3 100644 --- a/webapi/update.go +++ b/webapi/update.go @@ -36,23 +36,82 @@ func handleUpdate(w http.ResponseWriter, r *http.Request) { return } + ur.Config = uc + + // Start DEBUG Output + log.Println("Final request") + log.Println(ur.PrettyPrint()) + for _, other := range uc.Others { + log.Printf("Other %s, IID %v, merged: %v", + other.Hostname, other.V6IID, other.ConvertIIDToAddress(ur.IPv6Net)) + } + + log.Println("WebAPI Config:") + log.Println(C.PrettyPrint()) + log.Println("Service Config:") + log.Println(service.C.PrettyPrint()) + // End DEBUG Output + + if err := processUpdateRequest(ur); err != nil { + log.Printf("failed to process UpdateRequest: %v", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + } + w.Header().Set("Content-Type", "text/plain") fmt.Fprintln(w, "OK") - fmt.Fprintln(w, ur.PrettyPrint()) - log.Println(ur.PrettyPrint()) - log.Println(ur.IPv6Net.IP) - log.Println(ur.IPv6Net.Mask) - log.Printf("Request PW: %s, Config PW: %s", ur.Password, uc.PassWord) - fmt.Fprintln(w, "Unmarshalled userconfig:") - fmt.Fprintln(w, uc.PrettyPrint()) - fmt.Fprintln(w, "WebAPI Config:") - fmt.Fprintln(w, C.PrettyPrint()) - fmt.Fprintln(w, "Service Config:") - fmt.Fprintln(w, service.C.PrettyPrint()) - - for _, other := range uc.Others { - log.Printf("Other %s, IID %v, UR V6NEt: %v, merged: %v", - other.DNS, other.V6IID, ur.IPv6Net, - other.ConvertIIDToAddress(ur.IPv6Net)) - } +} + +func processUpdateRequest(ur *UpdateRequest) error { + nfu := service.NewNFTUpdate() + + if err := service.DNSUpdateEntry(ur.Config.Domain, ur.Config.Router.Hostname, ur.IPv4, ur.IPv6); err != nil { + return fmt.Errorf("failed to update router DNS: %v", err) + } + if ur.Config.Router.NFT.Table != "" { + if ur.IPv4 != nil && ur.Config.Router.NFT.Set4 != "" { + if err := nfu.AddIP(ur.Config.Router.NFT.Table, ur.Config.Router.NFT.Set4, ur.IPv4); err != nil { + return fmt.Errorf("failed to update IPv4 Router NFT setup: %v", err) + } + } + if ur.IPv6 != nil && ur.Config.Router.NFT.Set6 != "" { + if err := nfu.AddIP(ur.Config.Router.NFT.Table, ur.Config.Router.NFT.Set6, ur.IPv6); err != nil { + return fmt.Errorf("failed to update IPv6 Router NFT setup: %v", err) + } + } + } + + for _, other := range ur.Config.Others { + fullV6IP := other.ConvertIIDToAddress(ur.IPv6Net) + if other.RegisterV4 { + if err := service.DNSUpdateEntry(ur.Config.Domain, other.Hostname, ur.IPv4, fullV6IP); err != nil { + return fmt.Errorf("failed to update DNS for host %s: %v", other.Hostname, err) + } + } else { + if err := service.DNSUpdateEntry(ur.Config.Domain, other.Hostname, nil, fullV6IP); err != nil { + return fmt.Errorf("failed to update DNS for host %s: %v", other.Hostname, err) + } + } + + if other.NFT.Table != "" { + if other.NFT.Set6 != "" { + if err := nfu.AddIP(other.NFT.Table, other.NFT.Set6, fullV6IP); err != nil { + return fmt.Errorf("failed to update IPv6 NFT setup for host %s: %v", other.Hostname, err) + } + } + if other.RegisterV4 && other.NFT.Set4 != "" { + if err := nfu.AddIP(other.NFT.Table, other.NFT.Set4, ur.IPv4); err != nil { + return fmt.Errorf("failed to update IPv6 NFT setup for host %s: %v", other.Hostname, err) + } + } + } + } + + log.Println("Summary of collected NFT Updates:") + log.Println(nfu.PrettyPrint()) + + if err := nfu.Process(); err != nil { + return fmt.Errorf("failed to update NFT Setup: %v", err) + } + + return nil } diff --git a/webapi/updaterequest.go b/webapi/updaterequest.go index 56bd722..5c2b644 100644 --- a/webapi/updaterequest.go +++ b/webapi/updaterequest.go @@ -7,6 +7,8 @@ import ( "log" "net" "net/url" + + "gitea.nehmer.net/torben/dyndns/service" ) type UpdateRequest struct { @@ -15,6 +17,7 @@ type UpdateRequest struct { UserName string Password string IPv6Net *net.IPNet + Config *service.UserConfig } func (ur *UpdateRequest) String() string {