## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license

"""
Routing and handling of network interfaces.
"""


from __future__ import absolute_import


import scapy.consts
from scapy.config import conf
from scapy.error import Scapy_Exception, warning
from scapy.modules import six
from scapy.utils import atol, ltoa, itom, pretty_list


##############################
## Routing/Interfaces stuff ##
##############################

class Route:
    def __init__(self):
        self.resync()
        self.invalidate_cache()

    def invalidate_cache(self):
        self.cache = {}

    def resync(self):
        from scapy.arch import read_routes
        self.invalidate_cache()
        self.routes = read_routes()

    def __repr__(self):
        rtlst = []
        for net, msk, gw, iface, addr, metric in self.routes:
            rtlst.append((ltoa(net),
                      ltoa(msk),
                      gw,
                      (iface.name if not isinstance(iface, six.string_types) else iface),
                      addr,
                      str(metric)))

        return pretty_list(rtlst,
                             [("Network", "Netmask", "Gateway", "Iface", "Output IP", "Metric")])

    def make_route(self, host=None, net=None, gw=None, dev=None, metric=1):
        from scapy.arch import get_if_addr
        if host is not None:
            thenet,msk = host,32
        elif net is not None:
            thenet,msk = net.split("/")
            msk = int(msk)
        else:
            raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net")
        if gw is None:
            gw="0.0.0.0"
        if dev is None:
            if gw:
                nhop = gw
            else:
                nhop = thenet
            dev, ifaddr, _ = self.route(nhop)
        else:
            ifaddr = get_if_addr(dev)
        return (atol(thenet), itom(msk), gw, dev, ifaddr, metric)

    def add(self, *args, **kargs):
        """Ex:
        add(net="192.168.1.0/24",gw="1.2.3.4")
        """
        self.invalidate_cache()
        self.routes.append(self.make_route(*args,**kargs))

        
    def delt(self,  *args, **kargs):
        """delt(host|net, gw|dev)"""
        self.invalidate_cache()
        route = self.make_route(*args,**kargs)
        try:
            i=self.routes.index(route)
            del(self.routes[i])
        except ValueError:
            warning("no matching route found")
             
    def ifchange(self, iff, addr):
        self.invalidate_cache()
        the_addr,the_msk = (addr.split("/")+["32"])[:2]
        the_msk = itom(int(the_msk))
        the_rawaddr = atol(the_addr)
        the_net = the_rawaddr & the_msk
        
        
        for i, route in enumerate(self.routes):
            net, msk, gw, iface, addr, metric = route
            if scapy.consts.WINDOWS:
                if iff.guid != iface.guid:
                    continue
            elif iff != iface:
                continue
            if gw == '0.0.0.0':
                self.routes[i] = (the_net,the_msk,gw,iface,the_addr,metric)
            else:
                self.routes[i] = (net,msk,gw,iface,the_addr,metric)
        conf.netcache.flush()
        
                

    def ifdel(self, iff):
        self.invalidate_cache()
        new_routes=[]
        for rt in self.routes:
            if scapy.consts.WINDOWS:
                if iff.guid == rt[3].guid:
                    continue
            elif iff == rt[3]:
                continue
            new_routes.append(rt)
        self.routes=new_routes
        
    def ifadd(self, iff, addr):
        self.invalidate_cache()
        the_addr,the_msk = (addr.split("/")+["32"])[:2]
        the_msk = itom(int(the_msk))
        the_rawaddr = atol(the_addr)
        the_net = the_rawaddr & the_msk
        self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr,1))


    def route(self,dest,verbose=None):
        if isinstance(dest, list) and dest:
            dest = dest[0]
        if dest in self.cache:
            return self.cache[dest]
        if verbose is None:
            verbose=conf.verb
        # Transform "192.168.*.1-5" to one IP of the set
        dst = dest.split("/")[0]
        dst = dst.replace("*","0") 
        while True:
            l = dst.find("-")
            if l < 0:
                break
            m = (dst[l:]+".").find(".")
            dst = dst[:l]+dst[l+m:]

            
        dst = atol(dst)
        pathes=[]
        for d,m,gw,i,a,me in self.routes:
            if not a: # some interfaces may not currently be connected
                continue
            aa = atol(a)
            if aa == dst:
                pathes.append(
                    (0xffffffff, 1, (scapy.consts.LOOPBACK_INTERFACE, a, "0.0.0.0"))
                )
            if (dst & m) == (d & m):
                pathes.append((m, me, (i,a,gw)))
        if not pathes:
            if verbose:
                warning("No route found (no default route?)")
            return scapy.consts.LOOPBACK_INTERFACE, "0.0.0.0", "0.0.0.0"
        # Choose the more specific route
        # Sort by greatest netmask
        pathes.sort(key=lambda x: x[0], reverse=True)
        # Get all pathes having the (same) greatest mask
        pathes = [i for i in pathes if i[0] == pathes[0][0]]
        # Tie-breaker: Metrics
        pathes.sort(key=lambda x: x[1])
        # Return interface
        ret = pathes[0][2]
        self.cache[dest] = ret
        return ret
            
    def get_if_bcast(self, iff):
        for net, msk, gw, iface, addr, metric in self.routes:
            if net == 0:
                continue
            if scapy.consts.WINDOWS:
                if iff.guid != iface.guid:
                    continue
            elif iff != iface:
                continue
            bcast = atol(addr)|(~msk&0xffffffff); # FIXME: check error in atol()
            return ltoa(bcast)
        warning("No broadcast address found for iface %s\n", iff);

conf.route=Route()

iface = conf.route.route("0.0.0.0", verbose=0)[0]

# Warning: scapy.consts.LOOPBACK_INTERFACE must always be used statically, because it
# may be changed by scapy/arch/windows during execution

if (iface.name if hasattr(iface, "name") else iface) == scapy.consts.LOOPBACK_INTERFACE:
    from scapy.arch import get_working_if
    conf.iface = get_working_if()
else:
    conf.iface = iface

del iface
