def __init__(self, iface=None, proto=socket.IPPROTO_IP, ttl=128, ipv6=False, promisc=True, **kwargs): from scapy.layers.inet import IP from scapy.layers.inet6 import IPv6 for kwarg in kwargs: warning("Dropping unsupported option: %s" % kwarg) af = socket.AF_INET6 if ipv6 else socket.AF_INET self.proto = proto if ipv6: from scapy.arch import get_if_addr6 self.host_ip6 = get_if_addr6(conf.iface) or "::1" if proto == socket.IPPROTO_IP: # We'll restrict ourselves to UDP, as TCP isn't bindable # on AF_INET6 self.proto = socket.IPPROTO_UDP # On Windows, with promisc=False, you won't get much self.ipv6 = ipv6 self.cls = IPv6 if ipv6 else IP self.promisc = promisc # Notes: # - IPPROTO_RAW only works to send packets. # - IPPROTO_IPV6 exists in MSDN docs, but using it will result in # no packets being received. Same for its options (IPV6_HDRINCL...) # However, using IPPROTO_IP with AF_INET6 will still receive # the IPv6 packets try: self.ins = socket.socket(af, socket.SOCK_RAW, self.proto) self.outs = socket.socket(af, socket.SOCK_RAW, socket.IPPROTO_RAW) except OSError as e: if e.errno == 10013: raise OSError("Windows native L3 Raw sockets are only " "usable as administrator ! " "Install Winpcap/Npcap to workaround !") raise self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30) # IOCTL Include IP headers self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # set TTL self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) # Bind on all ports iface = resolve_iface(iface) or conf.iface host = iface.ip if iface.ip else socket.gethostname() self.ins.bind((host, 0)) self.ins.setblocking(False) # Get as much data as possible: reduce what is cropped if ipv6: try: # Not all Windows versions self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVTCLASS, 1) self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, 1) except (OSError, socket.error): pass else: try: # Not Windows XP self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVDSTADDR, 1) except (OSError, socket.error): pass try: # Windows 10+ recent builds only self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVTTL, 1) except (OSError, socket.error): pass if promisc: # IOCTL Receive all packets self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
def __init__(self, iface=None, proto=socket.IPPROTO_IP, ttl=128, ipv6=False, promisc=True, **kwargs): for kwarg in kwargs: warning("Dropping unsupported option: %s" % kwarg) af = socket.AF_INET6 if ipv6 else socket.AF_INET self.proto = proto if ipv6: from scapy.arch import get_if_addr6 self.host_ip6 = get_if_addr6(conf.iface) or "::1" if proto == socket.IPPROTO_IP: # We'll restrict ourselves to UDP, as TCP isn't bindable # on AF_INET6 self.proto = socket.IPPROTO_UDP # On Windows, with promisc=False, you won't get much self.ipv6 = ipv6 self.cls = IPv6 if ipv6 else IP self.promisc = promisc # Notes: # - IPPROTO_RAW only works to send packets. # - IPPROTO_IPV6 exists in MSDN docs, but using it will result in # no packets being received. Same for its options (IPV6_HDRINCL...) # However, using IPPROTO_IP with AF_INET6 will still receive # the IPv6 packets try: self.ins = socket.socket(af, socket.SOCK_RAW, self.proto) self.outs = socket.socket(af, socket.SOCK_RAW, socket.IPPROTO_RAW) except OSError as e: if e.errno == 10013: raise OSError("Windows native L3 Raw sockets are only " "usable as administrator ! " "Install Winpcap/Npcap to workaround !") raise self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30) # IOCTL Include IP headers self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # set TTL self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) # Bind on all ports host = iface.ip if iface else socket.gethostname() self.ins.bind((host, 0)) self.ins.setblocking(False) # Get as much data as possible: reduce what is cropped if ipv6: try: # Not all Windows versions self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVTCLASS, 1) self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, 1) except (OSError, socket.error): pass else: try: # Not Windows XP self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVDSTADDR, 1) except (OSError, socket.error): pass try: # Windows 10+ recent builds only self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVTTL, 1) except (OSError, socket.error): pass if promisc: # IOCTL Receive all packets self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)