
from __future__ import print_function

"""
RCSid:
	$Id: IPacl.py,v 1.8 2017/01/19 06:27:17 sjg Exp $

	@(#) Copyright (c) 2012 Simon J. Gerraty

	This file is provided in the hope that it will
	be of use.  There is absolutely NO WARRANTY.
	Permission to copy, redistribute or otherwise
	use this file is hereby granted provided that 
	the above copyright notice and this notice are
	left intact. 
      
	Please send copies of changes and bug-fixes to:
	sjg@crufty.net

"""

from conf import *
from iputils import *

def add_ip_acl(d, net):
    if net.find('/') > 0:
        ip,mask = net.split('/')
    else:
        ip = net
        mask = '/32'
    m = mask2int(mask)
    n = ip2int(ip) & m
    if m not in d:
        d[m] = {}
    d[m][n] = 1
        

def add_ip_acls(d, nets):
    for net in nets:
        add_ip_acl(d, net)
        
class IPacl(object):
    """IP based Access Control List"""
    def __init__(self, conf={}):
        self.conf = conf
        self.allowed = {}
        self.denied = {}

        allow_nets = conf.get('allow')
        deny_nets = conf.get('deny')

        if allow_nets:
            self.allow(allow_nets.split())

        if deny_nets:
            self.deny(deny_nets.split())
            
    def allow(self, nets):
        add_ip_acls(self.allowed, nets)

    def deny(self, nets):
        add_ip_acls(self.denied, nets)

    def check_ip(self, ip):
        """return True if ip is allowed"""

        i = ip2int(ip)
        r = True
        for m in list(self.denied.keys()):
            n = i & m
            if n in self.denied[m]:
                return False
            
        for m in list(self.allowed.keys()):
            r = False                   # default is now deny
            n = i & m
            if n in self.allowed[m]:
                return True
        return r

if __name__ == '__main__':
    import getopt, sys

    allow = []
    deny = []
    opts, args = getopt.getopt(sys.argv[1:], 'D:A:')
    for o,a in opts:
        if o == '-A':
            allow.append(a)
        elif o == '-D':
            deny.append(a)

    ACL = IPacl(conf={'allow': ' '.join(allow), 'deny': ' '.join(deny)})
    
    for n in args:
        r = ACL.check_ip(n)
        print(('{0}: {1}'.format(n, r)))
        

