(self, dst, dev=None)
return res[0][1]
Provide best route to IPv6 destination address, based on Scapy6 
        internal routing table content.

        When a set of address is passed (e.g. 2001:db8:cafe:*::1-5) an address
        of the set is used. Be aware of that behavior when using wildcards in
        upper parts of addresses !

        If 'dst' parameter is a FQDN, name resolution is performed and result
        is used.

        if optional 'dev' parameter is provided a specific interface, filtering
        is performed to limit search to route associated to that interface.
Provide best route to IPv6 destination address, based on Scapy6 
        internal routing table content.
Provide best route to IPv6 destination address based on Scapy6 internal routing table content .
def route(self, dst, dev=None):
        """
        Provide best route to IPv6 destination address, based on Scapy6 
        internal routing table content.

        When a set of address is passed (e.g. 2001:db8:cafe:*::1-5) an address
        of the set is used. Be aware of that behavior when using wildcards in
        upper parts of addresses !

        If 'dst' parameter is a FQDN, name resolution is performed and result
        is used.

        if optional 'dev' parameter is provided a specific interface, filtering
        is performed to limit search to route associated to that interface.
        """
        # Transform "2001:db8:cafe:*::1-5:0/120" to one IPv6 address of the set
        dst = dst.split("/")[0]
        savedst = dst # In case following inet_pton() fails 
        dst = dst.replace("*","0")
        l = dst.find("-")
        while l >= 0:
            m = (dst[l:]+":").find(":")
            dst = dst[:l]+dst[l+m:]
            l = dst.find("-")
            
        try:
            inet_pton(socket.AF_INET6, dst)
        except socket.error:
            dst = socket.getaddrinfo(savedst, None, socket.AF_INET6)[0][-1][0]
            # TODO : Check if name resolution went well

        # Deal with dev-specific request for cache search
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        if k in self.cache:
            return self.cache[k]

        pathes = []

        # TODO : review all kinds of addresses (scope and *cast) to see
        #        if we are able to cope with everything possible. I'm convinced 
        #        it's not the case.
        # -- arnaud
        for p, plen, gw, iface, cset in self.routes:
            if dev is not None and iface != dev:
                continue
            if in6_isincluded(dst, p, plen):
                pathes.append((plen, (iface, cset, gw)))
            elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):
                pathes.append((plen, (iface, cset, gw)))
                
        if not pathes:
            warning("No route found for IPv6 destination %s (no default route?)" % dst)
            return (LOOPBACK_NAME, "::", "::") # XXX Linux specific

        # Sort with longest prefix first
        pathes.sort(reverse=True)

        best_plen = pathes[0][0]
        pathes = filter(lambda x: x[0] == best_plen, pathes)

        res = []
        for p in pathes: # Here we select best source address for every route
            tmp = p[1]
            srcaddr = get_source_addr_from_candidate_set(dst, p[1][1])
            if srcaddr is not None:
                res.append((p[0], (tmp[0], srcaddr, tmp[2])))

        # Symptom  : 2 routes with same weight (our weight is plen)
        # Solution : 
        #  - dst is unicast global. Check if it is 6to4 and we have a source 
        #    6to4 address in those available
        #  - dst is link local (unicast or multicast) and multiple output
        #    interfaces are available. Take main one (conf.iface6)
        #  - if none of the previous or ambiguity persists, be lazy and keep
        #    first one
        #  XXX TODO : in a _near_ future, include metric in the game

        if len(res) > 1:
            tmp = []
            if in6_isgladdr(dst) and in6_isaddr6to4(dst):
                # TODO : see if taking the longest match between dst and
                #        every source addresses would provide better results
                tmp = filter(lambda x: in6_isaddr6to4(x[1][1]), res)
            elif in6_ismaddr(dst) or in6_islladdr(dst):
                # TODO : I'm sure we are not covering all addresses. Check that
                tmp = filter(lambda x: x[1][0] == conf.iface6, res)

            if tmp:
                res = tmp
                
        # Fill the cache (including dev-specific request)
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        self.cache[k] = res[0][1]

        return res[0][1]
def route ( self , dst , dev = None ) : # Transform "2001:db8:cafe:*::1-5:0/120" to one IPv6 address of the set dst = dst . split ( "/" ) [ 0 ] savedst = dst # In case following inet_pton() fails  dst = dst . replace ( "*" , "0" ) l = dst . find ( "-" ) while l >= 0 : m = ( dst [ l : ] + ":" ) . find ( ":" ) dst = dst [ : l ] + dst [ l + m : ] l = dst . find ( "-" ) try : inet_pton ( socket . AF_INET6 , dst ) except socket . error : dst = socket . getaddrinfo ( savedst , None , socket . AF_INET6 ) [ 0 ] [ - 1 ] [ 0 ] # TODO : Check if name resolution went well # Deal with dev-specific request for cache search k = dst if dev is not None : k = dst + "%%" + dev if k in self . cache : return self . cache [ k ] pathes = [ ] # TODO : review all kinds of addresses (scope and *cast) to see #        if we are able to cope with everything possible. I'm convinced  #        it's not the case. # -- arnaud for p , plen , gw , iface , cset in self . routes : if dev is not None and iface != dev : continue if in6_isincluded ( dst , p , plen ) : pathes . append ( ( plen , ( iface , cset , gw ) ) ) elif ( in6_ismlladdr ( dst ) and in6_islladdr ( p ) and in6_islladdr ( cset [ 0 ] ) ) : pathes . append ( ( plen , ( iface , cset , gw ) ) ) if not pathes : warning ( "No route found for IPv6 destination %s (no default route?)" % dst ) return ( LOOPBACK_NAME , "::" , "::" ) # XXX Linux specific # Sort with longest prefix first pathes . sort ( reverse = True ) best_plen = pathes [ 0 ] [ 0 ] pathes = filter ( lambda x : x [ 0 ] == best_plen , pathes ) res = [ ] for p in pathes : # Here we select best source address for every route tmp = p [ 1 ] srcaddr = get_source_addr_from_candidate_set ( dst , p [ 1 ] [ 1 ] ) if srcaddr is not None : res . append ( ( p [ 0 ] , ( tmp [ 0 ] , srcaddr , tmp [ 2 ] ) ) ) # Symptom  : 2 routes with same weight (our weight is plen) # Solution :  #  - dst is unicast global. Check if it is 6to4 and we have a source  #    6to4 address in those available #  - dst is link local (unicast or multicast) and multiple output #    interfaces are available. Take main one (conf.iface6) #  - if none of the previous or ambiguity persists, be lazy and keep #    first one #  XXX TODO : in a _near_ future, include metric in the game if len ( res ) > 1 : tmp = [ ] if in6_isgladdr ( dst ) and in6_isaddr6to4 ( dst ) : # TODO : see if taking the longest match between dst and #        every source addresses would provide better results tmp = filter ( lambda x : in6_isaddr6to4 ( x [ 1 ] [ 1 ] ) , res ) elif in6_ismaddr ( dst ) or in6_islladdr ( dst ) : # TODO : I'm sure we are not covering all addresses. Check that tmp = filter ( lambda x : x [ 1 ] [ 0 ] == conf . iface6 , res ) if tmp : res = tmp # Fill the cache (including dev-specific request) k = dst if dev is not None : k = dst + "%%" + dev self . cache [ k ] = res [ 0 ] [ 1 ] return res [ 0 ] [ 1 ]