Commit c35246804fff2e5be6f4302d89a1d7b48c8c891f
1 parent
476d2547ea
Exists in
master
기능 추가 및 변경
- 네트워크 설정 페이지 추가 - 기존 IP 주소 설정 항목 제거 - 추가된 페이지에 이더넷 주소, IP 주소, 넷마스크, 게이트웨이 설정 항목 추가 - 실행 명령줄 인자로 네트워크 인터페이스 갯수 설정 - 인자에 "-dual"을 추가하면 네트워크 인터페이스 갯수가 2개인 것으로 동작 - 실행 명령줄 인자로 장치 이름 설정하는 방법 변경 - 인자에 "-device "<장치 이름>""을 추가하는 방법으로 변경 (기존은 첫 번째 인자를 그대로 사용)
Showing
4 changed files
with
234 additions
and
104 deletions
Show diff stats
go/src/themaru/http.go
| ... | ... | @@ -3,7 +3,6 @@ package main |
| 3 | 3 | import ( |
| 4 | 4 | "html/template" |
| 5 | 5 | "net/http" |
| 6 | - "os" | |
| 7 | 6 | "sync" |
| 8 | 7 | |
| 9 | 8 | "github.com/gin-contrib/multitemplate" |
| ... | ... | @@ -23,17 +22,9 @@ var indexPage = template.Must(template.New("index.html").Parse(` |
| 23 | 22 | <body> |
| 24 | 23 | <h1>{{.Device}} Configuration</h1> |
| 25 | 24 | <div> |
| 26 | - <p>System Version: {{.Version}}</p> | |
| 25 | + <p>System Version: {{.falinux_version}}</p> | |
| 27 | 26 | </div> |
| 28 | 27 | <hr> |
| 29 | - <h1>Setting IP Address</h1> | |
| 30 | - <div> | |
| 31 | - <form action="/address" method="post"> | |
| 32 | - <input type="text" name="address" value="{{.IP}}" required /> | |
| 33 | - <input type="text" name="address2" value="{{.IP2}}" required /> | |
| 34 | - <input type="submit" value="Set" /> | |
| 35 | - </form> | |
| 36 | - </div> | |
| 37 | 28 | <h1>Updating System</h1> |
| 38 | 29 | <div> |
| 39 | 30 | <form action="/system" method="post" enctype="multipart/form-data"> |
| ... | ... | @@ -58,6 +49,101 @@ var indexPage = template.Must(template.New("index.html").Parse(` |
| 58 | 49 | </html> |
| 59 | 50 | `)) |
| 60 | 51 | |
| 52 | +var networkPage = template.Must(template.New("network.html").Parse(` | |
| 53 | +<html> | |
| 54 | +<head> | |
| 55 | + <title>Network Configuration</title> | |
| 56 | + <style type="text/css"> | |
| 57 | + div { margin-left: 20px; } | |
| 58 | + </style> | |
| 59 | +</head> | |
| 60 | +<body> | |
| 61 | + <form action="/network" method="post"> | |
| 62 | + <h1>Setting Network</h1> | |
| 63 | + <div> | |
| 64 | + <p> | |
| 65 | + <label for="ethaddr">Ethernet Address</label><br /> | |
| 66 | + <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> | |
| 67 | + </p> | |
| 68 | + <p> | |
| 69 | + <label for="ipaddr">IP Address</label><br /> | |
| 70 | + <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> | |
| 71 | + </p> | |
| 72 | + <p> | |
| 73 | + <label for="netmask">Netmask</label><br /> | |
| 74 | + <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> | |
| 75 | + </p> | |
| 76 | + <p> | |
| 77 | + <label for="gateway">Gateway</label><br /> | |
| 78 | + <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> | |
| 79 | + </p> | |
| 80 | + </div> | |
| 81 | + <label for="submit"><h1>Click to Apply</h1></label> | |
| 82 | + <div> | |
| 83 | + <p><input id="submit" type="submit" value="Set" /></p> | |
| 84 | + </div> | |
| 85 | + </form> | |
| 86 | +</body> | |
| 87 | +</html> | |
| 88 | +`)) | |
| 89 | + | |
| 90 | +var networkPageDual = template.Must(template.New("network.html").Parse(` | |
| 91 | +<html> | |
| 92 | +<head> | |
| 93 | + <title>Network Configuration</title> | |
| 94 | + <style type="text/css"> | |
| 95 | + div { margin-left: 20px; } | |
| 96 | + </style> | |
| 97 | +</head> | |
| 98 | +<body> | |
| 99 | + <form action="/network" method="post"> | |
| 100 | + <h1>Setting Network</h1> | |
| 101 | + <div> | |
| 102 | + <p> | |
| 103 | + <label for="ethaddr">Ethernet Address</label><br /> | |
| 104 | + <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> | |
| 105 | + </p> | |
| 106 | + <p> | |
| 107 | + <label for="ipaddr">IP Address</label><br /> | |
| 108 | + <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> | |
| 109 | + </p> | |
| 110 | + <p> | |
| 111 | + <label for="netmask">Netmask</label><br /> | |
| 112 | + <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> | |
| 113 | + </p> | |
| 114 | + <p> | |
| 115 | + <label for="gateway">Gateway</label><br /> | |
| 116 | + <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> | |
| 117 | + </p> | |
| 118 | + </div> | |
| 119 | + <h1>Setting Network 2</h1> | |
| 120 | + <div> | |
| 121 | + <p> | |
| 122 | + <label for="ethaddr2">Ethernet Address</label><br /> | |
| 123 | + <input type="text" id="ethaddr2" name="ethaddr2" value="{{.ethaddr2}}" required /> | |
| 124 | + </p> | |
| 125 | + <p> | |
| 126 | + <label for="ipaddr2">IP Address</label><br /> | |
| 127 | + <input type="text" id="ipaddr2" name="ipaddr2" value="{{.ipaddr2}}" required /> | |
| 128 | + </p> | |
| 129 | + <p> | |
| 130 | + <label for="netmask2">Netmask</label><br /> | |
| 131 | + <input type="text" id="netmask2" name="netmask2" value="{{.netmask2}}" required /> | |
| 132 | + </p> | |
| 133 | + <p> | |
| 134 | + <label for="gateway2">Gateway</label><br /> | |
| 135 | + <input type="text" id="gateway2" name="gateway2" value="{{.gateway2}}" required /> | |
| 136 | + </p> | |
| 137 | + </div> | |
| 138 | + <label for="submit"><h1>Click to Apply</h1></label> | |
| 139 | + <div> | |
| 140 | + <p><input id="submit" type="submit" value="Set" /></p> | |
| 141 | + </div> | |
| 142 | + </form> | |
| 143 | +</body> | |
| 144 | +</html> | |
| 145 | +`)) | |
| 146 | + | |
| 61 | 147 | var rebootPage = template.Must(template.New("reboot.html").Parse(` |
| 62 | 148 | <html> |
| 63 | 149 | <head> |
| ... | ... | @@ -81,11 +167,18 @@ func runHttp() { |
| 81 | 167 | r.Add("index.html", indexPage) |
| 82 | 168 | r.Add("reboot.html", rebootPage) |
| 83 | 169 | |
| 170 | + if hasDualNetwork { | |
| 171 | + r.Add("network.html", networkPageDual) | |
| 172 | + } else { | |
| 173 | + r.Add("network.html", networkPage) | |
| 174 | + } | |
| 175 | + | |
| 84 | 176 | g.HTMLRender = r |
| 85 | 177 | |
| 86 | 178 | g.GET("/", renderIndex) |
| 179 | + g.GET("/network", renderNetwork) | |
| 87 | 180 | |
| 88 | - g.POST("/address", handleAddress) | |
| 181 | + g.POST("/network", handleNetwork) | |
| 89 | 182 | g.POST("/system", handleSystem) |
| 90 | 183 | g.POST("/application", handleApplication) |
| 91 | 184 | |
| ... | ... | @@ -95,19 +188,26 @@ func runHttp() { |
| 95 | 188 | g.Run(":8988") |
| 96 | 189 | } |
| 97 | 190 | |
| 98 | -func handleAddress(c *gin.Context) { | |
| 191 | +func handleNetwork(c *gin.Context) { | |
| 99 | 192 | mu.Lock() |
| 100 | 193 | defer mu.Unlock() |
| 101 | 194 | |
| 102 | - addr := c.PostForm("address") | |
| 103 | - addr2 := c.PostForm("address2") | |
| 195 | + keyList := []string{"ethaddr", "ipaddr", "netmask", "gateway"} | |
| 196 | + if hasDualNetwork { | |
| 197 | + keyList = append(keyList, "ethaddr2", "ipaddr2", "netmask2", "gateway2") | |
| 198 | + } | |
| 199 | + | |
| 200 | + env := map[string]string{} | |
| 201 | + for _, key := range keyList { | |
| 202 | + env[key] = c.PostForm(key) | |
| 203 | + } | |
| 104 | 204 | |
| 105 | - if err := setIpAddress(addr, addr2); err != nil { | |
| 106 | - c.String(http.StatusBadRequest, "address: setIpAddress: %s", err.Error()) | |
| 205 | + if err := setNetwork(env); err != nil { | |
| 206 | + c.String(http.StatusBadRequest, "network: setNetwork: %s", err.Error()) | |
| 107 | 207 | return |
| 108 | 208 | } |
| 109 | 209 | |
| 110 | - c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "IP address is updated."}) | |
| 210 | + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Network is configured."}) | |
| 111 | 211 | } |
| 112 | 212 | |
| 113 | 213 | func handleSystem(c *gin.Context) { |
| ... | ... | @@ -160,17 +260,16 @@ func handleRestore(c *gin.Context) { |
| 160 | 260 | } |
| 161 | 261 | |
| 162 | 262 | func renderIndex(c *gin.Context) { |
| 163 | - device := "System" | |
| 164 | - if len(os.Args) > 1 { | |
| 165 | - device = os.Args[1] | |
| 166 | - } | |
| 263 | + env, _ := getEnv(1) | |
| 264 | + env["Device"] = deviceName | |
| 265 | + | |
| 266 | + c.HTML(http.StatusOK, "index.html", env) | |
| 267 | +} | |
| 268 | + | |
| 269 | +func renderNetwork(c *gin.Context) { | |
| 270 | + env, _ := getEnv(0) | |
| 167 | 271 | |
| 168 | - c.HTML(http.StatusOK, "index.html", gin.H{ | |
| 169 | - "Device": device, | |
| 170 | - "IP": getIpAddress(), | |
| 171 | - "IP2": getIpAddress2(), | |
| 172 | - "Version": getVersion(), | |
| 173 | - }) | |
| 272 | + c.HTML(http.StatusOK, "network.html", env) | |
| 174 | 273 | } |
| 175 | 274 | |
| 176 | 275 | func saveFormFile(c *gin.Context, name string, dst string) error { | ... | ... |
go/src/themaru/ip.go
| ... | ... | @@ -1,77 +0,0 @@ |
| 1 | -package main | |
| 2 | - | |
| 3 | -import ( | |
| 4 | - "errors" | |
| 5 | - "regexp" | |
| 6 | - "strconv" | |
| 7 | -) | |
| 8 | - | |
| 9 | -func getIpAddress() string { | |
| 10 | - env, err := getEnv(0) | |
| 11 | - if err != nil { | |
| 12 | - return "" | |
| 13 | - } | |
| 14 | - | |
| 15 | - return env["ipaddr"] | |
| 16 | -} | |
| 17 | - | |
| 18 | -func getIpAddress2() string { | |
| 19 | - env, err := getEnv(0) | |
| 20 | - if err != nil { | |
| 21 | - return "" | |
| 22 | - } | |
| 23 | - | |
| 24 | - return env["ipaddr2"] | |
| 25 | -} | |
| 26 | - | |
| 27 | -func setIpAddress(address, address2 string) error { | |
| 28 | - address = extractIpAddress(address) | |
| 29 | - if address == "" { | |
| 30 | - return errors.New("invalid IP address") | |
| 31 | - } | |
| 32 | - | |
| 33 | - address2 = extractIpAddress(address2) | |
| 34 | - if address2 == "" { | |
| 35 | - return errors.New("invalid IP address2") | |
| 36 | - } | |
| 37 | - | |
| 38 | - env, err := getEnv(0) | |
| 39 | - if err != nil { | |
| 40 | - return err | |
| 41 | - } | |
| 42 | - | |
| 43 | - env["ipaddr"] = address | |
| 44 | - env["ipaddr2"] = address2 | |
| 45 | - | |
| 46 | - err = setEnv(0, env) | |
| 47 | - if err != nil { | |
| 48 | - return err | |
| 49 | - } | |
| 50 | - | |
| 51 | - return nil | |
| 52 | -} | |
| 53 | - | |
| 54 | -func extractIpAddress(address string) string { | |
| 55 | - r := regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)`) | |
| 56 | - s := r.FindStringSubmatch(address) | |
| 57 | - if len(s) != 5 { | |
| 58 | - return "" | |
| 59 | - } | |
| 60 | - | |
| 61 | - for i, v := range s { | |
| 62 | - if i == 0 { | |
| 63 | - continue | |
| 64 | - } | |
| 65 | - | |
| 66 | - u, err := strconv.ParseUint(v, 10, 8) | |
| 67 | - if err != nil { | |
| 68 | - return "" | |
| 69 | - } | |
| 70 | - | |
| 71 | - if u > 255 { | |
| 72 | - return "" | |
| 73 | - } | |
| 74 | - } | |
| 75 | - | |
| 76 | - return s[0] | |
| 77 | -} |
go/src/themaru/main.go
| 1 | 1 | package main |
| 2 | 2 | |
| 3 | +import ( | |
| 4 | + "flag" | |
| 5 | +) | |
| 6 | + | |
| 7 | +var deviceName string | |
| 8 | +var hasDualNetwork bool | |
| 9 | + | |
| 10 | +func init() { | |
| 11 | + flag.StringVar(&deviceName, "device", "System", "Set device name") | |
| 12 | + flag.BoolVar(&hasDualNetwork, "dual", false, "Set if it has dual network") | |
| 13 | + flag.Parse() | |
| 14 | +} | |
| 15 | + | |
| 3 | 16 | func main() { |
| 4 | 17 | runHttp() |
| 5 | 18 | } | ... | ... |
go/src/themaru/network.go
| ... | ... | @@ -0,0 +1,95 @@ |
| 1 | +package main | |
| 2 | + | |
| 3 | +import ( | |
| 4 | + "errors" | |
| 5 | + "regexp" | |
| 6 | + "strconv" | |
| 7 | +) | |
| 8 | + | |
| 9 | +func setNetwork(env map[string]string) error { | |
| 10 | + if ok := validateEthernetAddr(env["ethaddr"]); !ok { | |
| 11 | + return errors.New("invalid ethernet address") | |
| 12 | + } | |
| 13 | + | |
| 14 | + if ok := validateIpAddr(env["ipaddr"]); !ok { | |
| 15 | + return errors.New("invalid ip address") | |
| 16 | + } | |
| 17 | + | |
| 18 | + if ok := validateIpAddr(env["netmask"]); !ok { | |
| 19 | + return errors.New("invalid netmask") | |
| 20 | + } | |
| 21 | + | |
| 22 | + if ok := validateIpAddr(env["gateway"]); !ok { | |
| 23 | + return errors.New("invalid gateway") | |
| 24 | + } | |
| 25 | + | |
| 26 | + if hasDualNetwork { | |
| 27 | + if ok := validateEthernetAddr(env["ethaddr2"]); !ok { | |
| 28 | + return errors.New("invalid ethernet address 2") | |
| 29 | + } | |
| 30 | + | |
| 31 | + if ok := validateIpAddr(env["ipaddr2"]); !ok { | |
| 32 | + return errors.New("invalid ip address 2") | |
| 33 | + } | |
| 34 | + | |
| 35 | + if ok := validateIpAddr(env["netmask2"]); !ok { | |
| 36 | + return errors.New("invalid netmask 2") | |
| 37 | + } | |
| 38 | + | |
| 39 | + if ok := validateIpAddr(env["gateway2"]); !ok { | |
| 40 | + return errors.New("invalid gateway 2") | |
| 41 | + } | |
| 42 | + } | |
| 43 | + | |
| 44 | + return setEnv(0, env) | |
| 45 | +} | |
| 46 | + | |
| 47 | +func validateEthernetAddr(addr string) (ok bool) { | |
| 48 | + 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})`) | |
| 49 | + s := r.FindStringSubmatch(addr) | |
| 50 | + if len(s) != 7 || s[0] != addr { | |
| 51 | + return false | |
| 52 | + } | |
| 53 | + | |
| 54 | + for i, v := range s { | |
| 55 | + if i == 0 { | |
| 56 | + continue | |
| 57 | + } | |
| 58 | + | |
| 59 | + u, err := strconv.ParseUint(v, 16, 8) | |
| 60 | + if err != nil { | |
| 61 | + return false | |
| 62 | + } | |
| 63 | + | |
| 64 | + if u > 255 { | |
| 65 | + return false | |
| 66 | + } | |
| 67 | + } | |
| 68 | + | |
| 69 | + return true | |
| 70 | +} | |
| 71 | + | |
| 72 | +func validateIpAddr(addr string) (ok bool) { | |
| 73 | + r := regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)`) | |
| 74 | + s := r.FindStringSubmatch(addr) | |
| 75 | + if len(s) != 5 || s[0] != addr { | |
| 76 | + return false | |
| 77 | + } | |
| 78 | + | |
| 79 | + for i, v := range s { | |
| 80 | + if i == 0 { | |
| 81 | + continue | |
| 82 | + } | |
| 83 | + | |
| 84 | + u, err := strconv.ParseUint(v, 10, 8) | |
| 85 | + if err != nil { | |
| 86 | + return false | |
| 87 | + } | |
| 88 | + | |
| 89 | + if u > 255 { | |
| 90 | + return false | |
| 91 | + } | |
| 92 | + } | |
| 93 | + | |
| 94 | + return true | |
| 95 | +} | ... | ... |