diff --git a/go/src/themaru/http.go b/go/src/themaru/http.go index 8d08871..4861239 100644 --- a/go/src/themaru/http.go +++ b/go/src/themaru/http.go @@ -3,7 +3,6 @@ package main import ( "html/template" "net/http" - "os" "sync" "github.com/gin-contrib/multitemplate" @@ -23,17 +22,9 @@ var indexPage = template.Must(template.New("index.html").Parse(` <body> <h1>{{.Device}} Configuration</h1> <div> - <p>System Version: {{.Version}}</p> + <p>System Version: {{.falinux_version}}</p> </div> <hr> - <h1>Setting IP Address</h1> - <div> - <form action="/address" method="post"> - <input type="text" name="address" value="{{.IP}}" required /> - <input type="text" name="address2" value="{{.IP2}}" required /> - <input type="submit" value="Set" /> - </form> - </div> <h1>Updating System</h1> <div> <form action="/system" method="post" enctype="multipart/form-data"> @@ -58,6 +49,101 @@ var indexPage = template.Must(template.New("index.html").Parse(` </html> `)) +var networkPage = template.Must(template.New("network.html").Parse(` +<html> +<head> + <title>Network Configuration</title> + <style type="text/css"> + div { margin-left: 20px; } + </style> +</head> +<body> + <form action="/network" method="post"> + <h1>Setting Network</h1> + <div> + <p> + <label for="ethaddr">Ethernet Address</label><br /> + <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> + </p> + <p> + <label for="ipaddr">IP Address</label><br /> + <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> + </p> + <p> + <label for="netmask">Netmask</label><br /> + <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> + </p> + <p> + <label for="gateway">Gateway</label><br /> + <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> + </p> + </div> + <label for="submit"><h1>Click to Apply</h1></label> + <div> + <p><input id="submit" type="submit" value="Set" /></p> + </div> + </form> +</body> +</html> +`)) + +var networkPageDual = template.Must(template.New("network.html").Parse(` +<html> +<head> + <title>Network Configuration</title> + <style type="text/css"> + div { margin-left: 20px; } + </style> +</head> +<body> + <form action="/network" method="post"> + <h1>Setting Network</h1> + <div> + <p> + <label for="ethaddr">Ethernet Address</label><br /> + <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> + </p> + <p> + <label for="ipaddr">IP Address</label><br /> + <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> + </p> + <p> + <label for="netmask">Netmask</label><br /> + <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> + </p> + <p> + <label for="gateway">Gateway</label><br /> + <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> + </p> + </div> + <h1>Setting Network 2</h1> + <div> + <p> + <label for="ethaddr2">Ethernet Address</label><br /> + <input type="text" id="ethaddr2" name="ethaddr2" value="{{.ethaddr2}}" required /> + </p> + <p> + <label for="ipaddr2">IP Address</label><br /> + <input type="text" id="ipaddr2" name="ipaddr2" value="{{.ipaddr2}}" required /> + </p> + <p> + <label for="netmask2">Netmask</label><br /> + <input type="text" id="netmask2" name="netmask2" value="{{.netmask2}}" required /> + </p> + <p> + <label for="gateway2">Gateway</label><br /> + <input type="text" id="gateway2" name="gateway2" value="{{.gateway2}}" required /> + </p> + </div> + <label for="submit"><h1>Click to Apply</h1></label> + <div> + <p><input id="submit" type="submit" value="Set" /></p> + </div> + </form> +</body> +</html> +`)) + var rebootPage = template.Must(template.New("reboot.html").Parse(` <html> <head> @@ -81,11 +167,18 @@ func runHttp() { r.Add("index.html", indexPage) r.Add("reboot.html", rebootPage) + if hasDualNetwork { + r.Add("network.html", networkPageDual) + } else { + r.Add("network.html", networkPage) + } + g.HTMLRender = r g.GET("/", renderIndex) + g.GET("/network", renderNetwork) - g.POST("/address", handleAddress) + g.POST("/network", handleNetwork) g.POST("/system", handleSystem) g.POST("/application", handleApplication) @@ -95,19 +188,26 @@ func runHttp() { g.Run(":8988") } -func handleAddress(c *gin.Context) { +func handleNetwork(c *gin.Context) { mu.Lock() defer mu.Unlock() - addr := c.PostForm("address") - addr2 := c.PostForm("address2") + keyList := []string{"ethaddr", "ipaddr", "netmask", "gateway"} + if hasDualNetwork { + keyList = append(keyList, "ethaddr2", "ipaddr2", "netmask2", "gateway2") + } + + env := map[string]string{} + for _, key := range keyList { + env[key] = c.PostForm(key) + } - if err := setIpAddress(addr, addr2); err != nil { - c.String(http.StatusBadRequest, "address: setIpAddress: %s", err.Error()) + if err := setNetwork(env); err != nil { + c.String(http.StatusBadRequest, "network: setNetwork: %s", err.Error()) return } - c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "IP address is updated."}) + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Network is configured."}) } func handleSystem(c *gin.Context) { @@ -160,17 +260,16 @@ func handleRestore(c *gin.Context) { } func renderIndex(c *gin.Context) { - device := "System" - if len(os.Args) > 1 { - device = os.Args[1] - } + env, _ := getEnv(1) + env["Device"] = deviceName + + c.HTML(http.StatusOK, "index.html", env) +} + +func renderNetwork(c *gin.Context) { + env, _ := getEnv(0) - c.HTML(http.StatusOK, "index.html", gin.H{ - "Device": device, - "IP": getIpAddress(), - "IP2": getIpAddress2(), - "Version": getVersion(), - }) + c.HTML(http.StatusOK, "network.html", env) } func saveFormFile(c *gin.Context, name string, dst string) error { diff --git a/go/src/themaru/ip.go b/go/src/themaru/ip.go deleted file mode 100644 index a3f09bd..0000000 --- a/go/src/themaru/ip.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "errors" - "regexp" - "strconv" -) - -func getIpAddress() string { - env, err := getEnv(0) - if err != nil { - return "" - } - - return env["ipaddr"] -} - -func getIpAddress2() string { - env, err := getEnv(0) - if err != nil { - return "" - } - - return env["ipaddr2"] -} - -func setIpAddress(address, address2 string) error { - address = extractIpAddress(address) - if address == "" { - return errors.New("invalid IP address") - } - - address2 = extractIpAddress(address2) - if address2 == "" { - return errors.New("invalid IP address2") - } - - env, err := getEnv(0) - if err != nil { - return err - } - - env["ipaddr"] = address - env["ipaddr2"] = address2 - - err = setEnv(0, env) - if err != nil { - return err - } - - return nil -} - -func extractIpAddress(address string) string { - r := regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)`) - s := r.FindStringSubmatch(address) - if len(s) != 5 { - return "" - } - - for i, v := range s { - if i == 0 { - continue - } - - u, err := strconv.ParseUint(v, 10, 8) - if err != nil { - return "" - } - - if u > 255 { - return "" - } - } - - return s[0] -} diff --git a/go/src/themaru/main.go b/go/src/themaru/main.go index 241ff1a..1859af4 100644 --- a/go/src/themaru/main.go +++ b/go/src/themaru/main.go @@ -1,5 +1,18 @@ package main +import ( + "flag" +) + +var deviceName string +var hasDualNetwork bool + +func init() { + flag.StringVar(&deviceName, "device", "System", "Set device name") + flag.BoolVar(&hasDualNetwork, "dual", false, "Set if it has dual network") + flag.Parse() +} + func main() { runHttp() } diff --git a/go/src/themaru/network.go b/go/src/themaru/network.go new file mode 100644 index 0000000..e084c16 --- /dev/null +++ b/go/src/themaru/network.go @@ -0,0 +1,95 @@ +package main + +import ( + "errors" + "regexp" + "strconv" +) + +func setNetwork(env map[string]string) error { + if ok := validateEthernetAddr(env["ethaddr"]); !ok { + return errors.New("invalid ethernet address") + } + + if ok := validateIpAddr(env["ipaddr"]); !ok { + return errors.New("invalid ip address") + } + + if ok := validateIpAddr(env["netmask"]); !ok { + return errors.New("invalid netmask") + } + + if ok := validateIpAddr(env["gateway"]); !ok { + return errors.New("invalid gateway") + } + + if hasDualNetwork { + if ok := validateEthernetAddr(env["ethaddr2"]); !ok { + return errors.New("invalid ethernet address 2") + } + + if ok := validateIpAddr(env["ipaddr2"]); !ok { + return errors.New("invalid ip address 2") + } + + if ok := validateIpAddr(env["netmask2"]); !ok { + return errors.New("invalid netmask 2") + } + + if ok := validateIpAddr(env["gateway2"]); !ok { + return errors.New("invalid gateway 2") + } + } + + return setEnv(0, env) +} + +func validateEthernetAddr(addr string) (ok bool) { + r := regexp.MustCompile(`([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2})`) + s := r.FindStringSubmatch(addr) + if len(s) != 7 || s[0] != addr { + return false + } + + for i, v := range s { + if i == 0 { + continue + } + + u, err := strconv.ParseUint(v, 16, 8) + if err != nil { + return false + } + + if u > 255 { + return false + } + } + + return true +} + +func validateIpAddr(addr string) (ok bool) { + r := regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)`) + s := r.FindStringSubmatch(addr) + if len(s) != 5 || s[0] != addr { + return false + } + + for i, v := range s { + if i == 0 { + continue + } + + u, err := strconv.ParseUint(v, 10, 8) + if err != nil { + return false + } + + if u > 255 { + return false + } + } + + return true +}