diff --git a/go.mod b/go.mod
index 1f0c71e..2b19e2e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module git.send.nrw/StadtHilden/ipv6calculator
+module git.send.nrw/sendnrw/ipv6calculator
go 1.23.1
diff --git a/main.go b/main.go
index 935c74c..8de3e1f 100644
--- a/main.go
+++ b/main.go
@@ -6,45 +6,23 @@ import (
"log"
"net"
"net/http"
+ "os"
+ "strings"
)
const (
- listenAddr = ":8080" // server port
- ulaPrefix = "fdcb:7de3:a12a:0::" // fixed ULA /96 prefix
+ listenAddr = ":8080" // TCP port for the web UI
+ defaultPrefix = "fdcb:7de3:a12a:0::" // fallback when ULA_PREFIX is unset
+ defaultIP = "172.16.0.0"
)
-// pageTemplate is served for both GET (empty result) and POST (with result).
-var pageTemplate = template.Must(template.New("page").Parse(`
-
-
-
-IPv4 → IPv6‑Mapper
-
-
-
- IPv4 → IPv6‑Mapper
-
- {{if .IPv6}}
- IPv6‑Adresse: {{.IPv6}}
- {{end}}
- {{if .Error}}
- Fehler: {{.Error}}
- {{end}}
- Präfix: ` + ulaPrefix + `
(feste /96‑Zuordnung)
-
-`))
+var (
+ ulaPrefix string // effective /96 prefix (always ending in "::")
+ pageTemplate *template.Template // populated in init()
+ pageIP string
+)
-// viewData transports data into the page template.
+// viewData feeds data into the HTML template.
type viewData struct {
IPv4 string
IPv6 string
@@ -52,9 +30,10 @@ type viewData struct {
}
func main() {
+ initPrefixAndTemplate()
+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- // Empty page on root
- renderPage(w, viewData{})
+ renderPage(w, viewData{}) // empty form
})
http.HandleFunc("/convert", func(w http.ResponseWriter, r *http.Request) {
@@ -73,19 +52,73 @@ func main() {
renderPage(w, data)
})
- log.Printf("Server läuft auf http://localhost%s …", listenAddr)
+ log.Printf("Server läuft auf http://localhost%s (Präfix: %s)", listenAddr, ulaPrefix)
log.Fatal(http.ListenAndServe(listenAddr, nil))
}
-// embedIPv4 converts an IPv4 dotted string into the ulaPrefix‑based IPv6 address.
+// initPrefixAndTemplate reads the environment variable and prepares the HTML template.
+func initPrefixAndTemplate() {
+ ulaPrefix = os.Getenv("ULA_PREFIX")
+ if ulaPrefix == "" {
+ ulaPrefix = defaultPrefix
+ }
+
+ pageIP = os.Getenv("IPv4")
+ if pageIP == "" {
+ pageIP = defaultIP
+ }
+
+ // Ensure the prefix ends with exactly two colons (::) so that we can append hex words.
+ if !strings.HasSuffix(ulaPrefix, "::") {
+ if strings.HasSuffix(ulaPrefix, ":") {
+ ulaPrefix += ":"
+ } else {
+ ulaPrefix += "::"
+ }
+ }
+
+ html := fmt.Sprintf(`
+
+
+
+IPv4 → IPv6‑Mapper
+
+
+
+ IPv4 → IPv6-Mapper
+
+ {{if .IPv6}}
+ IPv6-Adresse: {{.IPv6}}
+ {{end}}
+ {{if .Error}}
+ Fehler: {{.Error}}
+ {{end}}
+ Präfix: %s
(/96‑Zuordnung)
+
+`, pageIP, ulaPrefix)
+
+ pageTemplate = template.Must(template.New("page").Parse(html))
+}
+
+// embedIPv4 converts a dotted IPv4 string into the chosen ULA /96 IPv6 address.
func embedIPv4(ipv4 string) (string, error) {
ip := net.ParseIP(ipv4).To4()
if ip == nil {
- return "", fmt.Errorf("'%s' ist keine gültige IPv4‑Adresse", ipv4)
+ return "", fmt.Errorf("'%s' ist keine gültige IPv4-Adresse", ipv4)
}
- first := uint16(ip[0])<<8 | uint16(ip[1]) // High 16 bits
- second := uint16(ip[2])<<8 | uint16(ip[3]) // Low 16 bits
- return fmt.Sprintf("%s%x:%x", ulaPrefix, first, second), nil
+ hi := uint16(ip[0])<<8 | uint16(ip[1]) // high 16 bits (octets 0–1)
+ lo := uint16(ip[2])<<8 | uint16(ip[3]) // low 16 bits (octets 2–3)
+ return fmt.Sprintf("%s%x:%x", ulaPrefix, hi, lo), nil
}
func renderPage(w http.ResponseWriter, d viewData) {