#!/usr/bin/lua
http = require("ssl.https")
json = require("cjson")
require("uci")
log = require("posix.syslog")
fbwifi = require("fbwifi")

GATEWAY_TOKEN = fbwifi.gateway_token()

http_port = uci.get("fbwifi.main.http_port")
https_port = uci.get("fbwifi.main.https_port")

statefile = assert(io.open("/var/state/fbwifi", "a"), "could not create state file")
statefile:close()

state = uci.cursor("/var/state", "/tmp/fbwifi")

URL="https://api.fbwifi.com/v2.0/gateway"
body, code, headers = http.request(URL.."?access_token="..GATEWAY_TOKEN.."&fields=config,config_version")

if code == 200 then
	log.syslog(log.LOG_INFO, "[fbwifi] Got gateway config ("..code..")")
else
	log.syslog(log.LOG_CRIT, "[fbwifi] Failed to get gateway config ("..code..")")
	os.exit(1)
end

obj = json.decode(body)

function save_cert(name, value)
	log.syslog(log.LOG_INFO, "[fbwifi] Saving cert "..name)
	local f = assert(io.open("/tmp/fbwifi/"..name, "w"))
	f:write(value)
	f:close()
end

function process_redirect(ix, host)
	IP_SET = "ip addr replace dev lo "..host
	local result = os.execute(IP_SET)
	if result == 0 then
		log.syslog(log.LOG_INFO, "[fbwifi] Redirect address applied "..host)
	else
		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to apply redirect address "..host)
	end

	ip = string.match(host, '([0-9\.]*)/([0-9]*)')
	RULE_FMT="grep -q \"%s\" /etc/hosts || echo \"%s\tstar.fbwifigateway.net\" >> /etc/hosts"
	HOSTS_RULE = string.format(RULE_FMT, ip, ip)
	result = os.execute(HOSTS_RULE)
	if result == 0 then
		log.syslog(log.LOG_INFO, "[fbwifi] Cached redirect host for DNS")
	else
		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to amend /etc/hosts")
		log.syslog(log.LOG_INFO, "[fbwifi] "..HOSTS_RULE)
	end

	result = os.execute("iptables -t nat -A FBWIFI_HOST_REDIRLIST -p tcp --dport 80 -d "..ip.." -j ACCEPT # REDIRECT --to-ports "..http_port)
	--print(result)
	result = os.execute("iptables -t nat -A FBWIFI_HOST_REDIRLIST -p tcp --dport 443 -d "..ip.."  -j ACCEPT # REDIRECT --to-ports "..https_port)
	--print(result)
end

save_cert("https_server_cert", obj['config']['https_server_cert'])
save_cert("https_server_key", obj['config']['https_server_key'])

result = os.execute("iptables -t nat -F FBWIFI_HOST_REDIRLIST")
--print(result)
table.foreach(obj['config']['host_redirect_ips'], process_redirect)

RULE_FORMAT = "iptables -t mangle -A FBWIFI_TRAFFIC_ALLOWLIST -d %s -p %s --dport %s -j MARK --set-mark 0xfb"
function process_traffic_rule(ix, rule)
	log.syslog(log.LOG_INFO, "[fbwifi] Traffic rule "..ix)
	
	if rule["protocol"] == 6 then
		PROTO = "tcp"
	elseif rule["protocol"] == 17 then
		PROTO = "udp"
	end
	RULE = string.format(RULE_FORMAT, rule["ip"], PROTO, rule["port"])
	local result = os.execute(RULE)
	if result == 0 then
		log.syslog(log.LOG_INFO, "[fbwifi] Traffic rule "..ix)
	else
		log.syslog(log.LOG_WARNING, "[fbwifi] Failed to install traffic rule ; "..RULE)
	end
end

local cross_origin_list = {}
function process_cross_origin_rule(ix, url)
	log.syslog(log.LOG_INFO, "[fbwifi] Cross origin rule "..url)
	table.insert(cross_origin_list, url)
end

function process_url(url_purpose, fqdn)
	log.syslog(log.LOG_INFO, "[fbwifi] Caching "..url_purpose)
	state:set("fbwifi", "main", url_purpose, fqdn)	
end

state:set("fbwifi", "main", "config")

result = os.execute("iptables -t mangle -F FBWIFI_TRAFFIC_ALLOWLIST ")
--print(result)
table.foreach(obj['config']['traffic_allowlist'], process_traffic_rule)
table.foreach(obj['config']['cross_origin_allowlist'], process_cross_origin_rule)
table.foreach(obj['config']['urls'], process_url)

state:set("fbwifi", "main", "cross_origin_allow_rules", cross_origin_list)
state:set("fbwifi", "main", "config_version", obj['config_version'])

state:save('fbwifi')
state:commit('fbwifi')
