docs: def route(self, dst=None, dev=None, verbose=conf.verb):
          """
          Provide best route to IPv6 destination address, based on Scapy
          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.
          """
          dst = dst or "::/0"  # Enable route(None) to return default route
          # 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")
          idx = dst.find("-")
          while idx >= 0:
              m = (dst[idx:] + ":").find(":")
              dst = dst[:idx] + dst[idx + m:]
              idx = 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
  
          # Use the default interface while dealing with link-local addresses
          if dev is None and (in6_islladdr(dst) or in6_ismlladdr(dst)):
              dev = conf.iface
  
          # Deal with dev-specific request for cache search
          k = dst
          if dev is not None:
              k = dst + "%%" + (dev if isinstance(dev, six.string_types) else dev.pcap_name)  # noqa: E501
          if k in self.cache:
              return self.cache[k]
  
          paths = []
  
          # 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, me in self.routes:
              if dev is not None and iface != dev:
                  continue
              if in6_isincluded(dst, p, plen):
                  paths.append((plen, me, (iface, cset, gw)))
              elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):  # noqa: E501
                  paths.append((plen, me, (iface, cset, gw)))
  
          if not paths:
              if verbose:
                  warning("No route found for IPv6 destination %s "
                          "(no default route?)", dst)
              return (scapy.consts.LOOPBACK_INTERFACE, "::", "::")
  
          # Sort with longest prefix first then use metrics as a tie-breaker
          paths.sort(key=lambda x: (-x[0], x[1]))
  
          best_plen = (paths[0][0], paths[0][1])
          paths = [x for x in paths if (x[0], x[1]) == best_plen]
  
          res = []
          for p in paths:  # Here we select best source address for every route
              tmp = p[2]
              srcaddr = get_source_addr_from_candidate_set(dst, tmp[1])
              if srcaddr is not None:
                  res.append((p[0], p[1], (tmp[0], srcaddr, tmp[2])))
  
          if res == []:
              warning("Found a route for IPv6 destination '%s', but no possible source address.", dst)  # noqa: E501
              return (scapy.consts.LOOPBACK_INTERFACE, "::", "::")
  
          # 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
  
          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 = [x for x in res if in6_isaddr6to4(x[2][1])]
              elif in6_ismaddr(dst) or in6_islladdr(dst):
                  # TODO : I'm sure we are not covering all addresses. Check that
                  tmp = [x for x in res if x[2][0] == conf.iface6]
  
              if tmp:
                  res = tmp
  
          # Fill the cache (including dev-specific request)
          k = dst
          if dev is not None:
              k = dst + "%%" + (dev if isinstance(dev, six.string_types) else dev.pcap_name)  # noqa: E501
          self.cache[k] = res[0][2]
  
          return res[0][2]