#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import os
import subprocess
import sys

CONFIG_FILE = "/var/efw/customforward/config"
CHAIN = "CUSTOMFORWARD"

def check_and_create_chain():
    with open(os.devnull, 'wb') as devnull:
        ret = subprocess.call(["iptables", "-L", CHAIN], stdout=devnull, stderr=devnull)
    
    if ret != 0:
        subprocess.call(["iptables", "-N", CHAIN])
        subprocess.call(["iptables", "-A", "FORWARD", "-j", CHAIN])

def flush_chain():
    subprocess.call(["iptables", "-F", CHAIN])

def apply_rule(proto, src, dst, port, action, logflag):
    src_list = src.split('&') if src else ["0.0.0.0/0"]
    dst_list = dst.split('&') if dst else ["0.0.0.0/0"]
    

    port_list = port.split('&') if port else [""]

    for s in src_list:
        s = s.strip()
        if not s: s = "0.0.0.0/0"
        
        for d in dst_list:
            d = d.strip()
            if not d: d = "0.0.0.0/0"
            
            for p in port_list:
                p = p.strip()
                port_opt = ["--dport", p] if p else []


                if logflag == "on":
                    cmd_log = ["iptables", "-A", CHAIN, "-s", s, "-d", d]
                    if proto:
                        cmd_log.extend(["-p", proto])
                    if port_opt:
                        cmd_log.extend(port_opt)
                     
                    prefix = "{}:{} {}".format(CHAIN, action, p).strip()
                    cmd_log.extend(["-j", "NFLOG", "--nflog-prefix", prefix])
                    subprocess.call(cmd_log)
                    
                if action in ["ACCEPT", "ALLOW", "DROP", "REJECT"]:
                    cmd_rule = ["iptables", "-A", CHAIN, "-s", s, "-d", d]
                    if proto:
                        cmd_rule.extend(["-p", proto])
                    if port_opt:
                        cmd_rule.extend(port_opt)
                    cmd_rule.extend(["-j", action])
                    subprocess.call(cmd_rule)

def main():
    if not os.path.exists(CONFIG_FILE):
        if sys.stderr.isatty():
            print >> sys.stderr, "Error: Configuration file not found: {}".format(CONFIG_FILE)
        sys.exit(1)

    check_and_create_chain()
    flush_chain()

    with open(CONFIG_FILE, 'r') as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith('#'):
                continue

            parts = line.split(',')
            if len(parts) < 8:
                continue

            status = parts[0].strip()
            proto = parts[1].strip()
            src = parts[2].strip()
            dst = parts[3].strip()
            port = parts[4].strip()
            action = parts[5].strip()
            logflag = parts[7].strip()

            if status != "on":
                continue


            if proto.lower() == "any":
                proto = ""

            if proto == "tcp&udp":
                apply_rule("tcp", src, dst, port, action, logflag)
                apply_rule("udp", src, dst, port, action, logflag)
            else:
                apply_rule(proto, src, dst, port, action, logflag)

    if sys.stdout.isatty():
        print "Rules applied successfully!"

if __name__ == "__main__":
    main()