
--
-- system files
--
ifconfig = "/sbin/ifconfig"
iptables = "/sbin/iptables"
def_config = "/etc/blackwall/blackwall.conf"
def_forward = "/etc/blackwall/forward" 
def_ipforward = "/etc/blackwall/ipforward" 
log_path = "/var/log/blackwall"

retval = 0 --Eventual exit return value;


function get_addr (iface)
  local info = io.popen(ifconfig)
  local config = info:read("*a")
  info:close()
  if config:match(iface.." [.]*") == nil then
    print("Interface "..iface.." not found")
    return nil
  end

  info = io.popen(ifconfig.." "..iface)
  config = info:read("*a")
  info:close()

  local if_addr = config:match("inet addr:([0-9%.]+)")
  print(if_addr)
  if if_addr == nil then
    return nil
  end
  if_addr = if_addr:gsub("inet ", "")
  return if_addr
end

function read_file(filename)
  local content = { }
  local file,err = io.open(filename)
  if file == nil then
    print("Failed to open file: "..err)
    return nil
  end
  local line = file:read()
  while line do
    line = line:gsub("[\t]+", " ")
    line = line:gsub("[ ]+", " ")
    if line then
      if line:sub(1, 1) ~= "#" then
        table.insert(content, line)
      end
    end
    line = file:read()
  end
  file:close()
  return content
end

function read_conf(conf_file)
  local lines = read_file(conf_file)
  if lines == nil then
    return nil
  end

  local config = { }
  for i,line in ipairs(lines) do
    local param, value
    param = line:match("[^=]+")
    if param then
      value = line:gsub(param.."=", "")
    end
    if param ~= nil then
      param = param:match("[a-zA-Z0-9%._]+")
      value = value:match("[a-zA-Z0-9%._]+")
      config[param] = value
    end
  end
  return config
end

function read_table(table_file)
  local lines = read_file(table_file)
  if lines == nil then
    return nil
  end

  local tab = { }
  for i,line in ipairs(lines) do
    local row = { }
    local col = line:match("[a-zA-Z0-9%._]+")
    while col do
      table.insert(row, col)
      line = line:gsub(col, "", 1)
      col = line:match("[a-zA-Z0-9%._]+")
    end
    if #row > 0 then
      table.insert(tab, row)
    end
  end
  return tab
end

function flush_tables ()
  local cmd = { }
  local res = 0
  local stat
  local reason
  local temp_res

  cmd[1] = iptables.." --flush"
  cmd[2] = iptables.." --table nat --flush"
  cmd[3] = iptables.." --delete-chain"
  cmd[4] = iptables.." --table nat --delete-chain"

  for i,c in ipairs(cmd) do
    --print("exec "..i..": "..c)
    stat,reason,temp_res =  os.execute(c)
    res = res+temp_res
  end

  return res
end

function set_masq(config)
  if config.IF_EXTERNAL == nil then
    print("Option IF_EXTERNAL not specified. Aborting.")
    return 1
  end
  if config.IF_LOCAL == nil then
    print("Option IF_LOCAL not specified. Aborting.")
    return 1
  end
  local cmd = { }
  local res = 0
  local stat
  local reason
  local temp_res

  local out_if = config.IF_EXTERNAL;
  local in_if = config.IF_LOCAL;


  cmd[1] = iptables.." --table nat --append POSTROUTING --out-interface "..out_if.." -j MASQUERADE"
  cmd[2] = iptables.." --append FORWARD --in-interface "..in_if.." -j ACCEPT"

  for i,c in ipairs(cmd) do
    --print("exec "..i..": "..c)
    stat,reason,temp_res = os.execute(c)
    res = res+temp_res
  end

  local fw,err = io.open("/proc/sys/net/ipv4/ip_forward", "w")
  if fw == nil then
    print("Could not enable packet forwarding. "..err)
    return 1
  end
  fw:write("1")
  fw:flush()
  fw:close()

  return res
end

function create_fw_line(extif, proto, port, dest, destport)
  local line = iptables.." --table nat --append PREROUTING"
  line = line.." -i "..extif
  line = line.." --protocol "..proto
  line = line.." --dport "..port
  line = line.." --jump DNAT"
  line = line.." --to-destination "..dest..":"..destport
  return line
end

function set_forward(fw_table, config)
  local cmd = { }
  local res = 0
  local stat
  local reason
  local temp_res

  if config.IF_EXTERNAL == nil then
    print("Option IF_EXTERNAL not specified. Aborting.")
    return 1
  end

  --local myip = get_addr(config.IF_EXTERNAL)

  for i,line in ipairs(fw_table) do
    cmd[i] = create_fw_line(config.IF_EXTERNAL, line[1], line[2], line[3], line[4])
  end

  for i,c in ipairs(cmd) do
    --print("exec "..i..": "..c)
    stat,reason,temp_res = os.execute(c)
    res = res+temp_res
  end

  return res
end

function set_ipforward(fw_table, config)
  local cmd = { }
  local res = 0
  local stat
  local reason
  local temp_res


  for i,line in ipairs(fw_table) do
    local cmd_line = [[iptables -t nat -A PREROUTING -d ]]..line[1]..[[ -j DNAT --to-destination ]]..line[2]
    table.insert(cmd,cmd_line)
    cmd_line = [[iptables -t nat -A POSTROUTING -s ]]..line[2]..[[ -j SNAT --to-source ]]..line[1]
    table.insert(cmd,cmd_line)
  end

  for i,c in ipairs(cmd) do
    --print("exec "..i..": "..c)
    stat,reason,temp_res = os.execute(c)
    res = res+temp_res
  end

  return res
end




config = read_conf(def_config)

--for p,v in pairs(config) do
--    print("|"..p.."|","|"..v.."|")
--end

print("Flushing tables... "..flush_tables())
print("Setting up masquerading... "..set_masq(config))

tab = read_table(def_forward)
if tab then
  --    for i,row in ipairs(tab) do
  --	for j,col in ipairs(row) do
  --	    print("|"..col.."|")
  --	end
  --	print("----")
  --    end
  print("Setting up port forwarding... "..set_forward(tab, config))
end

tab = read_table(def_ipforward)
if tab then
  print("Setting up IP forwarding... "..set_ipforward(tab, config))
end

