diff --git a/scapy/utils6.py b/scapy/utils6.py
index 61971d34667aae9faea7c47723c3ea51a65bb752..eab813b35019a6576812f9cc60dddea42736d06f 100644
--- a/scapy/utils6.py
+++ b/scapy/utils6.py
@@ -67,21 +67,79 @@ def get_source_addr_from_candidate_set(dst, candidate_set):
     algorithm defined in section 5 of RFC 3484. The format is very different
     from that described in the document because it operates on a set 
     of candidate source address for some specific route.
-    
-    Rationale behind the implementation is to be able to make the right 
-    choice for a 6to4 destination when both a 6to4 address and a IPv6 native
-    address are available for that interface.
     """
+
+    def scope_cmp(a, b):
+        """
+        Given two addresses, returns -1, 0 or 1 based on comparison of
+        their scope
+        """
+        scope_mapper = {IPV6_ADDR_GLOBAL: 4,
+                        IPV6_ADDR_SITELOCAL: 3,
+                        IPV6_ADDR_LINKLOCAL: 2,
+                        IPV6_ADDR_LOOPBACK: 1}
+        sa = in6_getscope(a)
+        if sa == -1:
+            sa = IPV6_ADDR_LOOPBACK
+        sb = in6_getscope(b)
+        if sb == -1:
+            sb = IPV6_ADDR_LOOPBACK
+
+        sa = scope_mapper[sa]
+        sb = scope_mapper[sb]
+
+        if sa == sb:
+            return 0
+        if sa > sb:
+            return 1
+        return -1
+
+    def rfc3484_cmp(source_a, source_b):
+        """
+        The function implements a limited version of the rules from Source
+        Address selection algorithm defined section of RFC 3484.
+        """
+
+        # Rule 1: Prefer same address
+        if source_a == dst:
+            return 1
+        if source_b == dst:
+            return 1
+
+        # Rule 2: Prefer appropriate scope
+        tmp = scope_cmp(source_a, source_b)
+        if tmp == -1:
+            if scope_cmp(source_a, dst) == -1:
+                return 1
+            else:
+                return -1
+        elif tmp == 1:
+            if scope_cmp(source_b, dst) == -1:
+                return 1
+            else:
+                return -1
+
+        # Rule 3: cannot be easily implemented
+        # Rule 4: cannot be easily implemented
+        # Rule 5: does not make sense here
+        # Rule 6: cannot be implemented
+        # Rule 7: cannot be implemented
+        
+        # Rule 8: Longest prefix match
+        tmp1 = in6_get_common_plen(source_a, dst)
+        tmp2 = in6_get_common_plen(source_b, dst)
+        if tmp1 > tmp2:
+            return 1
+        elif tmp2 > tmp1:
+            return -1
+        return 0
     
-    if len(candidate_set) == 0:
+    if not candidate_set:
 	# Should not happen
 	return None
-    
-    if in6_isaddr6to4(dst):
-	tmp = filter(lambda x: in6_isaddr6to4(x), candidate_set)
-	if len(tmp) != 0:
-	    return tmp[0]
 
+    candidate_set.sort(cmp=rfc3484_cmp, reverse=True)
+    
     return candidate_set[0]