#! /usr/bin/env python
# -*- coding: utf-8 -*-
###########################################################################
#
# Eole NG
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
# eole@ac-dijon.fr
#
###########################################################################

from sys import argv, stderr, exit
#import ldap
#from ldap.modlist import addModlist
from era.noyau.constants import ACTION_DENY, ACTION_ALLOW
from era.tool.IPy import IP
from logging import error, DEBUG, getLogger

# Era action => NuFW decision
DECISION = {
    ACTION_DENY: 0,
    ACTION_ALLOW: 1,
# TODO
#    ACTION_REDIRECT: "Redirect",
#    ACTION_DNAT: "dnat",
#    ACTION_MASK: "mask",
}

PROTOCOL = {
    u'icmp': 1,
    u'tcp': 6,
    u'udp': 17,
}

def ip_range(extremites, inverse):
    if inverse:
        # Inverse _une_ adresse IP
        # 192.168.0.2 => (0.0.0.0 .. 192.168.0.1) et (192.168.0.3 .. 255.255.255.255)
        assert len(extremites) == 1
        extremite = extremites[0]
        assert len(extremite.ip_list) == 1
        assert not extremite.subnet
        ip = IP(extremite.ip_list[0]).int()
        ipmin = 0
        ipmax = 2**32 - 1
        if ipmin < ip:
            yield (ipmin, ip-1)
        if ip < ipmax:
            yield (ip+1, ipmax)
    else:
        for extremite in extremites:
            for ip in extremite.ip_list:
                ipdebut = IP(ip).int()
                if extremite.subnet:
                    netmask = IP(extremite.netmask).int()
                    ipdebut &= netmask
                    ipfin = ipdebut + (~netmask & 0xFFFFFFFF)
                else:
                    ipfin = ipdebut
                yield (ipdebut, ipfin)

def yield_all(extremite_src, src_inv, extremite_dst, dst_inv, port_list):
    port = (port_list[0], port_list[-1])
    for src in ip_range(extremite_src, src_inv):
        for dst in ip_range(extremite_dst, dst_inv):
            yield (src, dst, port)

def ldap_rule_factory(directive):
#        if directive.serv_inv
    service = directive.service
    try:
        protocol = PROTOCOL[service.protocol.lower()]
        decision = DECISION[directive.action]
    except LookupError, err:
        error("NuFW key error: %s" % err)
        return
    data = {
        'SrcPortStart': 1024,
        'SrcPortEnd': 65535,
        'Proto': protocol,
        'Decision': decision,
        'Group': directive.user_group,
        'description': directive.libelle,
# TODO
#            'OsName': None,
#            'OsVersion': None,
#            'OsRelease': None,
#            'AppName': None,
#            'AppSig': None,
#            'TimeRange': None,
    }
    for src, dst, port in yield_all(
    directive.src_list, directive.src_inv,
    directive.dest_list, directive.dest_inv,
    service.port_list):
        data['SrcIPStart'] = src[0]
        data['SrcIPEnd'] = src[1]
        data['DstIPStart'] = dst[0]
        data['DstIPEnd'] = dst[1]
        data['DstPortStart'] = port[0]
        data['DstPortEnd'] = port[1]
        yield data

def init():
    # prépare gettext
    import locale, gettext
    APP = 'editeur'
    DIR = 'i18n'
    locale.setlocale (locale.LC_ALL, '')
    gettext.bindtextdomain (APP, DIR)
    gettext.textdomain (APP)
    gettext.install (APP, DIR, unicode=1)

    # prépare le logging
    logger = getLogger()
    logger.setLevel(DEBUG)

def run():
    init()

    if len(argv) != 2:
        print >>stderr, "usage: %s model.xml" % argv[0]
        exit(1)
    model_file = argv[1]

    from era.noyau.initialize import initialize_app
    try:
        matrix_model = initialize_app(model_file)
    except Exception, e :
        exit(e)

    for d in matrix_model.visit_user_group():
        for data in ldap_rule_factory(d):
            print data

if __name__ == '__main__':
    run()

