dynapoint.lua (6015B)
1 #!/usr/bin/lua 2 3 --[[ 4 5 Copyright (C) 2016 Tobias Ilte <tobias.ilte@campus.tu-berlin.de> 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 --]] 21 22 23 require "uci" 24 require "ubus" 25 require "uloop" 26 log = require "nixio" 27 28 --open sys-logging 29 log.openlog("DynaPoint", "ndelay", "cons", "nowait"); 30 31 local uci_cursor = uci.cursor() 32 33 -- get all config sections with the given type 34 function getConfType(conf_file,type) 35 local ifce={} 36 uci_cursor:foreach(conf_file,type,function(s) ifce[s[".index"]]=s end) 37 return ifce 38 end 39 40 ubus = ubus.connect() 41 if not ubus then 42 error("Failed to connect to ubusd") 43 end 44 ubus:call("network", "reload", {}) 45 46 local interval = uci_cursor:get("dynapoint", "internet", "interval") 47 local timeout = uci_cursor:get("dynapoint", "internet", "timeout") 48 local offline_threshold = tonumber(uci_cursor:get("dynapoint", "internet", "offline_threshold")) 49 local hosts = uci_cursor:get("dynapoint", "internet", "hosts") 50 local numhosts = #hosts 51 local curl = tonumber(uci_cursor:get("dynapoint", "internet", "use_curl")) 52 if (curl == 1) then 53 curl_interface = uci_cursor:get("dynapoint", "internet", "curl_interface") 54 end 55 if (tonumber(uci_cursor:get("dynapoint", "internet", "add_hostname_to_ssid")) == 1 ) then 56 localhostname = uci_cursor:get("system", "system", "hostname") 57 end 58 59 local table_names_rule = {} 60 local table_names_not_rule = {} 61 local ssids_with_hostname = {} 62 local ssids_not_rule = {} 63 64 function get_dynapoint_sections(t) 65 for pos,val in pairs(t) do 66 if (type(val)=="table") then 67 get_dynapoint_sections(val); 68 elseif (type(val)=="string") then 69 if (pos == "dynapoint_rule") then 70 if (val == "internet") then 71 table_names_rule[#table_names_rule+1] = t[".name"] 72 elseif (val == "!internet") then 73 table_names_not_rule[#table_names_not_rule+1] = t[".name"] 74 if (localhostname) then 75 ssids_not_rule[#ssids_not_rule+1] = t[".ssid"] 76 ssids_with_hostname[#ssids_with_hostname+1] = t[".ssid"].."_"..localhostname 77 end 78 end 79 end 80 end 81 end 82 end 83 84 85 --print(table.getn(hosts)) 86 87 get_dynapoint_sections(getConfType("wireless","wifi-iface")) 88 89 -- revert all non-persistent ssid uci-changes regarding sections affecting dynapoint 90 for i = 1, #table_names_not_rule do 91 uci_cursor:revert("wireless", table_names_not_rule[i], "ssid") 92 end 93 94 95 local online = true 96 97 if (#table_names_rule > 0) then 98 if (tonumber(uci_cursor:get("wireless", table_names_rule[1], "disabled")) == 1) then 99 online = false 100 end 101 else 102 log.syslog("info","Not properly configured. Please add <option dynapoint_rule 'internet'> to /etc/config/wireless") 103 end 104 105 local timer 106 local offline_counter = 0 107 uloop.init() 108 109 function do_internet_check(host) 110 if (curl == 1 ) then 111 if (curl_interface) then 112 result = os.execute("curl -s -m "..timeout.." --max-redirs 0 --interface "..curl_interface.." --head "..host.." > /dev/null") 113 else 114 result = os.execute("curl -s -m "..timeout.." --max-redirs 0 --head "..host.." > /dev/null") 115 end 116 else 117 result = os.execute("wget -q --timeout="..timeout.." --spider "..host) 118 end 119 if (result == 0) then 120 return true 121 else 122 return false 123 end 124 end 125 126 function change_wireless_config(switch_to_offline) 127 if (switch_to_offline == 1) then 128 log.syslog("info","Switched to OFFLINE") 129 130 for i = 1, #table_names_not_rule do 131 uci_cursor:set("wireless",table_names_not_rule[i], "disabled", "0") 132 if (localhostname) then 133 uci_cursor:set("wireless", table_names_not_rule[i], "ssid", ssids_with_hostname[i]) 134 log.syslog("info","Bring up new AP "..ssids_with_hostname[i]) 135 else 136 log.syslog("info","Bring up new AP "..ssids_not_rule[i]) 137 end 138 end 139 140 for i = 1, #table_names_rule do 141 uci_cursor:set("wireless",table_names_rule[i], "disabled", "1") 142 end 143 144 else 145 log.syslog("info","Switched to ONLINE") 146 for i = 1, #table_names_not_rule do 147 uci_cursor:set("wireless",table_names_not_rule[i], "disabled", "1") 148 if (localhostname) then 149 uci_cursor:set("wireless", table_names_not_rule[i], "ssid", ssids_not_rule[i]) 150 end 151 end 152 for i = 1, #table_names_rule do 153 uci_cursor:set("wireless",table_names_rule[i], "disabled", "0") 154 log.syslog("info","Bring up new AP "..uci_cursor:get("wireless", table_names_rule[i], "ssid")) 155 end 156 end 157 uci_cursor:save("wireless") 158 ubus:call("network", "reload", {}) 159 end 160 161 162 local hostindex = 1 163 164 function check_internet_connection() 165 print("checking "..hosts[hostindex].."...") 166 if (do_internet_check(hosts[hostindex]) == true) then 167 -- online 168 print("...seems to be online") 169 offline_counter = 0 170 hostindex = 1 171 if (online == false) then 172 print("changed state to online") 173 online = true 174 change_wireless_config(0) 175 end 176 else 177 --offline 178 print("...seems to be offline") 179 hostindex = hostindex + 1 180 if (hostindex <= numhosts) then 181 check_internet_connection() 182 else 183 hostindex = 1 184 -- and activate offline-mode 185 print("all hosts offline") 186 if (online == true) then 187 offline_counter = offline_counter + 1 188 if (offline_counter == offline_threshold) then 189 print("changed state to offline") 190 online = false 191 change_wireless_config(1) 192 end 193 end 194 end 195 end 196 timer:set(interval * 1000) 197 end 198 199 timer = uloop.timer(check_internet_connection) 200 timer:set(interval * 1000) 201 202 uloop.run() 203