diff --git a/.travis/test.sh b/.travis/test.sh index 96c18ae248c24f77d1c08e9b2419f2f074f51c40..116221ec107d173a8b6d4670da1e60977852e7ba 100644 --- a/.travis/test.sh +++ b/.travis/test.sh @@ -23,6 +23,8 @@ if [ "$SCAPY_USE_PCAPDNET" = "yes" ] then UT_FLAGS+=" -K not_pcapdnet" fi +# IPv6 is not available yet on travis +UT_FLAGS+=" -K ipv6" # AES-CCM, ChaCha20Poly1305 and X25519 were added to Cryptography v2.0 # but the minimal version mandated by scapy is v1.7 @@ -72,9 +74,11 @@ then $SCAPY_SUDO ./run_tests -q -F -t bpf.uts $UT_FLAGS || exit $? fi UT_FLAGS+=" -K manufdb -K linux" -else - # IPv6 is not available yet on the linux machines (but is on OSX) - UT_FLAGS+=" -K ipv6" +fi + +if [ "$TRAVIS_OS_NAME" = "linux" ] +then + UT_FLAGS+=" -K osx" fi # Run all normal and contrib tests diff --git a/scapy/all.py b/scapy/all.py index 9d6e5b5d3f80e7ab619869b98242d468bcc23b18..f44c617e83cae309379b02e8524ad637364e704c 100644 --- a/scapy/all.py +++ b/scapy/all.py @@ -36,6 +36,7 @@ from scapy.automaton import * from scapy.autorun import * from scapy.main import * +from scapy.consts import * from scapy.layers.all import * diff --git a/scapy/arch/__init__.py b/scapy/arch/__init__.py index 0e8785f2639eef84e6ed4061834e7a7fbf709274..9a7ff230cab285ed61cd6ad863ef8efe943d91eb 100644 --- a/scapy/arch/__init__.py +++ b/scapy/arch/__init__.py @@ -70,7 +70,7 @@ elif WINDOWS: from scapy.arch.windows import * if scapy.config.conf.iface is None: - scapy.config.conf.iface = LOOPBACK_NAME + scapy.config.conf.iface = scapy.consts.LOOPBACK_INTERFACE def get_if_addr6(iff): diff --git a/scapy/arch/pcapdnet.py b/scapy/arch/pcapdnet.py index b52072c7074e20041b7e2306a97dd96240cb1d1f..8f4f40037c247248ffc35473404bbdbe6ebd80fc 100644 --- a/scapy/arch/pcapdnet.py +++ b/scapy/arch/pcapdnet.py @@ -18,6 +18,7 @@ from scapy.config import conf from scapy.utils import mac2str from scapy.supersocket import SuperSocket from scapy.error import Scapy_Exception, log_loading, warning +from scapy.pton_ntop import inet_ntop import scapy.arch import scapy.consts @@ -113,7 +114,7 @@ if conf.use_winpcapy: pcap_freealldevs(devs) if conf.use_winpcapy: get_if_list = winpcapy_get_if_list - def in6_getifaddr(): + def in6_getifaddr_raw(): err = create_string_buffer(PCAP_ERRBUF_SIZE) devs = POINTER(pcap_if_t)() ret = [] @@ -128,7 +129,7 @@ if conf.use_winpcapy: if a.contents.addr.contents.sa_family == socket.AF_INET6: ap = a.contents.addr val = cast(ap, POINTER(sockaddr_in6)) - addr = socket.inet_ntop(socket.AF_INET6, str(val.contents.sin6_addr[:])) + addr = inet_ntop(socket.AF_INET6, "".join(chr(x) for x in val.contents.sin6_addr[:])) scope = scapy.utils6.in6_getscope(addr) ret.append((addr, scope, p.contents.name.decode('ascii'))) a = a.contents.next @@ -332,7 +333,13 @@ if conf.use_winpcapy: else: return def send(self, x): - cls = conf.l2types[1] + # Makes send detects when it should add Loopback(), Dot11... instead of Ether() + ll = self.ins.datalink() + if ll in conf.l2types: + cls = conf.l2types[ll] + else: + cls = conf.default_l2 + warning("Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name)) sx = raw(cls()/x) if hasattr(x, "sent_time"): x.sent_time = time.time() diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py index 1399e2a97ee625d89ac81edfbefafe96b48c075c..4f4177171c32ec83c3020b0c499887209c90cd71 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -13,6 +13,7 @@ import subprocess as sp from glob import glob import tempfile +import scapy from scapy.config import conf, ConfClass from scapy.error import Scapy_Exception, log_loading, log_runtime, warning from scapy.utils import atol, itom, inet_aton, inet_ntoa, PcapReader @@ -261,7 +262,8 @@ if conf.prog.tcpdump and conf.use_npcap and conf.prog.os_access: try: p_test_windump = sp.Popen([conf.prog.tcpdump, "-help"], stdout=sp.PIPE, stderr=sp.STDOUT) stdout, err = p_test_windump.communicate() - return b"npcap" in stdout.lower() + _output = stdout.lower() + return b"npcap" in _output and not b"winpcap" in _output except: return False windump_ok = test_windump_npcap() @@ -293,7 +295,7 @@ def get_windows_if_list(): # Name InterfaceDescription ifIndex Status MacAddress LinkSpeed # ---- -------------------- ------- ------ ---------- --------- # Ethernet Killer E2200 Gigabit Ethernet Contro... 13 Up D0-50-99-56-DD-F9 1 Gbps - query = exec_query(['Get-NetAdapter -Physical'], + query = exec_query(['Get-NetAdapter'], ['InterfaceDescription', 'InterfaceIndex', 'Name', 'InterfaceGuid', 'MacAddress']) # It is normal that it is in this order else: @@ -647,42 +649,13 @@ def in6_getifaddr(): """ Returns all IPv6 addresses found on the computer """ - if is_new_release(): - ret = [] - ps = sp.Popen([conf.prog.powershell, 'Get-NetRoute', '-AddressFamily IPV6', '|', 'select ifIndex, DestinationPrefix'], stdout = sp.PIPE, universal_newlines = True) - stdout, stdin = ps.communicate() - netstat_line = '\s+'.join(['(\d+)', ''.join(['([A-z|0-9|:]+)', '(\/\d+)'])]) - pattern = re.compile(netstat_line) - for l in stdout.split('\n'): - match = re.search(pattern,l) - if match: - try: - if_index = match.group(1) - iface = dev_from_index(if_index) - except: - continue - scope = scapy.utils6.in6_getscope(match.group(2)) - ret.append((match.group(2), scope, iface)) # (addr,scope,iface) - continue - return ret - else: - ret = [] - # Get-WmiObject Win32_NetworkAdapterConfiguration | select InterfaceIndex, IpAddress - for line in exec_query(['Get-WmiObject', 'Win32_NetworkAdapterConfiguration'], ['InterfaceIndex', 'IPAddress']): - try: - iface = dev_from_index(line[0]) - except: - continue - _l_addresses = line[1] - _inline = [] - if _l_addresses: - _inline = _l_addresses[1:-1].split(",") - for _address in _inline: - _a = _address.strip() - if "." not in _a: - scope = scapy.utils6.in6_getscope(_a) - ret.append((_a, scope, iface)) # (addr,scope,iface) - return ret + ifaddrs = [] + for ifaddr in in6_getifaddr_raw(): + try: + ifaddrs.append((ifaddr[0], ifaddr[1], dev_from_pcapname(ifaddr[2]))) + except ValueError: + pass + return ifaddrs def _append_route6(routes, dpref, dp, nh, iface, lifaddr): cset = [] # candidate set (possible source addresses) @@ -843,7 +816,7 @@ def route_add_loopback(routes=None, ipv6=False, iflist=None): if not conf.route.routes: return data = {} - data['name'] = LOOPBACK_NAME + data['name'] = scapy.consts.LOOPBACK_NAME data['description'] = "Loopback" data['win_index'] = -1 data['guid'] = "{0XX00000-X000-0X0X-X00X-00XXXX000XXX}" @@ -856,11 +829,11 @@ def route_add_loopback(routes=None, ipv6=False, iflist=None): # Remove all LOOPBACK_NAME routes for route in list(conf.route.routes): iface = route[3] - if iface.name == LOOPBACK_NAME: + if iface.name == scapy.consts.LOOPBACK_NAME: conf.route.routes.remove(route) # Remove LOOPBACK_NAME interface for devname, iface in IFACES.items(): - if iface.name == LOOPBACK_NAME: + if iface.name == scapy.consts.LOOPBACK_NAME: IFACES.pop(devname) # Inject interface IFACES[data['guid']] = adapter diff --git a/scapy/base_classes.py b/scapy/base_classes.py index 610240416c9bd45a13a1d68b7c6e368fa675a768..f2c76a129030badf3ad6d8a42a5a73cfad09d4e0 100644 --- a/scapy/base_classes.py +++ b/scapy/base_classes.py @@ -51,7 +51,7 @@ class SetGen(Gen): class Net(Gen): """Generate a list of IPs from a network address or a name""" name = "ip" - ipaddress = re.compile(r"^(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)(/[0-3]?[0-9])?$") + ip_regex = re.compile(r"^(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)(/[0-3]?[0-9])?$") @staticmethod def _parse_digit(a,netmask): @@ -70,7 +70,7 @@ class Net(Gen): @classmethod def _parse_net(cls, net): tmp=net.split('/')+["32"] - if not cls.ipaddress.match(net): + if not cls.ip_regex.match(net): tmp[0]=socket.gethostbyname(tmp[0]) netmask = int(tmp[1]) ret_list = [cls._parse_digit(x, y-netmask) for (x, y) in zip(tmp[0].split('.'), [8, 16, 24, 32])] @@ -81,7 +81,10 @@ class Net(Gen): self.parsed,self.netmask = self._parse_net(net) def __str__(self): - return self.repr + try: + return next(self.__iter__()) + except StopIteration: + return None def __iter__(self): for d in range(*self.parsed[3]): diff --git a/scapy/consts.py b/scapy/consts.py index 9b31a71e9f53b2fffd038d1996a2d6a32c4fd995..ff6b771b55905142a33ae461fec6c350e437358c 100644 --- a/scapy/consts.py +++ b/scapy/consts.py @@ -68,12 +68,12 @@ if WINDOWS: LOOPBACK_NAME = "Microsoft Loopback Adapter" except ValueError: LOOPBACK_NAME = "Microsoft Loopback Adapter" + # Will be different on Windows + LOOPBACK_INTERFACE = None else: uname = os.uname() LOOPBACK_NAME = "lo" if LINUX else "lo0" - -# Will be different on Windows -LOOPBACK_INTERFACE = LOOPBACK_NAME + LOOPBACK_INTERFACE = LOOPBACK_NAME def parent_function(): return inspect.getouterframes(inspect.currentframe()) diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index 47ed0682d25654f77f8246206aaf04272371a55b..72eb5b136f668533027644d5551bd52fbba2d1be 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -48,11 +48,14 @@ class IPTools(object): print(whois(self.src)) else: os.system("whois %s" % self.src) + def _ttl(self): + """Returns ttl or hlim, depending on the IP version""" + return self.hlim if isinstance(self, IPv6) else self.ttl def ottl(self): - t = sorted([32,64,128,255]+[self.ttl]) - return t[t.index(self.ttl)+1] + t = sorted([32,64,128,255]+[self._ttl()]) + return t[t.index(self._ttl())+1] def hops(self): - return self.ottl() - self.ttl + return self.ottl() - self._ttl() _ip_options_names = { 0: "end_of_list", diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index 3e61a90ee7e2973de3627eeb4d01ee9c3cdae15b..69501fcee043efe69190c771a1a37d7af2176bbd 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -107,6 +107,9 @@ def getmacbyip6(ip6, chainCC=0): (chainCC parameter value ends up being passed to sending function used to perform the resolution, if needed) """ + + if isinstance(ip6, Net6): + ip6 = iter(ip6).next() if in6_ismaddr(ip6): # Multicast mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6)) @@ -150,13 +153,13 @@ def getmacbyip6(ip6, chainCC=0): class Net6(Gen): # syntax ex. fec0::/126 """Generate a list of IPv6s from a network address or a name""" name = "ipv6" - ipaddress = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$") + ip_regex = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$") def __init__(self, net): self.repr = net tmp = net.split('/')+["128"] - if not self.ipaddress.match(net): + if not self.ip_regex.match(net): tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0] netmask = int(tmp[1]) @@ -195,6 +198,18 @@ class Net6(Gen): # syntax ex. fec0::/126 return iter(rec(0, [''])) + def __str__(self): + try: + return next(self.__iter__()) + except StopIteration: + return None + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return str(other) != str(self) + def __repr__(self): return "Net6(%r)" % self.repr @@ -402,7 +417,7 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools): return conf.route6.route(dst) def mysummary(self): - return "%s > %s (%i)" % (self.src,self.dst, self.nh) + return "%s > %s (%i)" % (self.src, self.dst, self.nh) def post_build(self, p, pay): p += pay @@ -3288,10 +3303,10 @@ def _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None, # Check destination is the link-local solicited-node multicast # address associated with target address in received NS - tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt) + tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt) if tgt_filter and tgt != tgt_filter: return 0 - received_snma = socket.inet_pton(socket.AF_INET6, req[IPv6].dst) + received_snma = inet_pton(socket.AF_INET6, req[IPv6].dst) expected_snma = in6_getnsma(tgt) if received_snma != expected_snma: return 0 @@ -3507,7 +3522,7 @@ def NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None, if req[IPv6].src == "::": return 0 - tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt) + tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt) if tgt_filter and tgt != tgt_filter: return 0 diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py index ddb9307dbc4b8ccc7dae82f738481943591658e2..3aa148adcdcb28f00ecff0742253caabc355e32f 100644 --- a/scapy/layers/l2.py +++ b/scapy/layers/l2.py @@ -11,6 +11,7 @@ from __future__ import absolute_import from __future__ import print_function import os, struct, time, socket +import scapy from scapy.base_classes import Net from scapy.config import conf from scapy.data import * @@ -21,7 +22,6 @@ from scapy.plist import SndRcvList from scapy.fields import * from scapy.sendrecv import srp, srp1, srpflood from scapy.arch import get_if_hwaddr -from scapy.consts import LOOPBACK_INTERFACE from scapy.utils import inet_ntoa, inet_aton from scapy.error import warning if conf.route is None: @@ -66,7 +66,7 @@ def getmacbyip(ip, chainCC=0): if (tmp[0] & 0xf0) == 0xe0: # mcast @ return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3]) iff,a,gw = conf.route.route(ip) - if ( (iff == LOOPBACK_INTERFACE) or (ip == conf.route.get_if_bcast(iff)) ): + if ( (iff == scapy.consts.LOOPBACK_INTERFACE) or (ip == conf.route.get_if_bcast(iff)) ): return "ff:ff:ff:ff:ff:ff" if gw != "0.0.0.0": ip = gw diff --git a/scapy/pton_ntop.py b/scapy/pton_ntop.py index 991ed163245b5b37472cb20eb7d8bafa94b7ccfc..f7d3e52d77cf6d2885c96d4173722df6e14de2c9 100644 --- a/scapy/pton_ntop.py +++ b/scapy/pton_ntop.py @@ -79,6 +79,9 @@ _INET_PTON = { def inet_pton(af, addr): """Convert an IP address from text representation into binary form.""" + # Will replace Net/Net6 objects + if not isinstance(addr, str): + addr = str(addr) # Use inet_pton if available addr = plain_str(addr) try: diff --git a/scapy/route.py b/scapy/route.py index 40a730774228045e57e48af9aad6d6a787868d75..ee5791d0a77ee670301fea16556c4e1a1b089d9e 100644 --- a/scapy/route.py +++ b/scapy/route.py @@ -8,11 +8,11 @@ Routing and handling of network interfaces. """ from __future__ import absolute_import -from scapy.consts import LOOPBACK_NAME, LOOPBACK_INTERFACE from scapy.utils import atol, ltoa, itom, pretty_routes from scapy.config import conf from scapy.error import Scapy_Exception, warning from scapy.arch import WINDOWS +import scapy.consts import scapy.modules.six as six ############################## @@ -153,13 +153,13 @@ class Route: continue aa = atol(a) if aa == dst: - pathes.append((0xffffffff,(LOOPBACK_INTERFACE,a,"0.0.0.0"))) + pathes.append((0xffffffff,(scapy.consts.LOOPBACK_INTERFACE,a,"0.0.0.0"))) if (dst & m) == (d & m): pathes.append((m,(i,a,gw))) if not pathes: if verbose: warning("No route found (no default route?)") - return LOOPBACK_INTERFACE,"0.0.0.0","0.0.0.0" + return scapy.consts.LOOPBACK_INTERFACE,"0.0.0.0","0.0.0.0" # Choose the more specific route (greatest netmask). # XXX: we don't care about metrics pathes.sort(key=lambda x: x[0]) @@ -184,6 +184,6 @@ conf.route=Route() #XXX use "with" _betteriface = conf.route.route("0.0.0.0", verbose=0)[0] -if ((_betteriface if (isinstance(_betteriface, six.string_types) or _betteriface is None) else _betteriface.name) != LOOPBACK_NAME): +if ((_betteriface if (isinstance(_betteriface, six.string_types) or _betteriface is None) else _betteriface.name) != scapy.consts.LOOPBACK_NAME): conf.iface = _betteriface del(_betteriface) diff --git a/scapy/route6.py b/scapy/route6.py index fe433f33739ae59ae57fe2201472d18fec1eb085..38da81934be612b2f4191161d9cd9f968006321b 100644 --- a/scapy/route6.py +++ b/scapy/route6.py @@ -18,12 +18,12 @@ Routing and network interface handling for IPv6. from __future__ import absolute_import import socket +import scapy.consts from scapy.config import conf from scapy.utils6 import * from scapy.arch import * from scapy.pton_ntop import * from scapy.error import warning, log_loading -from scapy.consts import LOOPBACK_INTERFACE import scapy.modules.six as six @@ -220,7 +220,7 @@ class Route6: if not pathes: warning("No route found for IPv6 destination %s (no default route?)" % dst) - return (LOOPBACK_INTERFACE, "::", "::") + return (scapy.consts.LOOPBACK_INTERFACE, "::", "::") # Sort with longest prefix first pathes.sort(reverse=True) @@ -237,7 +237,7 @@ class Route6: if res == []: warning("Found a route for IPv6 destination '%s', but no possible source address." % dst) - return (LOOPBACK_INTERFACE, "::", "::") + return (scapy.consts.LOOPBACK_INTERFACE, "::", "::") # Symptom : 2 routes with same weight (our weight is plen) # Solution : diff --git a/scapy/utils.py b/scapy/utils.py index 9e81fbe1e028e64f7d612b7cadb05e3850697f65..2dbc038d8aa4fa720a0f4784a9c364a0d6468c11 100644 --- a/scapy/utils.py +++ b/scapy/utils.py @@ -395,11 +395,7 @@ else: inet_aton = socket.inet_aton inet_ntoa = socket.inet_ntoa -try: - inet_ntop = socket.inet_ntop - inet_pton = socket.inet_pton -except AttributeError: - from scapy.pton_ntop import * +from scapy.pton_ntop import * def atol(x): diff --git a/test/answering_machines.uts b/test/answering_machines.uts index 2131431738fc5eddec3b9d38f39098da665361b4..d61ac713d1be1309c7de0b91ab3f791f0215587f 100644 --- a/test/answering_machines.uts +++ b/test/answering_machines.uts @@ -59,3 +59,48 @@ def check_DNS_am_reply(packet): test_am(DNS_am, IP()/UDP()/DNS(qd=DNSQR(qname="www.secdev.org")), check_DNS_am_reply) + += DHCPv6_am - Basic Instantiaion +~ osx netaccess +a = DHCPv6_am() +a.usage() + +a.parse_options(dns="2001:500::1035", domain="localdomain, local", duid=None, + iface=conf.iface6, advpref=255, sntpservers=None, + sipdomains=None, sipservers=None, + nisdomain=None, nisservers=None, + nispdomain=None, nispservers=None, + bcmcsdomains=None, bcmcsservers=None, + debug=1) + += DHCPv6_am - SOLICIT +~ osx netaccess +req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=1)/DHCP6OptClientId(duid=DUID_LLT()) +assert a.is_request(req) +res = a.make_reply(req) +assert not a.is_request(res) +assert res[DHCP6_Advertise] +assert res[DHCP6OptPref].prefval == 255 +assert res[DHCP6OptReconfAccept] +a.print_reply(req, res) + += DHCPv6_am - INFO-REQUEST +~ osx netaccess +req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=11)/DHCP6OptClientId(duid=DUID_LLT()) +assert a.is_request(req) +res = a.make_reply(req) +assert not a.is_request(res) +assert res[DHCP6_Reply] +assert "local" in res[DHCP6OptDNSDomains].dnsdomains +a.print_reply(req, res) + += DHCPv6_am - REQUEST +~ osx netaccess +req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=3)/DHCP6OptClientId(duid=DUID_LLT())/DHCP6OptServerId(duid=a.duid) +assert a.is_request(req) +res = a.make_reply(req) +assert not a.is_request(res) +assert res[UDP].dport == 546 +assert res[DHCP6_Solicit] +a.print_reply(req, res) + diff --git a/test/configs/windows.utsc b/test/configs/windows.utsc index 42b6759bae30dfc33fe32591bbaea0c370cabf16..fb854b0644dddfa15b81265e27cd4d4c9711fd3a 100644 --- a/test/configs/windows.utsc +++ b/test/configs/windows.utsc @@ -12,6 +12,8 @@ }, "format": "text", "kw_ko": [ - "crypto_advanced" + "crypto_advanced", + "ipv6", + "osx" ] } diff --git a/test/mock_windows.uts b/test/mock_windows.uts index 98dc8c2b6851edfe342fd99b0bc8d9a982e372fc..16eb480bbb3cad8255c6a16d74dc0473d2f82b12 100644 --- a/test/mock_windows.uts +++ b/test/mock_windows.uts @@ -17,11 +17,9 @@ assert select_objects([TimeOutSelector()], 1) == [] ############ ############ -+ Mocked read_routes6() calls ++ Windows Networking tests -= Windows with fake IPv6 adapter - -route_add_loopback() += Mocked read_routes6() calls import mock from scapy.arch.windows import _read_routes6_post2008 @@ -92,6 +90,7 @@ ifIndex DestinationPrefix NextHop test_read_routes6_windows() + ############ ############ + Main.py emulator diff --git a/test/regression.uts b/test/regression.uts index 4e445490d660dbc024a578f0fe99b1175bd099d3..e1e10a16ecdebc98871ee559fafe8a5112c92ab2 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -509,12 +509,16 @@ assert all(p.hashret() == p2.hashret() for p in px) assert not any(p.answers(p2) for p in px) assert all(p2.answers(p) for p in px) conf.checkIPinIP = conf_back + +a1, a2 = Net("www.google.com"), Net("www.secdev.org") prt1, prt2 = 12345, 54321 s1, s2 = 2767216324, 3845532842 p1 = IP(src=a1, dst=a2)/TCP(flags='SA', seq=s1, ack=s2, sport=prt1, dport=prt2) p2 = IP(src=a2, dst=a1)/TCP(flags='R', seq=s2, ack=0, sport=prt2, dport=prt1) assert p2.answers(p1) assert not p1.answers(p2) +# Not available yet because of IPv6 +# a1, a2 = Net6("www.google.com"), Net6("www.secdev.org") p1 = IP(src=a1, dst=a2)/TCP(flags='S', seq=s1, ack=0, sport=prt1, dport=prt2) p2 = IP(src=a2, dst=a1)/TCP(flags='RA', seq=0, ack=s1+1, sport=prt2, dport=prt1) assert p2.answers(p1) @@ -690,6 +694,17 @@ assert x[IP].ottl() in [32, 64, 128, 255] assert 0 <= x[IP].hops() <= 126 x is not None and ICMP in x and x[ICMP].type == 0 += Sending and receiving an ICMPv6EchoRequest +~ netaccess ipv6 +old_debug_dissector = conf.debug_dissector +conf.debug_dissector = False +x = sr1(IPv6(dst="www.google.com")/ICMPv6EchoRequest(),timeout=3) +conf.debug_dissector = old_debug_dissector +x +assert x[IPv6].ottl() in [32, 64, 128, 255] +assert 0 <= x[IPv6].hops() <= 126 +x is not None and ICMPv6EchoReply in x and x[ICMPv6EchoReply].type == 129 + = DNS request ~ netaccess IP UDP DNS * A possible cause of failure could be that the open DNS (resolver1.opendns.com) @@ -1797,6 +1812,14 @@ b=IPv6(src="2047::deca", dst="2048::cafe")/ICMPv6EchoReply(id=0x6666, seq=0x7777 a=IPv6(src="2048::cafe", dst="2047::deca")/ICMPv6EchoRequest(id=0x6666, seq=0x7777, data="somedata") (a > b) == True += ICMPv6EchoRequest and ICMPv6EchoReply - live answers() use Net6 +~ netaccess ipv6 + +a = IPv6(dst="www.google.com")/ICMPv6EchoRequest() +b = IPv6(src="www.google.com", dst=a.src)/ICMPv6EchoReply() +assert b.answers(a) +assert (a > b) + ########### ICMPv6MRD* Classes ###################################### @@ -3134,6 +3157,22 @@ p = IPv6(s) ICMPv6MLQuery in p and p[IPv6].dst == "ff02::1" +############ +############ ++ Ether tests with IPv6 + += Logic +# No more routing test after this line +if WINDOWS: + route_add_loopback() + += Ether IPv6 checking for dst +~ netaccess ipv6 + +p = Ether()/IPv6(dst="www.google.com")/TCP() +assert p.dst != p[IPv6].dst +p.show() + ############ ############ + TracerouteResult6 @@ -4363,53 +4402,6 @@ str(DHCP6_RelayReply()) == b'\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ a=DHCP6_RelayReply(b'\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') a.msgtype == 13 and a.hopcount == 0 and a.linkaddr == "::" and a.peeraddr == "::" -############ -############ -+ Test DHCPv6_am - -= DHCPv6_am - Basic Instantiaion -~ ipv6 netaccess -a = DHCPv6_am() -a.usage() - -a.parse_options(dns="2001:500::1035", domain="localdomain, local", duid=None, - iface=conf.iface6, advpref=255, sntpservers=None, - sipdomains=None, sipservers=None, - nisdomain=None, nisservers=None, - nispdomain=None, nispservers=None, - bcmcsdomains=None, bcmcsservers=None, - debug=1) - -= DHCPv6_am - SOLICIT -~ ipv6 netaccess -req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=1)/DHCP6OptClientId(duid=DUID_LLT()) -assert a.is_request(req) -res = a.make_reply(req) -assert not a.is_request(res) -assert res[DHCP6_Advertise] -assert res[DHCP6OptPref].prefval == 255 -assert res[DHCP6OptReconfAccept] -a.print_reply(req, res) - -= DHCPv6_am - INFO-REQUEST -~ ipv6 netaccess -req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=11)/DHCP6OptClientId(duid=DUID_LLT()) -assert a.is_request(req) -res = a.make_reply(req) -assert not a.is_request(res) -assert res[DHCP6_Reply] -assert "local" in res[DHCP6OptDNSDomains].dnsdomains -a.print_reply(req, res) - -= DHCPv6_am - REQUEST -~ ipv6 netaccess -req = IPv6(dst="::1")/UDP()/DHCP6(msgtype=3)/DHCP6OptClientId(duid=DUID_LLT())/DHCP6OptServerId(duid=a.duid) -assert a.is_request(req) -res = a.make_reply(req) -assert not a.is_request(res) -assert res[UDP].dport == 546 -assert res[DHCP6_Solicit] -a.print_reply(req, res) ############ ############ @@ -4437,8 +4429,6 @@ not a < b and a > b + Mobile Prefix Solicitation/Advertisement = ICMPv6MPSol - build (default values) -if WINDOWS: - route_add_loopback() s = b'`\x00\x00\x00\x00\x08:@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x92\x00m\xbb\x00\x00\x00\x00' str(IPv6()/ICMPv6MPSol()) == s @@ -7922,6 +7912,14 @@ len([ip for ip in n3]) == 5 (n3 in n2) == True += Net using web address + +ip = IP(dst="www.google.com") +n1 = ip.dst +assert isinstance(n1, Net) +assert n1.ip_regex.match(str(n1)) +ip.show() + = OID oid = OID("1.2.3.4.5.6-8") @@ -7932,6 +7930,14 @@ len([ o for o in oid ]) == 3 n1 = Net6("2001:db8::/127") len([ip for ip in n1]) == 2 += Net6 using web address +~ netaccess ipv6 + +ip = IPv6(dst="www.google.com") +n1 = ip.dst +assert isinstance(n1, Net6) +assert n1.ip_regex.match(str(n1)) +ip.show() ############ ############ @@ -8900,3 +8906,15 @@ p1[IP] p2[MPLS] p2[MPLS:1] p2[IP] + + ++ Restore normal routes & Ifaces + += Windows + +if WINDOWS: + IFACES.reload() + conf.route.resync() + conf.route6.resync() + +True \ No newline at end of file