diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index 767ba4796..97e2c9d54 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -414,6 +414,7 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools): DestIP6Field("dst", "::1") ] def route(self): + """Used to select the L2 address""" dst = self.dst if isinstance(dst,Gen): dst = next(iter(dst)) diff --git a/scapy/route6.py b/scapy/route6.py index 9cb5c7c10..eb1893ee3 100644 --- a/scapy/route6.py +++ b/scapy/route6.py @@ -197,6 +197,10 @@ class Route6: 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: diff --git a/test/linux.uts b/test/linux.uts index e160a4e3c..c5abec553 100644 --- a/test/linux.uts +++ b/test/linux.uts @@ -172,3 +172,24 @@ assert(got_lo_device) exit_status = os.system("ip link del dev scapy_lo") assert(exit_status == 0) + += IPv6 link-local address selection + +from mock import patch +bck_conf_route6_routes = conf.route6.routes +conf.route6.routes = [('fe80::', 64, '::', 'scapy0', ['fe80::e039:91ff:fe79:1910'], 256)] +bck_conf_iface = conf.iface +conf.iface = "scapy0" +with patch("scapy.layers.l2.get_if_hwaddr") as mgih: + mgih.return_value = 'e2:39:91:79:19:10' + p = Ether()/IPv6(dst="ff02::1")/ICMPv6NIQueryName(data="ff02::1") + print(p.sprintf("%Ether.src% > %Ether.dst%\n%IPv6.src% > %IPv6.dst%")) + ip6_ll_address = 'fe80::e039:91ff:fe79:1910' + print(p[IPv6].src, ip6_ll_address) + assert p[IPv6].src == ip6_ll_address + mac_address = 'e2:39:91:79:19:10' + print(p[Ether].src, mac_address) + assert p[Ether].src == mac_address + +conf.route6.routes = bck_conf_route6_routes +conf.iface = bck_conf_iface diff --git a/test/regression.uts b/test/regression.uts index 713d351e8..f5c7a7a22 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -3435,6 +3435,8 @@ raw(defragment6(l)) == b'`\x00\x00\x00\x0f\xb4\x06@\x00\x00\x00\x00\x00\x00\x00\ + Test Route6 class = Route6 - Route6 flushing +conf_iface = conf.iface +conf.iface = "eth0" conf.route6.routes=[ ( '::1', 128, '::', 'lo', ['::1'], 1), ( 'fe80::20f:1fff:feca:4650', 128, '::', 'lo', ['::1'], 1)] @@ -3452,6 +3454,7 @@ conf.route6.routes=[ ( '::', 0, 'fe80::20f:34ff:fe8a:8aa1', 'eth0', ['2001:db8:0:4444:20f:1fff:feca:4650', '2002:db8:0:4444:20f:1fff:feca:4650'], 1) ] conf.route6.route("2002::1") == ('eth0', '2002:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1') and conf.route6.route("2001::1") == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1') and conf.route6.route("fe80::20f:1fff:feab:4870") == ('eth0', 'fe80::20f:1fff:feca:4650', '::') and conf.route6.route("::1") == ('lo', '::1', '::') and conf.route6.route("::") == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1') and conf.route6.route('ff00::') == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1') +conf.iface = conf_iface conf.route6.resync() if not len(conf.route6.routes): # IPv6 seems disabled. Force a route to ::1