wifi.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "runtime"
  6. "strings"
  7. wifi "imuslab.com/arozos/mod/network/wifi"
  8. prout "imuslab.com/arozos/mod/prouter"
  9. "imuslab.com/arozos/mod/utils"
  10. )
  11. /*
  12. Network WiFi Module
  13. This module handle wifi connections and scanning on the devices that support wpa_supplicant like the Raspberry Pi
  14. Require service launch with Dbus (Work well on stock Raspberry Pi OS)
  15. */
  16. var (
  17. wifiManager *wifi.WiFiManager
  18. )
  19. func WiFiInit() {
  20. //Start the Wifi Manager
  21. wifiManager = wifi.NewWiFiManager(sysdb, sudo_mode, *wpa_supplicant_path, *wan_interface_name)
  22. //Only activate script on linux and if hardware management is enabled
  23. router := prout.NewModuleRouter(prout.RouterOption{
  24. ModuleName: "System Setting",
  25. AdminOnly: true,
  26. UserHandler: userHandler,
  27. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  28. utils.SendErrorResponse(w, "Permission Denied")
  29. },
  30. })
  31. //Allow hardware management. Generate the endpoint for WiFi Control
  32. if *allow_hardware_management {
  33. //Register endpoints
  34. router.HandleFunc("/system/network/scanWifi", network_wifi_handleScan)
  35. router.HandleFunc("/system/network/connectWifi", network_wifi_handleConnect)
  36. router.HandleFunc("/system/network/removeWifi", network_wifi_handleWiFiRemove)
  37. router.HandleFunc("/system/network/wifiinfo", network_wifi_handleWiFiInfo)
  38. //Sudo mode only for wifi toggle
  39. if sudo_mode {
  40. router.HandleFunc("/system/network/power", network_wifi_handleWiFiPower)
  41. }
  42. //Register WiFi Settings if system have WiFi interface
  43. wlanInterfaces, _ := wifiManager.GetWirelessInterfaces()
  44. if len(wlanInterfaces) > 0 {
  45. //Contain at least 1 wireless interface Register System Settings
  46. registerSetting(settingModule{
  47. Name: "WiFi Info",
  48. Desc: "Current Connected WiFi Information",
  49. IconPath: "SystemAO/network/img/WiFi.png",
  50. Group: "Network",
  51. StartDir: "SystemAO/network/wifiinfo.html",
  52. })
  53. registerSetting(settingModule{
  54. Name: "WiFi Settings",
  55. Desc: "Set up WiFi connections",
  56. IconPath: "SystemAO/network/img/WiFi.png",
  57. Group: "Network",
  58. StartDir: "SystemAO/network/wifi.html",
  59. RequireAdmin: true,
  60. })
  61. }
  62. }
  63. }
  64. func network_wifi_handleWiFiPower(w http.ResponseWriter, r *http.Request) {
  65. //Require admin permission to scan and connect wifi
  66. user, err := userHandler.GetUserInfoFromRequest(w, r)
  67. if err != nil {
  68. utils.SendErrorResponse(w, "Internal Server Error")
  69. return
  70. }
  71. if !user.IsAdmin() {
  72. utils.SendErrorResponse(w, "Permission Denied")
  73. return
  74. }
  75. status, _ := utils.PostPara(r, "status")
  76. if status == "" {
  77. //Show current power status
  78. infs, err := wifiManager.GetWirelessInterfaces()
  79. if err != nil {
  80. utils.SendErrorResponse(w, err.Error())
  81. return
  82. }
  83. type WlanInterfaceStatus struct {
  84. Name string
  85. Running bool
  86. Controllable bool //SetInterfacePower is supported on this platform
  87. }
  88. results := []WlanInterfaceStatus{}
  89. for _, inf := range infs {
  90. status, _ := wifiManager.GetInterfacePowerStatuts(strings.TrimSpace(inf))
  91. results = append(results, WlanInterfaceStatus{
  92. Name: inf,
  93. Running: status,
  94. Controllable: wifiManager.CanControlInterfacePower(),
  95. })
  96. }
  97. js, _ := json.Marshal(results)
  98. utils.SendJSONResponse(w, string(js))
  99. } else {
  100. //Change current power status
  101. wlaninterface, err := utils.PostPara(r, "interface")
  102. if err != nil {
  103. utils.SendErrorResponse(w, "Invalid interface")
  104. return
  105. }
  106. if status == "on" {
  107. err := wifiManager.SetInterfacePower(wlaninterface, true)
  108. if err != nil {
  109. utils.SendErrorResponse(w, err.Error())
  110. } else {
  111. utils.SendOK(w)
  112. }
  113. } else if status == "off" {
  114. err := wifiManager.SetInterfacePower(wlaninterface, false)
  115. if err != nil {
  116. utils.SendErrorResponse(w, err.Error())
  117. } else {
  118. utils.SendOK(w)
  119. }
  120. } else {
  121. utils.SendErrorResponse(w, "Invalid status")
  122. }
  123. }
  124. }
  125. func network_wifi_handleScan(w http.ResponseWriter, r *http.Request) {
  126. //Require admin permission to scan and connect wifi
  127. user, err := userHandler.GetUserInfoFromRequest(w, r)
  128. if err != nil {
  129. utils.SendErrorResponse(w, "Internal Server Error")
  130. return
  131. }
  132. if !user.IsAdmin() {
  133. utils.SendErrorResponse(w, "Permission Denied")
  134. return
  135. }
  136. //Get a list of current on system wireless interface
  137. wirelessInterfaces, err := wifiManager.GetWirelessInterfaces()
  138. if err != nil {
  139. utils.SendErrorResponse(w, err.Error())
  140. return
  141. }
  142. if len(wirelessInterfaces) == 0 {
  143. //No wireless interface
  144. utils.SendErrorResponse(w, "Wireless Interface Not Found")
  145. return
  146. }
  147. //Scan with the requested interface, or the first one if none is given
  148. scanInterface := wirelessInterfaces[0]
  149. requestedInterface, _ := utils.GetPara(r, "interface")
  150. if requestedInterface != "" {
  151. found := false
  152. for _, inf := range wirelessInterfaces {
  153. if strings.TrimSpace(inf) == requestedInterface {
  154. scanInterface = inf
  155. found = true
  156. break
  157. }
  158. }
  159. if !found {
  160. utils.SendErrorResponse(w, "Wireless Interface Not Found")
  161. return
  162. }
  163. }
  164. scannedWiFiInfo, err := wifiManager.ScanNearbyWiFi(strings.TrimSpace(scanInterface))
  165. if err != nil {
  166. utils.SendErrorResponse(w, err.Error())
  167. return
  168. }
  169. jsonString, _ := json.Marshal(scannedWiFiInfo)
  170. utils.SendJSONResponse(w, string(jsonString))
  171. }
  172. func network_wifi_handleConnect(w http.ResponseWriter, r *http.Request) {
  173. user, err := userHandler.GetUserInfoFromRequest(w, r)
  174. if err != nil {
  175. utils.SendErrorResponse(w, "Internal Server Error")
  176. return
  177. }
  178. //Get information from client and create a new network config file
  179. if !user.IsAdmin() {
  180. utils.SendErrorResponse(w, "Permission denied")
  181. return
  182. }
  183. ssid, err := utils.PostPara(r, "ESSID")
  184. if err != nil {
  185. utils.SendErrorResponse(w, "ESSID not given")
  186. return
  187. }
  188. connType, _ := utils.PostPara(r, "ConnType")
  189. password, _ := utils.PostPara(r, "pwd")
  190. systemWideLogger.PrintAndLog("WiFi", "WiFi Switch Request Received. Genering Network Configuration...", nil)
  191. identity, err := utils.PostPara(r, "identity")
  192. if err != nil {
  193. identity = ""
  194. }
  195. result, err := wifiManager.ConnectWiFi(ssid, password, connType, identity)
  196. if err != nil {
  197. utils.SendErrorResponse(w, err.Error())
  198. return
  199. }
  200. jsonString, err := json.Marshal(result)
  201. if err != nil {
  202. utils.SendErrorResponse(w, err.Error())
  203. return
  204. }
  205. utils.SendJSONResponse(w, string(jsonString))
  206. systemWideLogger.PrintAndLog("WiFi", "WiFi Connected", nil)
  207. }
  208. func network_wifi_handleWiFiRemove(w http.ResponseWriter, r *http.Request) {
  209. //Require admin permission to scan and connect wifi
  210. user, err := userHandler.GetUserInfoFromRequest(w, r)
  211. if err != nil {
  212. utils.SendErrorResponse(w, "Internal Server Error")
  213. return
  214. }
  215. if !user.IsAdmin() {
  216. utils.SendErrorResponse(w, "Permission Denied")
  217. return
  218. }
  219. //Get ESSID from post request
  220. ESSID, err := utils.PostPara(r, "ESSID")
  221. if err != nil {
  222. utils.SendErrorResponse(w, "ESSID not given")
  223. return
  224. }
  225. err = wifiManager.RemoveWifi(ESSID)
  226. if err != nil {
  227. utils.SendErrorResponse(w, err.Error())
  228. return
  229. }
  230. utils.SendOK(w)
  231. }
  232. func network_wifi_handleWiFiInfo(w http.ResponseWriter, r *http.Request) {
  233. //Get and return the current conencted WiFi Information
  234. _, err := authAgent.GetUserName(w, r)
  235. if err != nil {
  236. utils.SendErrorResponse(w, "User not logged in")
  237. return
  238. }
  239. //Detailed state of every wireless interface
  240. interfaces, err := wifiManager.GetInterfaceStatus()
  241. if err != nil {
  242. utils.SendErrorResponse(w, "Failed to retrieve WiFi Information: "+err.Error())
  243. return
  244. }
  245. //ESSID and Interface are kept for older clients: the first connected
  246. //interface, or the first interface when none is connected
  247. ESSID, interfaceName := "", ""
  248. for _, inf := range interfaces {
  249. if inf.Connected {
  250. ESSID, interfaceName = inf.SSID, inf.Name
  251. break
  252. }
  253. }
  254. if interfaceName == "" && len(interfaces) > 0 {
  255. interfaceName = interfaces[0].Name
  256. } else if interfaceName == "" {
  257. //Platforms without a status implementation
  258. ESSID, interfaceName, err = wifiManager.GetConnectedWiFi()
  259. if err != nil {
  260. utils.SendErrorResponse(w, "Failed to retrieve WiFi Information")
  261. return
  262. }
  263. }
  264. jsonString, _ := json.Marshal(struct {
  265. ESSID string
  266. Interface string
  267. Interfaces []wifi.WiFiInterfaceStatus
  268. Platform string
  269. CanConnect bool //Connecting to and forgetting networks is supported
  270. CanControlPower bool //The radio power toggle is supported
  271. }{
  272. ESSID: ESSID,
  273. Interface: interfaceName,
  274. Interfaces: interfaces,
  275. Platform: runtime.GOOS,
  276. CanConnect: wifiManager.CanConnect(),
  277. CanControlPower: sudo_mode && wifiManager.CanControlInterfacePower(),
  278. })
  279. utils.SendJSONResponse(w, string(jsonString))
  280. }