summaryrefslogtreecommitdiffstats
path: root/scripts/external_libs
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-03-21 12:55:16 +0200
committerHanoh Haim <hhaim@cisco.com>2016-03-21 12:55:16 +0200
commit1831e9bbc03484b078dbd604dfec0e025cea8eca (patch)
tree96ffe76ee50a29f8eea36ada1cc21738de09bcb7 /scripts/external_libs
parent33c80d0f2c3af8b302e50ce3925869dfd37267ed (diff)
scapy 3-0.18 with trex client diff
Diffstat (limited to 'scripts/external_libs')
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/__init__.py15
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/abc.py1
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/all.py49
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/ansmachine.py130
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/__init__.py108
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/bsd.py12
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/cdnet.py229
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/linux.py530
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/pcapdnet.py565
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/solaris.py16
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/unix.py168
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/windows/__init__.py501
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/arch/winpcapy.py739
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/as_resolvers.py115
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1/__init__.py12
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1/asn1.py321
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1/ber.py370
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1/mib.py149
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1fields.py341
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/asn1packet.py26
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/automaton.py753
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/autorun.py142
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/base_classes.py237
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/config.py394
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/__init__.py8
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/avs.py57
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/bgp.py168
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/carp.py65
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/cdp.py306
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/chdlc.py42
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/dtp.py115
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/eigrp.py488
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/etherip.py19
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/gsm_um.py13119
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/gtp.py546
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmp.py171
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmpv3.py270
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ikev2.py362
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ldp.py475
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/mpls.py17
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ospf.py833
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi.py86
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_cace.py87
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_geotag.py464
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ripng.py41
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/rsvp.py188
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/skinny.py499
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/ubberlogger.py101
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/vqp.py58
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/vtp.py171
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/contrib/wpa_eapol.py35
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/crypto/__init__.py17
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/crypto/cert.py2486
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/dadict.py91
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/data.py215
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/error.py60
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/fields.py935
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/__init__.py8
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/all.py45
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/bluetooth.py213
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp.py381
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py1718
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/dns.py712
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/dot11.py560
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/gprs.py21
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/hsrp.py79
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/inet.py1569
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/inet6.py3047
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/ipsec.py995
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/ir.py44
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/isakmp.py355
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/l2.py543
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/l2tp.py36
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/llmnr.py65
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/mgcp.py45
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/mobileip.py47
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/netbios.py222
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/netflow.py48
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/ntp.py77
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/pflog.py59
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/ppp.py349
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/radius.py65
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/rip.py74
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/rtp.py40
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/sctp.py439
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/sebek.py109
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/skinny.py161
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/smb.py354
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/snmp.py255
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/tftp.py477
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/vrrp.py39
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/x509.py108
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/main.py380
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/__init__.py8
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/geoip.py77
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/nmap.py215
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/p0f.py549
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/queso.py113
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/modules/voip.py149
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/packet.py1360
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/pipetool.py566
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/plist.py517
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/pton_ntop.py90
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/route.py175
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/route6.py288
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/scapypipes.py123
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/sendrecv.py678
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/supersocket.py141
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/themes.py277
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/tools/UTscapy.py677
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/tools/__init__.py8
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/tools/check_asdis.py103
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/utils.py1054
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/utils6.py823
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/volatile.py685
-rw-r--r--scripts/external_libs/scapy3-0.18-origin.rarbin0 -> 367282 bytes
116 files changed, 50933 insertions, 0 deletions
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/__init__.py
new file mode 100644
index 00000000..443b3675
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/__init__.py
@@ -0,0 +1,15 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Scapy: create, send, sniff, dissect and manipulate network packets.
+
+Usable either from an interactive console or as a Python library.
+http://www.secdev.org/projects/scapy
+"""
+
+if __name__ == "__main__":
+ from scapy.main import interact
+ interact()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/abc.py b/scripts/external_libs/scapy-python3-0.18/scapy/abc.py
new file mode 100644
index 00000000..3d5f06e2
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/abc.py
@@ -0,0 +1 @@
+from config import conf
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/all.py b/scripts/external_libs/scapy-python3-0.18/scapy/all.py
new file mode 100644
index 00000000..46030c66
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/all.py
@@ -0,0 +1,49 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Aggregate top level objects from all Scapy modules.
+"""
+
+from .config import *
+from .base_classes import *
+from .dadict import *
+from .data import *
+from .error import *
+#from .themes import *
+from .arch import *
+
+from .plist import *
+from .fields import *
+from .packet import *
+#from .asn1fields import *
+#from .asn1packet import *
+
+from .utils import *
+#from .route import *
+#if conf.ipv6_enabled:
+# from .utils6 import *
+# from .route6 import *
+#from .sendrecv import *
+#from .supersocket import *
+#from .volatile import *
+#from .as_resolvers import *
+
+#from .ansmachine import *
+#from .automaton import *
+#from .autorun import *
+
+from .main import *
+
+from .layers.all import *
+
+#from .asn1.asn1 import *
+#from .asn1.ber import *
+#from .asn1.mib import *
+
+#from .crypto import *
+
+#from .pipetool import *
+#from .scapypipes import *
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/ansmachine.py b/scripts/external_libs/scapy-python3-0.18/scapy/ansmachine.py
new file mode 100644
index 00000000..b087ac44
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/ansmachine.py
@@ -0,0 +1,130 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Answering machines.
+"""
+
+########################
+## Answering machines ##
+########################
+
+from .sendrecv import send,sendp,sniff
+from .config import conf
+from .error import log_interactive
+
+class ReferenceAM(type):
+ def __new__(cls, name, bases, dct):
+ o = super(ReferenceAM, cls).__new__(cls, name, bases, dct)
+ if o.function_name:
+ globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)()
+ return o
+
+
+class AnsweringMachine(object):
+ __metaclass__ = ReferenceAM
+ function_name = ""
+ filter = None
+ sniff_options = { "store":0 }
+ sniff_options_list = [ "store", "iface", "count", "promisc", "filter", "type", "prn", "stop_filter" ]
+ send_options = { "verbose":0 }
+ send_options_list = ["iface", "inter", "loop", "verbose"]
+ send_function = staticmethod(send)
+
+
+ def __init__(self, **kargs):
+ self.mode = 0
+ if self.filter:
+ kargs.setdefault("filter",self.filter)
+ kargs.setdefault("prn", self.reply)
+ self.optam1 = {}
+ self.optam2 = {}
+ self.optam0 = {}
+ doptsend,doptsniff = self.parse_all_options(1, kargs)
+ self.defoptsend = self.send_options.copy()
+ self.defoptsend.update(doptsend)
+ self.defoptsniff = self.sniff_options.copy()
+ self.defoptsniff.update(doptsniff)
+ self.optsend,self.optsniff = [{},{}]
+
+ def __getattr__(self, attr):
+ for d in [self.optam2, self.optam1]:
+ if attr in d:
+ return d[attr]
+ raise AttributeError(attr)
+
+ def __setattr__(self, attr, val):
+ mode = self.__dict__.get("mode",0)
+ if mode == 0:
+ self.__dict__[attr] = val
+ else:
+ [self.optam1, self.optam2][mode-1][attr] = val
+
+ def parse_options(self):
+ pass
+
+ def parse_all_options(self, mode, kargs):
+ sniffopt = {}
+ sendopt = {}
+ for k in list(kargs):
+ if k in self.sniff_options_list:
+ sniffopt[k] = kargs[k]
+ if k in self.send_options_list:
+ sendopt[k] = kargs[k]
+ if k in self.sniff_options_list+self.send_options_list:
+ del(kargs[k])
+ if mode != 2 or kargs:
+ if mode == 1:
+ self.optam0 = kargs
+ elif mode == 2 and kargs:
+ k = self.optam0.copy()
+ k.update(kargs)
+ self.parse_options(**k)
+ kargs = k
+ omode = self.__dict__.get("mode",0)
+ self.__dict__["mode"] = mode
+ self.parse_options(**kargs)
+ self.__dict__["mode"] = omode
+ return sendopt,sniffopt
+
+ def is_request(self, req):
+ return 1
+
+ def make_reply(self, req):
+ return req
+
+ def send_reply(self, reply):
+ self.send_function(reply, **self.optsend)
+
+ def print_reply(self, req, reply):
+ print("%s ==> %s" % (req.summary(),reply.summary()))
+
+ def reply(self, pkt):
+ if not self.is_request(pkt):
+ return
+ reply = self.make_reply(pkt)
+ self.send_reply(reply)
+ if conf.verb >= 0:
+ self.print_reply(pkt, reply)
+
+ def run(self, *args, **kargs):
+ log_interactive.warning("run() method deprecated. The intance is now callable")
+ self(*args,**kargs)
+
+ def __call__(self, *args, **kargs):
+ optsend,optsniff = self.parse_all_options(2,kargs)
+ self.optsend=self.defoptsend.copy()
+ self.optsend.update(optsend)
+ self.optsniff=self.defoptsniff.copy()
+ self.optsniff.update(optsniff)
+
+ try:
+ self.sniff()
+ except KeyboardInterrupt:
+ print("Interrupted by user")
+
+ def sniff(self):
+ sniff(**self.optsniff)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/__init__.py
new file mode 100644
index 00000000..0066e049
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/__init__.py
@@ -0,0 +1,108 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Operating system specific functionality.
+"""
+
+
+import sys,os,socket
+from scapy.error import *
+import scapy.config
+
+try:
+ import matplotlib.pyplot as plt
+ MATPLOTLIB = True
+ if scapy.config.conf.interactive:
+ plt.ion()
+except ImportError:
+ log_loading.info("Can't import matplotlib. Not critical, but won't be able to plot.")
+ MATPLOTLIB = False
+
+try:
+ import networkx as nx
+ NETWORKX = True
+except ImportError:
+ log_loading.info("Can't import networkx. Not criticial, but won't be able to draw network graphs.")
+ NETWORKX = False
+
+try:
+ import pyx
+ PYX=1
+except ImportError:
+ log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump().")
+ PYX=0
+
+
+def str2mac(s):
+ #return ("%02x:"*6)[:-1] % tuple(map(ord, s))
+ return ("%02x:"*6)[:-1] % tuple(s)
+
+
+
+def get_if_addr(iff):
+ return socket.inet_ntoa(get_if_raw_addr(iff))
+
+def get_if_hwaddr(iff):
+ mac = get_if_raw_hwaddr(iff)
+ return str2mac(mac)
+
+
+LINUX=sys.platform.startswith("linux")
+OPENBSD=sys.platform.startswith("openbsd")
+FREEBSD=sys.platform.startswith("freebsd")
+NETBSD = sys.platform.startswith("netbsd")
+DARWIN=sys.platform.startswith("darwin")
+SOLARIS=sys.platform.startswith("sunos")
+WINDOWS=sys.platform.startswith("win32")
+
+X86_64 = not WINDOWS and (os.uname()[4] == 'x86_64')
+
+#if WINDOWS:
+# log_loading.warning("Windows support for scapy3k is currently in testing. Sniffing/sending/receiving packets should be working with WinPcap driver and Powershell. Create issues at https://github.com/phaethon/scapy")
+
+# Next step is to import following architecture specific functions:
+# def get_if_raw_hwaddr(iff)
+# def get_if_raw_addr(iff):
+# def get_if_list():
+# def get_working_if():
+# def attach_filter(s, filter):
+# def set_promisc(s,iff,val=1):
+# def read_routes():
+# def get_if(iff,cmd):
+# def get_if_index(iff):
+
+
+
+if LINUX:
+ from .linux import *
+ if scapy.config.conf.use_winpcapy or scapy.config.conf.use_netifaces:
+ from pcapdnet import *
+elif OPENBSD or FREEBSD or NETBSD or DARWIN:
+ from .bsd import *
+elif SOLARIS:
+ from .solaris import *
+elif WINDOWS:
+ pass;
+ #from .windows import *
+
+LOOPBACK_NAME="a"
+
+if scapy.config.conf.iface is None:
+ scapy.config.conf.iface = LOOPBACK_NAME
+
+def get_if_raw_addr6(iff):
+ """
+ Returns the main global unicast address associated with provided
+ interface, in network format. If no global address is found, None
+ is returned.
+ """
+ #r = filter(lambda x: x[2] == iff and x[1] == IPV6_ADDR_GLOBAL, in6_getifaddr())
+ r = [ x for x in in6_getifaddr() if x[2] == iff and x[1] == IPV6_ADDR_GLOBAL]
+ if len(r) == 0:
+ return None
+ else:
+ r = r[0][0]
+ return inet_pton(socket.AF_INET6, r)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/bsd.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/bsd.py
new file mode 100644
index 00000000..c4220308
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/bsd.py
@@ -0,0 +1,12 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Support for BSD-like operating systems such as FreeBSD, OpenBSD and Mac OS X.
+"""
+
+LOOPBACK_NAME="lo0"
+
+from .unix import *
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/cdnet.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/cdnet.py
new file mode 100644
index 00000000..98ebf084
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/cdnet.py
@@ -0,0 +1,229 @@
+from ctypes import *
+from ctypes.util import find_library
+import sys
+
+WIN=False
+
+if sys.platform.startswith('win'):
+ WIN=True
+
+if WIN:
+ SOCKET = c_uint
+ _lib=CDLL('dnet')
+else:
+ SOCKET = c_int
+ _lib_name = find_library('dnet')
+ if not _lib_name:
+ raise OSError("Cannot find libdnet.so")
+ _lib=CDLL(_lib_name)
+
+ETH_ADDR_LEN = 6
+INTF_NAME_LEN = 16
+INTF_NAME_COUNT = 20
+INTF_ALIAS_COUNT = 20
+IP6_ADDR_LEN = 16
+
+ADDR_TYPE_NONE = 0
+ADDR_TYPE_ETH = 1
+ADDR_TYPE_IP = 2
+ADDR_TYPE_IP6 = 3
+
+INTF_TYPE_OTHER = 1
+INTF_TYPE_ETH = 6
+INTF_TYPE_TOKENRING = 9
+INTF_TYPE_FDDI = 15
+INTF_TYPE_PPP = 23
+INTF_TYPE_LOOPBACK = 24
+INTF_TYPE_SLIP = 28
+INTF_TYPE_TUN = 53
+
+
+uint8_t = c_ubyte
+uint16_t = c_ushort
+uint32_t = c_uint
+ssize_t = c_long
+dnet_ip_addr_t = uint32_t
+
+dnet_intf_name = c_char * INTF_NAME_LEN
+
+class dnet_intf_list(Structure):
+ pass
+
+dnet_intf_list._fields_ = [ ('length', c_int),
+ ('interfaces', dnet_intf_name * 20) ]
+
+class dnet_eth_addr(Structure):
+ pass
+
+dnet_eth_addr._fields_ = [ ('data', uint8_t * ETH_ADDR_LEN) ]
+dnet_eth_addr_t = dnet_eth_addr
+
+class dnet_ip6_addr(Structure):
+ pass
+
+dnet_ip6_addr._fields_ = [ ('data', uint8_t * IP6_ADDR_LEN) ]
+dnet_ip6_addr_t = dnet_ip6_addr
+
+class dnet_addr_u(Union):
+ pass
+
+dnet_addr_u._fields_ = [ ('eth', dnet_eth_addr_t),
+ ('ip', dnet_ip_addr_t),
+ ('ip6', dnet_ip6_addr_t),
+ ('data8', uint8_t * 16),
+ ('data16', uint16_t * 8),
+ ('data32', uint32_t * 4) ]
+
+class dnet_addr(Structure):
+ pass
+dnet_addr._anonymous_ = ('__addr_u', )
+dnet_addr._fields_ = [ ('addr_type', uint16_t),
+ ('addr_bits', uint16_t),
+ ('__addr_u', dnet_addr_u) ]
+
+class dnet_intf_entry(Structure):
+ pass
+
+dnet_intf_entry._fields_ = [ ('intf_len', c_uint),
+ ('intf_name', c_char * INTF_NAME_LEN),
+ ('intf_type', c_ushort),
+ ('intf_flags', c_ushort),
+ ('intf_mtu', c_uint),
+ ('intf_addr', dnet_addr),
+ ('intf_dst_addr', dnet_addr),
+ ('intf_link_addr', dnet_addr),
+ ('intf_alias_num', c_uint),
+ ('intf_alias_addrs', dnet_addr * INTF_ALIAS_COUNT) ]
+
+
+eth_t = c_void_p
+intf_t = c_void_p
+ip_t = c_void_p
+dnet_intf_handler = CFUNCTYPE(c_int, POINTER(dnet_intf_entry), POINTER(c_void_p))
+
+dnet_eth_open = _lib.eth_open
+dnet_eth_open.restype = POINTER(eth_t)
+dnet_eth_open.argtypes = [ POINTER(c_char) ]
+
+dnet_eth_get = _lib.eth_get
+dnet_eth_get.restype = c_int
+dnet_eth_get.argtypes = [ POINTER(eth_t), POINTER(dnet_eth_addr_t) ]
+
+dnet_eth_set = _lib.eth_set
+dnet_eth_set.restype = c_int
+dnet_eth_set.argtypes = [ POINTER(eth_t), POINTER(dnet_eth_addr_t) ]
+
+dnet_eth_send = _lib.eth_send
+dnet_eth_send.restype = ssize_t
+dnet_eth_send.argtypes = [ POINTER(eth_t), c_void_p, c_size_t ]
+
+dnet_eth_close = _lib.eth_close
+dnet_eth_close.restype = POINTER(eth_t)
+dnet_eth_close.argtypes = [ POINTER(eth_t) ]
+
+dnet_intf_open = _lib.intf_open
+dnet_intf_open.restype = POINTER(intf_t)
+dnet_intf_open.argtypes = [ ]
+
+dnet_intf_get = _lib.intf_get
+dnet_intf_get.restype = c_int
+dnet_intf_get.argtypes = [ POINTER(intf_t), POINTER(dnet_intf_entry) ]
+
+dnet_intf_get_src = _lib.intf_get_src
+dnet_intf_get_src.restype = c_int
+dnet_intf_get_src.argtypes = [ POINTER(intf_t), POINTER(dnet_intf_entry), POINTER(dnet_addr) ]
+
+dnet_intf_get_dst = _lib.intf_get_dst
+dnet_intf_get_dst.restype = c_int
+dnet_intf_get_dst.argtypes = [ POINTER(intf_t), POINTER(dnet_intf_entry), POINTER(dnet_addr) ]
+
+dnet_intf_set = _lib.intf_set
+dnet_intf_set.restype = c_int
+dnet_intf_set.argtypes = [ POINTER(intf_t), POINTER(dnet_intf_entry) ]
+
+dnet_intf_loop = _lib.intf_loop
+dnet_intf_loop.restype = POINTER(intf_t)
+dnet_intf_loop.argtypes = [ POINTER(intf_t), dnet_intf_handler, c_void_p ]
+
+dnet_intf_close = _lib.intf_close
+dnet_intf_close.restype = POINTER(intf_t)
+dnet_intf_close.argtypes = [ POINTER(intf_t) ]
+
+dnet_ip_open = _lib.ip_open
+dnet_ip_open.restype = POINTER(ip_t)
+dnet_ip_open.argtypes = [ ]
+
+dnet_ip_add_option = _lib.ip_add_option
+dnet_ip_add_option.restype = ssize_t
+dnet_ip_add_option.argtypes = [ POINTER(c_void_p), c_size_t, c_int, POINTER(c_void_p), c_size_t ]
+
+dnet_ip_checksum = _lib.ip_checksum
+dnet_ip_checksum.restype = None
+dnet_ip_checksum.argtypes = [ POINTER(c_void_p), c_size_t ]
+
+dnet_ip_send = _lib.ip_send
+dnet_ip_send.restype = ssize_t
+dnet_ip_send.argtypes = [ POINTER(ip_t), c_void_p, c_size_t ]
+
+dnet_ip_close = _lib.ip_close
+dnet_ip_close.restype = POINTER(ip_t)
+dnet_ip_close.argtypes = [ POINTER(ip_t) ]
+
+class dnet_eth:
+ def __init__(self, iface):
+ self.iface_b = create_string_buffer(iface.encode('ascii'))
+ self.eth = dnet_eth_open(self.iface_b)
+ def send(self, sx):
+ dnet_eth_send(self.eth, sx, len(sx))
+ def close(self):
+ return dnet_eth_close(self.eth)
+
+class dnet_ip:
+ def __init__(self):
+ self.ip = dnet_ip_open()
+ def send(self, sx):
+ dnet_ip_send(self.ip, sx, len(sx))
+ def close(self):
+ return dnet_ip_close(self.ip)
+
+def dnet_intf_name_loop(entry, intf_list):
+ l = cast(intf_list, POINTER(dnet_intf_list))
+ if l.contents.length >= INTF_NAME_COUNT:
+ return -1
+ for i in enumerate(entry.contents.intf_name):
+ l.contents.interfaces[l.contents.length][i[0]] = i[1]
+ l.contents.length += 1
+ return 0
+
+class dnet_intf:
+ def __init__(self):
+ self.intf = dnet_intf_open()
+ intf_list = dnet_intf_list()
+ intf_list.length = 0
+ dnet_intf_loop(self.intf, dnet_intf_handler(dnet_intf_name_loop), pointer(intf_list))
+ self.names = []
+ for i in range(INTF_NAME_COUNT):
+ if i >= intf_list.length:
+ break
+ self.names.append(intf_list.interfaces[i].value.decode('ascii').strip('\0'))
+
+ def close(self):
+ return dnet_intf_close(self.intf)
+
+ def get(self, iface):
+ ret = {}
+ entry = dnet_intf_entry()
+ entry.intf_name = iface.encode('ascii')
+ entry.intf_len = sizeof(entry)
+ r = dnet_intf_get(self.intf, byref(entry))
+ if r < 0:
+ return {}
+ ret['addr6'] = []
+ for i in range(entry.intf_alias_num):
+ if entry.intf_alias_addrs[i].addr_type == ADDR_TYPE_IP6:
+ ret['addr6'].append(bytes(entry.intf_alias_addrs[i].data8[:16]))
+ ret['type'] = entry.intf_type
+ ret['addr'] = bytes(entry.intf_addr.data8[:4])
+ ret['link_addr'] = bytes(entry.intf_link_addr.data8[:6])
+ return ret
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/linux.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/linux.py
new file mode 100644
index 00000000..3eab16c6
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/linux.py
@@ -0,0 +1,530 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Linux specific functions.
+"""
+
+import sys,os,struct,socket,time,ctypes
+from select import select
+from fcntl import ioctl
+import scapy.utils
+import scapy.utils6
+from scapy.config import conf
+from scapy.data import *
+from scapy.supersocket import SuperSocket
+import scapy.arch
+from scapy.error import warning, Scapy_Exception
+
+
+
+# From bits/ioctls.h
+SIOCGIFHWADDR = 0x8927 # Get hardware address
+SIOCGIFADDR = 0x8915 # get PA address
+SIOCGIFNETMASK = 0x891b # get network PA mask
+SIOCGIFNAME = 0x8910 # get iface name
+SIOCSIFLINK = 0x8911 # set iface channel
+SIOCGIFCONF = 0x8912 # get iface list
+SIOCGIFFLAGS = 0x8913 # get flags
+SIOCSIFFLAGS = 0x8914 # set flags
+SIOCGIFINDEX = 0x8933 # name -> if_index mapping
+SIOCGIFCOUNT = 0x8938 # get number of devices
+SIOCGSTAMP = 0x8906 # get packet timestamp (as a timeval)
+
+# From if.h
+IFF_UP = 0x1 # Interface is up.
+IFF_BROADCAST = 0x2 # Broadcast address valid.
+IFF_DEBUG = 0x4 # Turn on debugging.
+IFF_LOOPBACK = 0x8 # Is a loopback net.
+IFF_POINTOPOINT = 0x10 # Interface is point-to-point link.
+IFF_NOTRAILERS = 0x20 # Avoid use of trailers.
+IFF_RUNNING = 0x40 # Resources allocated.
+IFF_NOARP = 0x80 # No address resolution protocol.
+IFF_PROMISC = 0x100 # Receive all packets.
+
+# From netpacket/packet.h
+PACKET_ADD_MEMBERSHIP = 1
+PACKET_DROP_MEMBERSHIP = 2
+PACKET_RECV_OUTPUT = 3
+PACKET_RX_RING = 5
+PACKET_STATISTICS = 6
+PACKET_MR_MULTICAST = 0
+PACKET_MR_PROMISC = 1
+PACKET_MR_ALLMULTI = 2
+
+# From bits/socket.h
+SOL_PACKET = 263
+# From asm/socket.h
+SO_ATTACH_FILTER = 26
+SOL_SOCKET = 1
+
+# From net/route.h
+RTF_UP = 0x0001 # Route usable
+RTF_REJECT = 0x0200
+
+# From pcap/pcap.h
+PCAP_ERRBUF_SIZE=256
+
+
+
+LOOPBACK_NAME="lo"
+
+with os.popen("tcpdump -V 2> /dev/null") as _f:
+ if _f.close() >> 8 == 0x7f:
+ log_loading.warning("Failed to execute tcpdump. Check it is installed and in the PATH")
+ TCPDUMP=0
+ else:
+ TCPDUMP=1
+del(_f)
+
+
+def get_if_raw_hwaddr(iff):
+ return struct.unpack("16xh6s8x",get_if(iff,SIOCGIFHWADDR))[1]
+
+def get_if_raw_addr(iff):
+ try:
+ return get_if(iff, SIOCGIFADDR)[20:24]
+ except IOError:
+ return b"\0\0\0\0"
+
+
+def get_if_list():
+ try:
+ f=open("/proc/net/dev","r")
+ except IOError:
+ warning("Can't open /proc/net/dev !")
+ return []
+ lst = []
+ f.readline()
+ f.readline()
+ for l in f:
+ lst.append(l.split(":")[0].strip())
+ f.close()
+ return lst
+
+def get_working_if():
+ for i in get_if_list():
+ if i == LOOPBACK_NAME:
+ continue
+ ifflags = struct.unpack("16xH14x",get_if(i,SIOCGIFFLAGS))[0]
+ if ifflags & IFF_UP:
+ return i
+ return LOOPBACK_NAME
+def attach_filter(s, filter):
+ # XXX We generate the filter on the interface conf.iface
+ # because tcpdump open the "any" interface and ppp interfaces
+ # in cooked mode. As we use them in raw mode, the filter will not
+ # work... one solution could be to use "any" interface and translate
+ # the filter from cooked mode to raw mode
+ # mode
+ if not TCPDUMP:
+ return
+ try:
+ f = os.popen("%s -i %s -ddd -s 1600 '%s'" % (conf.prog.tcpdump,conf.iface,filter))
+ except OSError as msg:
+ log_interactive.warning("Failed to execute tcpdump: (%s)")
+ return
+ lines = f.readlines()
+ if f.close():
+ raise Scapy_Exception("Filter parse error")
+ nb = int(lines[0])
+ bpf = b""
+ for l in lines[1:]:
+ bpf += struct.pack("HBBI",*[int(x) for x in l.split()])
+
+ # XXX. Argl! We need to give the kernel a pointer on the BPF,
+ # python object header seems to be 20 bytes. 36 bytes for x86 64bits arch.
+ bpf_buf = ctypes.create_string_buffer(bpf)
+ class BpfProgram(ctypes.Structure):
+ _fields_ = [ ("bf_len", ctypes.c_int), ("bf_insn", ctypes.POINTER(type(bpf_buf))) ]
+ #if scapy.arch.X86_64:
+ # bpfh = struct.pack("HL", nb, id(bpf)+36)
+ #else:
+ # bpfh = struct.pack("HI", nb, id(bpf)+20)
+ bpfh = BpfProgram(nb, ctypes.pointer(bpf_buf))
+ s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
+
+def set_promisc(s,iff,val=1):
+ mreq = struct.pack("IHH8s", get_if_index(iff), PACKET_MR_PROMISC, 0, b"")
+ if val:
+ cmd = PACKET_ADD_MEMBERSHIP
+ else:
+ cmd = PACKET_DROP_MEMBERSHIP
+ s.setsockopt(SOL_PACKET, cmd, mreq)
+
+
+
+def read_routes():
+ try:
+ f=open("/proc/net/route","rb")
+ except IOError:
+ warning("Can't open /proc/net/route !")
+ return []
+ routes = []
+ s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",LOOPBACK_NAME.encode('utf-8')))
+ addrfamily = struct.unpack("h",ifreq[16:18])[0]
+ if addrfamily == socket.AF_INET:
+ ifreq2 = ioctl(s, SIOCGIFNETMASK,struct.pack("16s16x",LOOPBACK_NAME.encode('utf-8')))
+ msk = socket.ntohl(struct.unpack("I",ifreq2[20:24])[0])
+ dst = socket.ntohl(struct.unpack("I",ifreq[20:24])[0]) & msk
+ ifaddr = scapy.utils.inet_ntoa(ifreq[20:24])
+ routes.append((dst, msk, "0.0.0.0", LOOPBACK_NAME, ifaddr))
+ else:
+ warning("Interface lo: unkown address family (%i)"% addrfamily)
+
+ for l in f.readlines()[1:]:
+ iff,dst,gw,flags,x,x,x,msk,x,x,x = l.split()
+ flags = int(flags,16)
+ if flags & RTF_UP == 0:
+ continue
+ if flags & RTF_REJECT:
+ continue
+ try:
+ ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",iff))
+ except IOError: # interface is present in routing tables but does not have any assigned IP
+ ifaddr="0.0.0.0"
+ else:
+ addrfamily = struct.unpack("h",ifreq[16:18])[0]
+ if addrfamily == socket.AF_INET:
+ ifaddr = scapy.utils.inet_ntoa(ifreq[20:24])
+ else:
+ warning("Interface %s: unkown address family (%i)"%(iff, addrfamily))
+ continue
+ routes.append((socket.htonl(int(dst,16))&0xffffffff,
+ socket.htonl(int(msk,16))&0xffffffff,
+ scapy.utils.inet_ntoa(struct.pack("I",int(gw,16))),
+ iff.decode('utf-8'), ifaddr))
+
+ f.close()
+ return routes
+
+############
+### IPv6 ###
+############
+
+def in6_getifaddr():
+ """
+ Returns a list of 3-tuples of the form (addr, scope, iface) where
+ 'addr' is the address of scope 'scope' associated to the interface
+ 'ifcace'.
+
+ This is the list of all addresses of all interfaces available on
+ the system.
+ """
+ ret = []
+ try:
+ f = open("/proc/net/if_inet6","rb")
+ except IOError as err:
+ return ret
+ l = f.readlines()
+ for i in l:
+ # addr, index, plen, scope, flags, ifname
+ tmp = i.split()
+ addr = struct.unpack('4s4s4s4s4s4s4s4s', tmp[0])
+ addr = scapy.utils6.in6_ptop(b':'.join(addr).decode('ascii'))
+ ret.append((addr, int(tmp[3], 16), tmp[5].decode('ascii'))) # (addr, scope, iface)
+ f.close()
+ return ret
+
+def read_routes6():
+ try:
+ f = open("/proc/net/ipv6_route","r")
+ except IOError as err:
+ return []
+ # 1. destination network
+ # 2. destination prefix length
+ # 3. source network displayed
+ # 4. source prefix length
+ # 5. next hop
+ # 6. metric
+ # 7. reference counter (?!?)
+ # 8. use counter (?!?)
+ # 9. flags
+ # 10. device name
+ routes = []
+ def proc2r(p):
+ ret = struct.unpack('4s4s4s4s4s4s4s4s', p.encode('ascii'))
+ ret = b':'.join(ret)
+ return scapy.utils6.in6_ptop(ret.decode('ascii'))
+
+ lifaddr = in6_getifaddr()
+ for l in f.readlines():
+ d,dp,s,sp,nh,m,rc,us,fl,dev = l.split()
+ fl = int(fl, 16)
+
+ if fl & RTF_UP == 0:
+ continue
+ if fl & RTF_REJECT:
+ continue
+
+ d = proc2r(d) ; dp = int(dp, 16)
+ s = proc2r(s) ; sp = int(sp, 16)
+ nh = proc2r(nh)
+
+ cset = [] # candidate set (possible source addresses)
+ if dev == LOOPBACK_NAME:
+ if d == '::':
+ continue
+ cset = ['::1']
+ else:
+ #devaddrs = filter(lambda x: x[2] == dev, lifaddr)
+ devaddrs = [ x for x in lifaddr if x[2] == dev ]
+ cset = scapy.utils6.construct_source_candidate_set(d, dp, devaddrs, LOOPBACK_NAME)
+
+ if len(cset) != 0:
+ routes.append((d, dp, nh, dev, cset))
+ f.close()
+ return routes
+
+
+
+
+def get_if(iff,cmd):
+ s=socket.socket()
+ ifreq = ioctl(s, cmd, struct.pack("16s16x",bytes(iff,'utf-8')))
+ s.close()
+ return ifreq
+
+
+def get_if_index(iff):
+ return int(struct.unpack("I",get_if(iff, SIOCGIFINDEX)[16:20])[0])
+
+if os.uname()[4] == 'x86_64':
+ def get_last_packet_timestamp(sock):
+ ts = ioctl(sock, SIOCGSTAMP, "1234567890123456")
+ s,us = struct.unpack("QQ",ts)
+ return s+us/1000000.0
+else:
+ def get_last_packet_timestamp(sock):
+ ts = ioctl(sock, SIOCGSTAMP, "12345678")
+ s,us = struct.unpack("II",ts)
+ return s+us/1000000.0
+
+
+def _flush_fd(fd):
+ if type(fd) is not int:
+ fd = fd.fileno()
+ while 1:
+ r,w,e = select([fd],[],[],0)
+ if r:
+ os.read(fd,MTU)
+ else:
+ break
+
+
+
+
+
+class L3PacketSocket(SuperSocket):
+ desc = "read/write packets at layer 3 using Linux PF_PACKET sockets"
+ def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
+ self.type = type
+ self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
+ if iface:
+ self.ins.bind((iface, type))
+ if not nofilter:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if filter is not None:
+ attach_filter(self.ins, filter)
+ _flush_fd(self.ins)
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
+ self.outs = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+ self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
+ if promisc is None:
+ promisc = conf.promisc
+ self.promisc = promisc
+ if self.promisc:
+ if iface is None:
+ self.iff = get_if_list()
+ else:
+ if iface.__class__ is list:
+ self.iff = iface
+ else:
+ self.iff = [iface]
+ for i in self.iff:
+ set_promisc(self.ins, i)
+ def close(self):
+ if self.closed:
+ return
+ self.closed=1
+ if self.promisc:
+ for i in self.iff:
+ set_promisc(self.ins, i, 0)
+ SuperSocket.close(self)
+ def recv(self, x=MTU):
+ pkt, sa_ll = self.ins.recvfrom(x)
+ if sa_ll[2] == socket.PACKET_OUTGOING:
+ return None
+ if sa_ll[3] in conf.l2types:
+ cls = conf.l2types[sa_ll[3]]
+ lvl = 2
+ elif sa_ll[1] in conf.l3types:
+ cls = conf.l3types[sa_ll[1]]
+ lvl = 3
+ else:
+ cls = conf.default_l2
+ warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
+ lvl = 2
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ if lvl == 2:
+ pkt = pkt.payload
+
+ if pkt is not None:
+ pkt.time = get_last_packet_timestamp(self.ins)
+ return pkt
+
+ def send(self, x):
+ iff,a,gw = x.route()
+ if iff is None:
+ iff = conf.iface
+ sdto = (iff, self.type)
+ self.outs.bind(sdto)
+ sn = self.outs.getsockname()
+ ll = lambda x:x
+ if type(x) in conf.l3types:
+ sdto = (iff, conf.l3types[type(x)])
+ if sn[3] in conf.l2types:
+ ll = lambda x:conf.l2types[sn[3]]()/x
+ try:
+ sx = bytes(ll(x))
+ x.sent_time = time.time()
+ self.outs.sendto(sx, sdto)
+ except OSError as msg:
+ x.sent_time = time.time() # bad approximation
+ if conf.auto_fragment and msg.errno == 90:
+ for p in x.fragment():
+ self.outs.sendto(bytes(ll(p)), sdto)
+ else:
+ raise
+
+
+
+class L2Socket(SuperSocket):
+ desc = "read/write packets at layer 2 using Linux PF_PACKET sockets"
+ def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+ if iface is None:
+ iface = conf.iface
+ self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
+ if not nofilter:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if filter is not None:
+ attach_filter(self.ins, filter)
+ self.ins.bind((iface, type))
+ _flush_fd(self.ins)
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
+ self.outs = self.ins
+ self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
+ sa_ll = self.outs.getsockname()
+ if sa_ll[3] in conf.l2types:
+ self.LL = conf.l2types[sa_ll[3]]
+ elif sa_ll[1] in conf.l3types:
+ self.LL = conf.l3types[sa_ll[1]]
+ else:
+ self.LL = conf.default_l2
+ warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],self.LL.name))
+
+ def recv(self, x=MTU):
+ pkt, sa_ll = self.ins.recvfrom(x)
+ if sa_ll[2] == socket.PACKET_OUTGOING:
+ return None
+ try:
+ q = self.LL(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ q = conf.raw_layer(pkt)
+ q.time = get_last_packet_timestamp(self.ins)
+ return q
+
+
+class L2ListenSocket(SuperSocket):
+ desc = "read packets at layer 2 using Linux PF_PACKET sockets"
+ def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
+ self.type = type
+ self.outs = None
+ self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
+ if iface is not None:
+ self.ins.bind((iface, type))
+ if not nofilter:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if filter is not None:
+ attach_filter(self.ins, filter)
+ if promisc is None:
+ promisc = conf.sniff_promisc
+ self.promisc = promisc
+ if iface is None:
+ self.iff = get_if_list()
+ else:
+ if iface.__class__ is list:
+ self.iff = iface
+ else:
+ self.iff = [iface]
+ if self.promisc:
+ for i in self.iff:
+ set_promisc(self.ins, i)
+ _flush_fd(self.ins)
+ self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
+ def close(self):
+ if self.promisc:
+ for i in self.iff:
+ set_promisc(self.ins, i, 0)
+ SuperSocket.close(self)
+
+ def recv(self, x=MTU):
+ pkt, sa_ll = self.ins.recvfrom(x)
+ if sa_ll[3] in conf.l2types :
+ cls = conf.l2types[sa_ll[3]]
+ elif sa_ll[1] in conf.l3types:
+ cls = conf.l3types[sa_ll[1]]
+ else:
+ cls = conf.default_l2
+ warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ pkt.time = get_last_packet_timestamp(self.ins)
+ return pkt
+
+ def send(self, x):
+ raise Scapy_Exception("Can't send anything with L2ListenSocket")
+
+
+conf.L3socket = L3PacketSocket
+conf.L2socket = L2Socket
+conf.L2listen = L2ListenSocket
+
+conf.iface = get_working_if()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/pcapdnet.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/pcapdnet.py
new file mode 100644
index 00000000..a2e8aa59
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/pcapdnet.py
@@ -0,0 +1,565 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Packet sending and receiving with libdnet and libpcap/WinPcap.
+"""
+
+import time,struct,sys,socket
+if not sys.platform.startswith("win"):
+ from fcntl import ioctl
+from scapy.data import *
+from scapy.config import conf
+from scapy.utils import warning
+from scapy.supersocket import SuperSocket
+from scapy.error import Scapy_Exception
+import scapy.arch
+
+if conf.use_dnet:
+ try:
+ from .cdnet import *
+ except OSError as e:
+ if conf.interactive:
+ log_loading.error("Unable to import libdnet library: %s" % e)
+ conf.use_dnet = False
+ else:
+ raise
+
+if conf.use_winpcapy:
+ try:
+ from .winpcapy import *
+ def winpcapy_get_if_list():
+ err = create_string_buffer(PCAP_ERRBUF_SIZE)
+ devs = POINTER(pcap_if_t)()
+ ret = []
+ if pcap_findalldevs(byref(devs), err) < 0:
+ return ret
+ try:
+ p = devs
+ while p:
+ ret.append(p.contents.name.decode('ascii'))
+ p = p.contents.next
+ return ret
+ finally:
+ pcap_freealldevs(devs)
+
+ except OSError as e:
+ if conf.interactive:
+ log_loading.error("Unable to import libpcap library: %s" % e)
+ conf.use_winpcapy = False
+ else:
+ raise
+
+ # From BSD net/bpf.h
+ #BIOCIMMEDIATE=0x80044270
+ BIOCIMMEDIATE=-2147204496
+
+ class PcapTimeoutElapsed(Scapy_Exception):
+ pass
+
+if conf.use_netifaces:
+ try:
+ import netifaces
+ except ImportError as e:
+ log_loading.warning("Could not load module netifaces: %s" % e)
+ conf.use_netifaces = False
+
+if conf.use_netifaces:
+ def get_if_raw_hwaddr(iff):
+ if iff == scapy.arch.LOOPBACK_NAME:
+ return (772, '\x00'*6)
+ try:
+ s = netifaces.ifaddresses(iff)[netifaces.AF_LINK][0]['addr']
+ return struct.pack('BBBBBB', *[ int(i, 16) for i in s.split(':') ])
+ except:
+ raise Scapy_Exception("Error in attempting to get hw address for interface [%s]" % iff)
+ return l
+ def get_if_raw_addr(ifname):
+ try:
+ s = netifaces.ifaddresses(ifname)[netifaces.AF_INET][0]['addr']
+ return socket.inet_aton(s)
+ except Exception as e:
+ return None
+ def get_if_list():
+ #return [ i[1] for i in socket.if_nameindex() ]
+ return netifaces.interfaces()
+ def in6_getifaddr():
+ """
+ Returns a list of 3-tuples of the form (addr, scope, iface) where
+ 'addr' is the address of scope 'scope' associated to the interface
+ 'ifcace'.
+
+ This is the list of all addresses of all interfaces available on
+ the system.
+ """
+
+ ret = []
+ interfaces = get_if_list()
+ for i in interfaces:
+ addrs = netifaces.ifaddresses(i)
+ if netifaces.AF_INET6 not in addrs:
+ continue
+ for a in addrs[netifaces.AF_INET6]:
+ addr = a['addr'].split('%')[0]
+ scope = scapy.utils6.in6_getscope(addr)
+ ret.append((addr, scope, i))
+ return ret
+elif conf.use_winpcapy:
+ def get_if_raw_hwaddr(iff):
+ err = create_string_buffer(PCAP_ERRBUF_SIZE)
+ devs = POINTER(pcap_if_t)()
+ ret = b"\0\0\0\0\0\0"
+ if pcap_findalldevs(byref(devs), err) < 0:
+ return ret
+ try:
+ p = devs
+ while p:
+ if p.contents.name.endswith(iff.encode('ascii')):
+ a = p.contents.addresses
+ while a:
+ if hasattr(socket, 'AF_LINK') and a.contents.addr.contents.sa_family == socket.AF_LINK:
+ ap = a.contents.addr
+ val = cast(ap, POINTER(sockaddr_dl))
+ ret = bytes(val.contents.sdl_data[ val.contents.sdl_nlen : val.contents.sdl_nlen + val.contents.sdl_alen ])
+ a = a.contents.next
+ break
+ p = p.contents.next
+ return ret
+ finally:
+ pcap_freealldevs(devs)
+ def get_if_raw_addr(iff):
+ err = create_string_buffer(PCAP_ERRBUF_SIZE)
+ devs = POINTER(pcap_if_t)()
+ ret = b"\0\0\0\0"
+ if pcap_findalldevs(byref(devs), err) < 0:
+ return ret
+ try:
+ p = devs
+ while p:
+ if p.contents.name.endswith(iff.encode('ascii')):
+ a = p.contents.addresses
+ while a:
+ if a.contents.addr.contents.sa_family == socket.AF_INET:
+ ap = a.contents.addr
+ val = cast(ap, POINTER(sockaddr_in))
+ ret = bytes(val.contents.sin_addr[:4])
+ a = a.contents.next
+ break
+ p = p.contents.next
+ return ret
+ finally:
+ pcap_freealldevs(devs)
+ get_if_list = winpcapy_get_if_list
+ def in6_getifaddr():
+ err = create_string_buffer(PCAP_ERRBUF_SIZE)
+ devs = POINTER(pcap_if_t)()
+ ret = []
+ if pcap_findalldevs(byref(devs), err) < 0:
+ return ret
+ try:
+ p = devs
+ ret = []
+ while p:
+ a = p.contents.addresses
+ while a:
+ 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, bytes(val.contents.sin6_addr[:]))
+ scope = scapy.utils6.in6_getscope(addr)
+ ret.append((addr, scope, p.contents.name.decode('ascii')))
+ a = a.contents.next
+ p = p.contents.next
+ return ret
+ finally:
+ pcap_freealldevs(devs)
+
+elif conf.use_dnet:
+ intf = dnet_intf()
+ def get_if_raw_hwaddr(iff):
+ return intf.get(iff)['link_addr']
+ def get_if_raw_addr(iff):
+ return intf.get(iff)['addr']
+ def get_if_list():
+ return intf.names
+ def in6_getifaddr():
+ ret = []
+ for i in get_if_list():
+ for a in intf.get(i)['addr6']:
+ addr = socket.inet_ntop(socket.AF_INET6, a)
+ scope = scapy.utils6.in6_getscope(addr)
+ ret.append((addr, scope, i))
+ return ret
+
+else:
+ log_loading.warning("No known method to get ip and hw address for interfaces")
+ def get_if_raw_hwaddr(iff):
+ "dummy"
+ return b"\0\0\0\0\0\0"
+ def get_if_raw_addr(iff):
+ "dummy"
+ return b"\0\0\0\0"
+ def get_if_list():
+ "dummy"
+ return []
+ def in6_getifaddr():
+ return []
+
+if conf.use_winpcapy:
+ from ctypes import POINTER, byref, create_string_buffer
+ class _PcapWrapper_pypcap:
+ def __init__(self, device, snaplen, promisc, to_ms):
+ self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
+ self.iface = create_string_buffer(device.encode('ascii'))
+ self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms, self.errbuf)
+ self.header = POINTER(pcap_pkthdr)()
+ self.pkt_data = POINTER(c_ubyte)()
+ self.bpf_program = bpf_program()
+ def next(self):
+ c = pcap_next_ex(self.pcap, byref(self.header), byref(self.pkt_data))
+ if not c > 0:
+ return
+ ts = self.header.contents.ts.tv_sec
+ #pkt = "".join([ chr(i) for i in self.pkt_data[:self.header.contents.len] ])
+ pkt = bytes(self.pkt_data[:self.header.contents.len])
+ return ts, pkt
+ def datalink(self):
+ return pcap_datalink(self.pcap)
+ def fileno(self):
+ if sys.platform.startswith("win"):
+ error("Cannot get selectable PCAP fd on Windows")
+ return 0
+ return pcap_get_selectable_fd(self.pcap)
+ def setfilter(self, f):
+ filter_exp = create_string_buffer(f.encode('ascii'))
+ if pcap_compile(self.pcap, byref(self.bpf_program), filter_exp, 0, -1) == -1:
+ error("Could not compile filter expression %s" % f)
+ return False
+ else:
+ if pcap_setfilter(self.pcap, byref(self.bpf_program)) == -1:
+ error("Could not install filter %s" % f)
+ return False
+ return True
+ def setnonblock(self, i):
+ pcap_setnonblock(self.pcap, i, self.errbuf)
+ def send(self, x):
+ pcap_sendpacket(self.pcap, x, len(x))
+ def close(self):
+ pcap_close(self.pcap)
+ open_pcap = lambda *args,**kargs: _PcapWrapper_pypcap(*args,**kargs)
+ class PcapTimeoutElapsed(Scapy_Exception):
+ pass
+
+ class L2pcapListenSocket(SuperSocket):
+ desc = "read packets at layer 2 using libpcap"
+ def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None):
+ self.type = type
+ self.outs = None
+ self.iface = iface
+ if iface is None:
+ iface = conf.iface
+ if promisc is None:
+ promisc = conf.sniff_promisc
+ self.promisc = promisc
+ self.ins = open_pcap(iface, 1600, self.promisc, 100)
+ try:
+ ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
+ except:
+ pass
+ if type == ETH_P_ALL: # Do not apply any filter if Ethernet type is given
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if filter:
+ self.ins.setfilter(filter)
+
+ def close(self):
+ self.ins.close()
+
+ def recv(self, x=MTU):
+ 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))
+
+ pkt = None
+ while pkt is None:
+ pkt = self.ins.next()
+ if pkt is not None:
+ ts,pkt = pkt
+ if scapy.arch.WINDOWS and pkt is None:
+ raise PcapTimeoutElapsed
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ pkt.time = ts
+ return pkt
+
+ def send(self, x):
+ raise Scapy_Exception("Can't send anything with L2pcapListenSocket")
+
+
+ conf.L2listen = L2pcapListenSocket
+ class L2pcapSocket(SuperSocket):
+ desc = "read/write packets at layer 2 using only libpcap"
+ def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+ if iface is None:
+ iface = conf.iface
+ self.iface = iface
+ self.ins = open_pcap(iface, 1600, 0, 100)
+ try:
+ ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
+ except:
+ pass
+ if nofilter:
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ filter = "ether proto %i" % type
+ else:
+ filter = None
+ else:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ if filter:
+ filter = "(ether proto %i) and (%s)" % (type,filter)
+ else:
+ filter = "ether proto %i" % type
+ if filter:
+ self.ins.setfilter(filter)
+ def send(self, x):
+ sx = bytes(x)
+ if hasattr(x, "sent_time"):
+ x.sent_time = time.time()
+ return self.ins.send(sx)
+
+ def recv(self,x=MTU):
+ 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))
+
+ pkt = self.ins.next()
+ if pkt is not None:
+ ts,pkt = pkt
+ if pkt is None:
+ return
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ pkt.time = ts
+ return pkt
+
+ def nonblock_recv(self):
+ self.ins.setnonblock(1)
+ p = self.recv(MTU)
+ self.ins.setnonblock(0)
+ return p
+
+ def close(self):
+ if hasattr(self, "ins"):
+ self.ins.close()
+ if hasattr(self, "outs"):
+ self.outs.close()
+
+ class L3pcapSocket(L2pcapSocket):
+ #def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+ # L2pcapSocket.__init__(self, iface, type, filter, nofilter)
+ def recv(self, x = MTU):
+ r = L2pcapSocket.recv(self, x)
+ if r:
+ return r.payload
+ else:
+ return
+ def send(self, x):
+ cls = conf.l2types[1]
+ sx = bytes(cls()/x)
+ if hasattr(x, "sent_time"):
+ x.sent_time = time.time()
+ return self.ins.send(sx)
+ conf.L2socket=L2pcapSocket
+ conf.L3socket=L3pcapSocket
+
+if conf.use_winpcapy and conf.use_dnet:
+ class L3dnetSocket(SuperSocket):
+ desc = "read/write packets at layer 3 using libdnet and libpcap"
+ def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
+ self.iflist = {}
+ self.intf = dnet_intf()
+ if iface is None:
+ iface = conf.iface
+ self.iface = iface
+ self.ins = open_pcap(iface, 1600, 0, 100)
+ try:
+ ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
+ except:
+ pass
+ if nofilter:
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ filter = "ether proto %i" % type
+ else:
+ filter = None
+ else:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ if filter:
+ filter = "(ether proto %i) and (%s)" % (type,filter)
+ else:
+ filter = "ether proto %i" % type
+ if filter:
+ self.ins.setfilter(filter)
+ def send(self, x):
+ iff,a,gw = x.route()
+ if iff is None:
+ iff = conf.iface
+ ifs,cls = self.iflist.get(iff,(None,None))
+ if ifs is None:
+ iftype = self.intf.get(iff)["type"]
+ if iftype == INTF_TYPE_ETH:
+ try:
+ cls = conf.l2types[1]
+ except KeyError:
+ warning("Unable to find Ethernet class. Using nothing")
+ ifs = dnet_eth(iff)
+ else:
+ ifs = dnet_ip()
+ self.iflist[iff] = ifs,cls
+ if cls is None:
+ #sx = str(x)
+ sx = bytes(x)
+ else:
+ sx = bytes(cls()/x)
+ x.sent_time = time.time()
+ ifs.send(sx)
+ def recv(self,x=MTU):
+ 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))
+
+ pkt = self.ins.next()
+ if pkt is not None:
+ ts,pkt = pkt
+ if pkt is None:
+ return
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ pkt.time = ts
+ return pkt.payload
+
+ def nonblock_recv(self):
+ self.ins.setnonblock(1)
+ p = self.recv()
+ self.ins.setnonblock(0)
+ return p
+
+ def close(self):
+ if hasattr(self, "ins"):
+ self.ins.close()
+ if hasattr(self, "outs"):
+ self.outs.close()
+
+ class L2dnetSocket(SuperSocket):
+ desc = "read/write packets at layer 2 using libdnet and libpcap"
+ def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+ if iface is None:
+ iface = conf.iface
+ self.iface = iface
+ self.ins = open_pcap(iface, 1600, 0, 100)
+ try:
+ ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
+ except:
+ pass
+ if nofilter:
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ filter = "ether proto %i" % type
+ else:
+ filter = None
+ else:
+ if conf.except_filter:
+ if filter:
+ filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+ else:
+ filter = "not (%s)" % conf.except_filter
+ if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
+ if filter:
+ filter = "(ether proto %i) and (%s)" % (type,filter)
+ else:
+ filter = "ether proto %i" % type
+ if filter:
+ self.ins.setfilter(filter)
+ self.outs = dnet_eth(iface)
+ def recv(self,x=MTU):
+ 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))
+
+ pkt = self.ins.next()
+ if pkt is not None:
+ ts,pkt = pkt
+ if pkt is None:
+ return
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ pkt.time = ts
+ return pkt
+
+ def nonblock_recv(self):
+ self.ins.setnonblock(1)
+ p = self.recv(MTU)
+ self.ins.setnonblock(0)
+ return p
+
+ def close(self):
+ if hasattr(self, "ins"):
+ self.ins.close()
+ if hasattr(self, "outs"):
+ self.outs.close()
+
+ conf.L3socket=L3dnetSocket
+ conf.L2socket=L2dnetSocket
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/solaris.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/solaris.py
new file mode 100644
index 00000000..3117076a
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/solaris.py
@@ -0,0 +1,16 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Customization for the Solaris operation system.
+"""
+
+# IPPROTO_GRE is missing on Solaris
+import socket
+socket.IPPROTO_GRE = 47
+
+LOOPBACK_NAME="lo0"
+
+from unix import *
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/unix.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/unix.py
new file mode 100644
index 00000000..43e694b5
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/unix.py
@@ -0,0 +1,168 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Common customizations for all Unix-like operating systems other than Linux
+"""
+
+import sys,os,struct,socket,time
+from subprocess import check_output
+from fcntl import ioctl
+from scapy.error import warning
+import scapy.config
+import scapy.utils
+import scapy.utils6
+import scapy.arch
+
+scapy.config.conf.use_winpcapy = True
+scapy.config.conf.use_netifaces = True
+scapy.config.conf.use_dnet = True
+from .pcapdnet import *
+
+
+
+##################
+## Routes stuff ##
+##################
+
+
+def read_routes():
+ if scapy.arch.SOLARIS:
+ f=check_output(["netstat", "-rvn"], universal_newlines = True) # -f inet
+ elif scapy.arch.FREEBSD:
+ f=check_output(["netstat", "-rnW"], universal_newlines = True) # -W to handle long interface names
+ else:
+ f=check_output(["netstat", "-rn"], universal_newlines = True) # -f inet
+ ok = False
+ routes = []
+ pending_if = []
+ for l in f.split('\n'):
+ l = l.strip()
+ if l.find("----") >= 0: # a separation line
+ continue
+ if not ok:
+ if_index = [ l.split().index(i) for i in ['Iface', 'Netif', 'Interface', 'Device'] if i in l.split()]
+ if if_index:
+ ok = True
+ if_index = if_index[0]
+ continue
+ if not l:
+ break
+ if scapy.arch.SOLARIS:
+ lspl = l.split()
+ if len(lspl) == 10:
+ dest,mask,gw,netif,mxfrg,rtt,ref,flg = lspl[:8]
+ else: # missing interface
+ dest,mask,gw,mxfrg,rtt,ref,flg = lspl[:7]
+ netif=None
+ else:
+ rt = l.split()
+ dest,gw,flg = rt[:3]
+ netif = rt[if_index]
+ if flg.find("Lc") >= 0:
+ continue
+ if dest == "default":
+ dest = 0
+ netmask = 0
+ else:
+ if scapy.arch.SOLARIS:
+ netmask = scapy.utils.atol(mask)
+ elif "/" in dest:
+ dest,netmask = dest.split("/")
+ netmask = scapy.utils.itom(int(netmask))
+ else:
+ netmask = scapy.utils.itom((dest.count(".") + 1) * 8)
+ dest += ".0"*(3-dest.count("."))
+ dest = scapy.utils.atol(dest)
+ if not "G" in flg:
+ gw = '0.0.0.0'
+ if netif is not None:
+ ifaddr = scapy.arch.get_if_addr(netif)
+ routes.append((dest,netmask,gw,netif,ifaddr))
+ else:
+ pending_if.append((dest,netmask,gw))
+
+ # On Solaris, netstat does not provide output interfaces for some routes
+ # We need to parse completely the routing table to route their gw and
+ # know their output interface
+ for dest,netmask,gw in pending_if:
+ gw_l = scapy.utils.atol(gw)
+ max_rtmask,gw_if,gw_if_addr, = 0,None,None
+ for rtdst,rtmask,_,rtif,rtaddr in routes[:]:
+ if gw_l & rtmask == rtdst:
+ if rtmask >= max_rtmask:
+ max_rtmask = rtmask
+ gw_if = rtif
+ gw_if_addr = rtaddr
+ if gw_if:
+ routes.append((dest,netmask,gw,gw_if,gw_if_addr))
+ else:
+ warning("Did not find output interface to reach gateway %s" % gw)
+
+ return routes
+
+############
+### IPv6 ###
+############
+
+def read_routes6():
+ f = os.popen("netstat -rn -f inet6")
+ ok = False
+ mtu_present = False
+ prio_present = False
+ routes = []
+ lifaddr = in6_getifaddr()
+ for l in f.readlines():
+ if not l:
+ break
+ l = l.strip()
+ if not ok:
+ if l.find("Destination") >= 0:
+ ok = 1
+ mtu_present = l.find("Mtu") >= 0
+ prio_present = l.find("Prio") >= 0
+ continue
+ # gv 12/12/06: under debugging
+ if scapy.arch.NETBSD or scapy.arch.OPENBSD:
+ lspl = l.split()
+ d,nh,fl = lspl[:3]
+ dev = lspl[5+mtu_present+prio_present]
+ expire = None
+ else: # FREEBSD or DARWIN
+ d,nh,fl,dev = l.split()[:4]
+ if [ x for x in lifaddr if x[2] == dev] == []:
+ continue
+ if 'L' in fl: # drop MAC addresses
+ continue
+
+ if 'link' in nh:
+ nh = '::'
+
+ cset = [] # candidate set (possible source addresses)
+ dp = 128
+ if d == 'default':
+ d = '::'
+ dp = 0
+ if '/' in d:
+ d,dp = d.split("/")
+ dp = int(dp)
+ if '%' in d:
+ d,dev = d.split('%')
+ if '%' in nh:
+ nh,dev = nh.split('%')
+ if scapy.arch.LOOPBACK_NAME in dev:
+ if d == '::' and dp == 96: #Do not use ::/96 deprecated IPV4 mapping address
+ continue
+ cset = ['::1']
+ nh = '::'
+ else:
+ devaddrs = [ x for x in lifaddr if x[2] == dev ]
+ cset = scapy.utils6.construct_source_candidate_set(d, dp, devaddrs, scapy.arch.LOOPBACK_NAME)
+
+ if len(cset) != 0:
+ routes.append((d, dp, nh, dev, cset))
+
+ f.close()
+ return routes
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/windows/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/windows/__init__.py
new file mode 100644
index 00000000..3bd1ade3
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/windows/__init__.py
@@ -0,0 +1,501 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Customizations needed to support Microsoft Windows.
+"""
+
+import os,re,sys,socket,time, itertools
+import subprocess as sp
+from glob import glob
+from scapy.config import conf,ConfClass
+from scapy.error import Scapy_Exception,log_loading,log_runtime
+from scapy.utils import atol, itom, inet_aton, inet_ntoa, PcapReader
+from scapy.base_classes import Gen, Net, SetGen
+import scapy.plist as plist
+from scapy.sendrecv import debug, srp1
+from scapy.layers.l2 import Ether, ARP
+from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP
+
+conf.use_winpcapy = True
+from scapy.arch import pcapdnet
+from scapy.arch.pcapdnet import *
+
+LOOPBACK_NAME="lo0"
+WINDOWS = True
+
+
+def _where(filename, dirs=[], env="PATH"):
+ """Find file in current dir or system path"""
+ if not isinstance(dirs, list):
+ dirs = [dirs]
+ if glob(filename):
+ return filename
+ paths = [os.curdir] + os.environ[env].split(os.path.pathsep) + dirs
+ for path in paths:
+ for match in glob(os.path.join(path, filename)):
+ if match:
+ return os.path.normpath(match)
+ raise IOError("File not found: %s" % filename)
+
+def win_find_exe(filename, installsubdir=None, env="ProgramFiles"):
+ """Find executable in current dir, system path or given ProgramFiles subdir"""
+ for fn in [filename, filename+".exe"]:
+ try:
+ if installsubdir is None:
+ path = _where(fn)
+ else:
+ path = _where(fn, dirs=[os.path.join(os.environ[env], installsubdir)])
+ except IOError:
+ path = filename
+ else:
+ break
+ return path
+
+
+class WinProgPath(ConfClass):
+ _default = "<System default>"
+ # We try some magic to find the appropriate executables
+ pdfreader = win_find_exe("AcroRd32")
+ psreader = win_find_exe("gsview32.exe", "Ghostgum/gsview")
+ dot = win_find_exe("dot", "ATT/Graphviz/bin")
+ tcpdump = win_find_exe("windump")
+ tcpreplay = win_find_exe("tcpreplay")
+ display = _default
+ hexedit = win_find_exe("hexer")
+ wireshark = win_find_exe("wireshark", "wireshark")
+
+conf.prog = WinProgPath()
+
+class PcapNameNotFoundError(Scapy_Exception):
+ pass
+
+def get_windows_if_list():
+ ps = sp.Popen(['powershell', 'Get-NetAdapter', '|', 'select Name, InterfaceIndex, InterfaceDescription, InterfaceGuid, MacAddress', '|', 'fl'], stdout = sp.PIPE)
+ stdout, stdin = ps.communicate(timeout = 10)
+ current_interface = None
+ interface_list = []
+ for i in stdout.split(b'\r\n'):
+ if not i.strip():
+ continue
+ if i.find(b':')<0:
+ continue
+ name, value = [ j.strip() for j in i.split(b':') ]
+ if name == b'Name':
+ if current_interface:
+ interface_list.append(current_interface)
+ current_interface = {}
+ current_interface['name'] = value.decode('ascii')
+ elif name == b'InterfaceIndex':
+ current_interface['win_index'] = int(value)
+ elif name == b'InterfaceDescription':
+ current_interface['description'] = value.decode('ascii')
+ elif name == b'InterfaceGuid':
+ current_interface['guid'] = value.decode('ascii')
+ elif name == b'MacAddress':
+ current_interface['mac'] = ':'.join([ j.decode('ascii') for j in value.split(b'-')])
+ if current_interface:
+ interface_list.append(current_interface)
+ return interface_list
+
+class NetworkInterface(object):
+ """A network interface of your local host"""
+
+ def __init__(self, data=None):
+ self.name = None
+ self.ip = None
+ self.mac = None
+ self.pcap_name = None
+ self.description = None
+ self.data = data
+ if data is not None:
+ self.update(data)
+
+ def update(self, data):
+ """Update info about network interface according to given dnet dictionary"""
+ self.name = data["name"]
+ self.description = data['description']
+ self.win_index = data['win_index']
+ # Other attributes are optional
+ self._update_pcapdata()
+ try:
+ self.ip = socket.inet_ntoa(get_if_raw_addr(data['guid']))
+ except (KeyError, AttributeError, NameError):
+ pass
+ try:
+ self.mac = data['mac']
+ except KeyError:
+ pass
+
+ def _update_pcapdata(self):
+ for i in winpcapy_get_if_list():
+ if i.endswith(self.data['guid']):
+ self.pcap_name = i
+ return
+
+ raise PcapNameNotFoundError
+
+ def __repr__(self):
+ return "<%s: %s %s %s pcap_name=%s description=%s>" % (self.__class__.__name__,
+ self.name, self.ip, self.mac, self.pcap_name, self.description)
+
+from collections import UserDict
+
+class NetworkInterfaceDict(UserDict):
+ """Store information about network interfaces and convert between names"""
+ def load_from_powershell(self):
+ for i in get_windows_if_list():
+ try:
+ interface = NetworkInterface(i)
+ self.data[interface.name] = interface
+ except (KeyError, PcapNameNotFoundError):
+ pass
+ if len(self.data) == 0:
+ log_loading.warning("No match between your pcap and windows network interfaces found. "
+ "You probably won't be able to send packets. "
+ "Deactivating unneeded interfaces and restarting Scapy might help."
+ "Check your winpcap and powershell installation, and access rights.")
+
+ def pcap_name(self, devname):
+ """Return pcap device name for given Windows device name."""
+
+ try:
+ pcap_name = self.data[devname].pcap_name
+ except KeyError:
+ raise ValueError("Unknown network interface %r" % devname)
+ else:
+ return pcap_name
+
+ def devname(self, pcap_name):
+ """Return Windows device name for given pcap device name."""
+
+ for devname, iface in self.items():
+ if iface.pcap_name == pcap_name:
+ return iface.name
+ raise ValueError("Unknown pypcap network interface %r" % pcap_name)
+
+ def devname_from_index(self, if_index):
+ """Return interface name from interface index"""
+ for devname, iface in self.items():
+ if iface.win_index == if_index:
+ return iface.name
+ raise ValueError("Unknown network interface index %r" % if_index)
+
+ def show(self, resolve_mac=True):
+ """Print list of available network interfaces in human readable form"""
+
+ print("%s %s %s %s" % ("INDEX".ljust(5), "IFACE".ljust(35), "IP".ljust(15), "MAC"))
+ for iface_name in sorted(self.data.keys()):
+ dev = self.data[iface_name]
+ mac = dev.mac
+ if resolve_mac:
+ mac = conf.manufdb._resolve_MAC(mac)
+ print("%s %s %s %s" % (str(dev.win_index).ljust(5), str(dev.name).ljust(35), str(dev.ip).ljust(15), mac) )
+
+ifaces = NetworkInterfaceDict()
+ifaces.load_from_powershell()
+
+def pcap_name(devname):
+ """Return pypcap device name for given libdnet/Scapy device name"""
+ try:
+ pcap_name = ifaces.pcap_name(devname)
+ except ValueError:
+ # pcap.pcap() will choose a sensible default for sniffing if iface=None
+ pcap_name = None
+ return pcap_name
+
+def devname(pcap_name):
+ """Return libdnet/Scapy device name for given pypcap device name"""
+ return ifaces.devname(pcap_name)
+
+def devname_from_index(if_index):
+ """Return Windows adapter name for given Windows interface index"""
+ return ifaces.devname_from_index(if_index)
+
+def show_interfaces(resolve_mac=True):
+ """Print list of available network interfaces"""
+ return ifaces.show(resolve_mac)
+
+_orig_open_pcap = pcapdnet.open_pcap
+pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcap_name(iface),*args,**kargs)
+
+_orig_get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr
+pcapdnet.get_if_raw_hwaddr = lambda iface,*args,**kargs: [ int(i, 16) for i in ifaces[iface].mac.split(':') ]
+get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr
+
+def read_routes():
+ routes = []
+ if_index = '(\d+)'
+ dest = '(\d+\.\d+\.\d+\.\d+)/(\d+)'
+ next_hop = '(\d+\.\d+\.\d+\.\d+)'
+ metric_pattern = "(\d+)"
+ delim = "\s+" # The columns are separated by whitespace
+ netstat_line = delim.join([if_index, dest, next_hop, metric_pattern])
+ pattern = re.compile(netstat_line)
+ ps = sp.Popen(['powershell', 'Get-NetRoute', '-AddressFamily IPV4', '|', 'select ifIndex, DestinationPrefix, NextHop, RouteMetric'], stdout = sp.PIPE)
+ stdout, stdin = ps.communicate(timeout = 10)
+ for l in stdout.split(b'\r\n'):
+ match = re.search(pattern,l.decode('utf-8'))
+ if match:
+ try:
+ iface = devname_from_index(int(match.group(1)))
+ addr = ifaces[iface].ip
+ except:
+ continue
+ dest = atol(match.group(2))
+ mask = itom(int(match.group(3)))
+ gw = match.group(4)
+ # try:
+ # intf = pcapdnet.dnet.intf().get_dst(pcapdnet.dnet.addr(type=2, addrtxt=dest))
+ # except OSError:
+ # log_loading.warning("Building Scapy's routing table: Couldn't get outgoing interface for destination %s" % dest)
+ # continue
+ routes.append((dest, mask, gw, iface, addr))
+ return routes
+
+def read_routes6():
+ return []
+
+try:
+ __IPYTHON__
+except NameError:
+ try:
+ import readline
+ console = readline.GetOutputFile()
+ except (ImportError, AttributeError):
+ log_loading.info("Could not get readline console. Will not interpret ANSI color codes.")
+ else:
+ conf.readfunc = readline.rl.readline
+ orig_stdout = sys.stdout
+ sys.stdout = console
+
+def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
+ if not isinstance(pkt, Gen):
+ pkt = SetGen(pkt)
+
+ if verbose is None:
+ verbose = conf.verb
+ debug.recv = plist.PacketList([],"Unanswered")
+ debug.sent = plist.PacketList([],"Sent")
+ debug.match = plist.SndRcvList([])
+ nbrecv=0
+ ans = []
+ # do it here to fix random fields, so that parent and child have the same
+ all_stimuli = tobesent = [p for p in pkt]
+ notans = len(tobesent)
+
+ hsent={}
+ for i in tobesent:
+ h = i.hashret()
+ if h in hsent:
+ hsent[h].append(i)
+ else:
+ hsent[h] = [i]
+ if retry < 0:
+ retry = -retry
+ autostop=retry
+ else:
+ autostop=0
+
+
+ while retry >= 0:
+ found=0
+
+ if timeout < 0:
+ timeout = None
+
+ pid=1
+ try:
+ if WINDOWS or pid == 0:
+ try:
+ try:
+ i = 0
+ if verbose:
+ print("Begin emission:")
+ for p in tobesent:
+ pks.send(p)
+ i += 1
+ time.sleep(inter)
+ if verbose:
+ print("Finished to send %i packets." % i)
+ except SystemExit:
+ pass
+ except KeyboardInterrupt:
+ pass
+ except:
+ log_runtime.exception("--- Error sending packets")
+ log_runtime.info("--- Error sending packets")
+ finally:
+ try:
+ sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
+ except:
+ pass
+ if WINDOWS or pid > 0:
+ # Timeout starts after last packet is sent (as in Unix version)
+ if timeout:
+ stoptime = time.time()+timeout
+ else:
+ stoptime = 0
+ remaintime = None
+ # inmask = [pks.ins.fd]
+ try:
+ try:
+ while 1:
+ if stoptime:
+ remaintime = stoptime-time.time()
+ if remaintime <= 0:
+ break
+ r = pks.recv(MTU)
+ if r is None:
+ continue
+ ok = 0
+ h = r.hashret()
+ if h in hsent:
+ hlst = hsent[h]
+ for i in range(len(hlst)):
+ if r.answers(hlst[i]):
+ ans.append((hlst[i],r))
+ if verbose > 1:
+ os.write(1, b"*")
+ ok = 1
+ if not multi:
+ del(hlst[i])
+ notans -= 1;
+ else:
+ if not hasattr(hlst[i], '_answered'):
+ notans -= 1;
+ hlst[i]._answered = 1;
+ break
+ if notans == 0 and not multi:
+ break
+ if not ok:
+ if verbose > 1:
+ os.write(1, b".")
+ nbrecv += 1
+ if conf.debug_match:
+ debug.recv.append(r)
+ except KeyboardInterrupt:
+ if chainCC:
+ raise
+ finally:
+ if WINDOWS:
+ for p,t in zip(all_stimuli, sent_times):
+ p.sent_time = t
+ finally:
+ pass
+
+ # remain = reduce(list.__add__, hsent.values(), [])
+ remain = list(itertools.chain(*[ i for i in hsent.values() ]))
+
+ if multi:
+ #remain = filter(lambda p: not hasattr(p, '_answered'), remain);
+ remain = [ p for p in remain if not hasattr(p, '_answered')]
+
+ if autostop and len(remain) > 0 and len(remain) != len(tobesent):
+ retry = autostop
+
+ tobesent = remain
+ if len(tobesent) == 0:
+ break
+ retry -= 1
+
+ if conf.debug_match:
+ debug.sent=plist.PacketList(remain[:],"Sent")
+ debug.match=plist.SndRcvList(ans[:])
+
+ #clean the ans list to delete the field _answered
+ if (multi):
+ for s,r in ans:
+ if hasattr(s, '_answered'):
+ del(s._answered)
+
+ if verbose:
+ print("\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans))
+ return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
+
+
+import scapy.sendrecv
+scapy.sendrecv.sndrcv = sndrcv
+
+def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
+ """Sniff packets
+sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
+Select interface to sniff by setting conf.iface. Use show_interfaces() to see interface names.
+ count: number of packets to capture. 0 means infinity
+ store: wether to store sniffed packets or discard them
+ prn: function to apply to each packet. If something is returned,
+ it is displayed. Ex:
+ ex: prn = lambda x: x.summary()
+lfilter: python function applied to each packet to determine
+ if further action may be done
+ ex: lfilter = lambda x: x.haslayer(Padding)
+offline: pcap file to read packets from, instead of sniffing them
+timeout: stop sniffing after a given time (default: None)
+L2socket: use the provided L2socket
+ """
+ c = 0
+
+ if offline is None:
+ log_runtime.info('Sniffing on %s' % conf.iface)
+ if L2socket is None:
+ L2socket = conf.L2listen
+ s = L2socket(type=ETH_P_ALL, *arg, **karg)
+ else:
+ s = PcapReader(offline)
+
+ lst = []
+ if timeout is not None:
+ stoptime = time.time()+timeout
+ remain = None
+ while 1:
+ try:
+ if timeout is not None:
+ remain = stoptime-time.time()
+ if remain <= 0:
+ break
+
+ try:
+ p = s.recv(MTU)
+ except PcapTimeoutElapsed:
+ continue
+ if p is None:
+ break
+ if lfilter and not lfilter(p):
+ continue
+ if store:
+ lst.append(p)
+ c += 1
+ if prn:
+ r = prn(p)
+ if r is not None:
+ print(r)
+ if count > 0 and c >= count:
+ break
+ except KeyboardInterrupt:
+ break
+ s.close()
+ return plist.PacketList(lst,"Sniffed")
+
+import scapy.sendrecv
+scapy.sendrecv.sniff = sniff
+
+# def get_if_list():
+# print('windows if_list')
+# return sorted(ifaces.keys())
+
+def get_working_if():
+ try:
+ if 'Ethernet' in ifaces and ifaces['Ethernet'].ip != '0.0.0.0':
+ return 'Ethernet'
+ elif 'Wi-Fi' in ifaces and ifaces['Wi-Fi'].ip != '0.0.0.0':
+ return 'Wi-Fi'
+ elif len(ifaces) > 0:
+ return ifaces[list(ifaces.keys())[0]]
+ else:
+ return LOOPBACK_NAME
+ except:
+ return LOOPBACK_NAME
+
+conf.iface = get_working_if()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/arch/winpcapy.py b/scripts/external_libs/scapy-python3-0.18/scapy/arch/winpcapy.py
new file mode 100644
index 00000000..fc452a02
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/arch/winpcapy.py
@@ -0,0 +1,739 @@
+#-------------------------------------------------------------------------------
+# Name: winpcapy.py
+#
+# Author: Massimo Ciani
+#
+# Created: 01/09/2009
+# Copyright: (c) Massimo Ciani 2009
+#
+#-------------------------------------------------------------------------------
+
+
+from ctypes import *
+from ctypes.util import find_library
+import sys
+
+WIN32=False
+HAVE_REMOTE=False
+
+
+if sys.platform.startswith('win'):
+ WIN32=True
+ HAVE_REMOTE=True
+
+if WIN32:
+ SOCKET = c_uint
+ _lib=CDLL('wpcap.dll')
+else:
+ SOCKET = c_int
+ _lib_name = find_library('pcap')
+ if not _lib_name:
+ raise OSError("Cannot fine libpcap.so library")
+ _lib=CDLL(_lib_name)
+
+
+
+##
+## misc
+##
+u_short = c_ushort
+bpf_int32 = c_int
+u_int = c_int
+bpf_u_int32 = u_int
+pcap = c_void_p
+pcap_dumper = c_void_p
+u_char = c_ubyte
+FILE = c_void_p
+STRING = c_char_p
+
+class bpf_insn(Structure):
+ _fields_=[("code",c_ushort),
+ ("jt",c_ubyte),
+ ("jf",c_ubyte),
+ ("k",bpf_u_int32)]
+
+class bpf_program(Structure):
+ pass
+bpf_program._fields_ = [('bf_len', u_int),
+ ('bf_insns', POINTER(bpf_insn))]
+
+class bpf_version(Structure):
+ _fields_=[("bv_major",c_ushort),
+ ("bv_minor",c_ushort)]
+
+
+class timeval(Structure):
+ pass
+timeval._fields_ = [('tv_sec', c_long),
+ ('tv_usec', c_long)]
+
+## sockaddr is used by pcap_addr.
+## For exapmle if sa_family==socket.AF_INET then we need cast
+## with sockaddr_in
+if WIN32:
+ class sockaddr(Structure):
+ _fields_ = [("sa_family", c_ushort),
+ ("sa_data",c_ubyte * 14)]
+
+ class sockaddr_in(Structure):
+ _fields_ = [("sin_family", c_ushort),
+ ("sin_port", c_uint16),
+ ("sin_addr", 4 * c_ubyte)]
+
+ class sockaddr_in6(Structure):
+ _fields_ = [("sin6_family", c_ushort),
+ ("sin6_port", c_uint16),
+ ("sin6_flowinfo", c_uint32),
+ ("sin6_addr", 16 * c_ubyte),
+ ("sin6_scope", c_uint32)]
+else:
+ class sockaddr(Structure):
+ _fields_ = [("sa_len", c_ubyte),
+ ("sa_family",c_ubyte),
+ ("sa_data",c_ubyte * 14)]
+
+ class sockaddr_in(Structure):
+ _fields_ = [("sin_len", c_ubyte),
+ ("sin_family", c_ubyte),
+ ("sin_port", c_uint16),
+ ("sin_addr", 4 * c_ubyte),
+ ("sin_zero", 8 * c_char)]
+
+ class sockaddr_in6(Structure):
+ _fields_ = [("sin6_len", c_ubyte),
+ ("sin6_family", c_ubyte),
+ ("sin6_port", c_uint16),
+ ("sin6_flowinfo", c_uint32),
+ ("sin6_addr", 16 * c_ubyte),
+ ("sin6_scope", c_uint32)]
+
+ class sockaddr_dl(Structure):
+ _fields_ = [("sdl_len", c_ubyte),
+ ("sdl_family", c_ubyte),
+ ("sdl_index", c_ushort),
+ ("sdl_type", c_ubyte),
+ ("sdl_nlen", c_ubyte),
+ ("sdl_alen", c_ubyte),
+ ("sdl_slen", c_ubyte),
+ ("sdl_data", 46 * c_ubyte)]
+##
+## END misc
+##
+
+##
+## Data Structures
+##
+
+## struct pcap_file_header
+## Header of a libpcap dump file.
+class pcap_file_header(Structure):
+ _fields_ = [('magic', bpf_u_int32),
+ ('version_major', u_short),
+ ('version_minor', u_short),
+ ('thiszone', bpf_int32),
+ ('sigfigs', bpf_u_int32),
+ ('snaplen', bpf_u_int32),
+ ('linktype', bpf_u_int32)]
+
+## struct pcap_pkthdr
+## Header of a packet in the dump file.
+class pcap_pkthdr(Structure):
+ _fields_ = [('ts', timeval),
+ ('caplen', bpf_u_int32),
+ ('len', bpf_u_int32)]
+
+## struct pcap_stat
+## Structure that keeps statistical values on an interface.
+class pcap_stat(Structure):
+ pass
+### _fields_ list in Structure is final.
+### We need a temp list
+_tmpList=[]
+_tmpList.append(("ps_recv",c_uint))
+_tmpList.append(("ps_drop",c_uint))
+_tmpList.append(("ps_ifdrop",c_uint))
+if HAVE_REMOTE:
+ _tmpList.append(("ps_capt",c_uint))
+ _tmpList.append(("ps_sent",c_uint))
+ _tmpList.append(("ps_netdrop",c_uint))
+pcap_stat._fields_=_tmpList
+
+## struct pcap_addr
+## Representation of an interface address, used by pcap_findalldevs().
+class pcap_addr(Structure):
+ pass
+pcap_addr._fields_ = [('next', POINTER(pcap_addr)),
+ ('addr', POINTER(sockaddr)),
+ ('netmask', POINTER(sockaddr)),
+ ('broadaddr', POINTER(sockaddr)),
+ ('dstaddr', POINTER(sockaddr))]
+
+## struct pcap_if
+## Item in a list of interfaces, used by pcap_findalldevs().
+class pcap_if(Structure):
+ pass
+pcap_if._fields_ = [('next', POINTER(pcap_if)),
+ ('name', STRING),
+ ('description', STRING),
+ ('addresses', POINTER(pcap_addr)),
+ ('flags', bpf_u_int32)]
+
+##
+## END Data Structures
+##
+
+##
+## Defines
+##
+
+##define PCAP_VERSION_MAJOR 2
+# Major libpcap dump file version.
+PCAP_VERSION_MAJOR = 2
+##define PCAP_VERSION_MINOR 4
+# Minor libpcap dump file version.
+PCAP_VERSION_MINOR = 4
+##define PCAP_ERRBUF_SIZE 256
+# Size to use when allocating the buffer that contains the libpcap errors.
+PCAP_ERRBUF_SIZE = 256
+##define PCAP_IF_LOOPBACK 0x00000001
+# interface is loopback
+PCAP_IF_LOOPBACK = 1
+##define MODE_CAPT 0
+# Capture mode, to be used when calling pcap_setmode().
+MODE_CAPT = 0
+##define MODE_STAT 1
+# Statistical mode, to be used when calling pcap_setmode().
+MODE_STAT = 1
+
+##
+## END Defines
+##
+
+##
+## Typedefs
+##
+
+#typedef int bpf_int32 (already defined)
+# 32-bit integer
+#typedef u_int bpf_u_int32 (already defined)
+# 32-bit unsigned integer
+#typedef struct pcap pcap_t
+# Descriptor of an open capture instance. This structure is opaque to the user, that handles its content through the functions provided by wpcap.dll.
+pcap_t = pcap
+#typedef struct pcap_dumper pcap_dumper_t
+# libpcap savefile descriptor.
+pcap_dumper_t = pcap_dumper
+#typedef struct pcap_if pcap_if_t
+# Item in a list of interfaces, see pcap_if.
+pcap_if_t = pcap_if
+#typedef struct pcap_addr pcap_addr_t
+# Representation of an interface address, see pcap_addr.
+pcap_addr_t = pcap_addr
+
+##
+## END Typedefs
+##
+
+
+
+
+
+# values for enumeration 'pcap_direction_t'
+#pcap_direction_t = c_int # enum
+
+##
+## Unix-compatible Functions
+## These functions are part of the libpcap library, and therefore work both on Windows and on Linux.
+##
+
+#typedef void(* pcap_handler )(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+# Prototype of the callback function that receives the packets.
+## This one is defined from programmer
+pcap_handler=CFUNCTYPE(None,POINTER(c_ubyte),POINTER(pcap_pkthdr),POINTER(c_ubyte))
+
+#pcap_t * pcap_open_live (const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+# Open a live capture from the network.
+pcap_open_live = _lib.pcap_open_live
+pcap_open_live.restype = POINTER(pcap_t)
+pcap_open_live.argtypes = [STRING, c_int, c_int, c_int, STRING]
+
+#pcap_t * pcap_open_dead (int linktype, int snaplen)
+# Create a pcap_t structure without starting a capture.
+pcap_open_dead = _lib.pcap_open_dead
+pcap_open_dead.restype = POINTER(pcap_t)
+pcap_open_dead.argtypes = [c_int, c_int]
+
+#pcap_t * pcap_open_offline (const char *fname, char *errbuf)
+# Open a savefile in the tcpdump/libpcap format to read packets.
+pcap_open_offline = _lib.pcap_open_offline
+pcap_open_offline.restype = POINTER(pcap_t)
+pcap_open_offline.argtypes = [STRING, STRING]
+
+#pcap_dumper_t * pcap_dump_open (pcap_t *p, const char *fname)
+# Open a file to write packets.
+pcap_dump_open = _lib.pcap_dump_open
+pcap_dump_open.restype = POINTER(pcap_dumper_t)
+pcap_dump_open.argtypes = [POINTER(pcap_t), STRING]
+
+#int pcap_setnonblock (pcap_t *p, int nonblock, char *errbuf)
+# Switch between blocking and nonblocking mode.
+pcap_setnonblock = _lib.pcap_setnonblock
+pcap_setnonblock.restype = c_int
+pcap_setnonblock.argtypes = [POINTER(pcap_t), c_int, STRING]
+
+#int pcap_getnonblock (pcap_t *p, char *errbuf)
+# Get the "non-blocking" state of an interface.
+pcap_getnonblock = _lib.pcap_getnonblock
+pcap_getnonblock.restype = c_int
+pcap_getnonblock.argtypes = [POINTER(pcap_t), STRING]
+
+#int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+# Construct a list of network devices that can be opened with pcap_open_live().
+pcap_findalldevs = _lib.pcap_findalldevs
+pcap_findalldevs.restype = c_int
+pcap_findalldevs.argtypes = [POINTER(POINTER(pcap_if_t)), STRING]
+
+#void pcap_freealldevs (pcap_if_t *alldevsp)
+# Free an interface list returned by pcap_findalldevs().
+pcap_freealldevs = _lib.pcap_freealldevs
+pcap_freealldevs.restype = None
+pcap_freealldevs.argtypes = [POINTER(pcap_if_t)]
+
+#char * pcap_lookupdev (char *errbuf)
+# Return the first valid device in the system.
+pcap_lookupdev = _lib.pcap_lookupdev
+pcap_lookupdev.restype = STRING
+pcap_lookupdev.argtypes = [STRING]
+
+#int pcap_lookupnet (const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf)
+# Return the subnet and netmask of an interface.
+pcap_lookupnet = _lib.pcap_lookupnet
+pcap_lookupnet.restype = c_int
+pcap_lookupnet.argtypes = [STRING, POINTER(bpf_u_int32), POINTER(bpf_u_int32), STRING]
+
+#int pcap_dispatch (pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+# Collect a group of packets.
+pcap_dispatch = _lib.pcap_dispatch
+pcap_dispatch.restype = c_int
+pcap_dispatch.argtypes = [POINTER(pcap_t), c_int, pcap_handler, POINTER(u_char)]
+
+#int pcap_loop (pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+# Collect a group of packets.
+pcap_loop = _lib.pcap_loop
+pcap_loop.restype = c_int
+pcap_loop.argtypes = [POINTER(pcap_t), c_int, pcap_handler, POINTER(u_char)]
+
+#u_char * pcap_next (pcap_t *p, struct pcap_pkthdr *h)
+# Return the next available packet.
+pcap_next = _lib.pcap_next
+pcap_next.restype = POINTER(u_char)
+pcap_next.argtypes = [POINTER(pcap_t), POINTER(pcap_pkthdr)]
+
+#int pcap_next_ex (pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data)
+# Read a packet from an interface or from an offline capture.
+pcap_next_ex = _lib.pcap_next_ex
+pcap_next_ex.restype = c_int
+pcap_next_ex.argtypes = [POINTER(pcap_t), POINTER(POINTER(pcap_pkthdr)), POINTER(POINTER(u_char))]
+
+#void pcap_breakloop (pcap_t *)
+# set a flag that will force pcap_dispatch() or pcap_loop() to return rather than looping.
+pcap_breakloop = _lib.pcap_breakloop
+pcap_breakloop.restype = None
+pcap_breakloop.argtypes = [POINTER(pcap_t)]
+
+#int pcap_sendpacket (pcap_t *p, u_char *buf, int size)
+# Send a raw packet.
+pcap_sendpacket = _lib.pcap_sendpacket
+pcap_sendpacket.restype = c_int
+#pcap_sendpacket.argtypes = [POINTER(pcap_t), POINTER(u_char), c_int]
+pcap_sendpacket.argtypes = [POINTER(pcap_t), c_void_p, c_int]
+
+#void pcap_dump (u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+# Save a packet to disk.
+pcap_dump = _lib.pcap_dump
+pcap_dump.restype = None
+pcap_dump.argtypes = [POINTER(pcap_dumper_t), POINTER(pcap_pkthdr), POINTER(u_char)]
+
+#long pcap_dump_ftell (pcap_dumper_t *)
+# Return the file position for a "savefile".
+pcap_dump_ftell = _lib.pcap_dump_ftell
+pcap_dump_ftell.restype = c_long
+pcap_dump_ftell.argtypes = [POINTER(pcap_dumper_t)]
+
+#int pcap_compile (pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)
+# Compile a packet filter, converting an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine.
+pcap_compile = _lib.pcap_compile
+pcap_compile.restype = c_int
+pcap_compile.argtypes = [POINTER(pcap_t), POINTER(bpf_program), STRING, c_int, bpf_u_int32]
+
+#int pcap_compile_nopcap (int snaplen_arg, int linktype_arg, struct bpf_program *program, char *buf, int optimize, bpf_u_int32 mask)
+# Compile a packet filter without the need of opening an adapter. This function converts an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine.
+pcap_compile_nopcap = _lib.pcap_compile_nopcap
+pcap_compile_nopcap.restype = c_int
+pcap_compile_nopcap.argtypes = [c_int, c_int, POINTER(bpf_program), STRING, c_int, bpf_u_int32]
+
+#int pcap_setfilter (pcap_t *p, struct bpf_program *fp)
+# Associate a filter to a capture.
+pcap_setfilter = _lib.pcap_setfilter
+pcap_setfilter.restype = c_int
+pcap_setfilter.argtypes = [POINTER(pcap_t), POINTER(bpf_program)]
+
+#void pcap_freecode (struct bpf_program *fp)
+# Free a filter.
+pcap_freecode = _lib.pcap_freecode
+pcap_freecode.restype = None
+pcap_freecode.argtypes = [POINTER(bpf_program)]
+
+#int pcap_datalink (pcap_t *p)
+# Return the link layer of an adapter.
+pcap_datalink = _lib.pcap_datalink
+pcap_datalink.restype = c_int
+pcap_datalink.argtypes = [POINTER(pcap_t)]
+
+#int pcap_list_datalinks (pcap_t *p, int **dlt_buf)
+# list datalinks
+pcap_list_datalinks = _lib.pcap_list_datalinks
+pcap_list_datalinks.restype = c_int
+#pcap_list_datalinks.argtypes = [POINTER(pcap_t), POINTER(POINTER(c_int))]
+
+#int pcap_set_datalink (pcap_t *p, int dlt)
+# Set the current data link type of the pcap descriptor to the type specified by dlt. -1 is returned on failure.
+pcap_set_datalink = _lib.pcap_set_datalink
+pcap_set_datalink.restype = c_int
+pcap_set_datalink.argtypes = [POINTER(pcap_t), c_int]
+
+#int pcap_datalink_name_to_val (const char *name)
+# Translates a data link type name, which is a DLT_ name with the DLT_ removed, to the corresponding data link type value. The translation is case-insensitive. -1 is returned on failure.
+pcap_datalink_name_to_val = _lib.pcap_datalink_name_to_val
+pcap_datalink_name_to_val.restype = c_int
+pcap_datalink_name_to_val.argtypes = [STRING]
+
+#const char * pcap_datalink_val_to_name (int dlt)
+# Translates a data link type value to the corresponding data link type name. NULL is returned on failure.
+pcap_datalink_val_to_name = _lib.pcap_datalink_val_to_name
+pcap_datalink_val_to_name.restype = STRING
+pcap_datalink_val_to_name.argtypes = [c_int]
+
+#const char * pcap_datalink_val_to_description (int dlt)
+# Translates a data link type value to a short description of that data link type. NULL is returned on failure.
+pcap_datalink_val_to_description = _lib.pcap_datalink_val_to_description
+pcap_datalink_val_to_description.restype = STRING
+pcap_datalink_val_to_description.argtypes = [c_int]
+
+#int pcap_snapshot (pcap_t *p)
+# Return the dimension of the packet portion (in bytes) that is delivered to the application.
+pcap_snapshot = _lib.pcap_snapshot
+pcap_snapshot.restype = c_int
+pcap_snapshot.argtypes = [POINTER(pcap_t)]
+
+#int pcap_is_swapped (pcap_t *p)
+# returns true if the current savefile uses a different byte order than the current system.
+pcap_is_swapped = _lib.pcap_is_swapped
+pcap_is_swapped.restype = c_int
+pcap_is_swapped.argtypes = [POINTER(pcap_t)]
+
+#int pcap_major_version (pcap_t *p)
+# return the major version number of the pcap library used to write the savefile.
+pcap_major_version = _lib.pcap_major_version
+pcap_major_version.restype = c_int
+pcap_major_version.argtypes = [POINTER(pcap_t)]
+
+#int pcap_minor_version (pcap_t *p)
+# return the minor version number of the pcap library used to write the savefile.
+pcap_minor_version = _lib.pcap_minor_version
+pcap_minor_version.restype = c_int
+pcap_minor_version.argtypes = [POINTER(pcap_t)]
+
+#FILE * pcap_file (pcap_t *p)
+# Return the standard stream of an offline capture.
+pcap_file=_lib.pcap_file
+pcap_file.restype = FILE
+pcap_file.argtypes = [POINTER(pcap_t)]
+
+#int pcap_stats (pcap_t *p, struct pcap_stat *ps)
+# Return statistics on current capture.
+pcap_stats = _lib.pcap_stats
+pcap_stats.restype = c_int
+pcap_stats.argtypes = [POINTER(pcap_t), POINTER(pcap_stat)]
+
+#void pcap_perror (pcap_t *p, char *prefix)
+# print the text of the last pcap library error on stderr, prefixed by prefix.
+pcap_perror = _lib.pcap_perror
+pcap_perror.restype = None
+pcap_perror.argtypes = [POINTER(pcap_t), STRING]
+
+#char * pcap_geterr (pcap_t *p)
+# return the error text pertaining to the last pcap library error.
+pcap_geterr = _lib.pcap_geterr
+pcap_geterr.restype = STRING
+pcap_geterr.argtypes = [POINTER(pcap_t)]
+
+#char * pcap_strerror (int error)
+# Provided in case strerror() isn't available.
+pcap_strerror = _lib.pcap_strerror
+pcap_strerror.restype = STRING
+pcap_strerror.argtypes = [c_int]
+
+#const char * pcap_lib_version (void)
+# Returns a pointer to a string giving information about the version of the libpcap library being used; note that it contains more information than just a version number.
+pcap_lib_version = _lib.pcap_lib_version
+pcap_lib_version.restype = STRING
+pcap_lib_version.argtypes = []
+
+#void pcap_close (pcap_t *p)
+# close the files associated with p and deallocates resources.
+pcap_close = _lib.pcap_close
+pcap_close.restype = None
+pcap_close.argtypes = [POINTER(pcap_t)]
+
+#FILE * pcap_dump_file (pcap_dumper_t *p)
+# return the standard I/O stream of the 'savefile' opened by pcap_dump_open().
+pcap_dump_file=_lib.pcap_dump_file
+pcap_dump_file.restype=FILE
+pcap_dump_file.argtypes= [POINTER(pcap_dumper_t)]
+
+#int pcap_dump_flush (pcap_dumper_t *p)
+# Flushes the output buffer to the ``savefile,'' so that any packets written with pcap_dump() but not yet written to the ``savefile'' will be written. -1 is returned on error, 0 on success.
+pcap_dump_flush = _lib.pcap_dump_flush
+pcap_dump_flush.restype = c_int
+pcap_dump_flush.argtypes = [POINTER(pcap_dumper_t)]
+
+#void pcap_dump_close (pcap_dumper_t *p)
+# Closes a savefile.
+pcap_dump_close = _lib.pcap_dump_close
+pcap_dump_close.restype = None
+pcap_dump_close.argtypes = [POINTER(pcap_dumper_t)]
+
+if not WIN32:
+
+ pcap_get_selectable_fd = _lib.pcap_get_selectable_fd
+ pcap_get_selectable_fd.restype = c_int
+ pcap_get_selectable_fd.argtypes = [POINTER(pcap_t)]
+
+###########################################
+## Windows-specific Extensions
+## The functions in this section extend libpcap to offer advanced functionalities
+## (like remote packet capture, packet buffer size variation or high-precision packet injection).
+## Howerver, at the moment they can be used only in Windows.
+###########################################
+if WIN32:
+ HANDLE = c_void_p
+
+ ##############
+ ## Identifiers related to the new source syntax
+ ##############
+ #define PCAP_SRC_FILE 2
+ #define PCAP_SRC_IFLOCAL 3
+ #define PCAP_SRC_IFREMOTE 4
+ #Internal representation of the type of source in use (file, remote/local interface).
+ PCAP_SRC_FILE = 2
+ PCAP_SRC_IFLOCAL = 3
+ PCAP_SRC_IFREMOTE = 4
+
+ ##############
+ ## Strings related to the new source syntax
+ ##############
+ #define PCAP_SRC_FILE_STRING "file://"
+ #define PCAP_SRC_IF_STRING "rpcap://"
+ #String that will be used to determine the type of source in use (file, remote/local interface).
+ PCAP_SRC_FILE_STRING="file://"
+ PCAP_SRC_IF_STRING="rpcap://"
+
+ ##############
+ ## Flags defined in the pcap_open() function
+ ##############
+ # define PCAP_OPENFLAG_PROMISCUOUS 1
+ # Defines if the adapter has to go in promiscuous mode.
+ PCAP_OPENFLAG_PROMISCUOUS=1
+ # define PCAP_OPENFLAG_DATATX_UDP 2
+ # Defines if the data trasfer (in case of a remote capture) has to be done with UDP protocol.
+ PCAP_OPENFLAG_DATATX_UDP=2
+ # define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4
+ PCAP_OPENFLAG_NOCAPTURE_RPCAP=4
+ # Defines if the remote probe will capture its own generated traffic.
+ # define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8
+ PCAP_OPENFLAG_NOCAPTURE_LOCAL = 8
+ # define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16
+ # This flag configures the adapter for maximum responsiveness.
+ PCAP_OPENFLAG_MAX_RESPONSIVENESS=16
+
+ ##############
+ ## Sampling methods defined in the pcap_setsampling() function
+ ##############
+ # define PCAP_SAMP_NOSAMP 0
+ # No sampling has to be done on the current capture.
+ PCAP_SAMP_NOSAMP=0
+ # define PCAP_SAMP_1_EVERY_N 1
+ # It defines that only 1 out of N packets must be returned to the user.
+ PCAP_SAMP_1_EVERY_N=1
+ #define PCAP_SAMP_FIRST_AFTER_N_MS 2
+ # It defines that we have to return 1 packet every N milliseconds.
+ PCAP_SAMP_FIRST_AFTER_N_MS=2
+
+ ##############
+ ## Authentication methods supported by the RPCAP protocol
+ ##############
+ # define RPCAP_RMTAUTH_NULL 0
+ # It defines the NULL authentication.
+ RPCAP_RMTAUTH_NULL=0
+ # define RPCAP_RMTAUTH_PWD 1
+ # It defines the username/password authentication.
+ RPCAP_RMTAUTH_PWD=1
+
+
+ ##############
+ ## Remote struct and defines
+ ##############
+ # define PCAP_BUF_SIZE 1024
+ # Defines the maximum buffer size in which address, port, interface names are kept.
+ PCAP_BUF_SIZE = 1024
+ # define RPCAP_HOSTLIST_SIZE 1024
+ # Maximum lenght of an host name (needed for the RPCAP active mode).
+ RPCAP_HOSTLIST_SIZE = 1024
+
+ class pcap_send_queue(Structure):
+ _fields_=[("maxlen",c_uint),
+ ("len",c_uint),
+ ("buffer",c_char_p)]
+
+ ## struct pcap_rmtauth
+ ## This structure keeps the information needed to autheticate the user on a remote machine
+ class pcap_rmtauth(Structure):
+ _fields_=[("type",c_int),
+ ("username",c_char_p),
+ ("password",c_char_p)]
+
+ ## struct pcap_samp
+ ## This structure defines the information related to sampling
+ class pcap_samp(Structure):
+ _fields_=[("method",c_int),
+ ("value",c_int)]
+
+ #PAirpcapHandle pcap_get_airpcap_handle (pcap_t *p)
+ # Returns the AirPcap handler associated with an adapter. This handler can be used to change the wireless-related settings of the CACE Technologies AirPcap wireless capture adapters.
+
+ #bool pcap_offline_filter (struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data)
+ # Returns if a given filter applies to an offline packet.
+ pcap_offline_filter = _lib.pcap_offline_filter
+ pcap_offline_filter.restype = c_bool
+ pcap_offline_filter.argtypes = [POINTER(bpf_program),POINTER(pcap_pkthdr),POINTER(u_char)]
+
+ #int pcap_live_dump (pcap_t *p, char *filename, int maxsize, int maxpacks)
+ # Save a capture to file.
+ pcap_live_dump = _lib.pcap_live_dump
+ pcap_live_dump.restype = c_int
+ pcap_live_dump.argtypes = [POINTER(pcap_t), POINTER(c_char), c_int,c_int]
+
+ #int pcap_live_dump_ended (pcap_t *p, int sync)
+ # Return the status of the kernel dump process, i.e. tells if one of the limits defined with pcap_live_dump() has been reached.
+ pcap_live_dump_ended = _lib.pcap_live_dump_ended
+ pcap_live_dump_ended.restype = c_int
+ pcap_live_dump_ended.argtypes = [POINTER(pcap_t), c_int]
+
+ #struct pcap_stat * pcap_stats_ex (pcap_t *p, int *pcap_stat_size)
+ # Return statistics on current capture.
+ pcap_stats_ex = _lib.pcap_stats_ex
+ pcap_stats_ex.restype = POINTER(pcap_stat)
+ pcap_stats_ex.argtypes = [POINTER(pcap_t), POINTER(c_int)]
+
+ #int pcap_setbuff (pcap_t *p, int dim)
+ # Set the size of the kernel buffer associated with an adapter.
+ pcap_setbuff = _lib.pcap_setbuff
+ pcap_setbuff.restype = c_int
+ pcap_setbuff.argtypes = [POINTER(pcap_t), c_int]
+
+ #int pcap_setmode (pcap_t *p, int mode)
+ # Set the working mode of the interface p to mode.
+ pcap_setmode = _lib.pcap_setmode
+ pcap_setmode.restype = c_int
+ pcap_setmode.argtypes = [POINTER(pcap_t), c_int]
+
+ #int pcap_setmintocopy (pcap_t *p, int size)
+ # Set the minumum amount of data received by the kernel in a single call.
+ pcap_setmintocopy = _lib.pcap_setmintocopy
+ pcap_setmintocopy.restype = c_int
+ pcap_setmintocopy.argtype = [POINTER(pcap_t), c_int]
+
+ #HANDLE pcap_getevent (pcap_t *p)
+ # Return the handle of the event associated with the interface p.
+ pcap_getevent = _lib.pcap_getevent
+ pcap_getevent.restype = HANDLE
+ pcap_getevent.argtypes = [POINTER(pcap_t)]
+
+ #pcap_send_queue * pcap_sendqueue_alloc (u_int memsize)
+ # Allocate a send queue.
+ pcap_sendqueue_alloc = _lib.pcap_sendqueue_alloc
+ pcap_sendqueue_alloc.restype = POINTER(pcap_send_queue)
+ pcap_sendqueue_alloc.argtypes = [c_uint]
+
+ #void pcap_sendqueue_destroy (pcap_send_queue *queue)
+ # Destroy a send queue.
+ pcap_sendqueue_destroy = _lib.pcap_sendqueue_destroy
+ pcap_sendqueue_destroy.restype = None
+ pcap_sendqueue_destroy.argtypes = [POINTER(pcap_send_queue)]
+
+ #int pcap_sendqueue_queue (pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+ # Add a packet to a send queue.
+ pcap_sendqueue_queue = _lib.pcap_sendqueue_queue
+ pcap_sendqueue_queue.restype = c_int
+ pcap_sendqueue_queue.argtypes = [POINTER(pcap_send_queue), POINTER(pcap_pkthdr), POINTER(u_char)]
+
+ #u_int pcap_sendqueue_transmit (pcap_t *p, pcap_send_queue *queue, int sync)
+ # Send a queue of raw packets to the network.
+ pcap_sendqueue_transmit = _lib.pcap_sendqueue_transmit
+ pcap_sendqueue_transmit.retype = u_int
+ pcap_sendqueue_transmit.argtypes = [POINTER(pcap_t), POINTER(pcap_send_queue), c_int]
+
+ #int pcap_findalldevs_ex (char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+ # Create a list of network devices that can be opened with pcap_open().
+ pcap_findalldevs_ex = _lib.pcap_findalldevs_ex
+ pcap_findalldevs_ex.retype = c_int
+ pcap_findalldevs_ex.argtypes = [STRING, POINTER(pcap_rmtauth), POINTER(POINTER(pcap_if_t)), STRING]
+
+ #int pcap_createsrcstr (char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
+ # Accept a set of strings (host name, port, ...), and it returns the complete source string according to the new format (e.g. 'rpcap://1.2.3.4/eth0').
+ pcap_createsrcstr = _lib.pcap_createsrcstr
+ pcap_createsrcstr.restype = c_int
+ pcap_createsrcstr.argtypes = [STRING, c_int, STRING, STRING, STRING, STRING]
+
+ #int pcap_parsesrcstr (const char *source, int *type, char *host, char *port, char *name, char *errbuf)
+ # Parse the source string and returns the pieces in which the source can be split.
+ pcap_parsesrcstr = _lib.pcap_parsesrcstr
+ pcap_parsesrcstr.retype = c_int
+ pcap_parsesrcstr.argtypes = [STRING, POINTER(c_int), STRING, STRING, STRING, STRING]
+
+ #pcap_t * pcap_open (const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+ # Open a generic source in order to capture / send (WinPcap only) traffic.
+ pcap_open = _lib.pcap_open
+ pcap_open.restype = POINTER(pcap_t)
+ pcap_open.argtypes = [STRING, c_int, c_int, c_int, POINTER(pcap_rmtauth), STRING]
+
+ #struct pcap_samp * pcap_setsampling (pcap_t *p)
+ # Define a sampling method for packet capture.
+ pcap_setsampling = _lib.pcap_setsampling
+ pcap_setsampling.restype = POINTER(pcap_samp)
+ pcap_setsampling.argtypes = [POINTER(pcap_t)]
+
+ #SOCKET pcap_remoteact_accept (const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+ # Block until a network connection is accepted (active mode only).
+ pcap_remoteact_accept = _lib.pcap_remoteact_accept
+ pcap_remoteact_accept.restype = SOCKET
+ pcap_remoteact_accept.argtypes = [STRING, STRING, STRING, STRING, POINTER(pcap_rmtauth), STRING]
+
+ #int pcap_remoteact_close (const char *host, char *errbuf)
+ # Drop an active connection (active mode only).
+ pcap_remoteact_close = _lib.pcap_remoteact_close
+ pcap_remoteact_close.restypes = c_int
+ pcap_remoteact_close.argtypes = [STRING, STRING]
+
+ #void pcap_remoteact_cleanup ()
+ # Clean the socket that is currently used in waiting active connections.
+ pcap_remoteact_cleanup = _lib.pcap_remoteact_cleanup
+ pcap_remoteact_cleanup.restypes = None
+ pcap_remoteact_cleanup.argtypes = []
+
+ #int pcap_remoteact_list (char *hostlist, char sep, int size, char *errbuf)
+ # Return the hostname of the host that have an active connection with us (active mode only).
+ pcap_remoteact_list = _lib.pcap_remoteact_list
+ pcap_remoteact_list.restype = c_int
+ pcap_remoteact_list.argtypes = [STRING, c_char, c_int, STRING]
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/as_resolvers.py b/scripts/external_libs/scapy-python3-0.18/scapy/as_resolvers.py
new file mode 100644
index 00000000..f04322b8
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/as_resolvers.py
@@ -0,0 +1,115 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Resolve Autonomous Systems (AS).
+"""
+
+
+import socket
+from .config import conf
+
+class AS_resolver:
+ server = None
+ options = "-k"
+ def __init__(self, server=None, port=43, options=None):
+ if server is not None:
+ self.server = server
+ self.port = port
+ if options is not None:
+ self.options = options
+
+ def _start(self):
+ self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.s.connect((self.server,self.port))
+ if self.options:
+ self.s.send(self.options+b"\n")
+ self.s.recv(8192)
+ def _stop(self):
+ self.s.close()
+
+ def _parse_whois(self, txt):
+ asn,desc = None,b""
+ for l in txt.splitlines():
+ if not asn and l.startswith(b"origin:"):
+ asn = l[7:].strip().decode('utf-8')
+ if l.startswith(b"descr:"):
+ if desc:
+ desc += br"\n"
+ desc += l[6:].strip()
+ if asn is not None and desc.strip():
+ desc = desc.strip().decode('utf-8')
+ break
+ return asn, desc
+
+ def _resolve_one(self, ip):
+ self.s.send(b"".join([ip.encode('ascii')])+b"\n")
+ x = b""
+ while not (b"%" in x or b"source" in x):
+ x += self.s.recv(8192)
+ asn, desc = self._parse_whois(x)
+ return ip,asn,desc
+ def resolve(self, *ips):
+ self._start()
+ ret = []
+ for ip in ips:
+ ip,asn,desc = self._resolve_one(ip)
+ if asn is not None:
+ ret.append((ip,asn,desc))
+ self._stop()
+ return ret
+
+class AS_resolver_riswhois(AS_resolver):
+ server = "riswhois.ripe.net"
+ options = b"-k -M -1"
+
+
+class AS_resolver_radb(AS_resolver):
+ server = "whois.ra.net"
+ options = b"-k -M"
+
+
+class AS_resolver_cymru(AS_resolver):
+ server = "whois.cymru.com"
+ options = None
+ def resolve(self, *ips):
+ ASNlist = []
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((self.server,self.port))
+ s.send(b"begin\r\n"+b"\r\n".join([ i.encode('ascii') for i in ips])+b"\r\nend\r\n")
+ r = b""
+ while 1:
+ l = s.recv(8192)
+ if l == b"":
+ break
+ r += l
+ s.close()
+ for l in r.splitlines()[1:]:
+ if b"|" not in l:
+ continue
+ asn,ip,desc = [ i.decode('ascii') for i in map(bytes.strip, l.split(b"|")) ]
+ if asn == "NA":
+ continue
+ asn = int(asn)
+ ASNlist.append((ip,asn,desc))
+ return ASNlist
+
+class AS_resolver_multi(AS_resolver):
+ resolvers_list = ( AS_resolver_cymru(),AS_resolver_riswhois(),AS_resolver_radb() )
+ def __init__(self, *reslist):
+ if reslist:
+ self.resolvers_list = reslist
+ def resolve(self, *ips):
+ todo = ips
+ ret = []
+ for ASres in self.resolvers_list:
+ res = ASres.resolve(*todo)
+ resolved = [ ip for ip,asn,desc in res ]
+ todo = [ ip for ip in todo if ip not in resolved ]
+ ret += res
+ return ret
+
+
+conf.AS_resolver = AS_resolver_multi()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/__init__.py
new file mode 100644
index 00000000..4827a588
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/__init__.py
@@ -0,0 +1,12 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Package holding ASN.1 related modules.
+"""
+
+# We do not import mib.py because it is more bound to scapy and
+# less prone to be used in a standalone fashion
+__all__ = ["asn1","ber"]
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1/asn1.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/asn1.py
new file mode 100644
index 00000000..c94d0b12
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/asn1.py
@@ -0,0 +1,321 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+ASN.1 (Abstract Syntax Notation One)
+"""
+
+import random
+from scapy.config import conf
+from scapy.error import Scapy_Exception,warning
+from scapy.volatile import RandField
+from scapy.utils import Enum_metaclass, EnumElement
+
+class RandASN1Object(RandField):
+ def __init__(self, objlist=None):
+ if objlist is None:
+ objlist = [ x._asn1_obj for x in
+ [ x for x in ASN1_Class_UNIVERSAL.__rdict__.values() if hasattr(x,"_asn1_obj") ]]
+# objlist = map(lambda x:x._asn1_obj,
+# [ x for x in ASN1_Class_UNIVERSAL.__rdict__.values() if hasattr(x,"_asn1_obj") ])
+ self.objlist = objlist
+ self.chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ def _fix(self, n=0):
+ o = random.choice(self.objlist)
+ if issubclass(o, ASN1_INTEGER):
+ return o(int(random.gauss(0,1000)))
+ elif issubclass(o, ASN1_IPADDRESS):
+ z = RandIP()._fix()
+ return o(z)
+ elif issubclass(o, ASN1_STRING):
+ z = int(random.expovariate(0.05)+1)
+ return o(bytes([random.choice(self.chars) for i in range(z)]))
+ elif issubclass(o, ASN1_SEQUENCE) and (n < 10):
+ z = int(random.expovariate(0.08)+1)
+# return o(map(lambda x:x._fix(n+1), [self.__class__(objlist=self.objlist)]*z))
+ return o([ x._fix(n+1) for x in [self.__class__(objlist=self.objlist)]*z])
+ return ASN1_INTEGER(int(random.gauss(0,1000)))
+
+
+##############
+#### ASN1 ####
+##############
+
+class ASN1_Error(Scapy_Exception):
+ pass
+
+class ASN1_Encoding_Error(ASN1_Error):
+ pass
+
+class ASN1_Decoding_Error(ASN1_Error):
+ pass
+
+class ASN1_BadTag_Decoding_Error(ASN1_Decoding_Error):
+ pass
+
+
+
+class ASN1Codec(EnumElement):
+ def register_stem(cls, stem):
+ cls._stem = stem
+ def dec(cls, s, context=None):
+ return cls._stem.dec(s, context=context)
+ def safedec(cls, s, context=None):
+ return cls._stem.safedec(s, context=context)
+ def get_stem(cls):
+ return cls.stem
+
+
+class ASN1_Codecs_metaclass(Enum_metaclass):
+ element_class = ASN1Codec
+
+class ASN1_Codecs(metaclass = ASN1_Codecs_metaclass):
+ #__metaclass__ = ASN1_Codecs_metaclass
+ BER = 1
+ DER = 2
+ PER = 3
+ CER = 4
+ LWER = 5
+ BACnet = 6
+ OER = 7
+ SER = 8
+ XER = 9
+
+class ASN1Tag(EnumElement):
+ def __init__(self, key, value, context=None, codec=None):
+ EnumElement.__init__(self, key, value)
+ self._context = context
+ if codec == None:
+ codec = {}
+ self._codec = codec
+ def clone(self): # /!\ not a real deep copy. self.codec is shared
+ return self.__class__(self._key, self._value, self._context, self._codec)
+ def register_asn1_object(self, asn1obj):
+ self._asn1_obj = asn1obj
+ def asn1_object(self, val):
+ if hasattr(self,"_asn1_obj"):
+ return self._asn1_obj(val)
+ raise ASN1_Error("%r does not have any assigned ASN1 object" % self)
+ def register(self, codecnum, codec):
+ self._codec[codecnum] = codec
+ def get_codec(self, codec):
+ try:
+ c = self._codec[codec]
+ except KeyError as msg:
+ raise ASN1_Error("Codec %r not found for tag %r" % (codec, self))
+ return c
+
+class ASN1_Class_metaclass(Enum_metaclass):
+ element_class = ASN1Tag
+ def __new__(cls, name, bases, dct): # XXX factorise a bit with Enum_metaclass.__new__()
+ for b in bases:
+ for k,v in b.__dict__.items():
+ if k not in dct and isinstance(v,ASN1Tag):
+ dct[k] = v.clone()
+
+ rdict = {}
+ for k,v in dct.items():
+ if type(v) is int:
+ v = ASN1Tag(k,v)
+ dct[k] = v
+ rdict[v] = v
+ elif isinstance(v, ASN1Tag):
+ rdict[v] = v
+ dct["__rdict__"] = rdict
+
+ cls = type.__new__(cls, name, bases, dct)
+ for v in cls.__dict__.values():
+ if isinstance(v, ASN1Tag):
+ v.context = cls # overwrite ASN1Tag contexts, even cloned ones
+ return cls
+
+
+class ASN1_Class(metaclass = ASN1_Class_metaclass):
+ pass
+
+class ASN1_Class_UNIVERSAL(ASN1_Class):
+ name = "UNIVERSAL"
+ ERROR = -3
+ RAW = -2
+ NONE = -1
+ ANY = 0
+ BOOLEAN = 1
+ INTEGER = 2
+ BIT_STRING = 3
+ STRING = 4
+ NULL = 5
+ OID = 6
+ OBJECT_DESCRIPTOR = 7
+ EXTERNAL = 8
+ REAL = 9
+ ENUMERATED = 10
+ EMBEDDED_PDF = 11
+ UTF8_STRING = 12
+ RELATIVE_OID = 13
+ SEQUENCE = 0x30#XXX 16 ??
+ SET = 0x31 #XXX 17 ??
+ NUMERIC_STRING = 18
+ PRINTABLE_STRING = 19
+ T61_STRING = 20
+ VIDEOTEX_STRING = 21
+ IA5_STRING = 22
+ UTC_TIME = 23
+ GENERALIZED_TIME = 24
+ GRAPHIC_STRING = 25
+ ISO646_STRING = 26
+ GENERAL_STRING = 27
+ UNIVERSAL_STRING = 28
+ CHAR_STRING = 29
+ BMP_STRING = 30
+ IPADDRESS = 0x40
+ COUNTER32 = 0x41
+ GAUGE32 = 0x42
+ TIME_TICKS = 0x43
+ SEP = 0x80
+
+class ASN1_Object_metaclass(type):
+ def __new__(cls, name, bases, dct):
+ c = super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)
+ try:
+ c.tag.register_asn1_object(c)
+ except:
+ warning("Error registering %r for %r" % (c.tag, c.codec))
+ return c
+
+
+class ASN1_Object(metaclass = ASN1_Object_metaclass):
+ tag = ASN1_Class_UNIVERSAL.ANY
+ def __init__(self, val):
+ self.val = val
+ def enc(self, codec):
+ return self.tag.get_codec(codec).enc(self.val)
+ def __repr__(self):
+ return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), self.val)
+ def __str__(self):
+ raise Exception("Should not get here")
+ #return self.enc(conf.ASN1_default_codec)
+ def __bytes__(self):
+ return self.enc(conf.ASN1_default_codec)
+ def strshow(self, lvl=0):
+ return (" "*lvl)+repr(self)+"\n"
+ def show(self, lvl=0):
+ print(self.strshow(lvl))
+ def __eq__(self, other):
+ return self.val == other
+ def __hash__(self):
+ return self.val
+ def __cmp__(self, other):
+ return cmp(self.val, other)
+
+class ASN1_DECODING_ERROR(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.ERROR
+ def __init__(self, val, exc=None):
+ ASN1_Object.__init__(self, val)
+ self.exc = exc
+ def __repr__(self):
+ return "<%s[%r]{{%s}}>" % (self.__dict__.get("name", self.__class__.__name__),
+ self.val, self.exc.args[0])
+ def enc(self, codec):
+ if isinstance(self.val, ASN1_Object):
+ return self.val.enc(codec)
+ return self.val
+
+class ASN1_force(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.RAW
+ def enc(self, codec):
+ if isinstance(self.val, ASN1_Object):
+ return self.val.enc(codec)
+ return self.val
+
+class ASN1_BADTAG(ASN1_force):
+ pass
+
+class ASN1_INTEGER(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.INTEGER
+
+class ASN1_STRING(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.STRING
+ def __init__(self, val):
+ if type(val) is str:
+ self.val = val.encode('ascii')
+ elif type(val) is bytes:
+ self.val = val
+ else:
+ raise Exception("Unknown value type for ASN1_STRING")
+
+class ASN1_BIT_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.BIT_STRING
+
+class ASN1_PRINTABLE_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
+
+class ASN1_T61_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.T61_STRING
+
+class ASN1_IA5_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.IA5_STRING
+
+class ASN1_NUMERIC_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
+
+class ASN1_VIDEOTEX_STRING(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
+
+class ASN1_IPADDRESS(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.IPADDRESS
+
+class ASN1_UTC_TIME(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.UTC_TIME
+
+class ASN1_GENERALIZED_TIME(ASN1_STRING):
+ tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
+class ASN1_TIME_TICKS(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+
+class ASN1_BOOLEAN(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.BOOLEAN
+
+class ASN1_ENUMERATED(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
+class ASN1_NULL(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.NULL
+
+class ASN1_SEP(ASN1_NULL):
+ tag = ASN1_Class_UNIVERSAL.SEP
+
+class ASN1_GAUGE32(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.GAUGE32
+
+class ASN1_COUNTER32(ASN1_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.COUNTER32
+
+class ASN1_SEQUENCE(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.SEQUENCE
+ def strshow(self, lvl=0):
+ s = (" "*lvl)+("# %s:" % self.__class__.__name__)+"\n"
+ for o in self.val:
+ s += o.strshow(lvl=lvl+1)
+ return s
+
+class ASN1_SET(ASN1_SEQUENCE):
+ tag = ASN1_Class_UNIVERSAL.SET
+
+class ASN1_OID(ASN1_Object):
+ tag = ASN1_Class_UNIVERSAL.OID
+ def __init__(self, val):
+ if type(val) is str:
+ val = val.encode('ascii')
+ val = conf.mib._oid(val)
+ ASN1_Object.__init__(self, val)
+ def __repr__(self):
+ return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), conf.mib._oidname(self.val))
+ def __oidname__(self):
+ return '%s'%conf.mib._oidname(self.val)
+
+
+
+conf.ASN1_default_codec = ASN1_Codecs.BER
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1/ber.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/ber.py
new file mode 100644
index 00000000..48cb1c2d
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/ber.py
@@ -0,0 +1,370 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Basic Encoding Rules (BER) for ASN.1
+"""
+
+from scapy.error import warning
+from scapy.utils import inet_aton,inet_ntoa
+from scapy.asn1.asn1 import ASN1_Decoding_Error,ASN1_Encoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1_Class_UNIVERSAL,ASN1_Error,ASN1_DECODING_ERROR,ASN1_BADTAG
+
+##################
+## BER encoding ##
+##################
+
+
+
+#####[ BER tools ]#####
+
+
+class BER_Exception(Exception):
+ pass
+
+class BER_Encoding_Error(ASN1_Encoding_Error):
+ def __init__(self, msg, encoded=None, remaining=None):
+ Exception.__init__(self, msg)
+ self.remaining = remaining
+ self.encoded = encoded
+ def __str__(self):
+ s = Exception.__str__(self)
+ if isinstance(self.encoded, BERcodec_Object):
+ s+="\n### Already encoded ###\n%s" % self.encoded.strshow()
+ else:
+ s+="\n### Already encoded ###\n%r" % self.encoded
+ s+="\n### Remaining ###\n%r" % self.remaining
+ return s
+
+class BER_Decoding_Error(ASN1_Decoding_Error):
+ def __init__(self, msg, decoded=None, remaining=None):
+ Exception.__init__(self, msg)
+ self.remaining = remaining
+ self.decoded = decoded
+ def __str__(self):
+ s = Exception.__str__(self)
+ if isinstance(self.decoded, BERcodec_Object):
+ s+="\n### Already decoded ###\n%s" % self.decoded.strshow()
+ else:
+ s+="\n### Already decoded ###\n%r" % self.decoded
+ s+="\n### Remaining ###\n%r" % self.remaining
+ return s
+
+class BER_BadTag_Decoding_Error(BER_Decoding_Error, ASN1_BadTag_Decoding_Error):
+ pass
+
+def BER_len_enc(l, size=0):
+ if l <= 127 and size==0:
+ return bytes([l])
+ s = b""
+ while l or size>0:
+ s = bytes([l&0xff])+s
+ l >>= 8
+ size -= 1
+ if len(s) > 127:
+ raise BER_Exception("BER_len_enc: Length too long (%i) to be encoded [%r]" % (len(s),s))
+ return bytes([len(s)|0x80])+s
+def BER_len_dec(s):
+ l = (s[0])
+ if not l & 0x80:
+ return l,s[1:]
+ l &= 0x7f
+ if len(s) <= l:
+ raise BER_Decoding_Error("BER_len_dec: Got %i bytes while expecting %i" % (len(s)-1, l),remaining=s)
+ ll = 0
+ for c in s[1:l+1]:
+ ll <<= 8
+ ll |= (c)
+ return ll,s[l+1:]
+
+def BER_num_enc(l, size=1):
+ x=[]
+ while l or size>0:
+ x.insert(0, l & 0x7f)
+ if len(x) > 1:
+ x[0] |= 0x80
+ l >>= 7
+ size -= 1
+ return bytes([(k) for k in x])
+def BER_num_dec(s):
+ x = 0
+ for i in range(len(s)):
+ c = (s[i])
+ x <<= 7
+ x |= c&0x7f
+ if not c&0x80:
+ break
+ if c&0x80:
+ raise BER_Decoding_Error("BER_num_dec: unfinished number description", remaining=s)
+ return x, s[i+1:]
+
+#####[ BER classes ]#####
+
+class BERcodec_metaclass(type):
+ def __new__(cls, name, bases, dct):
+ c = super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct)
+ try:
+ c.tag.register(c.codec, c)
+ except:
+ warning("Error registering %r for %r" % (c.tag, c.codec))
+ return c
+
+
+class BERcodec_Object( metaclass = BERcodec_metaclass):
+ codec = ASN1_Codecs.BER
+ tag = ASN1_Class_UNIVERSAL.ANY
+
+ @classmethod
+ def asn1_object(cls, val):
+ return cls.tag.asn1_object(val)
+
+ @classmethod
+ def check_string(cls, s):
+ if not s:
+ raise BER_Decoding_Error("%s: Got empty object while expecting tag %r" %
+ (cls.__name__,cls.tag), remaining=s)
+ @classmethod
+ def check_type(cls, s):
+ cls.check_string(s)
+ if hash(cls.tag) != (s[0]):
+ raise BER_BadTag_Decoding_Error("%s: Got tag [%i/%#x] while expecting %r" %
+ (cls.__name__, (s[0]), (s[0]),cls.tag), remaining=s)
+ return s[1:]
+ @classmethod
+ def check_type_get_len(cls, s):
+ s2 = cls.check_type(s)
+ if not s2:
+ raise BER_Decoding_Error("%s: No bytes while expecting a length" %
+ cls.__name__, remaining=s)
+ return BER_len_dec(s2)
+ @classmethod
+ def check_type_check_len(cls, s):
+ l,s3 = cls.check_type_get_len(s)
+ if len(s3) < l:
+ raise BER_Decoding_Error("%s: Got %i bytes while expecting %i" %
+ (cls.__name__, len(s3), l), remaining=s)
+ return l,s3[:l],s3[l:]
+
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ if context is None:
+ context = cls.tag.context
+ cls.check_string(s)
+ p = (s[0])
+ if p not in context:
+ t = s
+ if len(t) > 18:
+ t = t[:15]+"..."
+ raise BER_Decoding_Error("Unknown prefix [%02x] for [%r]" % (p,t), remaining=s)
+ codec = context[p].get_codec(ASN1_Codecs.BER)
+ return codec.dec(s,context,safe)
+
+ @classmethod
+ def dec(cls, s, context=None, safe=False):
+ if not safe:
+ return cls.do_dec(s, context, safe)
+ try:
+ return cls.do_dec(s, context, safe)
+ except BER_BadTag_Decoding_Error as e:
+ o,remain = BERcodec_Object.dec(e.remaining, context, safe)
+ return ASN1_BADTAG(o),remain
+ except BER_Decoding_Error as e:
+ return ASN1_DECODING_ERROR(s, exc=e),""
+ except ASN1_Error as e:
+ return ASN1_DECODING_ERROR(s, exc=e),""
+
+ @classmethod
+ def safedec(cls, s, context=None):
+ return cls.dec(s, context, safe=True)
+
+
+ @classmethod
+ def enc(cls, s):
+ if type(s) is str:
+ return BERcodec_STRING.enc(s)
+ #TODO3 wild guess
+ elif type(s) is bytes:
+ return BERcodec_STRING.enc(s)
+ else:
+ return BERcodec_INTEGER.enc(hash(s))
+
+
+
+ASN1_Codecs.BER.register_stem(BERcodec_Object)
+
+
+class BERcodec_INTEGER(BERcodec_Object):
+ tag = ASN1_Class_UNIVERSAL.INTEGER
+ @classmethod
+ def enc(cls, i):
+ s = []
+ while 1:
+ s.append(i&0xff)
+ if -127 <= i < 0:
+ break
+ if 128 <= i <= 255:
+ s.append(0)
+ i >>= 8
+ if not i:
+ break
+ #s = map(chr, s)
+ s = bytes(s) + BER_len_enc(len(s)) + bytes([hash(cls.tag)])
+ #s.reverse()
+ #return b"".join(s)
+ return s[::-1]
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ l,s,t = cls.check_type_check_len(s)
+ x = 0
+ if s:
+ if (s[0])&0x80: # negative int
+ x = -1
+ for c in s:
+ x <<= 8
+ x |= (c)
+ return cls.asn1_object(x),t
+
+
+class BERcodec_BOOLEAN(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.BOOLEAN
+
+class BERcodec_ENUMERATED(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
+class BERcodec_NULL(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.NULL
+ @classmethod
+ def enc(cls, i):
+ if i == 0:
+ return bytes([hash(cls.tag)])+b"\0"
+ else:
+ return BERcodec_INTEGER.enc(i)
+
+class BERcodec_SEP(BERcodec_NULL):
+ tag = ASN1_Class_UNIVERSAL.SEP
+
+class BERcodec_STRING(BERcodec_Object):
+ tag = ASN1_Class_UNIVERSAL.STRING
+ @classmethod
+ def enc(cls,s):
+ if type(s) is str:
+ s = s.encode('ascii')
+ return bytes([hash(cls.tag)])+BER_len_enc(len(s))+s
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ l,s,t = cls.check_type_check_len(s)
+ return cls.tag.asn1_object(s),t
+
+class BERcodec_BIT_STRING(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.BIT_STRING
+
+class BERcodec_PRINTABLE_STRING(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
+
+class BERcodec_T61_STRING (BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.T61_STRING
+
+class BERcodec_IA5_STRING(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.IA5_STRING
+
+class BERcodec_NUMERIC_STRING(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
+
+class BERcodec_VIDEOTEX_STRING(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
+
+class BERcodec_IPADDRESS(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.IPADDRESS
+
+ @classmethod
+ def enc(cls, ipaddr_ascii):
+ try:
+ s = inet_aton(ipaddr_ascii)
+ except Exception:
+ raise BER_Encoding_Error("IPv4 address could not be encoded")
+ return bytes([hash(cls.tag)])+BER_len_enc(len(s))+s
+
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ l,s,t = cls.check_type_check_len(s)
+ try:
+ ipaddr_ascii = inet_ntoa(s)
+ except Exception:
+ raise BER_Decoding_Error("IP address could not be decoded", decoded=obj)
+ return cls.asn1_object(ipaddr_ascii), t
+
+class BERcodec_UTC_TIME(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.UTC_TIME
+
+class BERcodec_GENERALIZED_TIME(BERcodec_STRING):
+ tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
+class BERcodec_TIME_TICKS(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+
+class BERcodec_GAUGE32(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.GAUGE32
+
+class BERcodec_COUNTER32(BERcodec_INTEGER):
+ tag = ASN1_Class_UNIVERSAL.COUNTER32
+
+class BERcodec_SEQUENCE(BERcodec_Object):
+ tag = ASN1_Class_UNIVERSAL.SEQUENCE
+ @classmethod
+ def enc(cls, l):
+ #if type(l) is not str:
+ if type(l) is not bytes:
+ l = b"".join(map(lambda x: x.enc(cls.codec), l))
+ return bytes([hash(cls.tag)])+BER_len_enc(len(l))+l
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ if context is None:
+ context = cls.tag.context
+ l,st = cls.check_type_get_len(s) # we may have len(s) < l
+ s,t = st[:l],st[l:]
+ obj = []
+ while s:
+ try:
+ o,s = BERcodec_Object.dec(s, context, safe)
+ except BER_Decoding_Error as err:
+ err.remaining += t
+ if err.decoded is not None:
+ obj.append(err.decoded)
+ err.decoded = obj
+ raise
+ obj.append(o)
+ if len(st) < l:
+ raise BER_Decoding_Error("Not enough bytes to decode sequence", decoded=obj)
+ return cls.asn1_object(obj),t
+
+class BERcodec_SET(BERcodec_SEQUENCE):
+ tag = ASN1_Class_UNIVERSAL.SET
+
+
+class BERcodec_OID(BERcodec_Object):
+ tag = ASN1_Class_UNIVERSAL.OID
+
+ @classmethod
+ def enc(cls, oid):
+ if type(oid) is str:
+ oid = oid.encode('ascii')
+ lst = [int(x) for x in oid.strip(b".").split(b".")]
+ if len(lst) >= 2:
+ lst[1] += 40*lst[0]
+ del(lst[0])
+ s = b"".join([BER_num_enc(k) for k in lst])
+ return bytes([hash(cls.tag)])+BER_len_enc(len(s))+s
+ @classmethod
+ def do_dec(cls, s, context=None, safe=False):
+ l,s,t = cls.check_type_check_len(s)
+ lst = []
+ while s:
+ l,s = BER_num_dec(s)
+ lst.append(l)
+ if (len(lst) > 0):
+ lst.insert(0,lst[0]//40)
+ lst[1] %= 40
+ return cls.asn1_object(b".".join([str(k).encode('ascii') for k in lst])), t
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1/mib.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/mib.py
new file mode 100644
index 00000000..8f3df25c
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1/mib.py
@@ -0,0 +1,149 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Management Information Base (MIB) parsing
+"""
+
+import re
+from glob import glob
+from scapy.dadict import DADict,fixname
+from scapy.config import conf
+from scapy.utils import do_graph
+
+#################
+## MIB parsing ##
+#################
+
+_mib_re_integer = re.compile(b"^[0-9]+$")
+_mib_re_both = re.compile(b"^([a-zA-Z_][a-zA-Z0-9_-]*)\(([0-9]+)\)$")
+_mib_re_oiddecl = re.compile(b"$\s*([a-zA-Z0-9_-]+)\s+OBJECT([^:\{\}]|\{[^:]+\})+::=\s*\{([^\}]+)\}",re.M)
+_mib_re_strings = re.compile(b'"[^"]*"')
+_mib_re_comments = re.compile(b'--.*(\r|\n)')
+
+class MIBDict(DADict):
+ def _findroot(self, x):
+ if x.startswith(b"."):
+ x = x[1:]
+ if not x.endswith(b"."):
+ x += b"."
+ max=0
+ root=b"."
+ for k in self.keys():
+ if x.startswith(self[k]+b"."):
+ if max < len(self[k]):
+ max = len(self[k])
+ root = k
+ return root, x[max:-1]
+ def _oidname(self, x):
+ root,remainder = self._findroot(x)
+ return root+remainder
+ def _oid(self, x):
+ if type(x) is str:
+ x = x.encode('ascii')
+ xl = x.strip(b".").split(b".")
+ p = len(xl)-1
+ while p >= 0 and _mib_re_integer.match(xl[p]):
+ p -= 1
+ if p != 0 or xl[p] not in self:
+ return x
+ xl[p] = self[xl[p]]
+ return b".".join(xl[p:])
+ def _make_graph(self, other_keys=[], **kargs):
+ nodes = [(k,self[k]) for k in self.keys()]
+ oids = [self[k] for k in self.keys()]
+ for k in other_keys:
+ if k not in oids:
+ nodes.append(self.oidname(k),k)
+ s = 'digraph "mib" {\n\trankdir=LR;\n\n'
+ for k,o in nodes:
+ s += '\t"%s" [ label="%s" ];\n' % (o,k)
+ s += "\n"
+ for k,o in nodes:
+ parent,remainder = self._findroot(o[:-1])
+ remainder = remainder[1:]+o[-1]
+ if parent != ".":
+ parent = self[parent]
+ s += '\t"%s" -> "%s" [label="%s"];\n' % (parent, o,remainder)
+ s += "}\n"
+ do_graph(s, **kargs)
+ def __len__(self):
+ return len(self.keys())
+
+
+def mib_register(ident, value, the_mib, unresolved):
+ if ident in the_mib or ident in unresolved:
+ return ident in the_mib
+ resval = []
+ not_resolved = 0
+ for v in value:
+ if _mib_re_integer.match(v):
+ resval.append(v)
+ else:
+ v = fixname(v)
+ if v not in the_mib:
+ not_resolved = 1
+ if v in the_mib:
+ v = the_mib[v]
+ elif v in unresolved:
+ v = unresolved[v]
+ if type(v) is list:
+ resval += v
+ else:
+ resval.append(v)
+ if not_resolved:
+ unresolved[ident] = resval
+ return False
+ else:
+ the_mib[ident] = resval
+ keys = unresolved.keys()
+ i = 0
+ while i < len(keys):
+ k = keys[i]
+ if mib_register(k,unresolved[k], the_mib, {}):
+ del(unresolved[k])
+ del(keys[i])
+ i = 0
+ else:
+ i += 1
+
+ return True
+
+
+def load_mib(filenames):
+ the_mib = {'iso': ['1']}
+ unresolved = {}
+ for k in conf.mib.keys():
+ mib_register(k, conf.mib[k].split("."), the_mib, unresolved)
+
+ if type(filenames) is str:
+ filenames = [filenames]
+ for fnames in filenames:
+ for fname in glob(fnames):
+ f = open(fname)
+ text = f.read()
+ cleantext = " ".join(_mib_re_strings.split(" ".join(_mib_re_comments.split(text))))
+ for m in _mib_re_oiddecl.finditer(cleantext):
+ gr = m.groups()
+ ident,oid = gr[0],gr[-1]
+ ident=fixname(ident)
+ oid = oid.split()
+ for i in range(len(oid)):
+ m = _mib_re_both.match(oid[i])
+ if m:
+ oid[i] = m.groups()[1]
+ mib_register(ident, oid, the_mib, unresolved)
+
+ newmib = MIBDict(_name="MIB")
+ for k,o in the_mib.items():
+ newmib[k]=".".join(o)
+ for k,o in unresolved.items():
+ newmib[k]=".".join(o)
+
+ conf.mib=newmib
+
+
+
+conf.mib = MIBDict(_name="MIB")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1fields.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1fields.py
new file mode 100644
index 00000000..e7165a83
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1fields.py
@@ -0,0 +1,341 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Classes that implement ASN.1 data structures.
+"""
+
+import itertools
+from scapy.asn1.asn1 import *
+from scapy.asn1.ber import *
+from scapy.volatile import *
+from scapy.base_classes import BasePacket
+
+
+#####################
+#### ASN1 Fields ####
+#####################
+
+class ASN1F_badsequence(Exception):
+ pass
+
+class ASN1F_element:
+ pass
+
+class ASN1F_optionnal(ASN1F_element):
+ def __init__(self, field):
+ self._field=field
+ def __getattr__(self, attr):
+ return getattr(self._field,attr)
+ def dissect(self,pkt,s):
+ try:
+ return self._field.dissect(pkt,s)
+ except ASN1F_badsequence:
+ self._field.set_val(pkt,None)
+ return s
+ except BER_Decoding_Error:
+ self._field.set_val(pkt,None)
+ return s
+ def build(self, pkt):
+ if self._field.is_empty(pkt):
+ return b""
+ return self._field.build(pkt)
+
+class ASN1F_field(ASN1F_element):
+ holds_packets=0
+ islist=0
+
+ ASN1_tag = ASN1_Class_UNIVERSAL.ANY
+ context=ASN1_Class_UNIVERSAL
+
+ def __init__(self, name, default, context=None):
+ if context is not None:
+ self.context = context
+ self.name = name
+ self.default = default
+
+ def i2repr(self, pkt, x):
+ return repr(x)
+ def i2h(self, pkt, x):
+ return x
+ def any2i(self, pkt, x):
+ return x
+ def m2i(self, pkt, x):
+ return self.ASN1_tag.get_codec(pkt.ASN1_codec).safedec(x, context=self.context)
+ def i2m(self, pkt, x):
+ if x is None:
+ x = 0
+ if isinstance(x, ASN1_Object):
+ if ( self.ASN1_tag == ASN1_Class_UNIVERSAL.ANY
+ or x.tag == ASN1_Class_UNIVERSAL.RAW
+ or x.tag == ASN1_Class_UNIVERSAL.ERROR
+ or self.ASN1_tag == x.tag ):
+ return x.enc(pkt.ASN1_codec)
+ else:
+ raise ASN1_Error("Encoding Error: got %r instead of an %r for field [%s]" % (x, self.ASN1_tag, self.name))
+ return self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x)
+
+ def do_copy(self, x):
+ if hasattr(x, "copy"):
+ return x.copy()
+ if type(x) is list:
+ x = x[:]
+ for i in range(len(x)):
+ if isinstance(x[i], BasePacket):
+ x[i] = x[i].copy()
+ return x
+
+ def build(self, pkt):
+ return self.i2m(pkt, getattr(pkt, self.name))
+
+ def set_val(self, pkt, val):
+ setattr(pkt, self.name, val)
+ def is_empty(self, pkt):
+ return getattr(pkt,self.name) is None
+
+ def dissect(self, pkt, s):
+ v,s = self.m2i(pkt, s)
+ self.set_val(pkt, v)
+ return s
+
+ def get_fields_list(self):
+ return [self]
+
+ def __hash__(self):
+ return hash(self.name)
+ def __str__(self):
+ return self.name
+ def __eq__(self, other):
+ return self.name == other
+ def __repr__(self):
+ return self.name
+ def randval(self):
+ return RandInt()
+
+
+class ASN1F_INTEGER(ASN1F_field):
+ ASN1_tag= ASN1_Class_UNIVERSAL.INTEGER
+ def randval(self):
+ return RandNum(-2**64, 2**64-1)
+
+class ASN1F_BOOLEAN(ASN1F_field):
+ ASN1_tag= ASN1_Class_UNIVERSAL.BOOLEAN
+ def randval(self):
+ return RandChoice(True,False)
+
+class ASN1F_NULL(ASN1F_INTEGER):
+ ASN1_tag= ASN1_Class_UNIVERSAL.NULL
+
+class ASN1F_SEP(ASN1F_NULL):
+ ASN1_tag= ASN1_Class_UNIVERSAL.SEP
+
+class ASN1F_enum_INTEGER(ASN1F_INTEGER):
+ def __init__(self, name, default, enum):
+ ASN1F_INTEGER.__init__(self, name, default)
+ i2s = self.i2s = {}
+ s2i = self.s2i = {}
+ if type(enum) is list:
+ keys = range(len(enum))
+ else:
+ keys = enum.keys()
+ #if filter(lambda x: type(x) is str, keys):
+ if list(filter(lambda x: type(x) is str, keys)):
+ i2s,s2i = s2i,i2s
+ for k in keys:
+ i2s[k] = enum[k]
+ s2i[enum[k]] = k
+ def any2i_one(self, pkt, x):
+ if type(x) is str:
+ x = self.s2i[x]
+ return x
+ def i2repr_one(self, pkt, x):
+ return self.i2s.get(x, repr(x))
+
+ def any2i(self, pkt, x):
+ if type(x) is list:
+ return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
+ else:
+ return self.any2i_one(pkt,x)
+ def i2repr(self, pkt, x):
+ if type(x) is list:
+ return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
+ else:
+ return self.i2repr_one(pkt,x)
+
+class ASN1F_ENUMERATED(ASN1F_enum_INTEGER):
+ ASN1_tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
+class ASN1F_STRING(ASN1F_field):
+ ASN1_tag = ASN1_Class_UNIVERSAL.STRING
+ def randval(self):
+ return RandString(RandNum(0, 1000))
+
+class ASN1F_PRINTABLE_STRING(ASN1F_STRING):
+ ASN1_tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
+
+class ASN1F_BIT_STRING(ASN1F_STRING):
+ ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
+
+class ASN1F_IPADDRESS(ASN1F_STRING):
+ ASN1_tag = ASN1_Class_UNIVERSAL.IPADDRESS
+
+class ASN1F_TIME_TICKS(ASN1F_INTEGER):
+ ASN1_tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+
+class ASN1F_UTC_TIME(ASN1F_STRING):
+ ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
+
+class ASN1F_GENERALIZED_TIME(ASN1F_STRING):
+ ASN1_tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
+class ASN1F_OID(ASN1F_field):
+ ASN1_tag = ASN1_Class_UNIVERSAL.OID
+ def randval(self):
+ return RandOID()
+
+class ASN1F_SEQUENCE(ASN1F_field):
+ ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE
+ def __init__(self, *seq, **kargs):
+ if "ASN1_tag" in kargs:
+ self.ASN1_tag = kargs["ASN1_tag"]
+ self.seq = seq
+ def __repr__(self):
+ return "<%s%r>" % (self.__class__.__name__,self.seq,)
+ def set_val(self, pkt, val):
+ for f in self.seq:
+ f.set_val(pkt,val)
+ def is_empty(self, pkt):
+ for f in self.seq:
+ if not f.is_empty(pkt):
+ return False
+ return True
+ def get_fields_list(self):
+ #return reduce(lambda x,y: x+y.get_fields_list(), self.seq, [])
+ return list(itertools.chain(*[ i.get_fields_list() for i in self.seq ]))
+ def build(self, pkt):
+ #s = reduce(lambda x,y: x+y.build(pkt), self.seq, b"")
+ s = b""
+ for i in self.seq:
+ s += i.build(pkt)
+ return self.i2m(pkt, s)
+ def dissect(self, pkt, s):
+ codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+ try:
+ i,s,remain = codec.check_type_check_len(s)
+ for obj in self.seq:
+ s = obj.dissect(pkt,s)
+ if s:
+ warning("Too many bytes to decode sequence: [%r]" % s) # XXX not reversible!
+ return remain
+ except ASN1_Error as e:
+ raise ASN1F_badsequence(e)
+
+class ASN1F_SET(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_UNIVERSAL.SET
+
+class ASN1F_SEQUENCE_OF(ASN1F_SEQUENCE):
+ holds_packets = 1
+ islist = 1
+ def __init__(self, name, default, asn1pkt, ASN1_tag=0x30):
+ self.asn1pkt = asn1pkt
+ self.tag = bytes([ASN1_tag])
+ self.name = name
+ self.default = default
+ def i2repr(self, pkt, i):
+ if i is None:
+ return []
+ return i
+ def get_fields_list(self):
+ return [self]
+ def set_val(self, pkt, val):
+ ASN1F_field.set_val(self, pkt, val)
+ def is_empty(self, pkt):
+ return ASN1F_field.is_empty(self, pkt)
+ def build(self, pkt):
+ val = getattr(pkt, self.name)
+ if isinstance(val, ASN1_Object) and val.tag == ASN1_Class_UNIVERSAL.RAW:
+ s = val
+ elif val is None:
+ s = b""
+ else:
+ #print(val)
+ #s = b"".join(map(str, val ))
+ s = b"".join([ bytes(i) for i in val ])
+ return self.i2m(pkt, s)
+ def dissect(self, pkt, s):
+ codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+ i,s1,remain = codec.check_type_check_len(s)
+ lst = []
+ while s1:
+ try:
+ p = self.asn1pkt(s1)
+ except ASN1F_badsequence as e:
+ lst.append(conf.raw_layer(s1))
+ break
+ lst.append(p)
+ if conf.raw_layer in p:
+ s1 = p[conf.raw_layer].load
+ del(p[conf.raw_layer].underlayer.payload)
+ else:
+ break
+ self.set_val(pkt, lst)
+ return remain
+ def randval(self):
+ return fuzz(self.asn1pkt())
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__,self.name)
+
+class ASN1F_PACKET(ASN1F_field):
+ holds_packets = 1
+ def __init__(self, name, default, cls):
+ ASN1F_field.__init__(self, name, default)
+ self.cls = cls
+ def i2m(self, pkt, x):
+ if x is None:
+ x = b""
+ return bytes(x)
+ def extract_packet(self, cls, x):
+ try:
+ c = cls(x)
+ except ASN1F_badsequence:
+ c = conf.raw_layer(x)
+ cpad = c.getlayer(conf.padding_layer)
+ x = b""
+ if cpad is not None:
+ x = cpad.load
+ del(cpad.underlayer.payload)
+ return c,x
+ def m2i(self, pkt, x):
+ return self.extract_packet(self.cls, x)
+
+
+class ASN1F_CHOICE(ASN1F_PACKET):
+ ASN1_tag = ASN1_Class_UNIVERSAL.NONE
+ def __init__(self, name, default, *args):
+ self.name=name
+ self.choice = {}
+ for p in args:
+ self.choice[p.ASN1_root.ASN1_tag] = p
+# self.context=context
+ self.default=default
+ def m2i(self, pkt, x):
+ if len(x) == 0:
+ return conf.raw_layer(),b""
+ raise ASN1_Error("ASN1F_CHOICE: got empty string")
+ #if ord(x[0]) not in self.choice:
+ if (x[0]) not in self.choice:
+ return conf.raw_layer(x),b"" # XXX return RawASN1 packet ? Raise error
+ #raise ASN1_Error("Decoding Error: choice [%i] not found in %r" % (ord(x[0]), self.choice.keys()))
+ raise ASN1_Error("Decoding Error: choice [%i] not found in %r" % ((x[0]), self.choice.keys()))
+
+ #z = ASN1F_PACKET.extract_packet(self, self.choice[ord(x[0])], x)
+ z = ASN1F_PACKET.extract_packet(self, self.choice[(x[0])], x)
+ return z
+ def randval(self):
+ return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
+
+
+# This import must come in last to avoid problems with cyclic dependencies
+import scapy.packet
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/asn1packet.py b/scripts/external_libs/scapy-python3-0.18/scapy/asn1packet.py
new file mode 100644
index 00000000..049e2b75
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/asn1packet.py
@@ -0,0 +1,26 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Packet holding data in Abstract Syntax Notation (ASN.1).
+"""
+
+from scapy.packet import *
+
+class ASN1_Packet(Packet):
+ ASN1_root = None
+ ASN1_codec = None
+ def init_fields(self):
+ flist = self.ASN1_root.get_fields_list()
+ self.do_init_fields(flist)
+ self.fields_desc = flist
+ def self_build(self):
+ if self.raw_packet_cache is not None:
+ return self.raw_packet_cache
+ return self.ASN1_root.build(self)
+ def do_dissect(self, x):
+ return self.ASN1_root.dissect(self, x)
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/automaton.py b/scripts/external_libs/scapy-python3-0.18/scapy/automaton.py
new file mode 100644
index 00000000..cd32b5c0
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/automaton.py
@@ -0,0 +1,753 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Automata with states, transitions and actions.
+"""
+
+from __future__ import with_statement
+import types,itertools,time,os,sys,socket,functools
+from select import select
+from collections import deque
+import _thread
+from .config import conf
+from .utils import do_graph
+from .error import log_interactive
+from .plist import PacketList
+from .data import MTU
+from .supersocket import SuperSocket
+
+class ObjectPipe:
+ def __init__(self):
+ self.rd,self.wr = os.pipe()
+ self.queue = deque()
+ def fileno(self):
+ return self.rd
+ def send(self, obj):
+ self.queue.append(obj)
+ os.write(self.wr,b"X")
+ def recv(self, n=0):
+ os.read(self.rd,1)
+ return self.queue.popleft()
+
+
+class Message:
+ def __init__(self, **args):
+ self.__dict__.update(args)
+ def __repr__(self):
+ return "<Message %s>" % " ".join("%s=%r"%(k,v)
+ for (k,v) in self.__dict__.items()
+ if not k.startswith("_"))
+
+# Currently does not seem necessary
+# class _meta_instance_state(type):
+# def __init__(cls, name, bases, dct):
+# def special_gen(special_method):
+# def special_wrapper(self):
+# print("Calling %s" % special_method)
+# return getattr(getattr(self, "im_func"), special_method)
+# return special_wrapper
+
+# type.__init__(cls, name, bases, dct)
+# for i in ["__int__", "__repr__", "__str__", "__index__", "__add__", "__radd__", "__bytes__"]:
+# setattr(cls, i, property(special_gen(i)))
+
+class _instance_state():
+ def __init__(self, instance):
+ self.im_self = instance.__self__
+ self.im_func = instance.__func__
+ self.im_class = instance.__self__.__class__
+ def __getattr__(self, attr):
+ return getattr(self.im_func, attr)
+
+ def __call__(self, *args, **kargs):
+ return self.im_func(self.im_self, *args, **kargs)
+ def breaks(self):
+ return self.im_self.add_breakpoints(self.im_func)
+ def intercepts(self):
+ return self.im_self.add_interception_points(self.im_func)
+ def unbreaks(self):
+ return self.im_self.remove_breakpoints(self.im_func)
+ def unintercepts(self):
+ return self.im_self.remove_interception_points(self.im_func)
+
+
+##############
+## Automata ##
+##############
+
+class ATMT:
+ STATE = "State"
+ ACTION = "Action"
+ CONDITION = "Condition"
+ RECV = "Receive condition"
+ TIMEOUT = "Timeout condition"
+ IOEVENT = "I/O event"
+
+ class NewStateRequested(Exception):
+ def __init__(self, state_func, automaton, *args, **kargs):
+ self.func = state_func
+ self.state = state_func.atmt_state
+ self.initial = state_func.atmt_initial
+ self.error = state_func.atmt_error
+ self.final = state_func.atmt_final
+ Exception.__init__(self, "Request state [%s]" % self.state)
+ self.automaton = automaton
+ self.args = args
+ self.kargs = kargs
+ self.action_parameters() # init action parameters
+ def action_parameters(self, *args, **kargs):
+ self.action_args = args
+ self.action_kargs = kargs
+ return self
+ def run(self):
+ return self.func(self.automaton, *self.args, **self.kargs)
+ def __repr__(self):
+ return "NewStateRequested(%s)" % self.state
+
+ @staticmethod
+ def state(initial=0,final=0,error=0):
+ def deco(f,initial=initial, final=final):
+ f.atmt_type = ATMT.STATE
+ f.atmt_state = f.__name__
+ f.atmt_initial = initial
+ f.atmt_final = final
+ f.atmt_error = error
+# @functools.wraps(f) This is possible alternative to assigning __qualname__; it would save __doc__, too
+ def state_wrapper(self, *args, **kargs):
+ return ATMT.NewStateRequested(f, self, *args, **kargs)
+
+ state_wrapper.__qualname__ = "%s_wrapper" % f.__name__
+ state_wrapper.atmt_type = ATMT.STATE
+ state_wrapper.atmt_state = f.__name__
+ state_wrapper.atmt_initial = initial
+ state_wrapper.atmt_final = final
+ state_wrapper.atmt_error = error
+ state_wrapper.atmt_origfunc = f
+ return state_wrapper
+ return deco
+ @staticmethod
+ def action(cond, prio=0):
+ def deco(f,cond=cond):
+ if not hasattr(f,"atmt_type"):
+ f.atmt_cond = {}
+ f.atmt_type = ATMT.ACTION
+ f.atmt_cond[cond.atmt_condname] = prio
+ return f
+ return deco
+ @staticmethod
+ def condition(state, prio=0):
+ def deco(f, state=state):
+ f.atmt_type = ATMT.CONDITION
+ f.atmt_state = state.atmt_state
+ f.atmt_condname = f.__name__
+ f.atmt_prio = prio
+ return f
+ return deco
+ @staticmethod
+ def receive_condition(state, prio=0):
+ def deco(f, state=state):
+ f.atmt_type = ATMT.RECV
+ f.atmt_state = state.atmt_state
+ f.atmt_condname = f.__name__
+ f.atmt_prio = prio
+ return f
+ return deco
+ @staticmethod
+ def ioevent(state, name, prio=0, as_supersocket=None):
+ def deco(f, state=state):
+ f.atmt_type = ATMT.IOEVENT
+ f.atmt_state = state.atmt_state
+ f.atmt_condname = f.__name__
+ f.atmt_ioname = name
+ f.atmt_prio = prio
+ f.atmt_as_supersocket = as_supersocket
+ return f
+ return deco
+ @staticmethod
+ def timeout(state, timeout):
+ def deco(f, state=state, timeout=timeout):
+ f.atmt_type = ATMT.TIMEOUT
+ f.atmt_state = state.atmt_state
+ f.atmt_timeout = timeout
+ f.atmt_condname = f.__name__
+ return f
+ return deco
+
+class _ATMT_Command:
+ RUN = "RUN"
+ NEXT = "NEXT"
+ FREEZE = "FREEZE"
+ STOP = "STOP"
+ END = "END"
+ EXCEPTION = "EXCEPTION"
+ SINGLESTEP = "SINGLESTEP"
+ BREAKPOINT = "BREAKPOINT"
+ INTERCEPT = "INTERCEPT"
+ ACCEPT = "ACCEPT"
+ REPLACE = "REPLACE"
+ REJECT = "REJECT"
+
+class _ATMT_supersocket(SuperSocket):
+ def __init__(self, name, ioevent, automaton, proto, args, kargs):
+ self.name = name
+ self.ioevent = ioevent
+ self.proto = proto
+ self.spa,self.spb = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM)
+ kargs["external_fd"] = {ioevent:self.spb}
+ self.atmt = automaton(*args, **kargs)
+ self.atmt.runbg()
+ def fileno(self):
+ return self.spa.fileno()
+ def send(self, s):
+ if type(s) is str:
+ s = s.encode()
+ elif type(s) is not bytes:
+ s = bytes(s)
+ return self.spa.send(s)
+ def recv(self, n=MTU):
+ r = self.spa.recv(n)
+ if self.proto is not None:
+ r = self.proto(r)
+ return r
+ def close(self):
+ pass
+
+class _ATMT_to_supersocket:
+ def __init__(self, name, ioevent, automaton):
+ self.name = name
+ self.ioevent = ioevent
+ self.automaton = automaton
+ def __call__(self, proto, *args, **kargs):
+ return _ATMT_supersocket(self.name, self.ioevent, self.automaton, proto, args, kargs)
+
+class Automaton_metaclass(type):
+ def __new__(cls, name, bases, dct):
+ cls = super(Automaton_metaclass, cls).__new__(cls, name, bases, dct)
+ cls.states={}
+ cls.state = None
+ cls.recv_conditions={}
+ cls.conditions={}
+ cls.ioevents={}
+ cls.timeout={}
+ cls.actions={}
+ cls.initial_states=[]
+ cls.ionames = []
+ cls.iosupersockets = []
+
+ members = {}
+ classes = [cls]
+ while classes:
+ c = classes.pop(0) # order is important to avoid breaking method overloading
+ classes += list(c.__bases__)
+ for k,v in c.__dict__.items():
+ if k not in members:
+ members[k] = v
+
+ decorated = [v for v in members.values()
+ if type(v) is types.FunctionType and hasattr(v, "atmt_type")]
+
+ for m in decorated:
+ if m.atmt_type == ATMT.STATE:
+ s = m.atmt_state
+ cls.states[s] = m
+ cls.recv_conditions[s]=[]
+ cls.ioevents[s]=[]
+ cls.conditions[s]=[]
+ cls.timeout[s]=[]
+ if m.atmt_initial:
+ cls.initial_states.append(m)
+ elif m.atmt_type in [ATMT.CONDITION, ATMT.RECV, ATMT.TIMEOUT, ATMT.IOEVENT]:
+ cls.actions[m.atmt_condname] = []
+
+ for m in decorated:
+ if m.atmt_type == ATMT.CONDITION:
+ cls.conditions[m.atmt_state].append(m)
+ elif m.atmt_type == ATMT.RECV:
+ cls.recv_conditions[m.atmt_state].append(m)
+ elif m.atmt_type == ATMT.IOEVENT:
+ cls.ioevents[m.atmt_state].append(m)
+ cls.ionames.append(m.atmt_ioname)
+ if m.atmt_as_supersocket is not None:
+ cls.iosupersockets.append(m)
+ elif m.atmt_type == ATMT.TIMEOUT:
+ cls.timeout[m.atmt_state].append((m.atmt_timeout, m))
+ elif m.atmt_type == ATMT.ACTION:
+ for c in m.atmt_cond:
+ cls.actions[c].append(m)
+
+
+ for v in cls.timeout.values():
+ #v.sort(lambda (t1,f1),(t2,f2): cmp(t1,t2))
+ v.sort(key = lambda x: x[0])
+ v.append((None, None))
+ for v in itertools.chain(cls.conditions.values(),
+ cls.recv_conditions.values(),
+ cls.ioevents.values()):
+ v.sort(key = lambda x: x.atmt_prio)
+ for condname,actlst in cls.actions.items():
+ actlst.sort(key = lambda x: x.atmt_cond[condname])
+
+ for ioev in cls.iosupersockets:
+ setattr(cls, ioev.atmt_as_supersocket, _ATMT_to_supersocket(ioev.atmt_as_supersocket, ioev.atmt_ioname, cls))
+
+ return cls
+
+ def graph(self, **kargs):
+ s = 'digraph "%s" {\n' % self.__class__.__name__
+
+ se = "" # Keep initial nodes at the begining for better rendering
+ for st in self.states.values():
+ if st.atmt_initial:
+ se = ('\t"%s" [ style=filled, fillcolor=blue, shape=box, root=true];\n' % st.atmt_state)+se
+ elif st.atmt_final:
+ se += '\t"%s" [ style=filled, fillcolor=green, shape=octagon ];\n' % st.atmt_state
+ elif st.atmt_error:
+ se += '\t"%s" [ style=filled, fillcolor=red, shape=octagon ];\n' % st.atmt_state
+ s += se
+
+ for st in self.states.values():
+ for n in st.atmt_origfunc.__code__.co_names+st.atmt_origfunc.__code__.co_consts:
+ if n in self.states:
+ s += '\t"%s" -> "%s" [ color=green ];\n' % (st.atmt_state,n)
+
+
+ for c,k,v in ([("purple",k,v) for k,v in self.conditions.items()]+
+ [("red",k,v) for k,v in self.recv_conditions.items()]+
+ [("orange",k,v) for k,v in self.ioevents.items()]):
+ for f in v:
+ for n in f.__code__.co_names+f.__code__.co_consts:
+ if n in self.states:
+ l = f.atmt_condname
+ for x in self.actions[f.atmt_condname]:
+ l += "\\l>[%s]" % x.__name__
+ s += '\t"%s" -> "%s" [label="%s", color=%s];\n' % (k,n,l,c)
+ for k,v in self.timeout.items():
+ for t,f in v:
+ if f is None:
+ continue
+ for n in f.__code__.co_names+f.__code__.co_consts:
+ if n in self.states:
+ l = "%s/%.1fs" % (f.atmt_condname,t)
+ for x in self.actions[f.atmt_condname]:
+ l += "\\l>[%s]" % x.__name__
+ s += '\t"%s" -> "%s" [label="%s",color=blue];\n' % (k,n,l)
+ s += "}\n"
+ return do_graph(s, **kargs)
+
+
+
+class Automaton(metaclass = Automaton_metaclass):
+
+ ## Methods to overload
+ def parse_args(self, debug=0, store=1, **kargs):
+ self.debug_level=debug
+ self.socket_kargs = kargs
+ self.store_packets = store
+
+ def master_filter(self, pkt):
+ return True
+
+ def my_send(self, pkt):
+ self.send_sock.send(pkt)
+
+
+ ## Utility classes and exceptions
+ class _IO_fdwrapper:
+ def __init__(self,rd,wr):
+ if rd is not None and type(rd) is not int:
+ rd = rd.fileno()
+ if wr is not None and type(wr) is not int:
+ wr = wr.fileno()
+ self.rd = rd
+ self.wr = wr
+ def fileno(self):
+ return self.rd
+ def read(self, n=65535):
+ return os.read(self.rd, n)
+ def write(self, msg):
+ return os.write(self.wr,msg)
+ def recv(self, n=65535):
+ return self.read(n)
+ def send(self, msg):
+ return self.write(msg)
+
+ class _IO_mixer:
+ def __init__(self,rd,wr):
+ self.rd = rd
+ self.wr = wr
+ def fileno(self):
+ if type(self.rd) is int:
+ return self.rd
+ return self.rd.fileno()
+ def recv(self, n=None):
+ return self.rd.recv(n)
+ def read(self, n=None):
+ return self.rd.recv(n)
+ def send(self, msg):
+ return self.wr.send(msg)
+ def write(self, msg):
+ return self.wr.send(msg)
+
+
+ class AutomatonException(Exception):
+ def __init__(self, msg, state=None, result=None):
+ Exception.__init__(self, msg)
+ self.state = state
+ self.result = result
+
+ class AutomatonError(AutomatonException):
+ pass
+ class ErrorState(AutomatonException):
+ pass
+ class Stuck(AutomatonException):
+ pass
+ class AutomatonStopped(AutomatonException):
+ pass
+
+ class Breakpoint(AutomatonStopped):
+ pass
+ class Singlestep(AutomatonStopped):
+ pass
+ class InterceptionPoint(AutomatonStopped):
+ def __init__(self, msg, state=None, result=None, packet=None):
+ Automaton.AutomatonStopped.__init__(self, msg, state=state, result=result)
+ self.packet = packet
+
+ class CommandMessage(AutomatonException):
+ pass
+
+
+ ## Services
+ def debug(self, lvl, msg):
+ if self.debug_level >= lvl:
+ log_interactive.debug(msg)
+
+ def send(self, pkt):
+ if self.state.state in self.interception_points:
+ self.debug(3,"INTERCEPT: packet intercepted: %s" % pkt.summary())
+ self.intercepted_packet = pkt
+ cmd = Message(type = _ATMT_Command.INTERCEPT, state=self.state, pkt=pkt)
+ self.cmdout.send(cmd)
+ cmd = self.cmdin.recv()
+ self.intercepted_packet = None
+ if cmd.type == _ATMT_Command.REJECT:
+ self.debug(3,"INTERCEPT: packet rejected")
+ return
+ elif cmd.type == _ATMT_Command.REPLACE:
+ pkt = cmd.pkt
+ self.debug(3,"INTERCEPT: packet replaced by: %s" % pkt.summary())
+ elif cmd.type == _ATMT_Command.ACCEPT:
+ self.debug(3,"INTERCEPT: packet accepted")
+ else:
+ raise self.AutomatonError("INTERCEPT: unkown verdict: %r" % cmd.type)
+ self.my_send(pkt)
+ self.debug(3,"SENT : %s" % pkt.summary())
+ self.packets.append(pkt.copy())
+
+
+ ## Internals
+ def __init__(self, *args, **kargs):
+ external_fd = kargs.pop("external_fd",{})
+ self.send_sock_class = kargs.pop("ll", conf.L3socket)
+ self.started = _thread.allocate_lock()
+ self.threadid = None
+ self.breakpointed = None
+ self.breakpoints = set()
+ self.interception_points = set()
+ self.intercepted_packet = None
+ self.debug_level=0
+ self.init_args=args
+ self.init_kargs=kargs
+ self.io = type.__new__(type, "IOnamespace",(),{})
+ self.oi = type.__new__(type, "IOnamespace",(),{})
+ self.cmdin = ObjectPipe()
+ self.cmdout = ObjectPipe()
+ self.ioin = {}
+ self.ioout = {}
+ for n in self.ionames:
+ extfd = external_fd.get(n)
+ if type(extfd) is not tuple:
+ extfd = (extfd,extfd)
+ ioin,ioout = extfd
+ if ioin is None:
+ ioin = ObjectPipe()
+ #elif type(ioin) is not types.InstanceType:
+ else:
+ #print(type(ioin))
+ ioin = self._IO_fdwrapper(ioin,None)
+ if ioout is None:
+ ioout = ObjectPipe()
+ #elif type(ioout) is not types.InstanceType:
+ else:
+ #print(type(ioout))
+ ioout = self._IO_fdwrapper(None,ioout)
+
+ self.ioin[n] = ioin
+ self.ioout[n] = ioout
+ ioin.ioname = n
+ ioout.ioname = n
+ setattr(self.io, n, self._IO_mixer(ioout,ioin))
+ setattr(self.oi, n, self._IO_mixer(ioin,ioout))
+
+ for stname in self.states:
+ setattr(self, stname,
+ _instance_state(getattr(self, stname)))
+
+ self.parse_args(*args, **kargs)
+
+ self.start()
+
+ def __iter__(self):
+ return self
+
+ def __del__(self):
+ self.stop()
+
+ def _run_condition(self, cond, *args, **kargs):
+ try:
+ self.debug(5, "Trying %s [%s]" % (cond.atmt_type, cond.atmt_condname))
+ cond(self,*args, **kargs)
+ except ATMT.NewStateRequested as state_req:
+ self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state))
+ if cond.atmt_type == ATMT.RECV:
+ self.packets.append(args[0])
+ for action in self.actions[cond.atmt_condname]:
+ self.debug(2, " + Running action [%s]" % action.__name__)
+ action(self, *state_req.action_args, **state_req.action_kargs)
+ raise
+ except Exception as e:
+ self.debug(2, "%s [%s] raised exception [%s]" % (cond.atmt_type, cond.atmt_condname, e))
+ raise
+ else:
+ self.debug(2, "%s [%s] not taken" % (cond.atmt_type, cond.atmt_condname))
+
+ def _do_start(self, *args, **kargs):
+
+ _thread.start_new_thread(self._do_control, args, kargs)
+
+
+ def _do_control(self, *args, **kargs):
+ with self.started:
+ self.threadid = _thread.get_ident()
+
+ # Update default parameters
+ a = args+self.init_args[len(args):]
+ k = self.init_kargs.copy()
+ k.update(kargs)
+ self.parse_args(*a,**k)
+
+ # Start the automaton
+ self.state=self.initial_states[0](self)
+ self.send_sock = self.send_sock_class()
+ self.listen_sock = conf.L2listen(**self.socket_kargs)
+ self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
+
+ singlestep = True
+ iterator = self._do_iter()
+ self.debug(3, "Starting control thread [tid=%i]" % self.threadid)
+ try:
+ while True:
+ c = self.cmdin.recv()
+ self.debug(5, "Received command %s" % c.type)
+ if c.type == _ATMT_Command.RUN:
+ singlestep = False
+ elif c.type == _ATMT_Command.NEXT:
+ singlestep = True
+ elif c.type == _ATMT_Command.FREEZE:
+ continue
+ elif c.type == _ATMT_Command.STOP:
+ break
+ while True:
+ state = next(iterator)
+ if isinstance(state, self.CommandMessage):
+ break
+ elif isinstance(state, self.Breakpoint):
+ c = Message(type=_ATMT_Command.BREAKPOINT,state=state)
+ self.cmdout.send(c)
+ break
+ if singlestep:
+ c = Message(type=_ATMT_Command.SINGLESTEP,state=state)
+ self.cmdout.send(c)
+ break
+ except StopIteration as e:
+ c = Message(type=_ATMT_Command.END, result=e.args[0])
+ self.cmdout.send(c)
+ except Exception as e:
+ self.debug(3, "Transfering exception [%s] from tid=%i"% (e,self.threadid))
+ m = Message(type = _ATMT_Command.EXCEPTION, exception=e, exc_info=sys.exc_info())
+ self.cmdout.send(m)
+ self.debug(3, "Stopping control thread (tid=%i)"%self.threadid)
+ self.threadid = None
+
+ def _do_iter(self):
+ while True:
+ try:
+ self.debug(1, "## state=[%s]" % self.state.state)
+
+ # Entering a new state. First, call new state function
+ if self.state.state in self.breakpoints and self.state.state != self.breakpointed:
+ self.breakpointed = self.state.state
+ yield self.Breakpoint("breakpoint triggered on state %s" % self.state.state,
+ state = self.state.state)
+ self.breakpointed = None
+ state_output = self.state.run()
+ if self.state.error:
+ raise self.ErrorState("Reached %s: [%r]" % (self.state.state, state_output),
+ result=state_output, state=self.state.state)
+ if self.state.final:
+ raise StopIteration(state_output)
+
+ if state_output is None:
+ state_output = ()
+ elif type(state_output) is not list:
+ state_output = state_output,
+
+ # Then check immediate conditions
+ for cond in self.conditions[self.state.state]:
+ self._run_condition(cond, *state_output)
+
+ # If still there and no conditions left, we are stuck!
+ if ( len(self.recv_conditions[self.state.state]) == 0 and
+ len(self.ioevents[self.state.state]) == 0 and
+ len(self.timeout[self.state.state]) == 1 ):
+ raise self.Stuck("stuck in [%s]" % self.state.state,
+ state=self.state.state, result=state_output)
+
+ # Finally listen and pay attention to timeouts
+ expirations = iter(self.timeout[self.state.state])
+ next_timeout,timeout_func = next(expirations)
+ t0 = time.time()
+
+ fds = [self.cmdin]
+ if len(self.recv_conditions[self.state.state]) > 0:
+ fds.append(self.listen_sock)
+ for ioev in self.ioevents[self.state.state]:
+ fds.append(self.ioin[ioev.atmt_ioname])
+ while 1:
+ t = time.time()-t0
+ if next_timeout is not None:
+ if next_timeout <= t:
+ self._run_condition(timeout_func, *state_output)
+ next_timeout,timeout_func = next(expirations)
+ if next_timeout is None:
+ remain = None
+ else:
+ remain = next_timeout-t
+
+ self.debug(5, "Select on %r" % fds)
+ r,_,_ = select(fds,[],[],remain)
+ self.debug(5, "Selected %r" % r)
+ for fd in r:
+ self.debug(5, "Looking at %r" % fd)
+ if fd == self.cmdin:
+ yield self.CommandMessage("Received command message")
+ elif fd == self.listen_sock:
+ pkt = self.listen_sock.recv(MTU)
+ if pkt is not None:
+ if self.master_filter(pkt):
+ self.debug(3, "RECVD: %s" % pkt.summary())
+ for rcvcond in self.recv_conditions[self.state.state]:
+ self._run_condition(rcvcond, pkt, *state_output)
+ else:
+ self.debug(4, "FILTR: %s" % pkt.summary())
+ else:
+ self.debug(3, "IOEVENT on %s" % fd.ioname)
+ for ioevt in self.ioevents[self.state.state]:
+ if ioevt.atmt_ioname == fd.ioname:
+ self._run_condition(ioevt, fd, *state_output)
+
+ except ATMT.NewStateRequested as state_req:
+ self.debug(2, "switching from [%s] to [%s]" % (self.state.state,state_req.state))
+ self.state = state_req
+ yield state_req
+
+ ## Public API
+ def add_interception_points(self, *ipts):
+ for ipt in ipts:
+ if hasattr(ipt,"atmt_state"):
+ ipt = ipt.atmt_state
+ self.interception_points.add(ipt)
+
+ def remove_interception_points(self, *ipts):
+ for ipt in ipts:
+ if hasattr(ipt,"atmt_state"):
+ ipt = ipt.atmt_state
+ self.interception_points.discard(ipt)
+
+ def add_breakpoints(self, *bps):
+ for bp in bps:
+ if hasattr(bp,"atmt_state"):
+ bp = bp.atmt_state
+ self.breakpoints.add(bp)
+
+ def remove_breakpoints(self, *bps):
+ for bp in bps:
+ if hasattr(bp,"atmt_state"):
+ bp = bp.atmt_state
+ self.breakpoints.discard(bp)
+
+ def start(self, *args, **kargs):
+ if not self.started.locked():
+ self._do_start(*args, **kargs)
+
+ def run(self, resume=None, wait=True):
+ if resume is None:
+ resume = Message(type = _ATMT_Command.RUN)
+ self.cmdin.send(resume)
+ if wait:
+ try:
+ c = self.cmdout.recv()
+ except KeyboardInterrupt:
+ self.cmdin.send(Message(type = _ATMT_Command.FREEZE))
+ return
+ if c.type == _ATMT_Command.END:
+ return c.result
+ elif c.type == _ATMT_Command.INTERCEPT:
+ raise self.InterceptionPoint("packet intercepted", state=c.state.state, packet=c.pkt)
+ elif c.type == _ATMT_Command.SINGLESTEP:
+ raise self.Singlestep("singlestep state=[%s]"%c.state.state, state=c.state.state)
+ elif c.type == _ATMT_Command.BREAKPOINT:
+ raise self.Breakpoint("breakpoint triggered on state [%s]"%c.state.state, state=c.state.state)
+ elif c.type == _ATMT_Command.EXCEPTION:
+ raise c.exc_info[0](c.exc_info[1])
+ #raise c.exc_info[0],c.exc_info[1],c.exc_info[2]
+
+ def runbg(self, resume=None, wait=False):
+ self.run(resume, wait)
+
+ def next(self):
+ return self.run(resume = Message(type=_ATMT_Command.NEXT))
+
+ def stop(self):
+ self.cmdin.send(Message(type=_ATMT_Command.STOP))
+ with self.started:
+ # Flush command pipes
+ while True:
+ r,_,_ = select([self.cmdin, self.cmdout],[],[],0)
+ if not r:
+ break
+ for fd in r:
+ fd.recv()
+
+ def restart(self, *args, **kargs):
+ self.stop()
+ self.start(*args, **kargs)
+
+ def accept_packet(self, pkt=None, wait=False):
+ rsm = Message()
+ if pkt is None:
+ rsm.type = _ATMT_Command.ACCEPT
+ else:
+ rsm.type = _ATMT_Command.REPLACE
+ rsm.pkt = pkt
+ return self.run(resume=rsm, wait=wait)
+
+ def reject_packet(self, wait=False):
+ rsm = Message(type = _ATMT_Command.REJECT)
+ return self.run(resume=rsm, wait=wait)
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/autorun.py b/scripts/external_libs/scapy-python3-0.18/scapy/autorun.py
new file mode 100644
index 00000000..063d93dc
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/autorun.py
@@ -0,0 +1,142 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Run commands when the Scapy interpreter starts.
+"""
+
+import code,sys
+from .config import conf
+from .themes import *
+from .error import Scapy_Exception
+from .utils import tex_escape
+
+
+#########################
+##### Autorun stuff #####
+#########################
+
+class StopAutorun(Scapy_Exception):
+ code_run = ""
+
+class ScapyAutorunInterpreter(code.InteractiveInterpreter):
+ def __init__(self, *args, **kargs):
+ code.InteractiveInterpreter.__init__(self, *args, **kargs)
+ self.error = 0
+ def showsyntaxerror(self, *args, **kargs):
+ self.error = 1
+ return code.InteractiveInterpreter.showsyntaxerror(self, *args, **kargs)
+ def showtraceback(self, *args, **kargs):
+ self.error = 1
+ exc_type, exc_value, exc_tb = sys.exc_info()
+ if isinstance(exc_value, StopAutorun):
+ raise exc_value
+ return code.InteractiveInterpreter.showtraceback(self, *args, **kargs)
+
+
+def autorun_commands(cmds,my_globals=None,verb=0):
+ sv = conf.verb
+ import builtins
+ try:
+ try:
+ if my_globals is None:
+ my_globals = __import__("scapy.all").all.__dict__
+ conf.verb = verb
+ interp = ScapyAutorunInterpreter(my_globals)
+ cmd = ""
+ cmds = cmds.splitlines()
+ cmds.append("") # ensure we finish multiline commands
+ cmds.reverse()
+ builtins.__dict__["_"] = None
+ while 1:
+ if cmd:
+ sys.stderr.write(sys.__dict__.get("ps2","... "))
+ else:
+ sys.stderr.write(str(sys.__dict__.get("ps1",ColorPrompt())))
+
+ l = cmds.pop()
+ print(l)
+ cmd += "\n"+l
+ if interp.runsource(cmd):
+ continue
+ if interp.error:
+ return 0
+ cmd = ""
+ if len(cmds) <= 1:
+ break
+ except SystemExit:
+ pass
+ finally:
+ conf.verb = sv
+ return _
+
+def autorun_get_interactive_session(cmds, **kargs):
+ class StringWriter:
+ def __init__(self):
+ self.s = ""
+ def write(self, x):
+ self.s += x
+
+ sw = StringWriter()
+ sstdout,sstderr = sys.stdout,sys.stderr
+ try:
+ try:
+ sys.stdout = sys.stderr = sw
+ res = autorun_commands(cmds, **kargs)
+ except StopAutorun as e:
+ e.code_run = sw.s
+ raise
+ finally:
+ sys.stdout,sys.stderr = sstdout,sstderr
+ return sw.s,res
+
+def autorun_get_text_interactive_session(cmds, **kargs):
+ ct = conf.color_theme
+ try:
+ conf.color_theme = NoTheme()
+ s,res = autorun_get_interactive_session(cmds, **kargs)
+ finally:
+ conf.color_theme = ct
+ return s,res
+
+def autorun_get_ansi_interactive_session(cmds, **kargs):
+ ct = conf.color_theme
+ try:
+ conf.color_theme = DefaultTheme()
+ s,res = autorun_get_interactive_session(cmds, **kargs)
+ finally:
+ conf.color_theme = ct
+ return s,res
+
+def autorun_get_html_interactive_session(cmds, **kargs):
+ ct = conf.color_theme
+ to_html = lambda s: s.replace("<","&lt;").replace(">","&gt;").replace("#[#","<").replace("#]#",">")
+ try:
+ try:
+ conf.color_theme = HTMLTheme2()
+ s,res = autorun_get_interactive_session(cmds, **kargs)
+ except StopAutorun as e:
+ e.code_run = to_html(e.code_run)
+ raise
+ finally:
+ conf.color_theme = ct
+
+ return to_html(s),res
+
+def autorun_get_latex_interactive_session(cmds, **kargs):
+ ct = conf.color_theme
+ to_latex = lambda s: tex_escape(s).replace("@[@","{").replace("@]@","}").replace("@`@","\\")
+ try:
+ try:
+ conf.color_theme = LatexTheme2()
+ s,res = autorun_get_interactive_session(cmds, **kargs)
+ except StopAutorun as e:
+ e.code_run = to_latex(e.code_run)
+ raise
+ finally:
+ conf.color_theme = ct
+ return to_latex(s),res
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/base_classes.py b/scripts/external_libs/scapy-python3-0.18/scapy/base_classes.py
new file mode 100644
index 00000000..bace90d6
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/base_classes.py
@@ -0,0 +1,237 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Generators and packet meta classes.
+"""
+
+###############
+## Generators ##
+################
+
+import re,random,socket
+from types import GeneratorType
+import scapy.config
+from . import error
+
+class Gen(object):
+ def __iter__(self):
+ return iter([])
+
+class SetGen(Gen):
+ def __init__(self, col, _iterpacket=1):
+ self._iterpacket=_iterpacket
+ if type(col) is list or isinstance(col, GeneratorType):
+ self.col = col
+ elif isinstance(col, BasePacketList):
+ self.col = list(col)
+ else:
+ self.col = [col]
+ # DEPRECATED
+ # def transf(self, element):
+ # return element
+ def __iter__(self):
+ for i in self.col:
+ if (type(i) is tuple) and (len(i) == 2) and type(i[0]) is int and type(i[1]) is int:
+ if (i[0] <= i[1]):
+ j=i[0]
+ while j <= i[1]:
+ yield j
+ j += 1
+ elif isinstance(i, Gen) and (self._iterpacket or not isinstance(i,BasePacket)):
+ for j in i:
+ yield j
+ else:
+ yield i
+ def __repr__(self):
+ return "<SetGen %s>" % self.col.__repr__()
+
+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])?$")
+
+ @staticmethod
+ def _parse_digit(a,netmask):
+ netmask = min(8,max(netmask,0))
+ if a == "*":
+ a = (0,256)
+ elif a.find("-") >= 0:
+ x,y = map(int,a.split("-"))
+ if x > y:
+ y = x
+ a = (x & (0xff<<netmask) , max(y, (x | (0xff>>(8-netmask))))+1)
+ else:
+ a = (int(a) & (0xff<<netmask),(int(a) | (0xff>>(8-netmask)))+1)
+ return a
+
+ @classmethod
+ def _parse_net(cls, net):
+ tmp=net.split('/')+["32"]
+ if not cls.ipaddress.match(net):
+ tmp[0]=socket.gethostbyname(tmp[0])
+ netmask = int(tmp[1])
+ #return map(lambda x,y: cls._parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32))),netmask
+ return list(map(lambda x,y: cls._parse_digit(x,y), tmp[0].split("."), [ i - netmask for i in (8,16,24,32)] )),netmask
+
+ def __init__(self, net):
+ self.repr=net
+ self.parsed,self.netmask = self._parse_net(net)
+
+ def __iter__(self):
+ for d in range(*self.parsed[3]):
+ for c in range(*self.parsed[2]):
+ for b in range(*self.parsed[1]):
+ for a in range(*self.parsed[0]):
+ yield "%i.%i.%i.%i" % (a,b,c,d)
+ def choice(self):
+ ip = []
+ for v in self.parsed:
+ ip.append(str(random.randint(v[0],v[1]-1)))
+ return ".".join(ip)
+
+ def __repr__(self):
+ return "Net(%r)" % self.repr
+ def __eq__(self, other):
+ if hasattr(other, "parsed"):
+ p2 = other.parsed
+ else:
+ p2,nm2 = self._parse_net(other)
+ return self.parsed == p2
+ def __contains__(self, other):
+ if hasattr(other, "parsed"):
+ p2 = other.parsed
+ else:
+ p2,nm2 = self._parse_net(other)
+ for (a1,b1),(a2,b2) in zip(self.parsed,p2):
+ if a1 > a2 or b1 < b2:
+ return False
+ return True
+ def __rcontains__(self, other):
+ return self in self.__class__(other)
+
+
+class OID(Gen):
+ name = "OID"
+ def __init__(self, oid):
+ self.oid = oid
+ self.cmpt = []
+ fmt = []
+ for i in oid.split("."):
+ if "-" in i:
+ fmt.append("%i")
+ self.cmpt.append(tuple(map(int, i.split("-"))))
+ else:
+ fmt.append(i)
+ self.fmt = ".".join(fmt)
+ def __repr__(self):
+ return "OID(%r)" % self.oid
+ def __iter__(self):
+ ii = [k[0] for k in self.cmpt]
+ while 1:
+ yield self.fmt % tuple(ii)
+ i = 0
+ while 1:
+ if i >= len(ii):
+ raise StopIteration
+ if ii[i] < self.cmpt[i][1]:
+ ii[i]+=1
+ break
+ else:
+ ii[i] = self.cmpt[i][0]
+ i += 1
+
+
+
+######################################
+## Packet abstract and base classes ##
+######################################
+
+class Packet_metaclass(type):
+ def __new__(cls, name, bases, dct):
+ if "fields_desc" in dct: # perform resolution of references to other packets
+ current_fld = dct["fields_desc"]
+ resolved_fld = []
+ for f in current_fld:
+ if isinstance(f, Packet_metaclass): # reference to another fields_desc
+ for f2 in f.fields_desc:
+ resolved_fld.append(f2)
+ else:
+ resolved_fld.append(f)
+ else: # look for a field_desc in parent classes
+ resolved_fld = None
+ for b in bases:
+ if hasattr(b,"fields_desc"):
+ resolved_fld = b.fields_desc
+ break
+
+ if resolved_fld: # perform default value replacements
+ final_fld = []
+ for f in resolved_fld:
+ if f.name in dct:
+ f = f.copy()
+ f.default = dct[f.name]
+ del(dct[f.name])
+ final_fld.append(f)
+
+ dct["fields_desc"] = final_fld
+
+ newcls = super(Packet_metaclass, cls).__new__(cls, name, bases, dct)
+ if hasattr(newcls,"register_variant"):
+ newcls.register_variant()
+ for f in newcls.fields_desc:
+ f.register_owner(newcls)
+ scapy.config.conf.layers.register(newcls)
+ return newcls
+
+ def __getattr__(self, attr):
+ for k in self.fields_desc:
+ if k.name == attr:
+ return k
+ raise AttributeError(attr)
+
+ def __call__(cls, *args, **kargs):
+ if "dispatch_hook" in cls.__dict__:
+ cls = cls.dispatch_hook(*args, **kargs)
+ i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
+ i.__init__(*args, **kargs)
+ return i
+
+
+class NewDefaultValues(Packet_metaclass):
+ """NewDefaultValues is deprecated (not needed anymore)
+
+ remove this:
+ __metaclass__ = NewDefaultValues
+ and it should still work.
+ """
+ def __new__(cls, name, bases, dct):
+ from error import log_loading
+ import traceback
+ try:
+ for tb in traceback.extract_stack()+[("??",-1,None,"")]:
+ f,l,_,line = tb
+ if line.startswith("class"):
+ break
+ except:
+ f,l="??",-1
+ raise
+ log_loading.warning("Deprecated (no more needed) use of NewDefaultValues (%s l. %i)." % (f,l))
+
+ return super(NewDefaultValues, cls).__new__(cls, name, bases, dct)
+
+class BasePacket(Gen):
+ pass
+
+
+#############################
+## Packet list base classe ##
+#############################
+
+class BasePacketList:
+ pass
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/config.py b/scripts/external_libs/scapy-python3-0.18/scapy/config.py
new file mode 100644
index 00000000..88c324f8
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/config.py
@@ -0,0 +1,394 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Implementation for of the configuration object.
+"""
+
+import os,time,socket,sys
+from .data import *
+import scapy.base_classes
+import scapy.themes
+from .error import log_scapy
+
+############
+## Config ##
+############
+
+class ConfClass(object):
+ def configure(self, cnf):
+ self.__dict__ = cnf.__dict__.copy()
+ def __repr__(self):
+ return str(self)
+ def __str__(self):
+ s=""
+ keys = self.__class__.__dict__.copy()
+ keys.update(self.__dict__)
+ keys = list(keys.keys())
+ keys.sort()
+ for i in keys:
+ if i[0] != "_":
+ r = repr(getattr(self, i))
+ r = " ".join(r.split())
+ wlen = 76-max(len(i),10)
+ if len(r) > wlen:
+ r = r[:wlen-3]+"..."
+ s += "%-10s = %s\n" % (i, r)
+ return s[:-1]
+
+class Interceptor(object):
+ def __init__(self, name, default, hook, args=None, kargs=None):
+ self.name = name
+ self.intname = "_intercepted_%s" % name
+ self.default=default
+ self.hook = hook
+ self.args = args if args is not None else []
+ self.kargs = kargs if kargs is not None else {}
+ def __get__(self, obj, typ=None):
+ if not hasattr(obj, self.intname):
+ setattr(obj, self.intname, self.default)
+ return getattr(obj, self.intname)
+ def __set__(self, obj, val):
+ setattr(obj, self.intname, val)
+ self.hook(self.name, val, *self.args, **self.kargs)
+
+
+class ProgPath(ConfClass):
+ pdfreader = "acroread"
+ psreader = "gv"
+ dot = "dot"
+ display = "display"
+ tcpdump = "tcpdump"
+ tcpreplay = "tcpreplay"
+ hexedit = "hexedit"
+ wireshark = "wireshark"
+
+
+class ConfigFieldList:
+ def __init__(self):
+ self.fields = set()
+ self.layers = set()
+ @staticmethod
+ def _is_field(f):
+ return hasattr(f, "owners")
+ def _recalc_layer_list(self):
+ self.layers = set([owner for f in self.fields for owner in f.owners])
+ def add(self, *flds):
+ self.fields |= set([f for f in flds if self._is_field(f)])
+ self._recalc_layer_list()
+ def remove(self, *flds):
+ self.fields -= set(flds)
+ self._recalc_layer_list()
+ def __contains__(self, elt):
+ if isinstance(elt, scapy.base_classes.Packet_metaclass):
+ return elt in self.layers
+ return elt in self.fields
+ def __repr__(self):
+ return "<%s [%s]>" % (self.__class__.__name__," ".join(str(x) for x in self.fields))
+
+class Emphasize(ConfigFieldList):
+ pass
+
+class Resolve(ConfigFieldList):
+ pass
+
+
+class Num2Layer:
+ def __init__(self):
+ self.num2layer = {}
+ self.layer2num = {}
+
+ def register(self, num, layer):
+ self.register_num2layer(num, layer)
+ self.register_layer2num(num, layer)
+
+ def register_num2layer(self, num, layer):
+ self.num2layer[num] = layer
+ def register_layer2num(self, num, layer):
+ self.layer2num[layer] = num
+
+ def __getitem__(self, item):
+ if isinstance(item, scapy.base_classes.Packet_metaclass):
+ return self.layer2num[item]
+ return self.num2layer[item]
+ def __contains__(self, item):
+ if isinstance(item, scapy.base_classes.Packet_metaclass):
+ return item in self.layer2num
+ return item in self.num2layer
+ def get(self, item, default=None):
+ if item in self:
+ return self[item]
+ return default
+
+ def __repr__(self):
+ lst = []
+ for num,layer in self.num2layer.items():
+ if layer in self.layer2num and self.layer2num[layer] == num:
+ dir = "<->"
+ else:
+ dir = " ->"
+ lst.append((num,"%#6x %s %-20s (%s)" % (num,dir,layer.__name__,layer.name)))
+ for layer,num in self.layer2num.items():
+ if num not in self.num2layer or self.num2layer[num] != layer:
+ lst.append((num,"%#6x <- %-20s (%s)" % (num,layer.__name__,layer.name)))
+ lst.sort()
+ return "\n".join(y for x,y in lst)
+
+
+class LayersList(list):
+ def __repr__(self):
+ s=[]
+ for l in self:
+ s.append("%-20s: %s" % (l.__name__,l.name))
+ return "\n".join(s)
+ def register(self, layer):
+ self.append(layer)
+
+class CommandsList(list):
+ def __repr__(self):
+ s=[]
+ for l in sorted(self,key=lambda x:x.__name__):
+ if l.__doc__:
+ doc = l.__doc__.split("\n")[0]
+ else:
+ doc = "--"
+ s.append("%-20s: %s" % (l.__name__,doc))
+ return "\n".join(s)
+ def register(self, cmd):
+ self.append(cmd)
+ return cmd # return cmd so that method can be used as a decorator
+
+def lsc():
+ print(repr(conf.commands))
+
+class CacheInstance(dict):
+ def __init__(self, name="noname", timeout=None):
+ self.timeout = timeout
+ self.name = name
+ self._timetable = {}
+ def __getitem__(self, item):
+ val = dict.__getitem__(self,item)
+ if self.timeout is not None:
+ t = self._timetable[item]
+ if time.time()-t > self.timeout:
+ raise KeyError(item)
+ return val
+ def get(self, item, default=None):
+ # overloading this method is needed to force the dict to go through
+ # the timetable check
+ try:
+ return self[item]
+ except KeyError:
+ return default
+ def __setitem__(self, item, v):
+ try:
+ self._timetable[item] = time.time()
+ except AttributeError:
+ pass
+ dict.__setitem__(self, item,v)
+ def update(self, other):
+ dict.update(self, other)
+ self._timetable.update(other._timetable)
+ def items(self):
+ if self.timeout is None:
+ return dict.items(self)
+ t0=time.time()
+ return ((k,v) for (k,v) in dict.items(self) if t0-self._timetable[k] < self.timeout)
+ def keys(self):
+ if self.timeout is None:
+ return dict.keys(self)
+ t0=time.time()
+ return (k for k in dict.keys(self) if t0-self._timetable[k] < self.timeout)
+ def __iter__(self):
+ return self.keys()
+ def values(self):
+ if self.timeout is None:
+ return dict.values(self)
+ t0=time.time()
+ return (v for (k,v) in dict.items(self) if t0-self._timetable[k] < self.timeout)
+ def items(self):
+ if self.timeout is None:
+ return dict.items(self)
+ t0=time.time()
+ return [(k,v) for (k,v) in dict.items(self) if t0-self._timetable[k] < self.timeout]
+ def keys(self):
+ if self.timeout is None:
+ return dict.keys(self)
+ t0=time.time()
+ return [k for k in dict.keys(self) if t0-self._timetable[k] < self.timeout]
+ def values(self):
+ if self.timeout is None:
+ return dict.values(self)
+ t0=time.time()
+ return [v for (k,v) in dict.items(self) if t0-self._timetable[k] < self.timeout]
+ def __len__(self):
+ if self.timeout is None:
+ return dict.__len__(self)
+ return len(self.keys())
+ def summary(self):
+ return "%s: %i valid items. Timeout=%rs" % (self.name, len(self), self.timeout)
+ def __repr__(self):
+ s = []
+ if self:
+ mk = max(len(k) for k in self.keys())
+ fmt = "%%-%is %%s" % (mk+1)
+ for item in self.items():
+ s.append(fmt % item)
+ return "\n".join(s)
+
+
+
+
+class NetCache:
+ def __init__(self):
+ self._caches_list = []
+
+
+ def add_cache(self, cache):
+ self._caches_list.append(cache)
+ setattr(self,cache.name,cache)
+ def new_cache(self, name, timeout=None):
+ c = CacheInstance(name=name, timeout=timeout)
+ self.add_cache(c)
+ def __delattr__(self, attr):
+ raise AttributeError("Cannot delete attributes")
+ def update(self, other):
+ for co in other._caches_list:
+ if hasattr(self, co.name):
+ getattr(self,co.name).update(co)
+ else:
+ self.add_cache(co.copy())
+ def flush(self):
+ for c in self._caches_list:
+ c.flush()
+ def __repr__(self):
+ return "\n".join(c.summary() for c in self._caches_list)
+
+
+class LogLevel(object):
+ def __get__(self, obj, otype):
+ return obj._logLevel
+ def __set__(self,obj,val):
+ log_scapy.setLevel(val)
+ obj._logLevel = val
+
+
+
+def _prompt_changer(attr,val):
+ prompt = conf.prompt
+ try:
+ ct = val
+ if isinstance(ct, AnsiColorTheme) and ct.prompt(""):
+ ## ^A and ^B delimit invisible caracters for readline to count right.
+ ## And we need ct.prompt() to do change something or else ^A and ^B will be
+ ## displayed
+ prompt = "\001%s\002" % ct.prompt("\002"+prompt+"\001")
+ else:
+ prompt = ct.prompt(prompt)
+ except:
+ pass
+ sys.ps1 = prompt
+
+
+class Conf(ConfClass):
+ """This object contains the configuration of scapy.
+session : filename where the session will be saved
+interactive_shell : If set to "ipython", use IPython as shell. Default: IPython.
+ipython_embedded : If True use embedded ipython shell, standard ipython shell otherwise.
+stealth : if 1, prevents any unwanted packet to go out (ARP, DNS, ...)
+checkIPID: if 0, doesn't check that IPID matches between IP sent and ICMP IP citation received
+ if 1, checks that they either are equal or byte swapped equals (bug in some IP stacks)
+ if 2, strictly checks that they are equals
+checkIPsrc: if 1, checks IP src in IP and ICMP IP citation match (bug in some NAT stacks)
+check_TCPerror_seqack: if 1, also check that TCP seq and ack match the ones in ICMP citation
+iff : selects the default output interface for srp() and sendp(). default:"eth0")
+verb : level of verbosity, from 0 (almost mute) to 3 (verbose)
+promisc : default mode for listening socket (to get answers if you spoof on a lan)
+sniff_promisc : default mode for sniff()
+filter : bpf filter added to every sniffing socket to exclude traffic from analysis
+histfile : history file
+padding : includes padding in desassembled packets
+except_filter : BPF filter for packets to ignore
+debug_match : when 1, store received packet that are not matched into debug.recv
+route : holds the Scapy routing table and provides methods to manipulate it
+warning_threshold : how much time between warnings from the same place
+ASN1_default_codec: Codec used by default for ASN1 objects
+mib : holds MIB direct access dictionnary
+resolve : holds list of fields for which resolution should be done
+noenum : holds list of enum fields for which conversion to string should NOT be done
+AS_resolver: choose the AS resolver class to use
+extensions_paths: path or list of paths where extensions are to be looked for
+"""
+ version = "3.0.0"
+ session = ""
+ interactive = False
+ interactive_shell = "ipython"
+ ipython_embedded = True
+ stealth = "not implemented"
+ iface = None
+ readfunc = None
+ layers = LayersList()
+ commands = CommandsList()
+ logLevel = LogLevel()
+ checkIPID = 0
+ checkIPsrc = 1
+ checkIPaddr = 1
+ check_TCPerror_seqack = 0
+ verb = 2
+ prompt = ">>> "
+ promisc = 1
+ sniff_promisc = 1
+ raw_layer = None
+ raw_summary = False
+ default_l2 = None
+ l2types = Num2Layer()
+ l3types = Num2Layer()
+ L3socket = None
+ L2socket = None
+ L2listen = None
+ histfile = os.path.join(os.path.expanduser("~"), ".scapy_history")
+ padding = 1
+ except_filter = ""
+ debug_match = 0
+ wepkey = ""
+ route = None # Filled by route.py
+ route6 = None # Filled by route6.py
+ auto_fragment = 1
+ debug_dissector = 0
+ color_theme = Interceptor("color_theme", scapy.themes.NoTheme(), _prompt_changer)
+ warning_threshold = 5
+ prog = ProgPath()
+ resolve = Resolve()
+ noenum = Resolve()
+ emph = Emphasize()
+ use_dnet = False
+ use_winpcapy = False
+ use_netifaces = False
+ ipv6_enabled = socket.has_ipv6
+ ethertypes = ETHER_TYPES
+ protocols = IP_PROTOS
+ services_tcp = TCP_SERVICES
+ services_udp = UDP_SERVICES
+ extensions_paths = "."
+ manufdb = MANUFDB
+ stats_classic_protocols = []
+ stats_dot11_protocols = []
+ temp_files = []
+ netcache = NetCache()
+ load_layers = [ "l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp",
+ "mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp",
+ "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp",
+ "ipsec" ]
+
+if not Conf.ipv6_enabled:
+ log_scapy.warning("IPv6 support disabled in Python. Cannot load scapy IPv6 layers.")
+ for m in ["inet6","dhcp6"]:
+ if m in Conf.load_layers:
+ Conf.load_layers.remove(m)
+
+
+conf=Conf()
+conf.logLevel=30 # 30=Warning
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/__init__.py
new file mode 100644
index 00000000..99654377
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/__init__.py
@@ -0,0 +1,8 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Package of contrib modules that have to be loaded explicitly.
+"""
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/avs.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/avs.py
new file mode 100644
index 00000000..461b94b8
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/avs.py
@@ -0,0 +1,57 @@
+#! /usr/bin/env python
+
+# http://trac.secdev.org/scapy/ticket/82
+
+# scapy.contrib.description = AVS WLAN Monitor Header
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.dot11 import *
+
+AVSWLANPhyType = { 0 : "Unknown",
+ 1 : "FHSS 802.11 '97",
+ 2 : "DSSS 802.11 '97",
+ 3 : "IR Baseband",
+ 4 : "DSSS 802.11b",
+ 5 : "PBCC 802.11b",
+ 6 : "OFDM 802.11g",
+ 7 : "PBCC 802.11g",
+ 8 : "OFDM 802.11a" }
+
+AVSWLANEncodingType = { 0 : "Unknown",
+ 1 : "CCK",
+ 2 : "PBCC",
+ 3 : "OFDM"}
+
+AVSWLANSSIType = { 0 : "None",
+ 1 : "Normalized RSSI",
+ 2 : "dBm",
+ 3 : "Raw RSSI"}
+
+AVSWLANPreambleType = { 0 : "Unknown",
+ 1 : "Short",
+ 2 : "Long" }
+
+
+class AVSWLANHeader(Packet):
+ """ iwpriv eth1 set_prismhdr 1 """
+ name = "AVS WLAN Monitor Header"
+ fields_desc = [ IntField("version",1),
+ IntField("len",64),
+ LongField("mactime",0),
+ LongField("hosttime",0),
+ IntEnumField("phytype",0, AVSWLANPhyType),
+ IntField("channel",0),
+ IntField("datarate",0),
+ IntField("antenna",0),
+ IntField("priority",0),
+ IntEnumField("ssi_type",0, AVSWLANSSIType),
+ SignedIntField("ssi_signal",0),
+ SignedIntField("ssi_noise",0),
+ IntEnumField("preamble",0, AVSWLANPreambleType),
+ IntEnumField("encoding",0, AVSWLANEncodingType),
+ ]
+
+bind_layers(AVSWLANHeader, Dot11)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/bgp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/bgp.py
new file mode 100644
index 00000000..525dac5f
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/bgp.py
@@ -0,0 +1,168 @@
+#! /usr/bin/env python
+
+# http://trac.secdev.org/scapy/ticket/162
+
+# scapy.contrib.description = BGP
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import TCP
+
+
+class BGPIPField(Field):
+ """Represents how bgp dose an ip prefix in (length, prefix)"""
+ def mask2iplen(self,mask):
+ """turn the mask into the length in bytes of the ip field"""
+ return (mask + 7) // 8
+ def h2i(self, pkt, h):
+ """human x.x.x.x/y to internal"""
+ ip,mask = re.split( '/', h)
+ return int(mask), ip
+ def i2h( self, pkt, i):
+ mask, ip = i
+ return ip + '/' + str( mask )
+ def i2repr( self, pkt, i):
+ """make it look nice"""
+ return self.i2h(pkt,i)
+ def i2len(self, pkt, i):
+ """rely on integer division"""
+ mask, ip = i
+ return self.mask2iplen(mask) + 1
+ def i2m(self, pkt, i):
+ """internal (ip as bytes, mask as int) to machine"""
+ mask, ip = i
+ ip = inet_aton( ip )
+ return struct.pack(">B",mask) + ip[:self.mask2iplen(mask)]
+ def addfield(self, pkt, s, val):
+ return s+self.i2m(pkt, val)
+ def getfield(self, pkt, s):
+ l = self.mask2iplen( struct.unpack(">B",s[0])[0] ) + 1
+ return s[l:], self.m2i(pkt,s[:l])
+ def m2i(self,pkt,m):
+ mask = struct.unpack(">B",m[0])[0]
+ ip = "".join( [ m[i + 1] if i < self.mask2iplen(mask) else '\x00' for i in range(4)] )
+ return (mask,inet_ntoa(ip))
+
+class BGPHeader(Packet):
+ """The first part of any BGP packet"""
+ name = "BGP header"
+ fields_desc = [
+ XBitField("marker",0xffffffffffffffffffffffffffffffff, 0x80 ),
+ ShortField("len", None),
+ ByteEnumField("type", 4, {0:"none", 1:"open",2:"update",3:"notification",4:"keep_alive"}),
+ ]
+ def post_build(self, p, pay):
+ if self.len is None and pay:
+ l = len(p) + len(pay)
+ p = p[:16]+struct.pack("!H", l)+p[18:]
+ return p+pay
+
+class BGPOptionalParameter(Packet):
+ """Format of optional Parameter for BGP Open"""
+ name = "BGP Optional Parameters"
+ fields_desc = [
+ ByteField("type", 2),
+ ByteField("len", None),
+ StrLenField("value", "", length_from = lambda x: x.len),
+ ]
+ def post_build(self,p,pay):
+ if self.len is None:
+ l = len(p) - 2 # 2 is length without value
+ p = p[:1]+struct.pack("!B", l)+p[2:]
+ return p+pay
+ def extract_padding(self, p):
+ """any thing after this packet is extracted is padding"""
+ return "",p
+
+class BGPOpen(Packet):
+ """ Opens a new BGP session"""
+ name = "BGP Open Header"
+ fields_desc = [
+ ByteField("version", 4),
+ ShortField("AS", 0),
+ ShortField("hold_time", 0),
+ IPField("bgp_id","0.0.0.0"),
+ ByteField("opt_parm_len", None),
+ PacketListField("opt_parm",[], BGPOptionalParameter, length_from=lambda p:p.opt_parm_len),
+ ]
+ def post_build(self, p, pay):
+ if self.opt_parm_len is None:
+ l = len(p) - 10 # 10 is regular length with no additional options
+ p = p[:9] + struct.pack("!B",l) +p[10:]
+ return p+pay
+
+class BGPAuthenticationData(Packet):
+ name = "BGP Authentication Data"
+ fields_desc = [
+ ByteField("AuthenticationCode", 0),
+ ByteField("FormMeaning", 0),
+ FieldLenField("Algorithm", 0),
+ ]
+
+class BGPPathAttribute(Packet):
+ "the attribute of total path"
+ name = "BGP Attribute fields"
+ fields_desc = [
+ FlagsField("flags", 0x40, 8, ["NA0","NA1","NA2","NA3","Extended-Length","Partial","Transitive","Optional"]), #Extened leght may not work
+ ByteEnumField("type", 1, {1:"ORIGIN", 2:"AS_PATH", 3:"NEXT_HOP", 4:"MULTI_EXIT_DISC", 5:"LOCAL_PREF", 6:"ATOMIC_AGGREGATE", 7:"AGGREGATOR"}),
+ ByteField("attr_len", None),
+ StrLenField("value", "", length_from = lambda p: p.attr_len),
+ ]
+ def post_build(self, p, pay):
+ if self.attr_len is None:
+ l = len(p) - 3 # 3 is regular length with no additional options
+ p = p[:2] + struct.pack("!B",l) +p[3:]
+ return p+pay
+ def extract_padding(self, p):
+ """any thing after this packet is extracted is padding"""
+ return "",p
+
+class BGPUpdate(Packet):
+ """Update the routes WithdrawnRoutes = UnfeasiableRoutes"""
+ name = "BGP Update fields"
+ fields_desc = [
+ ShortField("withdrawn_len", None),
+ FieldListField("withdrawn",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.withdrawn_len),
+ ShortField("tp_len", None),
+ PacketListField("total_path", [], BGPPathAttribute, length_from = lambda p: p.tp_len),
+ FieldListField("nlri",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.underlayer.len - 23 - p.tp_len - p.withdrawn_len), # len should be BGPHeader.len
+ ]
+ def post_build(self,p,pay):
+ wl = self.withdrawn_len
+ subpacklen = lambda p: len ( str( p ))
+ subfieldlen = lambda p: BGPIPField("", "0.0.0.0/0").i2len(self, p )
+ if wl is None:
+ wl = sum ( map ( subfieldlen , self.withdrawn))
+ p = p[:0]+struct.pack("!H", wl)+p[2:]
+ if self.tp_len is None:
+ l = sum ( map ( subpacklen , self.total_path))
+ p = p[:2+wl]+struct.pack("!H", l)+p[4+wl:]
+ return p+pay
+
+class BGPNotification(Packet):
+ name = "BGP Notification fields"
+ fields_desc = [
+ ByteEnumField("ErrorCode",0,{1:"Message Header Error",2:"OPEN Message Error",3:"UPDATE Messsage Error",4:"Hold Timer Expired",5:"Finite State Machine",6:"Cease"}),
+ ByteEnumField("ErrorSubCode",0,{1:"MessageHeader",2:"OPENMessage",3:"UPDATEMessage"}),
+ LongField("Data", 0),
+ ]
+
+class BGPErrorSubcodes(Packet):
+ name = "BGP Error Subcodes"
+ Fields_desc = [
+ ByteEnumField("MessageHeader",0,{1:"Connection Not Synchronized",2:"Bad Message Length",3:"Bad Messsage Type"}),
+ ByteEnumField("OPENMessage",0,{1:"Unsupported Version Number",2:"Bad Peer AS",3:"Bad BGP Identifier",4:"Unsupported Optional Parameter",5:"Authentication Failure",6:"Unacceptable Hold Time"}),
+ ByteEnumField("UPDATEMessage",0,{1:"Malformed Attribute List",2:"Unrecognized Well-Known Attribute",3:"Missing Well-Known Attribute",4:"Attribute Flags Error",5:"Attribute Length Error",6:"Invalid ORIGIN Attribute",7:"AS Routing Loop",8:"Invalid NEXT_HOP Attribute",9:"Optional Attribute Error",10:"Invalid Network Field",11:"Malformed AS_PATH"}),
+ ]
+
+bind_layers( TCP, BGPHeader, dport=179)
+bind_layers( TCP, BGPHeader, sport=179)
+bind_layers( BGPHeader, BGPOpen, type=1)
+bind_layers( BGPHeader, BGPUpdate, type=2)
+bind_layers( BGPHeader, BGPHeader, type=4)
+
+
+if __name__ == "__main__":
+ interact(mydict=globals(), mybanner="BGP addon .05")
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/carp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/carp.py
new file mode 100644
index 00000000..e785adef
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/carp.py
@@ -0,0 +1,65 @@
+
+# scapy.contrib.description = CARP
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.layers.inet import IP
+from scapy.fields import BitField, ByteField, XShortField, IntField, XIntField
+from scapy.utils import checksum
+import struct, hmac, hashlib
+
+class CARP(Packet):
+ name = "CARP"
+ fields_desc = [ BitField("version", 4, 4),
+ BitField("type", 4, 4),
+ ByteField("vhid", 1),
+ ByteField("advskew", 0),
+ ByteField("authlen", 0),
+ ByteField("demotion", 0),
+ ByteField("advbase", 0),
+ XShortField("chksum", 0),
+ XIntField("counter1", 0),
+ XIntField("counter2", 0),
+ XIntField("hmac1", 0),
+ XIntField("hmac2", 0),
+ XIntField("hmac3", 0),
+ XIntField("hmac4", 0),
+ XIntField("hmac5", 0)
+ ]
+
+ def post_build(self, pkt, pay):
+ if self.chksum == None:
+ pkt = pkt[:6] + struct.pack("!H", checksum(pkt)) + pkt[8:]
+
+ return pkt
+
+def build_hmac_sha1(pkt, pw = '\0' * 20, ip4l = [], ip6l = []):
+ if not pkt.haslayer(CARP):
+ return None
+
+ p = pkt[CARP]
+ h = hmac.new(pw, digestmod = hashlib.sha1)
+ # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field
+ h.update('\x21')
+ # XXX: mac addy if different from special link layer. comes before vhid
+ h.update(struct.pack('!B', p.vhid))
+
+ sl = []
+ for i in ip4l:
+ # sort ips from smallest to largest
+ sl.append(inet_aton(i))
+ sl.sort()
+
+ for i in sl:
+ h.update(i)
+
+ # XXX: do ip6l sorting
+
+ return h.digest()
+
+"""
+XXX: Usually CARP is multicast to 224.0.0.18 but because of virtual setup, it'll
+be unicast between nodes. Uncomment the following line for normal use
+bind_layers(IP, CARP, proto=112, dst='224.0.0.18')
+"""
+bind_layers(IP, CARP, proto=112)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/cdp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/cdp.py
new file mode 100644
index 00000000..ed336162
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/cdp.py
@@ -0,0 +1,306 @@
+#! /usr/bin/env python
+
+# scapy.contrib.description = Cisco Discovery Protocol
+# scapy.contrib.status = loads
+
+#############################################################################
+## ##
+## cdp.py --- Cisco Discovery Protocol (CDP) extension for Scapy ##
+## ##
+## Copyright (C) 2006 Nicolas Bareil <nicolas.bareil AT eads DOT net> ##
+## Arnaud Ebalard <arnaud.ebalard AT eads DOT net> ##
+## EADS/CRC security team ##
+## ##
+## This program is free software; you can redistribute it and/or modify it ##
+## under the terms of the GNU General Public License version 2 as ##
+## published by the Free Software Foundation; version 2. ##
+## ##
+## This program is distributed in the hope that it will be useful, but ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of ##
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
+## General Public License for more details. ##
+## ##
+#############################################################################
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet6 import *
+
+
+#####################################################################
+# Helpers and constants
+#####################################################################
+
+# CDP TLV classes keyed by type
+_cdp_tlv_cls = { 0x0001: "CDPMsgDeviceID",
+ 0x0002: "CDPMsgAddr",
+ 0x0003: "CDPMsgPortID",
+ 0x0004: "CDPMsgCapabilities",
+ 0x0005: "CDPMsgSoftwareVersion",
+ 0x0006: "CDPMsgPlatform",
+ 0x0007: "CDPMsgIPPrefix",
+ 0x0008: "CDPMsgProtoHello",
+ 0x0009: "CDPMsgVTPMgmtDomain", # CDPv2
+ 0x000a: "CDPMsgNativeVLAN", # CDPv2
+ 0x000b: "CDPMsgDuplex", #
+# 0x000c: "CDPMsgGeneric",
+# 0x000d: "CDPMsgGeneric",
+ 0x000e: "CDPMsgVoIPVLANReply",
+ 0x000f: "CDPMsgVoIPVLANQuery",
+ 0x0010: "CDPMsgPower",
+ 0x0011: "CDPMsgMTU",
+# 0x0012: "CDPMsgTrustBitmap",
+# 0x0013: "CDPMsgUntrustedPortCoS",
+# 0x0014: "CDPMsgSystemName",
+# 0x0015: "CDPMsgSystemOID",
+ 0x0016: "CDPMsgMgmtAddr",
+# 0x0017: "CDPMsgLocation",
+ 0x0019: "CDPMsgUnknown19",
+# 0x001a: "CDPPowerAvailable"
+ }
+
+_cdp_tlv_types = { 0x0001: "Device ID",
+ 0x0002: "Addresses",
+ 0x0003: "Port ID",
+ 0x0004: "Capabilities",
+ 0x0005: "Software Version",
+ 0x0006: "Platform",
+ 0x0007: "IP Prefix",
+ 0x0008: "Protocol Hello",
+ 0x0009: "VTP Mangement Domain", # CDPv2
+ 0x000a: "Native VLAN", # CDPv2
+ 0x000b: "Duplex", #
+ 0x000c: "CDP Unknown command (send us a pcap file)",
+ 0x000d: "CDP Unknown command (send us a pcap file)",
+ 0x000e: "VoIP VLAN Reply",
+ 0x000f: "VoIP VLAN Query",
+ 0x0010: "Power",
+ 0x0011: "MTU",
+ 0x0012: "Trust Bitmap",
+ 0x0013: "Untrusted Port CoS",
+ 0x0014: "System Name",
+ 0x0015: "System OID",
+ 0x0016: "Management Address",
+ 0x0017: "Location",
+ 0x0018: "CDP Unknown command (send us a pcap file)",
+ 0x0019: "CDP Unknown command (send us a pcap file)",
+ 0x001a: "Power Available"}
+
+def _CDPGuessPayloadClass(p, **kargs):
+ cls = conf.raw_layer
+ if len(p) >= 2:
+ t = struct.unpack("!H", p[:2])[0]
+ clsname = _cdp_tlv_cls.get(t, "CDPMsgGeneric")
+ cls = globals()[clsname]
+
+ return cls(p, **kargs)
+
+class CDPMsgGeneric(Packet):
+ name = "CDP Generic Message"
+ fields_desc = [ XShortEnumField("type", None, _cdp_tlv_types),
+ FieldLenField("len", None, "val", "!H"),
+ StrLenField("val", "", length_from=lambda x:x.len - 4) ]
+
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer # _CDPGuessPayloadClass
+
+class CDPMsgDeviceID(CDPMsgGeneric):
+ name = "Device ID"
+ type = 0x0001
+
+_cdp_addr_record_ptype = {0x01: "NLPID", 0x02: "802.2"}
+_cdp_addrrecord_proto_ip = "\xcc"
+_cdp_addrrecord_proto_ipv6 = "\xaa\xaa\x03\x00\x00\x00\x86\xdd"
+
+class CDPAddrRecord(Packet):
+ name = "CDP Address"
+ fields_desc = [ ByteEnumField("ptype", 0x01, _cdp_addr_record_ptype),
+ FieldLenField("plen", None, "proto", "B"),
+ StrLenField("proto", None, length_from=lambda x:x.plen),
+ FieldLenField("addrlen", None, length_of=lambda x:x.addr),
+ StrLenField("addr", None, length_from=lambda x:x.addrlen)]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+class CDPAddrRecordIPv4(CDPAddrRecord):
+ name = "CDP Address IPv4"
+ fields_desc = [ ByteEnumField("ptype", 0x01, _cdp_addr_record_ptype),
+ FieldLenField("plen", 1, "proto", "B"),
+ StrLenField("proto", _cdp_addrrecord_proto_ip, length_from=lambda x:x.plen),
+ ShortField("addrlen", 4),
+ IPField("addr", "0.0.0.0")]
+
+class CDPAddrRecordIPv6(CDPAddrRecord):
+ name = "CDP Address IPv6"
+ fields_desc = [ ByteEnumField("ptype", 0x02, _cdp_addr_record_ptype),
+ FieldLenField("plen", 8, "proto", "B"),
+ StrLenField("proto", _cdp_addrrecord_proto_ipv6, length_from=lambda x:x.plen),
+ ShortField("addrlen", 16),
+ IP6Field("addr", "::1")]
+
+def _CDPGuessAddrRecord(p, **kargs):
+ cls = conf.raw_layer
+ if len(p) >= 2:
+ plen = struct.unpack("B", p[1])[0]
+ proto = ''.join(struct.unpack("s" * plen, p[2:plen + 2])[0:plen])
+
+ if proto == _cdp_addrrecord_proto_ip:
+ clsname = "CDPAddrRecordIPv4"
+ elif proto == _cdp_addrrecord_proto_ipv6:
+ clsname = "CDPAddrRecordIPv6"
+ else:
+ clsname = "CDPAddrRecord"
+
+ cls = globals()[clsname]
+
+ return cls(p, **kargs)
+
+class CDPMsgAddr(CDPMsgGeneric):
+ name = "Addresses"
+ fields_desc = [ XShortEnumField("type", 0x0002, _cdp_tlv_types),
+ ShortField("len", None),
+ FieldLenField("naddr", None, "addr", "!I"),
+ PacketListField("addr", [], _CDPGuessAddrRecord, count_from=lambda x:x.naddr) ]
+
+ def post_build(self, pkt, pay):
+ if self.len is None:
+ l = 8 + len(self.addr) * 9
+ pkt = pkt[:2] + struct.pack("!H", l) + pkt[4:]
+ p = pkt + pay
+ return p
+
+class CDPMsgPortID(CDPMsgGeneric):
+ name = "Port ID"
+ fields_desc = [ XShortEnumField("type", 0x0003, _cdp_tlv_types),
+ FieldLenField("len", None, "iface", "!H"),
+ StrLenField("iface", "Port 1", length_from=lambda x:x.len - 4) ]
+
+
+_cdp_capabilities = [ "Router",
+ "TransparentBridge",
+ "SourceRouteBridge",
+ "Switch",
+ "Host",
+ "IGMPCapable",
+ "Repeater"] + ["Bit%d" % x for x in range(25,0,-1)]
+
+
+class CDPMsgCapabilities(CDPMsgGeneric):
+ name = "Capabilities"
+ fields_desc = [ XShortEnumField("type", 0x0004, _cdp_tlv_types),
+ ShortField("len", 8),
+ FlagsField("cap", 0, 32, _cdp_capabilities) ]
+
+
+class CDPMsgSoftwareVersion(CDPMsgGeneric):
+ name = "Software Version"
+ type = 0x0005
+
+
+class CDPMsgPlatform(CDPMsgGeneric):
+ name = "Platform"
+ type = 0x0006
+
+_cdp_duplex = { 0x00: "Half", 0x01: "Full" }
+
+# ODR Routing
+class CDPMsgIPPrefix(CDPMsgGeneric):
+ name = "IP Prefix"
+ type = 0x0007
+ fields_desc = [ XShortEnumField("type", 0x0007, _cdp_tlv_types),
+ ShortField("len", 8),
+ IPField("defaultgw", "192.168.0.1") ]
+
+# TODO : Do me !!!!!! 0x0008
+class CDPMsgProtoHello(CDPMsgGeneric):
+ name = "Protocol Hello"
+ type = 0x0008
+
+class CDPMsgVTPMgmtDomain(CDPMsgGeneric):
+ name = "VTP Management Domain"
+ type = 0x0009
+
+class CDPMsgNativeVLAN(CDPMsgGeneric):
+ name = "Native VLAN"
+ fields_desc = [ XShortEnumField("type", 0x000a, _cdp_tlv_types),
+ ShortField("len", 6),
+ ShortField("vlan", 1) ]
+
+class CDPMsgDuplex(CDPMsgGeneric):
+ name = "Duplex"
+ fields_desc = [ XShortEnumField("type", 0x000b, _cdp_tlv_types),
+ ShortField("len", 5),
+ ByteEnumField("duplex", 0x00, _cdp_duplex) ]
+
+class CDPMsgVoIPVLANReply(CDPMsgGeneric):
+ name = "VoIP VLAN Reply"
+ fields_desc = [ XShortEnumField("type", 0x000e, _cdp_tlv_types),
+ ShortField("len", 7),
+ ByteField("status?", 1),
+ ShortField("vlan", 1)]
+
+
+# TODO : Do me !!! 0x000F
+class CDPMsgVoIPVLANQuery(CDPMsgGeneric):
+ name = "VoIP VLAN Query"
+ type = 0x000f
+
+# fields_desc = [XShortEnumField("type", 0x000f, _cdp_tlv_types),
+# FieldLenField("len", None, "val", "!H") ]
+
+
+class _CDPPowerField(ShortField):
+ def i2repr(self, pkt, x):
+ if x is None:
+ x = 0
+ return "%d mW" % x
+
+
+class CDPMsgPower(CDPMsgGeneric):
+ name = "Power"
+ # Check if field length is fixed (2 bytes)
+ fields_desc = [ XShortEnumField("type", 0x0010, _cdp_tlv_types),
+ ShortField("len", 6),
+ _CDPPowerField("power", 1337)]
+
+
+class CDPMsgMTU(CDPMsgGeneric):
+ name = "MTU"
+ # Check if field length is fixed (2 bytes)
+ fields_desc = [ XShortEnumField("type", 0x0011, _cdp_tlv_types),
+ ShortField("len", 6),
+ ShortField("mtu", 1500)]
+
+class CDPMsgMgmtAddr(CDPMsgAddr):
+ name = "Management Address"
+ type = 0x0016
+
+class CDPMsgUnknown19(CDPMsgGeneric):
+ name = "Unknown CDP Message"
+ type = 0x0019
+
+class CDPMsg(CDPMsgGeneric):
+ name = "CDP "
+ fields_desc = [ XShortEnumField("type", None, _cdp_tlv_types),
+ FieldLenField("len", None, "val", "!H"),
+ StrLenField("val", "", length_from=lambda x:x.len - 4) ]
+
+class _CDPChecksum:
+ def post_build(self, pkt, pay):
+ p = pkt + pay
+ if self.cksum is None:
+ cksum = checksum(p)
+ p = p[:2] + struct.pack("!H", cksum) + p[4:]
+ return p
+
+class CDPv2_HDR(_CDPChecksum, CDPMsgGeneric):
+ name = "Cisco Discovery Protocol version 2"
+ fields_desc = [ ByteField("vers", 2),
+ ByteField("ttl", 180),
+ XShortField("cksum", None),
+ PacketListField("msg", [], _CDPGuessPayloadClass) ]
+
+bind_layers(SNAP, CDPv2_HDR, {"code": 0x2000, "OUI": 0xC})
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/chdlc.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/chdlc.py
new file mode 100644
index 00000000..6e483762
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/chdlc.py
@@ -0,0 +1,42 @@
+# http://trac.secdev.org/scapy/ticket/88
+
+# scapy.contrib.description = Cisco HDLC and SLARP
+# scapy.contrib.status = loads
+
+# This layer is based on information from http://www.nethelp.no/net/cisco-hdlc.txt
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import *
+from scapy.layers.inet import *
+from scapy.layers.inet6 import *
+
+class CHDLC(Packet):
+ name = "Cisco HDLC"
+ fields_desc = [ ByteEnumField("address", 0x0f, {0x0f : "unicast", 0x8f :"multicast"}),
+ ByteField("control", 0),
+ XShortField("proto", 0x0800)]
+
+class SLARP(Packet):
+ name = "SLARP"
+ fields_desc = [ IntEnumField("type", 2, {0 : "request", 1 : "reply", 2 :"line keepalive"}),
+ ConditionalField(IPField("address", "192.168.0.1"),
+ lambda pkt : pkt.type == 0 or pkt.type == 1),
+ ConditionalField(IPField("mask", "255.255.255.0"),
+ lambda pkt : pkt.type == 0 or pkt.type == 1),
+ ConditionalField(XShortField("unused", 0),
+ lambda pkt : pkt.type == 0 or pkt.type == 1),
+ ConditionalField(IntField("mysequence", 0),
+ lambda pkt : pkt.type == 2),
+ ConditionalField(IntField("yoursequence", 0),
+ lambda pkt : pkt.type == 2),
+ ConditionalField(XShortField("reliability", 0xffff),
+ lambda pkt : pkt.type == 2)]
+
+bind_layers( CHDLC, Dot3, proto=0x6558)
+bind_layers( CHDLC, IP, proto=0x800)
+bind_layers( CHDLC, IPv6, proto=0x86dd)
+bind_layers( CHDLC, SLARP, proto=0x8035)
+bind_layers( CHDLC, STP, proto=0x4242)
+
+conf.l2types.register(104, CHDLC)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/dtp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/dtp.py
new file mode 100644
index 00000000..1907300b
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/dtp.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+
+# scapy.contrib.description = DTP
+# scapy.contrib.status = loads
+
+"""
+ DTP Scapy Extension
+ ~~~~~~~~~~~~~~~~~~~
+
+ :version: 2008-12-22
+ :author: Jochen Bartl <lobo@c3a.de>
+
+ :Thanks:
+
+ - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard)
+ http://trac.secdev.org/scapy/ticket/18
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import SNAP,Dot3,LLC
+from scapy.sendrecv import sendp
+
+class DtpGenericTlv(Packet):
+ name = "DTP Generic TLV"
+ fields_desc = [ XShortField("type", 0x0001),
+ FieldLenField("length", None, length_of=lambda pkt:pkt.value + 4),
+ StrLenField("value", "", length_from=lambda pkt:pkt.length - 4)
+ ]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+class RepeatedTlvListField(PacketListField):
+ def __init__(self, name, default, cls):
+ PacketField.__init__(self, name, default, cls)
+
+ def getfield(self, pkt, s):
+ lst = []
+ remain = s
+ while len(remain) > 0:
+ p = self.m2i(pkt,remain)
+ if conf.padding_layer in p:
+ pad = p[conf.padding_layer]
+ remain = pad.load
+ del(pad.underlayer.payload)
+ else:
+ remain = ""
+ lst.append(p)
+ return remain,lst
+
+ def addfield(self, pkt, s, val):
+ return s+reduce(str.__add__, map(str, val),"")
+
+_DTP_TLV_CLS = {
+ 0x0001 : "DTPDomain",
+ 0x0002 : "DTPStatus",
+ 0x0003 : "DTPType",
+ 0x0004 : "DTPNeighbor"
+ }
+
+class DTPDomain(DtpGenericTlv):
+ name = "DTP Domain"
+ fields_desc = [ ShortField("type", 1),
+ FieldLenField("length", None, "domain", adjust=lambda pkt,x:x + 4),
+ StrLenField("domain", "\x00", length_from=lambda pkt:pkt.length - 4)
+ ]
+
+class DTPStatus(DtpGenericTlv):
+ name = "DTP Status"
+ fields_desc = [ ShortField("type", 2),
+ FieldLenField("length", None, "status", adjust=lambda pkt,x:x + 4),
+ StrLenField("status", "\x03", length_from=lambda pkt:pkt.length - 4)
+ ]
+
+class DTPType(DtpGenericTlv):
+ name = "DTP Type"
+ fields_desc = [ ShortField("type", 3),
+ FieldLenField("length", None, "dtptype", adjust=lambda pkt,x:x + 4),
+ StrLenField("dtptype", "\xa5", length_from=lambda pkt:pkt.length - 4)
+ ]
+
+class DTPNeighbor(DtpGenericTlv):
+ name = "DTP Neighbor"
+ fields_desc = [ ShortField("type", 4),
+ #FieldLenField("length", None, "neighbor", adjust=lambda pkt,x:x + 4),
+ ShortField("len", 10),
+ MACField("neighbor", None)
+ ]
+
+def _DTPGuessPayloadClass(p, **kargs):
+ cls = conf.raw_layer
+ if len(p) >= 2:
+ t = struct.unpack("!H", p[:2])[0]
+ clsname = _DTP_TLV_CLS.get(t, "DtpGenericTlv")
+ cls = globals()[clsname]
+ return cls(p, **kargs)
+
+class DTP(Packet):
+ name = "DTP"
+ fields_desc = [ ByteField("ver", 1),
+ RepeatedTlvListField("tlvlist", [], _DTPGuessPayloadClass)
+ ]
+
+bind_layers(SNAP, DTP, code=0x2004, OUI=0xc)
+
+
+def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())):
+ print("Trying to negotiate a trunk on interface %s" % iface)
+ p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)])
+ sendp(p)
+
+if __name__ == "__main__":
+ from scapy.main import interact
+ interact(mydict=globals(), mybanner="DTP")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/eigrp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/eigrp.py
new file mode 100644
index 00000000..f304ae68
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/eigrp.py
@@ -0,0 +1,488 @@
+#!/usr/bin/env python
+
+# scapy.contrib.description = EIGRP
+# scapy.contrib.status = loads
+
+"""
+ EIGRP Scapy Extension
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ :version: 2009-08-13
+ :copyright: 2009 by Jochen Bartl
+ :e-mail: lobo@c3a.de / jochen.bartl@gmail.com
+ :license: GPL v2
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ :TODO
+
+ - Replace TLV code with a more generic solution
+ * http://trac.secdev.org/scapy/ticket/90
+ - Write function for calculating authentication data
+
+ :Known bugs:
+
+ -
+
+ :Thanks:
+
+ - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard)
+ http://trac.secdev.org/scapy/ticket/18
+ - IOS / EIGRP Version Representation FIX by Dirk Loss
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP
+from scapy.layers.inet6 import *
+
+class EigrpIPField(StrField, IPField):
+ """
+ This is a special field type for handling ip addresses of destination networks in internal and
+ external route updates.
+
+ EIGRP removes zeros from the host portion of the ip address if the netmask is 8, 16 or 24 bits.
+ """
+
+ def __init__(self, name, default, length=None, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+ if length is not None:
+ self.length_from = lambda pkt,length=length: length
+
+ def h2i(self, pkt, x):
+ return IPField.h2i(self, pkt, x)
+
+ def i2m(self, pkt, x):
+ x = inet_aton(x)
+ l = self.length_from(pkt)
+
+ if l <= 8:
+ return x[:1]
+ elif l <= 16:
+ return x[:2]
+ elif l <= 24:
+ return x[:3]
+ else:
+ return x
+
+ def m2i(self, pkt, x):
+ l = self.length_from(pkt)
+
+ if l <= 8:
+ x += "\x00\x00\x00"
+ elif l <= 16:
+ x += "\x00\x00"
+ elif l <= 24:
+ x += "\x00"
+
+ return inet_ntoa(x)
+
+ def prefixlen_to_bytelen(self, l):
+ if l <= 8:
+ l = 1
+ elif l <= 16:
+ l = 2
+ elif l <= 24:
+ l = 3
+ else:
+ l = 4
+
+ return l
+
+ def i2len(self, pkt, x):
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return l
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return s[l:], self.m2i(pkt, s[:l])
+
+ def randval(self):
+ return IPField.randval(self)
+
+class EigrpIP6Field(StrField, IP6Field, EigrpIPField):
+ """
+ This is a special field type for handling ip addresses of destination networks in internal and
+ external route updates.
+
+ """
+
+ def __init__(self, name, default, length=None, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+ if length is not None:
+ self.length_from = lambda pkt,length=length: length
+
+ def any2i(self, pkt, x):
+ return IP6Field.any2i(self, pkt, x)
+
+ def i2repr(self, pkt, x):
+ return IP6Field.i2repr(self, pkt, x)
+
+ def h2i(self, pkt, x):
+ return IP6Field.h2i(self, pkt, x)
+
+ def i2m(self, pkt, x):
+ x = inet_pton(socket.AF_INET6, x)
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return x[:l]
+
+ def m2i(self, pkt, x):
+ l = self.length_from(pkt)
+
+ prefixlen = self.prefixlen_to_bytelen(l)
+ if l > 128:
+ warning("EigrpIP6Field: Prefix length is > 128. Dissection of this packet will fail")
+ else:
+ pad = "\x00" * (16 - prefixlen)
+ x += pad
+
+ return inet_ntop(socket.AF_INET6, x)
+
+ def prefixlen_to_bytelen(self, l):
+ l = l / 8
+
+ if l < 16:
+ l += 1
+
+ return l
+
+ def i2len(self, pkt, x):
+ return EigrpIPField.i2len(self, pkt, x)
+
+ def getfield(self, pkt, s):
+ return EigrpIPField.getfield(self, pkt, s)
+
+class ThreeBytesField(X3BytesField, ByteField):
+ def i2repr(self, pkt, x):
+ return ByteField.i2repr(self, pkt, x)
+
+
+class EIGRPGeneric(Packet):
+ name = "EIGRP Generic TLV"
+ fields_desc = [ XShortField("type", 0x0000),
+ FieldLenField("len", None, "value", "!H", adjust=lambda pkt,x: x + 4),
+ StrLenField("value", "\x00", length_from=lambda pkt: pkt.len - 4)]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+class EIGRPParam(EIGRPGeneric):
+ name = "EIGRP Parameters"
+ fields_desc = [ XShortField("type", 0x0001),
+ ShortField("len", 12),
+ # Bandwidth
+ ByteField("k1", 1),
+ # Load
+ ByteField("k2", 0),
+ # Delay
+ ByteField("k3", 1),
+ # Reliability
+ ByteField("k4", 0),
+ # MTU
+ ByteField("k5", 0),
+ ByteField("reserved", 0),
+ ShortField("holdtime", 15)
+ ]
+
+class EIGRPAuthData(EIGRPGeneric):
+ name = "EIGRP Authentication Data"
+ fields_desc = [ XShortField("type", 0x0002),
+ FieldLenField("len", None, "authdata", "!H", adjust=lambda pkt,x: x + 24),
+ ShortEnumField("authtype", 2, {2 : "MD5"}),
+ ShortField("keysize", None),
+ IntField("keyid", 1),
+ StrFixedLenField("nullpad", "\x00" * 12, 12),
+ StrLenField("authdata", RandString(16), length_from=lambda pkt: pkt.keysize)
+ ]
+
+ def post_build(self, p, pay):
+ p += pay
+
+ if self.keysize is None:
+ keysize = len(self.authdata)
+ p = p[:6] + chr((keysize >> 8) & 0xff) + chr(keysize & 0xff) + p[8:]
+
+ return p
+
+class EIGRPSeq(EIGRPGeneric):
+ name = "EIGRP Sequence"
+ fields_desc = [ XShortField("type", 0x0003),
+ ShortField("len", None),
+ ByteField("addrlen", 4),
+ ConditionalField(IPField("ipaddr", "192.168.0.1"),
+ lambda pkt:pkt.addrlen == 4),
+ ConditionalField(IP6Field("ip6addr", "2001::"),
+ lambda pkt:pkt.addrlen == 16)
+ ]
+
+ def post_build(self, p, pay):
+ p += pay
+
+ if self.len is None:
+ l = len(p)
+ p = p[:2] + chr((l >> 8) & 0xff) + chr(l & 0xff) + p[4:]
+
+ return p
+
+class ShortVersionField(ShortField):
+ def i2repr(self, pkt, x):
+ try:
+ minor = x & 0xff
+ major = (x >> 8) & 0xff
+ except TypeError:
+ return "unknown"
+ else:
+ # We print a leading 'v' so that these values don't look like floats
+ return "v%s.%s" % (major, minor)
+
+ def h2i(self, pkt, x):
+ """The field accepts string values like v12.1, v1.1 or integer values.
+ String values have to start with a "v" folled by a floating point number.
+ Valid numbers are between 0 and 255.
+ """
+
+ if type(x) is str and x.startswith("v") and len(x) <= 8:
+ major = int(x.split(".")[0][1:])
+ minor = int(x.split(".")[1])
+
+ return (major << 8) | minor
+
+ elif type(x) is int and x >= 0 and x <= 65535:
+ return x
+ else:
+ if self.default != None:
+ warning("set value to default. Format of %r is invalid" % x)
+ return self.default
+ else:
+ raise Scapy_Exception("Format of value is invalid")
+
+ def randval(self):
+ return RandShort()
+
+class EIGRPSwVer(EIGRPGeneric):
+ name = "EIGRP Software Version"
+ fields_desc = [ XShortField("type", 0x0004),
+ ShortField("len", 8),
+ ShortVersionField("ios", "v12.0"),
+ ShortVersionField("eigrp", "v1.2")
+ ]
+
+class EIGRPNms(EIGRPGeneric):
+ name = "EIGRP Next Multicast Sequence"
+ fields_desc = [ XShortField("type", 0x0005),
+ ShortField("len", 8),
+ IntField("nms", 2)
+ ]
+
+# Don't get confused by the term "receive-only". This flag is always set, when you configure
+# one of the stub options. It's also the only flag set, when you configure "eigrp stub receive-only".
+_EIGRP_STUB_FLAGS = ["connected", "static", "summary", "receive-only", "redistributed", "leak-map"]
+
+class EIGRPStub(EIGRPGeneric):
+ name = "EIGRP Stub Router"
+ fields_desc = [ XShortField("type", 0x0006),
+ ShortField("len", 6),
+ FlagsField("flags", 0x000d, 16, _EIGRP_STUB_FLAGS)]
+
+# Delay 0xffffffff == Destination Unreachable
+class EIGRPIntRoute(EIGRPGeneric):
+ name = "EIGRP Internal Route"
+ fields_desc = [ XShortField("type", 0x0102),
+ FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 25),
+ IPField("nexthop", "192.168.0.0"),
+ IntField("delay", 128000),
+ IntField("bandwidth", 256),
+ ThreeBytesField("mtu", 1500),
+ ByteField("hopcount", 0),
+ ByteField("reliability", 255),
+ ByteField("load", 0),
+ XShortField("reserved", 0),
+ ByteField("prefixlen", 24),
+ EigrpIPField("dst", "192.168.1.0", length_from=lambda pkt: pkt.prefixlen),
+ ]
+
+_EIGRP_EXTERNAL_PROTOCOL_ID = {
+ 0x01 : "IGRP",
+ 0x02 : "EIGRP",
+ 0x03 : "Static Route",
+ 0x04 : "RIP",
+ 0x05 : "Hello",
+ 0x06 : "OSPF",
+ 0x07 : "IS-IS",
+ 0x08 : "EGP",
+ 0x09 : "BGP",
+ 0x0A : "IDRP",
+ 0x0B : "Connected Link"
+ }
+
+_EIGRP_EXTROUTE_FLAGS = ["external", "candidate-default"]
+
+class EIGRPExtRoute(EIGRPGeneric):
+ name = "EIGRP External Route"
+ fields_desc = [ XShortField("type", 0x0103),
+ FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 45),
+ IPField("nexthop", "192.168.0.0"),
+ IPField("originrouter", "192.168.0.1"),
+ IntField("originasn", 0),
+ IntField("tag", 0),
+ IntField("externalmetric", 0),
+ ShortField("reserved", 0),
+ ByteEnumField("extprotocolid", 3, _EIGRP_EXTERNAL_PROTOCOL_ID),
+ FlagsField("flags", 0, 8, _EIGRP_EXTROUTE_FLAGS),
+ IntField("delay", 0),
+ IntField("bandwidth", 256),
+ ThreeBytesField("mtu", 1500),
+ ByteField("hopcount", 0),
+ ByteField("reliability", 255),
+ ByteField("load", 0),
+ XShortField("reserved2", 0),
+ ByteField("prefixlen", 24),
+ EigrpIPField("dst", "192.168.1.0", length_from=lambda pkt: pkt.prefixlen)
+ ]
+
+class EIGRPv6IntRoute(EIGRPGeneric):
+ name = "EIGRP for IPv6 Internal Route"
+ fields_desc = [ XShortField("type", 0x0402),
+ FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 37),
+ IP6Field("nexthop", "::"),
+ IntField("delay", 128000),
+ IntField("bandwidth", 256000),
+ ThreeBytesField("mtu", 1500),
+ ByteField("hopcount", 1),
+ ByteField("reliability", 255),
+ ByteField("load", 0),
+ XShortField("reserved", 0),
+ ByteField("prefixlen", 16),
+ EigrpIP6Field("dst", "2001::", length_from=lambda pkt: pkt.prefixlen)
+ ]
+
+class EIGRPv6ExtRoute(EIGRPGeneric):
+ name = "EIGRP for IPv6 External Route"
+ fields_desc = [ XShortField("type", 0x0403),
+ FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 57),
+ IP6Field("nexthop", "::"),
+ IPField("originrouter", "192.168.0.1"),
+ IntField("originasn", 0),
+ IntField("tag", 0),
+ IntField("externalmetric", 0),
+ ShortField("reserved", 0),
+ ByteEnumField("extprotocolid", 3, _EIGRP_EXTERNAL_PROTOCOL_ID),
+ FlagsField("flags", 0, 8, _EIGRP_EXTROUTE_FLAGS),
+ IntField("delay", 0),
+ IntField("bandwidth", 256000),
+ ThreeBytesField("mtu", 1500),
+ ByteField("hopcount", 1),
+ ByteField("reliability", 0),
+ ByteField("load", 1),
+ XShortField("reserved2", 0),
+ ByteField("prefixlen", 8),
+ EigrpIP6Field("dst", "::", length_from=lambda pkt: pkt.prefixlen)
+ ]
+
+_eigrp_tlv_cls = {
+ 0x0001: "EIGRPParam",
+ 0x0002: "EIGRPAuthData",
+ 0x0003: "EIGRPSeq",
+ 0x0004: "EIGRPSwVer",
+ 0x0005: "EIGRPNms",
+ 0x0006: "EIGRPStub",
+ 0x0102: "EIGRPIntRoute",
+ 0x0103: "EIGRPExtRoute",
+ 0x0402: "EIGRPv6IntRoute",
+ 0x0403: "EIGRPv6ExtRoute"
+ }
+
+class RepeatedTlvListField(PacketListField):
+ def __init__(self, name, default, cls):
+ PacketField.__init__(self, name, default, cls)
+
+ def getfield(self, pkt, s):
+ lst = []
+ remain = s
+ while len(remain) > 0:
+ p = self.m2i(pkt, remain)
+ if conf.padding_layer in p:
+ pad = p[conf.padding_layer]
+ remain = pad.load
+ del(pad.underlayer.payload)
+ else:
+ remain = ""
+ lst.append(p)
+ return remain,lst
+
+ def addfield(self, pkt, s, val):
+ return s + reduce(str.__add__, map(str, val), "")
+
+def _EIGRPGuessPayloadClass(p, **kargs):
+ cls = conf.raw_layer
+ if len(p) >= 2:
+ t = struct.unpack("!H", p[:2])[0]
+ clsname = _eigrp_tlv_cls.get(t, "EIGRPGeneric")
+ cls = globals()[clsname]
+ return cls(p, **kargs)
+
+_EIGRP_OPCODES = { 1 : "Update",
+ 2 : "Request",
+ 3 : "Query",
+ 4 : "Replay",
+ 5 : "Hello",
+ 6 : "IPX SAP",
+ 10 : "SIA Query",
+ 11 : "SIA Reply" }
+
+# The Conditional Receive bit is used for reliable multicast communication.
+# Update-Flag: Not sure if Cisco calls it that way, but it's set when neighbors
+# are exchanging routing information
+_EIGRP_FLAGS = ["init", "cond-recv", "unknown", "update"]
+
+class EIGRP(Packet):
+ name = "EIGRP"
+ fields_desc = [ ByteField("ver", 2),
+ ByteEnumField("opcode", 5, _EIGRP_OPCODES),
+ XShortField("chksum", None),
+ FlagsField("flags", 0, 32, _EIGRP_FLAGS),
+ IntField("seq", 0),
+ IntField("ack", 0),
+ IntField("asn", 100),
+ RepeatedTlvListField("tlvlist", [], _EIGRPGuessPayloadClass)
+ ]
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.chksum is None:
+ c = checksum(p)
+ p = p[:2] + chr((c >> 8) & 0xff) + chr(c & 0xff) + p[4:]
+ return p
+
+ def mysummary(self):
+ summarystr = "EIGRP (AS=%EIGRP.asn% Opcode=%EIGRP.opcode%"
+ if self.opcode == 5 and self.ack != 0:
+ summarystr += " (ACK)"
+ if self.flags != 0:
+ summarystr += " Flags=%EIGRP.flags%"
+
+ return self.sprintf(summarystr + ")")
+
+bind_layers(IP, EIGRP, proto=88)
+bind_layers(IPv6, EIGRP, nh=88)
+
+if __name__ == "__main__":
+ from scapy.main import interact
+ interact(mydict=globals(), mybanner="EIGRP")
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/etherip.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/etherip.py
new file mode 100644
index 00000000..e331c146
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/etherip.py
@@ -0,0 +1,19 @@
+
+# http://trac.secdev.org/scapy/ticket/297
+
+# scapy.contrib.description = EtherIP
+# scapy.contrib.status = loads
+
+from scapy.fields import BitField
+from scapy.packet import Packet, bind_layers
+from scapy.layers.inet import IP
+from scapy.layers.l2 import Ether
+
+class EtherIP(Packet):
+ name = "EtherIP / RFC 3378"
+ fields_desc = [ BitField("version", 3, 4),
+ BitField("reserved", 0, 12)]
+
+bind_layers( IP, EtherIP, frag=0, proto=0x61)
+bind_layers( EtherIP, Ether)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gsm_um.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gsm_um.py
new file mode 100644
index 00000000..7b1354a4
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gsm_um.py
@@ -0,0 +1,13119 @@
+#!/usr/bin/env python
+
+# scapy.contrib.description = PPI
+# scapy.contrib.status = loads
+
+"""
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+ ####################################################################
+ # This file holds the GSM UM interface implementation for Scapy #
+ # author: Laurent Weber <k@0xbadcab1e.lu> #
+ # #
+ # Some examples on how to use this script: #
+ # http://0xbadcab1e.lu/scapy_gsm_um-howto.txt #
+ # #
+ # tested on: scapy-version: 2.2.0 (dev) #
+ ####################################################################
+
+import logging
+from types import IntType
+from types import NoneType
+from types import StringType
+#from time import sleep
+import socket
+logging.getLogger("scapy").setLevel(1)
+from scapy.all import *
+
+# This method is intended to send gsm air packets. It uses a unix domain
+# socket. It opens a socket, sends the parameter to the socket and
+# closes the socket.
+# typeSock determines the type of the socket, can be:
+# 0 for UDP Socket
+# 1 for Unix Domain Socket
+# 2 for TCP
+
+
+def sendum(x, typeSock=0):
+ try:
+ if type(x) is not str:
+ x = str(x)
+ if typeSock is 0:
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ host = '127.0.0.1'
+ port = 28670 # default for openBTS
+ s.connect((host, port))
+ elif typeSock is 1:
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.connect("/tmp/osmoL")
+ elif typeSock is 2:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ host = '127.0.0.1'
+ port = 43797
+ s.connect((host, port))
+ s.send(x)
+ s.close()
+ except:
+ print("[Error]: There was a problem when trying to transmit data.\
+ Please make sure you started the socket server.")
+
+# Known Bugs/Problems:
+# If a message uses multiple times the same IE you cannot set the values
+# of this IE's if you use the preconfigured packets. You need to build
+# the IE's by hand and than assemble them as entire messages.
+
+# The ErrorLength class is a custom exception that gets raised when a
+# packet doesn't have the correct size.
+
+
+class ErrorLength(Exception):
+ def __str__(self):
+ error = "ERROR: Please make sure you build entire, 8 bit fields."
+ return repr(error)
+###
+# This method computes the length of the actual IE.
+# It computes how many "None" fields have to be removed (if any).
+# The method returns an integer containing the number of bytes that have to be
+# cut off the packet.
+# parameter length contains the max length of the IE can be found in
+# 0408
+# The parameter fields contains the value of the fields (not the default but
+# the real, actual value.
+# The parameter fields2 contains fields_desc.
+# Location contains the location of the length field in the IE. Everything
+# after the the length field has to be counted (04.07 11.2.1.1.2)
+
+
+def adapt(min_length, max_length, fields, fields2, location=2):
+ # find out how much bytes there are between min_length and the location of
+ # the length field
+ location = min_length - location
+ i = len(fields) - 1
+ rm = mysum = 0
+ while i >= 0:
+ if fields[i] is None:
+ rm += 1
+ try:
+ mysum += fields2[i].size
+ except AttributeError: # ByteFields don't have .size
+ mysum += 8
+ else:
+ break
+ i -= 1
+ if mysum % 8 is 0:
+ length = mysum / 8 # Number of bytes we have to delete
+ dyn_length = (max_length - min_length - length)
+ if dyn_length < 0:
+ dyn_length = 0
+ if length is max_length: # Fix for packets that have all values set
+ length -= min_length # to None
+ return [length, dyn_length + location]
+ else:
+ raise ErrorLength()
+
+
+def examples(example=None):
+ if example == None:
+ print("""This command presents some example to introduce scapy
+gsm-um to new users.
+The following parameters can be used:
+ examples("imsiDetach")
+ examples("call")
+ examples("dissect")""")
+ elif example == "imsiDetach":
+ print("""
+>>> a=imsiDetachIndication()
+... a.typeOfId=1; a.odd=1; a.idDigit1=0xF;
+... a.idDigit2_1=2; a.idDigit2=7; a.idDigit3_1=0;
+... a.idDigit3=7; a.idDigit4_1=7; a.idDigit4=2;
+... a.idDigit5_1=0; a.idDigit5=0; a.idDigit6_1=0;
+... a.idDigit6=1; a.idDigit7_1=2; a.idDigit7=7;
+... a.idDigit8_1=7; a.idDigit8=5; a.idDigit9_1=1; a.idDigit9=4;
+>>> hexdump(a)
+0000 05 01 00 08 F0 27 07 72 00 01 27 75 14 .....'.r..'u.
+>>> sendum(a)
+""")
+ elif example == "call":
+ print("""
+If you use an USRP and the testcall function this sets up a phonecall:
+>>> sendum(setupMobileOriginated())
+>>> sendum(connectAcknowledge())
+""")
+
+
+# Section 10.2/3
+class TpPd(Packet):
+ """Skip indicator and transaction identifier and Protocol Discriminator"""
+ name = "Skip Indicator And Transaction Identifier and Protocol \
+Discriminator"
+ fields_desc = [
+ BitField("ti", 0x0, 4),
+ BitField("pd", 0x3, 4)
+ ]
+
+
+class MessageType(Packet):
+ """Message Type Section 10.4"""
+ name = "Message Type"
+ fields_desc = [
+ XByteField("mesType", 0x3C)
+ ]
+
+
+##
+# Message for Radio Resources management (RR) Section 9.1
+###
+
+# Network to MS
+def additionalAssignment(MobileAllocation_presence=0,
+ StartingTime_presence=0):
+ """ADDITIONAL ASSIGNMENT Section 9.1.1"""
+ # Mandatory
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x3B) # 00111011
+ c = ChannelDescription()
+ packet = a / b / c
+ # Not Mandatory
+ if MobileAllocation_presence is 1:
+ d = MobileAllocationHdr(ieiMA=0x72, eightBitMA=0x0)
+ packet = packet / d
+ if StartingTime_presence is 1:
+ e = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / e
+ return packet
+
+
+# Network to MS
+def assignmentCommand(FrequencyList_presence=0,
+ CellChannelDescription_presence=0,
+ CellChannelDescription_presence1=0,
+ MultislotAllocation_presence=0,
+ ChannelMode_presence=0, ChannelMode_presence1=0,
+ ChannelMode_presence2=0, ChannelMode_presence3=0,
+ ChannelMode_presence4=0, ChannelMode_presence5=0,
+ ChannelMode_presence6=0, ChannelMode_presence7=0,
+ ChannelDescription=0, ChannelMode2_presence=0,
+ MobileAllocation_presence=0, StartingTime_presence=0,
+ FrequencyList_presence1=0,
+ ChannelDescription2_presence=0,
+ ChannelDescription_presence=0,
+ FrequencyChannelSequence_presence=0,
+ MobileAllocation_presence1=0,
+ CipherModeSetting_presence=0,
+ VgcsTargetModeIdentication_presence=0,
+ MultiRateConfiguration_presence=0):
+ """ASSIGNMENT COMMAND Section 9.1.2"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2e) # 101110
+ c = ChannelDescription2()
+ d = PowerCommand()
+ packet = a / b / c / d
+ if FrequencyList_presence is 1:
+ e = FrequencyListHdr(ieiFL=0x05, eightBitFL=0x0)
+ packet = packet / e
+ if CellChannelDescription_presence is 1:
+ f = CellChannelDescriptionHdr(ieiCCD=0x62, eightBitCCD=0x0)
+ packet = packet / f
+ if MultislotAllocation_presence is 1:
+ g = MultislotAllocationHdr(ieiMSA=0x10, eightBitMSA=0x0)
+ packet = packet / g
+ if ChannelMode_presence is 1:
+ h = ChannelModeHdr(ieiCM=0x63, eightBitCM=0x0)
+ packet = packet / h
+ if ChannelMode_presence1 is 1:
+ i = ChannelModeHdr(ieiCM=0x11, eightBitCM=0x0)
+ packet = packet / i
+ if ChannelMode_presence2 is 1:
+ j = ChannelModeHdr(ieiCM=0x13, eightBitCM=0x0)
+ packet = packet / j
+ if ChannelMode_presence3 is 1:
+ k = ChannelModeHdr(ieiCM=0x14, eightBitCM=0x0)
+ packet = packet / k
+ if ChannelMode_presence4 is 1:
+ l = ChannelModeHdr(ieiCM=0x15, eightBitCM=0x0)
+ packet = packet / l
+ if ChannelMode_presence5 is 1:
+ m = ChannelModeHdr(ieiCM=0x16, eightBitCM=0x0)
+ packet = packet / m
+ if ChannelMode_presence6 is 1:
+ n = ChannelModeHdr(ieiCM=0x17, eightBitCM=0x0)
+ packet = packet / n
+ if ChannelMode_presence7 is 1:
+ o = ChannelModeHdr(ieiCM=0x18, eightBitCM=0x0)
+ packet = packet / o
+ if ChannelDescription_presence is 1:
+ p = ChannelDescriptionHdr(ieiCD=0x64, eightBitCD=0x0)
+ packet = packet / p
+ if ChannelMode2_presence is 1:
+ q = ChannelMode2Hdr(ieiCM2=0x66, eightBitCM2=0x0)
+ packet = packet / q
+ if MobileAllocation_presence is 1:
+ r = MobileAllocationHdr(ieiMA=0x72, eightBitMA=0x0)
+ packet = packet / r
+ if StartingTime_presence is 1:
+ s = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / s
+ if FrequencyList_presence1 is 1:
+ t = FrequencyListHdr(ieiFL=0x19, eightBitFL=0x0)
+ packet = packet / t
+ if ChannelDescription2_presence is 1:
+ u = ChannelDescription2Hdr(ieiCD2=0x1C, eightBitCD2=0x0)
+ packet = packet / u
+ if ChannelDescription_presence is 1:
+ v = ChannelDescriptionHdr(ieiCD=0x1D, eightBitCD=0x0)
+ packet = packet / v
+ if FrequencyChannelSequence_presence is 1:
+ w = FrequencyChannelSequenceHdr(ieiFCS=0x1E, eightBitFCS=0x0)
+ packet = packet / w
+ if MobileAllocation_presence1 is 1:
+ x = MobileAllocationHdr(ieiMA=0x21, eightBitMA=0x0)
+ packet = packet / x
+ if CipherModeSetting_presence is 1:
+ y = CipherModeSettingHdr(ieiCMS=0x9, eightBitCMS=0x0)
+ packet = packet / y
+ if VgcsTargetModeIdentication_presence is 1:
+ z = VgcsTargetModeIdenticationHdr(ieiVTMI=0x01, eightBitVTMI=0x0)
+ packet = packet / z
+ if MultiRateConfiguration_presence is 1:
+ aa = MultiRateConfigurationHdr(ieiMRC=0x03, eightBitMRC=0x0)
+ packet = packet / aa
+ return packet
+
+
+# MS to Network
+def assignmentComplete():
+ """ASSIGNMENT COMPLETE Section 9.1.3"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x29) # 00101001
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+# MS to Network
+def assignmentFailure():
+ """ASSIGNMENT FAILURE Section 9.1.4"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2F) # 00101111
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def channelModeModify(VgcsTargetModeIdentication_presence=0,
+ MultiRateConfiguration_presence=0):
+ """CHANNEL MODE MODIFY Section 9.1.5"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x8) # 0001000
+ c = ChannelDescription2()
+ d = ChannelMode()
+ packet = a / b / c / d
+ if VgcsTargetModeIdentication is 1:
+ e = VgcsTargetModeIdenticationHdr(ieiVTMI=0x01, eightBitVTMI=0x0)
+ packet = packet / e
+ if MultiRateConfiguration is 1:
+ f = MultiRateConfigurationHdr(ieiMRC=0x03, eightBitMRC=0x0)
+ packet = packet / f
+ return packet
+
+
+def channelModeModifyAcknowledge():
+ """CHANNEL MODE MODIFY ACKNOWLEDGE Section 9.1.6"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x17) # 00010111
+ c = ChannelDescription2()
+ d = ChannelMode()
+ packet = a / b / c / d
+ return packet
+
+
+# Network to MS
+def channelRelease(BaRange_presence=0, GroupChannelDescription_presence=0,
+ GroupCipherKeyNumber_presence=0, GprsResumption_presence=0,
+ BaListPref_presence=0):
+ """CHANNEL RELEASE Section 9.1.7"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0xD) # 00001101
+ c = RrCause()
+ packet = a / b / c
+ if BaRange_presence is 1:
+ d = BaRangeHdr(ieiBR=0x73, eightBitBR=0x0)
+ packet = packet / d
+ if GroupChannelDescription_presence is 1:
+ e = GroupChannelDescriptionHdr(ieiGCD=0x74, eightBitGCD=0x0)
+ packet = packet / e
+ if GroupCipherKeyNumber_presence is 1:
+ f = GroupCipherKeyNumber(ieiGCKN=0x8)
+ packet = packet / f
+ if GprsResumption_presence is 1:
+ g = GprsResumptionHdr(ieiGR=0xC, eightBitGR=0x0)
+ packet = packet / g
+ if BaListPref_presence is 1:
+ h = BaListPrefHdr(ieiBLP=0x75, eightBitBLP=0x0)
+ packet = packet / h
+ return packet
+
+
+class ChannelRequest(Packet):
+ """Channel request Section 9.1.8"""
+ name = "Channel Request"
+ fields_desc = [
+ ByteField("estCause", 0x0)
+ ]
+
+
+def channelRequest():
+ return ChannelRequest()
+
+
+# Network to MS
+def cipheringModeCommand():
+ """CIPHERING MODE COMMAND Section 9.1.9"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x35) # 00110101
+ c = RrCause()
+ #d=cipherModeSetting()
+ #e=cipherResponse()
+ # FIX
+ d = CipherModeSettingAndcipherResponse()
+ packet = a / b / c / d
+ return packet
+
+
+def cipheringModeComplete(MobileId_presence=0):
+ """CIPHERING MODE COMPLETE Section 9.1.10"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x32) # 00110010
+ packet = a / b
+ if MobileId_presence is 1:
+ c = MobileIdHdr(ieiMI=0x17, eightBitMI=0x0)
+ packet = packet / c
+ return packet
+
+
+# Network to MS
+def classmarkChange(MobileStationClassmark3_presence=0):
+ """CLASSMARK CHANGE Section 9.1.11"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x16) # 00010110
+ c = MobileStationClassmark2()
+ packet = a / b / c
+ if MobileStationClassmark3_presence is 1:
+ e = MobileStationClassmark3(ieiMSC3=0x20)
+ packet = packet / e
+ return packet
+
+
+# Network to MS
+def classmarkEnquiry():
+ """CLASSMARK ENQUIRY Section 9.1.12"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x13) # 00010011
+ packet = a / b
+ return packet
+# 9.1.12a Spare
+
+
+# Network to MS
+def configurationChangeCommand(ChannelMode_presence=0,
+ ChannelMode_presence1=0,
+ ChannelMode_presence2=0,
+ ChannelMode_presence3=0,
+ ChannelMode_presence4=0,
+ ChannelMode_presence5=0,
+ ChannelMode_presence6=0,
+ ChannelMode_presence7=0):
+ """CONFIGURATION CHANGE COMMAND Section 9.1.12b"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x30) # 00110000
+ c = MultislotAllocation()
+ packet = a / b / c
+ if ChannelMode_presence is 1:
+ d = ChannelModeHdr(ieiCM=0x63, eightBitCM=0x0)
+ packet = packet / d
+ if ChannelMode_presence1 is 1:
+ e = ChannelModeHdr(ieiCM=0x11, eightBitCM=0x0)
+ packet = packet / e
+ if ChannelMode_presence2 is 1:
+ f = ChannelModeHdr(ieiCM=0x13, eightBitCM=0x0)
+ packet = packet / f
+ if ChannelMode_presence3 is 1:
+ g = ChannelModeHdr(ieiCM=0x14, eightBitCM=0x0)
+ packet = packet / g
+ if ChannelMode_presence4 is 1:
+ h = ChannelModeHdr(ieiCM=0x15, eightBitCM=0x0)
+ packet = packet / h
+ if ChannelMode_presence5 is 1:
+ i = ChannelModeHdr(ieiCM=0x16, eightBitCM=0x0)
+ packet = packet / i
+ if ChannelMode_presence6 is 1:
+ j = ChannelModeHdr(ieiCM=0x17, eightBitCM=0x0)
+ packet = packet / j
+ if ChannelMode_presence7 is 1:
+ k = ChannelModeHdr(ieiCM=0x18, eightBitCM=0x0)
+ packet = packet / k
+ return packet
+
+
+def configurationChangeAcknowledge():
+ """CONFIGURATION CHANGE ACKNOWLEDGE Section 9.1.12c"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x31) # 00110001
+ c = MobileId()
+ packet = a / b / c
+ return packet
+
+
+def configurationChangeReject():
+ """CONFIGURATION CHANGE REJECT Section 9.1.12d"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x33) # 00110011
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def frequencyRedefinition(CellChannelDescription_presence=0):
+ """Frequency redefinition Section 9.1.13"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x14) # 00010100
+ c = ChannelDescription()
+ d = MobileAllocation()
+ e = StartingTime()
+ packet = a / b / c / d / e
+ if CellChannelDescription_presence is 1:
+ f = CellChannelDescriptionHdr(ieiCCD=0x62, eightBitCCD=0x0)
+ packet = packet / f
+ return packet
+
+
+# Network to MS
+def pdchAssignmentCommand(ChannelDescription_presence=0,
+ CellChannelDescription_presence=0,
+ MobileAllocation_presence=0,
+ StartingTime_presence=0, FrequencyList_presence=0,
+ ChannelDescription_presence1=0,
+ FrequencyChannelSequence_presence=0,
+ MobileAllocation_presence1=0,
+ PacketChannelDescription_presence=0,
+ DedicatedModeOrTBF_presence=0):
+ """PDCH ASSIGNMENT COMMAND Section 9.1.13a"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x23) # 00100011
+ c = ChannelDescription()
+ packet = a / b / c
+ if ChannelDescription_presence is 1:
+ d = ChannelDescriptionHdr(ieiCD=0x62, eightBitCD=0x0)
+ packet = packet / d
+ if CellChannelDescription_presence is 1:
+ e = CellChannelDescriptionHdr(ieiCCD=0x05, eightBitCCD=0x0)
+ packet = packet / e
+ if MobileAllocation_presence is 1:
+ f = MobileAllocationHdr(ieiMA=0x72, eightBitMA=0x0)
+ packet = packet / f
+ if StartingTime_presence is 1:
+ g = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / g
+ if FrequencyList_presence is 1:
+ h = FrequencyListHdr(ieiFL=0x19, eightBitFL=0x0)
+ packet = packet / h
+ if ChannelDescription_presence1 is 1:
+ i = ChannelDescriptionHdr(ieiCD=0x1C, eightBitCD=0x0)
+ packet = packet / i
+ if FrequencyChannelSequence_presence is 1:
+ j = FrequencyChannelSequenceHdr(ieiFCS=0x1E, eightBitFCS=0x0)
+ packet = packet / j
+ if MobileAllocation_presence1 is 1:
+ k = MobileAllocationHdr(ieiMA=0x21, eightBitMA=0x0)
+ packet = packet / k
+ if PacketChannelDescription_presence is 1:
+ l = PacketChannelDescription(ieiPCD=0x22)
+ packet = packet / l
+ if DedicatedModeOrTBF_presence is 1:
+ m = DedicatedModeOrTBFHdr(ieiDMOT=0x23, eightBitDMOT=0x0)
+ packet = packet / m
+ return packet
+
+
+def gprsSuspensionRequest():
+ """GPRS SUSPENSION REQUEST Section 9.1.13b"""
+ a = TpPd(pd=0x6)
+ b = MessageType()
+ c = Tlli()
+ d = RoutingAreaIdentification()
+ e = SuspensionCause()
+ packet = a / b / c / d / e
+ return packet
+
+
+class HandoverAccess(Packet):
+ name = "Handover Access" # Section 9.1.14"
+ fields_desc = [
+ ByteField("handover", None),
+ ]
+
+
+# Network to MS
+def handoverCommand(SynchronizationIndication_presence=0,
+ FrequencyShortList_presence=0, FrequencyList_presence=0,
+ CellChannelDescription_presence=0,
+ MultislotAllocation_presence=0,
+ ChannelMode_presence=0, ChannelMode_presence1=0,
+ ChannelMode_presence2=0,
+ ChannelMode_presence3=0, ChannelMode_presence4=0,
+ ChannelMode_presence5=0,
+ ChannelMode_presence6=0, ChannelMode_presence7=0,
+ ChannelDescription_presence1=0, ChannelMode2_presence=0,
+ FrequencyChannelSequence_presence=0,
+ MobileAllocation_presence=0,
+ StartingTime_presence=0, TimeDifference_presence=0,
+ TimingAdvance_presence=0,
+ FrequencyShortList_presence1=0,
+ FrequencyList_presence1=0,
+ ChannelDescription2_presence=0,
+ ChannelDescription_presence2=0,
+ FrequencyChannelSequence_presence1=0,
+ MobileAllocation_presence1=0,
+ CipherModeSetting_presence=0,
+ VgcsTargetModeIdentication_presence=0,
+ MultiRateConfiguration_presence=0):
+ """HANDOVER COMMAND Section 9.1.15"""
+ name = "Handover Command"
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2b) # 00101011
+ c = CellDescription()
+ d = ChannelDescription2()
+ e = HandoverReference()
+ f = PowerCommandAndAccessType()
+ packet = a / b / c / d / e / f
+ if SynchronizationIndication_presence is 1:
+ g = SynchronizationIndicationHdr(ieiSI=0xD, eightBitSI=0x0)
+ packet = packet / g
+ if FrequencyShortList_presence is 1:
+ h = FrequencyShortListHdr(ieiFSL=0x02)
+ packet = packet / h
+ if FrequencyList_presence is 1:
+ i = FrequencyListHdr(ieiFL=0x05, eightBitFL=0x0)
+ packet = packet / i
+ if CellChannelDescription_presence is 1:
+ j = CellChannelDescriptionHdr(ieiCCD=0x62, eightBitCCD=0x0)
+ packet = packet / j
+ if MultislotAllocation_presence is 1:
+ k = MultislotAllocationHdr(ieiMSA=0x10, eightBitMSA=0x0)
+ packet = packet / k
+ if ChannelMode_presence is 1:
+ l = ChannelModeHdr(ieiCM=0x63, eightBitCM=0x0)
+ packet = packet / l
+ if ChannelMode_presence1 is 1:
+ m = ChannelModeHdr(ieiCM=0x11, eightBitCM=0x0)
+ packet = packet / m
+ if ChannelMode_presence2 is 1:
+ n = ChannelModeHdr(ieiCM=0x13, eightBitCM=0x0)
+ packet = packet / n
+ if ChannelMode_presence3 is 1:
+ o = ChannelModeHdr(ieiCM=0x14, eightBitCM=0x0)
+ packet = packet / o
+ if ChannelMode_presence4 is 1:
+ p = ChannelModeHdr(ieiCM=0x15, eightBitCM=0x0)
+ packet = packet / p
+ if ChannelMode_presence5 is 1:
+ q = ChannelModeHdr(ieiCM=0x16, eightBitCM=0x0)
+ packet = packet / q
+ if ChannelMode_presence6 is 1:
+ r = ChannelModeHdr(ieiCM=0x17, eightBitCM=0x0)
+ packet = packet / r
+ if ChannelMode_presence7 is 1:
+ s = ChannelModeHdr(ieiCM=0x18, eightBitCM=0x0)
+ packet = packet / s
+ if ChannelDescription_presence1 is 1:
+ s1 = ChannelDescriptionHdr(ieiCD=0x64, eightBitCD=0x0)
+ packet = packet / s1
+ if ChannelMode2_presence is 1:
+ t = ChannelMode2Hdr(ieiCM2=0x66, eightBitCM2=0x0)
+ packet = packet / t
+ if FrequencyChannelSequence_presence is 1:
+ u = FrequencyChannelSequenceHdr(ieiFCS=0x69, eightBitFCS=0x0)
+ packet = packet / u
+ if MobileAllocation_presence is 1:
+ v = MobileAllocationHdr(ieiMA=0x72, eightBitMA=0x0)
+ packet = packet / v
+ if StartingTime_presence is 1:
+ w = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / w
+ if TimeDifference_presence is 1:
+ x = TimeDifferenceHdr(ieiTD=0x7B, eightBitTD=0x0)
+ packet = packet / x
+ if TimingAdvance_presence is 1:
+ y = TimingAdvanceHdr(ieiTA=0x7D, eightBitTA=0x0)
+ packet = packet / y
+ if FrequencyShortList_presence1 is 1:
+ z = FrequencyShortListHdr(ieiFSL=0x12)
+ packet = packet / z
+ if FrequencyList_presence1 is 1:
+ aa = FrequencyListHdr(ieiFL=0x19, eightBitFL=0x0)
+ packet = packet / aa
+ if ChannelDescription2_presence is 1:
+ ab = ChannelDescription2Hdr(ieiCD2=0x1C, eightBitCD2=0x0)
+ packet = packet / ab
+ if ChannelDescription_presence2 is 1:
+ ac = ChannelDescriptionHdr(ieiCD=0x1D, eightBitCD=0x0)
+ packet = packet / ac
+ if FrequencyChannelSequence_presence1 is 1:
+ ad = FrequencyChannelSequenceHdr(ieiFCS=0x1E, eightBitFCS=0x0)
+ packet = packet / ad
+ if MobileAllocation_presence1 is 1:
+ ae = MobileAllocationHdr(ieiMA=0x21, eightBitMA=0x0)
+ packet = packet / ae
+ if CipherModeSetting_presence is 1:
+ af = CipherModeSettingHdr(ieiCMS=0x9, eightBitCMS=0x0)
+ packet = packet / af
+ if VgcsTargetModeIdentication_presence is 1:
+ ag = VgcsTargetModeIdenticationHdr(ieiVTMI=0x01, eightBitVTMI=0x0)
+ packet = packet / ag
+ if MultiRateConfiguration_presence is 1:
+ ah = MultiRateConfigurationHdr(ieiMRC=0x03, eightBitMRC=0x0)
+ packet = packet / ah
+ return packet
+
+
+def handoverComplete(MobileTimeDifference_presence=0):
+ """HANDOVER COMPLETE Section 9.1.16"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2c) # 00101100
+ c = RrCause()
+ packet = a / b / c
+ if MobileTimeDifference_presence is 1:
+ d = MobileTimeDifferenceHdr(ieiMTD=0x77, eightBitMTD=0x0)
+ packet = packet / d
+ return packet
+
+
+def handoverFailure():
+ """HANDOVER FAILURE Section 9.1.17"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x28) # 00101000
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+#The L2 pseudo length of this message is the sum of lengths of all
+#information elements present in the message except
+#the IA Rest Octets and L2 Pseudo Length information elements.
+# Network to MS
+def immediateAssignment(ChannelDescription_presence=0,
+ PacketChannelDescription_presence=0,
+ StartingTime_presence=0):
+ """IMMEDIATE ASSIGNMENT Section 9.1.18"""
+ a = L2PseudoLength()
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x3F) # 00111111
+ d = PageModeAndDedicatedModeOrTBF()
+ packet = a / b / c / d
+ if ChannelDescription_presence is 1:
+ f = ChannelDescription()
+ packet = packet / f
+ if PacketChannelDescription_presence is 1:
+ g = PacketChannelDescription()
+ packet = packet / g
+ h = RequestReference()
+ i = TimingAdvance()
+ j = MobileAllocation()
+ packet = packet / h / i / j
+ if StartingTime_presence is 1:
+ k = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / k
+ l = IaRestOctets()
+ packet = packet / l
+ return packet
+
+
+#The L2 pseudo length of this message is the sum of lengths of all
+#information elements present in the message except
+#the IAX Rest Octets and L2 Pseudo Length information elements.
+
+# Network to MS
+def immediateAssignmentExtended(StartingTime_presence=0):
+ """IMMEDIATE ASSIGNMENT EXTENDED Section 9.1.19"""
+ a = L2PseudoLength()
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x39) # 00111001
+ d = PageModeAndSpareHalfOctets()
+ f = ChannelDescription()
+ g = RequestReference()
+ h = TimingAdvance()
+ i = MobileAllocation()
+ packet = a / b / c / d / f / g / h / i
+ if StartingTime_presence is 1:
+ j = StartingTimeHdr(ieiST=0x7C, eightBitST=0x0)
+ packet = packet / j
+ k = IaxRestOctets()
+ packet = packet / k
+ return packet
+
+
+# This message has L2 pseudo length 19
+# Network to MS
+def immediateAssignmentReject():
+ """IMMEDIATE ASSIGNMENT REJECT Section 9.1.20"""
+ a = L2PseudoLength(l2pLength=0x13)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x3a) # 00111010
+ d = PageModeAndSpareHalfOctets()
+ f = RequestReference()
+ g = WaitIndication()
+ h = RequestReference()
+ i = WaitIndication()
+ j = RequestReference()
+ k = WaitIndication()
+ l = RequestReference()
+ m = WaitIndication()
+ n = IraRestOctets()
+ packet = a / b / c / d / f / g / h / i / j / k / l / m / n
+ return packet
+
+
+def measurementReport():
+ """MEASUREMENT REPORT Section 9.1.21"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x15) # 00010101
+ c = MeasurementResults()
+ packet = a / b / c
+ return packet
+
+
+# len max 20
+class NotificationFacch():
+ """NOTIFICATION/FACCH Section 9.1.21a"""
+ name = "Notification/facch"
+ fields_desc = [
+ BitField("rr", 0x0, 1),
+ BitField("msgTyoe", 0x0, 5),
+ BitField("layer2Header", 0x0, 2),
+ BitField("frChanDes", 0x0, 24)
+ ]
+
+
+# The L2 pseudo length of this message has a value one
+# Network to MS
+def notificationNch():
+ """NOTIFICATION/NCH Section 9.1.21b"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x20) # 00100000
+ d = NtNRestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+def notificationResponse():
+ """NOTIFICATION RESPONSE Section 9.1.21d"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x26) # 00100110
+ c = MobileStationClassmark2()
+ d = MobileId()
+ e = DescriptiveGroupOrBroadcastCallReference()
+ packet = a / b / c / d / e
+ return packet
+
+
+# Network to MS
+def rrCellChangeOrder():
+ """RR-CELL CHANGE ORDER Section 9.1.21e"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x8) # 00001000
+ c = CellDescription()
+ d = NcModeAndSpareHalfOctets()
+ packet = a / b / c / d
+ return packet
+
+
+# Network to MS
+def pagingRequestType1(MobileId_presence=0):
+ """PAGING REQUEST TYPE 1 Section 9.1.22"""
+ #The L2 pseudo length of this message is the sum of lengths of all
+ #information elements present in the message except
+ #the P1 Rest Octets and L2 Pseudo Length information elements.
+ a = L2PseudoLength()
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x21) # 00100001
+ d = PageModeAndChannelNeeded()
+ f = MobileId()
+ packet = a / b / c / d / f
+ if MobileId_presence is 1:
+ g = MobileIdHdr(ieiMI=0x17, eightBitMI=0x0)
+ packet = packet / g
+ h = P1RestOctets()
+ packet = packet / h
+ return packet
+
+
+# The L2 pseudo length of this message is the sum of lengths of all
+# information elements present in the message except
+# Network to MS
+def pagingRequestType2(MobileId_presence=0):
+ """PAGING REQUEST TYPE 2 Section 9.1.23"""
+ a = L2PseudoLength()
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x22) # 00100010
+ d = PageModeAndChannelNeeded()
+ f = MobileId()
+ g = MobileId()
+ packet = a / b / c / d / f / g
+ if MobileId_presence is 1:
+ h = MobileIdHdr(ieiMI=0x17, eightBitMI=0x0)
+ packet = packet / h
+ i = P2RestOctets()
+ packet = packet / i
+ return packet
+
+
+# Network to MS
+def pagingRequestType3():
+ """PAGING REQUEST TYPE 3 Section 9.1.24"""
+# This message has a L2 Pseudo Length of 19
+ a = L2PseudoLength(l2pLength=0x13)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x24) # 00100100
+ d = PageModeAndChannelNeeded()
+ e = TmsiPTmsi()
+ f = TmsiPTmsi()
+ g = TmsiPTmsi()
+ h = TmsiPTmsi()
+ i = P3RestOctets()
+ packet = a / b / c / d / e / f / g / h / i
+ return packet
+
+
+def pagingResponse():
+ """PAGING RESPONSE Section 9.1.25"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x27) # 00100111
+ c = CiphKeySeqNrAndSpareHalfOctets()
+ d = MobileStationClassmark2()
+ e = MobileId()
+ packet = a / b / c / d / e
+ return packet
+
+
+# Network to MS
+def partialRelease():
+ """PARTIAL RELEASE Section 9.1.26"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0xa) # 00001010
+ c = ChannelDescription()
+ packet = a / b / c
+ return packet
+
+
+def partialReleaseComplete():
+ """PARTIAL RELEASE COMPLETE Section 9.1.27"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0xf) # 00001111
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def physicalInformation():
+ """PHYSICAL INFORMATION Section 9.1.28"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2d) # 00101101
+ c = TimingAdvance()
+ packet = a / b / c
+ return packet
+
+
+def rrInitialisationRequest():
+ """RR Initialisation Request Section 9.1.28.a"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x3c) # 00111100
+ c = CiphKeySeqNrAndMacModeAndChannelCodingRequest()
+ e = MobileStationClassmark2()
+ f = Tlli()
+ g = ChannelRequestDescription()
+ h = GprsMeasurementResults()
+ packet = a / b / c / e / f / g / h
+ return packet
+
+
+def rrStatus():
+ """RR STATUS Section 9.1.29"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x12) # 00010010
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+# It does not
+# follow the basic format. Its length is _25_ bits. The
+# order of bit transmission is defined in GSM 04.04.
+# Network to MS
+class SynchronizationChannelInformation():
+ """SYNCHRONIZATION CHANNEL INFORMATION Section 9.1.30"""
+ name = "Synchronization Channel Information"
+ fields_desc = [
+ BitField("bsic", 0x0, 5),
+ BitField("t1Hi", 0x0, 3),
+ ByteField("t1Mi", 0x0),
+ BitField("t1Lo", 0x0, 1),
+ BitField("t2", 0x0, 5),
+ BitField("t3Hi", 0x0, 2),
+ BitField("t3Lo", 0x0, 1)
+ ]
+
+
+# This message has a L2 Pseudo Length of 21.
+# Network to MS
+def systemInformationType1():
+ """SYSTEM INFORMATION TYPE 1 Section 9.1.31"""
+ a = L2PseudoLength(l2pLength=0x15)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x19) # 00011001
+ d = CellChannelDescription()
+ e = RachControlParameters()
+ f = Si1RestOctets()
+ packet = a / b / c / d / e / f
+ return packet
+
+
+# This message has a L2 Pseudo Length of 22.
+# Network to MS
+def systemInformationType2():
+ """SYSTEM INFORMATION TYPE 2 Section 9.1.32"""
+ a = L2PseudoLength(l2pLength=0x16)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x1a) # 00011010
+ d = NeighbourCellsDescription()
+ e = NccPermitted()
+ f = RachControlParameters()
+ packet = a / b / c / d / e / f
+ return packet
+
+
+# This message has a L2 pseudo length of 21
+# Network to MS
+def systemInformationType2bis():
+ """SYSTEM INFORMATION TYPE 2bis Section 9.1.33"""
+ a = L2PseudoLength(l2pLength=0x15)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x2) # 00000010
+ d = NeighbourCellsDescription()
+ e = RachControlParameters()
+ f = Si2bisRestOctets()
+ packet = a / b / c / d / e / f
+ return packet
+
+
+# This message has a L2 pseudo length of 18
+# Network to MS
+def systemInformationType2ter():
+ """SYSTEM INFORMATION TYPE 2ter Section 9.1.34"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x3) # 00000011
+ d = NeighbourCellsDescription2()
+ e = Si2terRestOctets()
+ packet = a / b / c / d / e
+ return packet
+
+
+# This message has a L2 Pseudo Length of 18
+# Network to MS
+def systemInformationType3():
+ """SYSTEM INFORMATION TYPE 3 Section 9.1.35"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x1b) # 00011011
+ d = CellIdentity()
+ e = LocalAreaId()
+ f = ControlChannelDescription()
+ g = CellOptionsBCCH()
+ h = CellSelectionParameters()
+ i = RachControlParameters()
+ j = Si3RestOctets()
+ packet = a / b / c / d / e / f / g / h / i / j
+ return packet
+
+
+#The L2 pseudo length of this message is the
+#sum of lengths of all information elements present in the message except
+#the SI 4 Rest Octets and L2 Pseudo Length
+# Network to MS
+def systemInformationType4(ChannelDescription_presence=0,
+ MobileAllocation_presence=0):
+ """SYSTEM INFORMATION TYPE 4 Section 9.1.36"""
+ a = L2PseudoLength()
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x1C) # 000111100
+ d = LocalAreaId()
+ e = CellSelectionParameters()
+ f = RachControlParameters()
+ packet = a / b / c / d / e / f
+ if ChannelDescription_presence is 1:
+ g = ChannelDescriptionHdr(ieiCD=0x64, eightBitCD=0x0)
+ packet = packet / g
+ if MobileAllocation_presence is 1:
+ h = MobileAllocationHdr(ieiMA=0x72, eightBitMA=0x0)
+ packet = packet / h
+ i = Si4RestOctets()
+ packet = packet / i
+ return packet
+
+
+#This message has a L2 Pseudo Length of 18
+# Network to MS
+def systemInformationType5():
+ """SYSTEM INFORMATION TYPE 5 Section 9.1.37"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x35) # 000110101
+ d = NeighbourCellsDescription()
+ packet = a / b / c / d
+ return packet
+
+
+#This message has a L2 Pseudo Length of 18
+# Network to MS
+def systemInformationType5bis():
+ """SYSTEM INFORMATION TYPE 5bis Section 9.1.38"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x5) # 00000101
+ d = NeighbourCellsDescription()
+ packet = a / b / c / d
+ return packet
+
+
+# This message has a L2 Pseudo Length of 18
+# Network to MS
+def systemInformationType5ter():
+ """SYSTEM INFORMATION TYPE 5ter Section 9.1.39"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x6) # 00000110
+ d = NeighbourCellsDescription2()
+ packet = a / b / c / d
+ return packet
+
+
+#This message has a L2 Pseudo Length of 11
+# Network to MS
+def systemInformationType6():
+ """SYSTEM INFORMATION TYPE 6 Section 9.1.40"""
+ a = L2PseudoLength(l2pLength=0x0b)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x1e) # 00011011
+ d = CellIdentity()
+ e = LocalAreaId()
+ f = CellOptionsBCCH()
+ g = NccPermitted()
+ h = Si6RestOctets()
+ packet = a / b / c / d / e / f / g
+ return packet
+
+
+# The L2 pseudo length of this message has the value 1
+# Network to MS
+def systemInformationType7():
+ """SYSTEM INFORMATION TYPE 7 Section 9.1.41"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x37) # 000110111
+ d = Si7RestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+# The L2 pseudo length of this message has the value 1
+# Network to MS
+def systemInformationType8():
+ """SYSTEM INFORMATION TYPE 8 Section 9.1.42"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x18) # 00011000
+ d = Si8RestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+# The L2 pseudo length of this message has the value 1
+# Network to MS
+def systemInformationType9():
+ """SYSTEM INFORMATION TYPE 9 Section 9.1.43"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x4) # 00000100
+ d = Si9RestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+# The L2 pseudo length of this message has the value 0
+# Network to MS
+def systemInformationType13():
+ """SYSTEM INFORMATION TYPE 13 Section 9.1.43a"""
+ a = L2PseudoLength(l2pLength=0x00)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x0) # 00000000
+ d = Si13RestOctets()
+ packet = a / b / c / d
+ return packet
+#
+# 9.1.43b / c spare
+#
+
+
+# The L2 pseudo length of this message has the value 1
+# Network to MS
+def systemInformationType16():
+ """SYSTEM INFORMATION TYPE 16 Section 9.1.43d"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x3d) # 00111101
+ d = Si16RestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+# The L2 pseudo length of this message has the value 1
+# Network to MS
+def systemInformationType17():
+ """SYSTEM INFORMATION TYPE 17 Section 9.1.43e"""
+ a = L2PseudoLength(l2pLength=0x01)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x3e) # 00111110
+ d = Si17RestOctets()
+ packet = a / b / c / d
+ return packet
+
+
+def talkerIndication():
+ """TALKER INDICATION Section 9.1.44"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x11) # 00010001
+ c = MobileStationClassmark2()
+ d = MobileId()
+ packet = a / b / c / d
+ return packet
+
+
+class UplinkAccess():
+ """UPLINK ACCESS Section 9.1.45"""
+ name = "Uplink Access"
+ fields_desc = [
+ ByteField("establishment", 0x0)
+ ]
+
+
+# Network to MS
+def uplinkBusy():
+ """UPLINK BUSY Section 9.1.46"""
+ name = "Uplink Busy"
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x2a) # 00101010
+ packet = a / b
+ return packet
+
+
+# Network to MS
+class UplinkFree():
+ """UPLINK FREE Section 9.1.47"""
+ name = "Uplink Free"
+ fields_desc = [
+ BitField("pd", 0x0, 1),
+ BitField("msgType", 0x0, 5),
+ BitField("layer2Header", 0x0, 2),
+ BitField("uplinkAccess", 0x0, 1),
+ BitField("lOrH", 0x0, 1), # 0 for L, 1 for H
+ BitField("upIdCode", 0x0, 6),
+ ]
+
+
+def uplinkRelease():
+ """UPLINK RELEASE Section 9.1.48"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0xe) # 00001110
+ c = RrCause()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def vgcsUplinkGrant():
+ """VGCS UPLINK GRANT Section 9.1.49"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x9) # 00001001
+ c = RrCause()
+ d = RequestReference()
+ e = TimingAdvance()
+ packet = a / b / c / d / e
+ return packet
+
+
+# Network to MS
+def systemInformationType10():
+ """SYSTEM INFORMATION TYPE 10 Section 9.1.50"""
+ name = "SyStem Information Type 10"
+ fields_desc = [
+ BitField("pd", 0x0, 1),
+ BitField("msgType", 0x0, 5),
+ BitField("layer2Header", 0x0, 2),
+ BitField("si10", 0x0, 160)
+ ]
+
+
+# Network to MS
+# The L2 pseudo length of this message has the value 18
+def extendedMeasurementOrder():
+ """EXTENDED MEASUREMENT ORDER Section 9.1.51"""
+ a = L2PseudoLength(l2pLength=0x12)
+ b = TpPd(pd=0x6)
+ c = MessageType(mesType=0x37) # 00110111
+ d = ExtendedMeasurementFrequencyList()
+ packet = a / b / c / d
+ return packet
+
+
+def extendedMeasurementReport():
+ """EXTENDED MEASUREMENT REPORT Section 9.1.52"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x36) # 00110110
+ c = ExtendedMeasurementResults()
+ packet = a / b / c
+ return packet
+
+
+def applicationInformation():
+ """APPLICATION INFORMATION Section 9.1.53"""
+ a = TpPd(pd=0x6)
+ b = MessageType(mesType=0x38) # 00111000
+ c = ApduIDAndApduFlags()
+ e = ApduData()
+ packet = a / b / c / e
+ return packet
+#
+# 9.2 Messages for mobility management
+#
+
+
+# Network to MS
+def authenticationReject():
+ """AUTHENTICATION REJECT Section 9.2.1"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x11) # 00010001
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def authenticationRequest():
+ """AUTHENTICATION REQUEST Section 9.2.2"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x12) # 00010010
+ c = CiphKeySeqNrAndSpareHalfOctets()
+ d = AuthenticationParameterRAND()
+ packet = a / b / c / d
+ return packet
+
+
+def authenticationResponse():
+ """AUTHENTICATION RESPONSE Section 9.2.3"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x14) # 00010100
+ c = AuthenticationParameterSRES()
+ packet = a / b / c
+ return packet
+
+
+def cmReestablishmentRequest(LocalAreaId_presence=0):
+ """CM RE-ESTABLISHMENT REQUEST Section 9.2.4"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x28) # 00101000
+ c = CiphKeySeqNrAndSpareHalfOctets()
+ e = MobileStationClassmark2()
+ f = MobileId()
+ if LocalAreaId_presence is 1:
+ g = LocalAreaId(iei=0x13, eightbit=0x0)
+ packet = packet / g
+ packet = a / b / c / e / f
+ return packet
+
+
+# Network to MS
+def cmServiceAccept():
+ """CM SERVICE ACCEPT Section 9.2.5"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x21) # 00100001
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def cmServicePrompt():
+ """CM SERVICE PROMPT Section 9.2.5a"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x25) # 00100101
+ c = PdAndSapi()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def cmServiceReject():
+ """CM SERVICE REJECT Section 9.2.6"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x22) # 00100010
+ c = RejectCause()
+ packet = a / b / c
+ return packet
+
+
+def cmServiceAbort():
+ """CM SERVICE ABORT Section 9.2.7"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x23) # 00100011
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def abort():
+ """ABORT Section 9.2.8"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x29) # 00101001
+ c = RejectCause()
+ packet = a / b / c
+ return packet
+
+
+def cmServiceRequest(PriorityLevel_presence=0):
+ """CM SERVICE REQUEST Section 9.2.9"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x24) # 00100100
+ c = CmServiceTypeAndCiphKeySeqNr()
+ e = MobileStationClassmark2()
+ f = MobileId()
+ packet = a / b / c / e / f
+ if PriorityLevel_presence is 1:
+ g = PriorityLevelHdr(ieiPL=0x8, eightBitPL=0x0)
+ packet = packet / g
+ return packet
+
+
+# Network to MS
+def identityRequest():
+ """IDENTITY REQUEST Section 9.2.10"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x8) # 00001000
+ c = IdentityTypeAndSpareHalfOctets()
+ packet = a / b / c
+ return packet
+
+
+def identityResponse():
+ """IDENTITY RESPONSE Section 9.2.11"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x9) # 00001001
+ c = MobileId()
+ packet = a / b / c
+ return packet
+
+
+def imsiDetachIndication():
+ """IMSI DETACH INDICATION Section 9.2.12"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x1) # 00000001
+ c = MobileStationClassmark1()
+ d = MobileId()
+ packet = a / b / c / d
+ return packet
+
+
+# Network to MS
+def locationUpdatingAccept(MobileId_presence=0,
+ FollowOnProceed_presence=0,
+ CtsPermission_presence=0):
+ """LOCATION UPDATING ACCEPT Section 9.2.13"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x02) # 00000010
+ c = LocalAreaId()
+ packet = a / b / c
+ if MobileId_presence is 1:
+ d = MobileIdHdr(ieiMI=0x17, eightBitMI=0x0)
+ packet = packet / d
+ if FollowOnProceed_presence is 1:
+ e = FollowOnProceed(ieiFOP=0xA1)
+ packet = packet / e
+ if CtsPermission_presence is 1:
+ f = CtsPermissionHdr(ieiCP=0xA2, eightBitCP=0x0)
+ packet = packet / f
+ return packet
+
+
+# Network to MS
+def locationUpdatingReject():
+ """LOCATION UPDATING REJECT Section 9.2.14"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x4) # 0x00000100
+ c = RejectCause()
+ packet = a / b / c
+ return packet
+
+
+def locationUpdatingRequest():
+ """LOCATION UPDATING REQUEST Section 9.2.15"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x8) # 00001000
+ c = LocationUpdatingTypeAndCiphKeySeqNr()
+ e = LocalAreaId()
+ f = MobileStationClassmark1()
+ g = MobileId()
+ packet = a / b / c / e / f / g
+ return packet
+
+
+# Network to MS
+def mmInformation(NetworkName_presence=0, NetworkName_presence1=0,
+ TimeZone_presence=0, TimeZoneAndTime_presence=0,
+ LsaIdentifier_presence=0):
+ """MM INFORMATION Section 9.2.15a"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x32) # 00110010
+ packet = a / b
+ if NetworkName_presence is 1:
+ c = NetworkNameHdr(ieiNN=0x43, eightBitNN=0x0)
+ packet = packet / c
+ if NetworkName_presence1 is 1:
+ d = NetworkNameHdr(ieiNN=0x45, eightBitNN=0x0)
+ packet = packet / d
+ if TimeZone_presence is 1:
+ e = TimeZoneHdr(ieiTZ=0x46, eightBitTZ=0x0)
+ packet = packet / e
+ if TimeZoneAndTime_presence is 1:
+ f = TimeZoneAndTimeHdr(ieiTZAT=0x47, eightBitTZAT=0x0)
+ packet = packet / f
+ if LsaIdentifier_presence is 1:
+ g = LsaIdentifierHdr(ieiLI=0x48, eightBitLI=0x0)
+ packet = packet / g
+ return packet
+
+
+def mmStatus():
+ """MM STATUS Section 9.2.16"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x31) # 00110001
+ c = RejectCause()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def tmsiReallocationCommand():
+ """TMSI REALLOCATION COMMAND Section 9.2.17"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x1a) # 00011010
+ c = LocalAreaId()
+ d = MobileId()
+ packet = a / b / c / d
+ return packet
+
+
+def tmsiReallocationComplete():
+ """TMSI REALLOCATION COMPLETE Section 9.2.18"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x1b) # 00011011
+ packet = a / b
+ return packet
+
+
+def mmNull():
+ """MM NULL Section 9.2.19"""
+ a = TpPd(pd=0x5)
+ b = MessageType(mesType=0x30) # 00110000
+ packet = a / b
+ return packet
+
+#
+# 9.3 Messages for circuit-switched call control
+#
+
+
+# Network to MS
+def alertingNetToMs(Facility_presence=0, ProgressIndicator_presence=0,
+ UserUser_presence=0):
+ """ALERTING Section 9.3.1.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1) # 00000001
+ packet = a / b
+ if Facility_presence is 1:
+ c = FacilityHdr(ieiF=0x1C)
+ packet = packet / c
+ if ProgressIndicator_presence is 1:
+ d = ProgressIndicatorHdr(ieiPI=0x1E)
+ packet = packet / d
+ if UserUser_presence is 1:
+ e = UserUserHdr(ieiUU=0x7E)
+ packet = packet / e
+ return packet
+
+
+def alertingMsToNet(Facility_presence=0, UserUser_presence=0,
+ SsVersionIndicator_presence=0):
+ """ALERTING Section 9.3.1.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1) # 00000001
+ packet = a / b
+ if Facility_presence is 1:
+ c = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / c
+ if UserUser_presence is 1:
+ d = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / d
+ if SsVersionIndicator_presence is 1:
+ e = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / e
+ return packet
+
+
+def callConfirmed(RepeatIndicator_presence=0,
+ BearerCapability_presence=0, BearerCapability_presence1=0,
+ Cause_presence=0, CallControlCapabilities_presence=0):
+ """CALL CONFIRMED Section 9.3.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x8) # 00001000
+ packet = a / b
+ if RepeatIndicator_presence is 1:
+ c = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / c
+ if BearerCapability_presence is 1:
+ d = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / d
+ if BearerCapability_presence1 is 1:
+ e = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / e
+ if Cause_presence is 1:
+ f = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / f
+ if CallControlCapabilities_presence is 1:
+ g = CallControlCapabilitiesHdr(ieiCCC=0x15, eightBitCCC=0x0)
+ packet = packet / g
+ return packet
+
+
+# Network to MS
+def callProceeding(RepeatIndicator_presence=0,
+ BearerCapability_presence=0,
+ BearerCapability_presence1=0,
+ Facility_presence=0, ProgressIndicator_presence=0,
+ PriorityLevel_presence=0):
+ """CALL PROCEEDING Section 9.3.3"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2) # 00000010
+ packet = a / b
+ if RepeatIndicator_presence is 1:
+ c = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / c
+ if BearerCapability_presence is 1:
+ d = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / d
+ if BearerCapability_presence1 is 1:
+ e = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / e
+ if Facility_presence is 1:
+ f = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / f
+ if ProgressIndicator_presence is 1:
+ g = ProgressIndicatorHdr(ieiPI=0x1E, eightBitPI=0x0)
+ packet = packet / g
+ if PriorityLevel_presence is 1:
+ h = PriorityLevelHdr(ieiPL=0x80, eightBitPL=0x0)
+ packet = packet / h
+ return packet
+
+
+# Network to MS
+def congestionControl(Cause_presence=0):
+ """CONGESTION CONTROL Section 9.3.4"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x39) # 00111001
+ c = CongestionLevelAndSpareHalfOctets()
+ packet = a / b / c
+ if Cause_presence is 1:
+ e = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / e
+ return packet
+
+
+# Network to MS
+def connectNetToMs(Facility_presence=0, ProgressIndicator_presence=0,
+ ConnectedNumber_presence=0, ConnectedSubaddress_presence=0,
+ UserUser_presence=0):
+ """CONNECT Section 9.3.5.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x7) # 00000111
+ packet = a / b
+ if Facility_presence is 1:
+ c = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / c
+ if ProgressIndicator_presence is 1:
+ d = ProgressIndicatorHdr(ieiPI=0x1E, eightBitPI=0x0)
+ packet = packet / d
+ if ConnectedNumber_presence is 1:
+ e = ConnectedNumberHdr(ieiCN=0x4C, eightBitCN=0x0)
+ packet = packet / e
+ if ConnectedSubaddress_presence is 1:
+ f = ConnectedSubaddressHdr(ieiCS=0x4D, eightBitCS=0x0)
+ packet = packet / f
+ if UserUser_presence is 1:
+ g = UserUserHdr(ieiUU=0x7F, eightBitUU=0x0)
+ packet = packet / g
+ return packet
+
+
+def connectMsToNet(Facility_presence=0, ConnectedSubaddress_presence=0,
+ UserUser_presence=0, SsVersionIndicator_presence=0):
+ """CONNECT Section 9.3.5.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x7) # 00000111
+ packet = a / b
+ if Facility_presence is 1:
+ c = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / c
+ if ConnectedSubaddress_presence is 1:
+ d = ConnectedSubaddressHdr(ieiCS=0x4D, eightBitCS=0x0)
+ packet = packet / d
+ if UserUser_presence is 1:
+ e = UserUserHdr(ieiUU=0x7F, eightBitUU=0x0)
+ packet = packet / e
+ if SsVersionIndicator_presence is 1:
+ f = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / f
+ return packet
+
+
+def connectAcknowledge():
+ """CONNECT ACKNOWLEDGE Section 9.3.6"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0xf) # 00001111
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def disconnectNetToMs(Facility_presence=0, ProgressIndicator_presence=0,
+ UserUser_presence=0, AllowedActions_presence=0):
+ """DISCONNECT Section 9.3.7.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x25) # 00100101
+ c = Cause()
+ packet = a / b / c
+ if Facility_presence is 1:
+ d = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / d
+ if ProgressIndicator_presence is 1:
+ e = ProgressIndicatorHdr(ieiPI=0x1E, eightBitPI=0x0)
+ packet = packet / e
+ if UserUser_presence is 1:
+ f = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / f
+ if AllowedActions_presence is 1:
+ g = AllowedActionsHdr(ieiAA=0x7B, eightBitAA=0x0)
+ packet = packet / g
+ return packet
+
+
+def disconnectMsToNet(Facility_presence=0, UserUser_presence=0,
+ SsVersionIndicator_presence=0):
+ """Disconnect Section 9.3.7.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x25) # 00100101
+ c = Cause()
+ packet = a / b / c
+ if Facility_presence is 1:
+ d = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / d
+ if UserUser_presence is 1:
+ e = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / e
+ if SsVersionIndicator_presence is 1:
+ f = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / f
+ return packet
+
+
+def emergencySetup(BearerCapability_presence=0):
+ """EMERGENCY SETUP Section 9.3.8"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0xe) # 00001110
+ packet = a / b
+ if BearerCapability_presence is 1:
+ c = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / c
+ return packet
+
+
+# Network to MS
+def facilityNetToMs():
+ """FACILITY Section 9.3.9.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3a) # 00111010
+ c = Facility()
+ packet = a / b / c
+ return packet
+
+
+def facilityMsToNet(SsVersionIndicator_presence=0):
+ """FACILITY Section 9.3.9.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3a) # 00111010
+ c = Facility()
+ packet = a / b / c
+ if SsVersionIndicator_presence is 1:
+ d = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / d
+ return packet
+
+
+def hold():
+ """HOLD Section 9.3.10"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x18) # 00011000
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def holdAcknowledge():
+ """HOLD ACKNOWLEDGE Section 9.3.11"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x19) # 00011001
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def holdReject():
+ """HOLD REJECT Section 9.3.12"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1a) # 00011010
+ c = Cause()
+ packet = a / b / c
+ return packet
+
+
+def modify(LowLayerCompatibility_presence=0,
+ HighLayerCompatibility_presence=0,
+ ReverseCallSetupDirection_presence=0):
+ """MODIFY Section 9.3.13"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x17) # 00010111
+ c = BearerCapability()
+ packet = a / b / c
+ if LowLayerCompatibility_presence is 1:
+ d = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / d
+ if HighLayerCompatibility_presence is 1:
+ e = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / e
+ if ReverseCallSetupDirection_presence is 1:
+ f = ReverseCallSetupDirectionHdr(ieiRCSD=0xA3)
+ packet = packet / f
+ return packet
+
+
+def modifyComplete(LowLayerCompatibility_presence=0,
+ HighLayerCompatibility_presence=0,
+ ReverseCallSetupDirection_presence=0):
+ """MODIFY COMPLETE Section 9.3.14"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1f) # 00011111
+ c = BearerCapability()
+ packet = a / b / c
+ if LowLayerCompatibility_presence is 1:
+ d = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / d
+ if HighLayerCompatibility_presence is 1:
+ e = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / e
+ if ReverseCallSetupDirection_presence is 1:
+ f = ReverseCallSetupDirection(ieiRCSD=0xA3)
+ packet = packet / f
+ return packet
+
+
+def modifyReject(LowLayerCompatibility_presence=0,
+ HighLayerCompatibility_presence=0):
+ """MODIFY REJECT Section 9.3.15"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x13) # 00010011
+ c = BearerCapability()
+ d = Cause()
+ packet = a / b / c / d
+ if LowLayerCompatibility_presence is 1:
+ e = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / e
+ if HighLayerCompatibility_presence is 1:
+ f = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / f
+ return packet
+
+
+def notify():
+ """NOTIFY Section 9.3.16"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3e) # 00111110
+ c = NotificationIndicator()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def progress(UserUser_presence=0):
+ """PROGRESS Section 9.3.17"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3) # 00000011
+ c = ProgressIndicator()
+ packet = a / b / c
+ if UserUser_presence is 1:
+ d = UserUserHdr()
+ packet = packet / d
+ return packet
+
+
+# Network to MS
+def ccEstablishment():
+ """CC-ESTABLISHMENT Section 9.3.17a"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x4) # 00000100
+ c = SetupContainer()
+ packet = a / b / c
+ return packet
+
+
+def ccEstablishmentConfirmed(RepeatIndicator_presence=0,
+ BearerCapability_presence=0,
+ BearerCapability_presence1=0,
+ Cause_presence=0):
+ """CC-ESTABLISHMENT CONFIRMED Section 9.3.17b"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x6) # 00000110
+ packet = a / b
+ if RepeatIndicator_presence is 1:
+ c = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / c
+ if BearerCapability_presence is 1:
+ d = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / d
+ if BearerCapability_presence1 is 1:
+ e = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / e
+ if Cause_presence is 1:
+ f = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / f
+ return packet
+
+
+# Network to MS
+def releaseNetToMs():
+ """RELEASE Section 9.3.18.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2d) # 00101101
+ c = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ d = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ e = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ f = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = a / b / c / d / e / f
+ return packet
+
+
+def releaseMsToNet(Cause_presence=0, Cause_presence1=0,
+ Facility_presence=0, UserUser_presence=0,
+ SsVersionIndicator_presence=0):
+ """RELEASE Section 9.3.18.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2d) # 00101101
+ packet = a / b
+ if Cause_presence is 1:
+ c = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / c
+ if Cause_presence1 is 1:
+ d = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / d
+ if Facility_presence is 1:
+ e = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / e
+ if UserUser_presence is 1:
+ f = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / f
+ if SsVersionIndicator_presence is 1:
+ g = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / g
+ return packet
+
+
+# Network to MS
+def recall():
+ """RECALL Section 9.3.18a"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0xb) # 00001011
+ c = RecallType()
+ d = Facility()
+ packet = a / b / c / d
+ return packet
+
+
+# Network to MS
+def releaseCompleteNetToMs(Cause_presence=0, Facility_presence=0,
+ UserUser_presence=0):
+ """RELEASE COMPLETE Section 9.3.19.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2a) # 00101010
+ packet = a / b
+ if Cause_presence is 1:
+ c = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / c
+ if Facility_presence is 1:
+ d = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / d
+ if UserUser_presence is 1:
+ e = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / e
+ return packet
+
+
+def releaseCompleteMsToNet(Cause_presence=0, Facility_presence=0,
+ UserUser_presence=0, SsVersionIndicator_presence=0):
+ """RELEASE COMPLETE Section 9.3.19.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2a) # 00101010
+ packet = a / b
+ if Cause_presence is 1:
+ c = CauseHdr(ieiC=0x08, eightBitC=0x0)
+ packet = packet / c
+ if Facility_presence is 1:
+ d = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / d
+ if UserUser_presence is 1:
+ e = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / e
+ if SsVersionIndicator_presence is 1:
+ f = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / f
+ return packet
+
+
+def retrieve():
+ """RETRIEVE Section 9.3.20"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1c) # 00011100
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def retrieveAcknowledge():
+ """RETRIEVE ACKNOWLEDGE Section 9.3.21"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1d) # 00011101
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def retrieveReject():
+ """RETRIEVE REJECT Section 9.3.22"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1e) # 00011110
+ c = Cause()
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def setupMobileTerminated(RepeatIndicator_presence=0,
+ BearerCapability_presence=0,
+ BearerCapability_presence1=0,
+ Facility_presence=0, ProgressIndicator_presence=0,
+ Signal_presence=0,
+ CallingPartyBcdNumber_presence=0,
+ CallingPartySubaddress_presence=0,
+ CalledPartyBcdNumber_presence=0,
+ CalledPartySubaddress_presence=0,
+# RecallType_presence=0,
+ RedirectingPartyBcdNumber_presence=0,
+ RedirectingPartySubaddress_presence=0,
+ RepeatIndicator_presence1=0,
+ LowLayerCompatibility_presence=0,
+ LowLayerCompatibility_presence1=0,
+ RepeatIndicator_presence2=0,
+ HighLayerCompatibility_presence=0,
+ HighLayerCompatibility_presence1=0,
+ UserUser_presence=0, PriorityLevel_presence=0,
+ AlertingPattern_presence=0):
+ """SETUP Section 9.3.23.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x5) # 00000101
+ packet = a / b
+ if RepeatIndicator_presence is 1:
+ c = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / c
+ if BearerCapability_presence is 1:
+ d = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / d
+ if BearerCapability_presence1 is 1:
+ e = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / e
+ if Facility_presence is 1:
+ f = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / f
+ if ProgressIndicator_presence is 1:
+ g = ProgressIndicatorHdr(ieiPI=0x1E, eightBitPI=0x0)
+ packet = packet / g
+ if Signal_presence is 1:
+ h = SignalHdr(ieiS=0x34, eightBitS=0x0)
+ packet = packet / h
+ if CallingPartyBcdNumber_presence is 1:
+ i = CallingPartyBcdNumberHdr(ieiCPBN=0x5C, eightBitCPBN=0x0)
+ packet = packet / i
+ if CallingPartySubaddress_presence is 1:
+ j = CallingPartySubaddressHdr(ieiCPS=0x5D, eightBitCPS=0x0)
+ packet = packet / j
+ if CalledPartyBcdNumber_presence is 1:
+ k = CalledPartyBcdNumberHdr(ieiCPBN=0x5E, eightBitCPBN=0x0)
+ packet = packet / k
+ if CalledPartySubaddress_presence is 1:
+ l = CalledPartySubaddressHdr(ieiCPS=0x6D, eightBitCPS=0x0)
+ packet = packet / l
+ if RedirectingPartyBcdNumber_presence is 1:
+ n = RedirectingPartyBcdNumberHdr(ieiRPBN=0x74, eightBitRPBN=0x0)
+ packet = packet / n
+ if RedirectingPartySubaddress_presence is 1:
+ m = RedirectingPartySubaddress_presence(ieiRPBN=0x75, eightBitRPBN=0x0)
+ packet = packet / m
+ if RepeatIndicator_presence1 is 1:
+ o = RepeatIndicatorHdr(ieiRI=0xD0, eightBitRI=0x0)
+ packet = packet / o
+ if LowLayerCompatibility_presence is 1:
+ p = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / p
+ if LowLayerCompatibility_presence1 is 1:
+ q = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / q
+ if RepeatIndicator_presence2 is 1:
+ r = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / r
+ if HighLayerCompatibility_presence is 1:
+ s = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / s
+ if HighLayerCompatibility_presence1 is 1:
+ t = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / t
+ if UserUser_presence is 1:
+ u = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / u
+ if PriorityLevel_presence is 1:
+ v = PriorityLevelHdr(ieiPL=0x8, eightBitPL=0x0)
+ packet = packet / v
+ if AlertingPattern_presence is 1:
+ w = AlertingPatternHdr(ieiAP=0x19, eightBitAP=0x0)
+ packet = packet / w
+ return packet
+
+
+def setupMobileOriginated(RepeatIndicator_presence=0,
+ BearerCapability_presence=0,
+ BearerCapability_presence1=0,
+ Facility_presence=0,
+ CallingPartySubaddress_presence=0,
+ CalledPartyBcdNumber_presence=0,
+ CalledPartySubaddress_presence=0,
+ RepeatIndicator_presence1=0,
+ LowLayerCompatibility_presence=0,
+ LowLayerCompatibility_presence1=0,
+ RepeatIndicator_presence2=0,
+ HighLayerCompatibility_presence=0,
+ HighLayerCompatibility_presence1=0,
+ UserUser_presence=0, SsVersionIndicator_presence=0,
+ ClirSuppression_presence=0,
+ ClirInvocation_presence=0,
+ CallControlCapabilities_presence=0,
+ Facility_presence1=0,
+ Facility_presence2=0):
+ """SETUP Section 9.3.23.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x5) # 00000101
+ packet = a / b
+ if RepeatIndicator_presence is 1:
+ c = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / c
+ if BearerCapability_presence is 1:
+ d = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / d
+ if BearerCapability_presence1 is 1:
+ e = BearerCapabilityHdr(ieiBC=0x04, eightBitBC=0x0)
+ packet = packet / e
+ if Facility_presence is 1:
+ f = FacilityHdr(ieiF=0x1C, eightBitF=0x0)
+ packet = packet / f
+ if CallingPartySubaddress_presence is 1:
+ g = CallingPartySubaddressHdr(ieiCPS=0x5D, eightBitCPS=0x0)
+ packet = packet / g
+ if CalledPartyBcdNumber_presence is 1:
+ h = CalledPartyBcdNumberHdr(ieiCPBN=0x5E, eightBitCPBN=0x0)
+ packet = packet / h
+ if CalledPartySubaddress_presence is 1:
+ i = CalledPartySubaddressHdr(ieiCPS=0x6D, eightBitCPS=0x0)
+ packet = packet / i
+ if RepeatIndicator_presence1 is 1:
+ j = RepeatIndicatorHdr(ieiRI=0xD0, eightBitRI=0x0)
+ packet = packet / j
+ if LowLayerCompatibility_presence is 1:
+ k = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / k
+ if LowLayerCompatibility_presence1 is 1:
+ l = LowLayerCompatibilityHdr(ieiLLC=0x7C, eightBitLLC=0x0)
+ packet = packet / l
+ if RepeatIndicator_presence2 is 1:
+ m = RepeatIndicatorHdr(ieiRI=0xD, eightBitRI=0x0)
+ packet = packet / m
+ if HighLayerCompatibility_presence is 1:
+ n = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / n
+ if HighLayerCompatibility_presence1 is 1:
+ o = HighLayerCompatibilityHdr(ieiHLC=0x7D, eightBitHLC=0x0)
+ packet = packet / o
+ if UserUser_presence is 1:
+ p = UserUserHdr(ieiUU=0x7E, eightBitUU=0x0)
+ packet = packet / p
+ if SsVersionIndicator_presence is 1:
+ q = SsVersionIndicatorHdr(ieiSVI=0x7F, eightBitSVI=0x0)
+ packet = packet / q
+ if ClirSuppression_presence is 1:
+ r = ClirSuppressionHdr(ieiCS=0xA1, eightBitCS=0x0)
+ packet = packet / r
+ if ClirInvocation_presence is 1:
+ s = ClirInvocationHdr(ieiCI=0xA2, eightBitCI=0x0)
+ packet = packet / s
+ if CallControlCapabilities_presence is 1:
+ t = CallControlCapabilitiesHdr(ieiCCC=0x15, eightBitCCC=0x0)
+ packet = packet / t
+ if Facility_presence1 is 1:
+ u = FacilityHdr(ieiF=0x1D, eightBitF=0x0)
+ packet = packet / u
+ if Facility_presence2 is 1:
+ v = FacilityHdr(ieiF=0x1B, eightBitF=0x0)
+ packet = packet / v
+ return packet
+
+
+def startCc(CallControlCapabilities_presence=0):
+ """START CC Section 9.3.23a"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x9) # 00001001
+ packet = a / b
+ if CallControlCapabilities_presence is 1:
+ c = CallControlCapabilitiesHdr(ieiCCC=0x15, eightBitCCC=0x0)
+ packet = paclet / c
+ return packet
+
+
+def startDtmf():
+ """START DTMF Section 9.3.24"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x35) # 00110101
+ c = KeypadFacilityHdr(ieiKF=0x2C, eightBitKF=0x0)
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def startDtmfAcknowledge():
+ """START DTMF ACKNOWLEDGE Section 9.3.25"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x32) # 00110010
+ c = KeypadFacilityHdr(ieiKF=0x2C, eightBitKF=0x0)
+ packet = a / b / c
+ return packet
+
+
+# Network to MS
+def startDtmfReject():
+ """ START DTMF REJECT Section 9.3.26"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x37) # 00110111
+ c = Cause()
+ packet = a / b / c
+ return packet
+
+
+def status(AuxiliaryStates_presence=0):
+ """STATUS Section 9.3.27"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3d) # 00111101
+ c = Cause()
+ d = CallState()
+ packet = a / b / c / d
+ if AuxiliaryStates_presence is 1:
+ e = AuxiliaryStatesHdr(ieiAS=0x24, eightBitAS=0x0)
+ packet = packet / e
+ return packet
+
+
+def statusEnquiry():
+ """STATUS ENQUIRY Section 9.3.28"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x34) # 00110100
+ packet = a / b
+ return packet
+
+
+def stopDtmf():
+ """STOP DTMF Section 9.3.29"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x31) # 00110001
+ packet = a / b
+ return packet
+
+
+# Network to MS
+def stopDtmfAcknowledge():
+ """STOP DTMF ACKNOWLEDGE Section 9.3.30"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x32) # 00110010
+ packet = a / b
+ return packet
+
+
+def userInformation(MoreData_presence=0):
+ """USER INFORMATION Section 9.3.31"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x20) # 000100000
+ c = UserUser()
+ packet = a / b / c
+ if MoreData_presence is 1:
+ d = MoreDataHdr(ieiMD=0xA0, eightBitMD=0x0)
+ packet = packet / d
+ return packet
+
+#
+# 9.4 GPRS Mobility Management Messages
+#
+
+
+def attachRequest(PTmsiSignature_presence=0, GprsTimer_presence=0,
+ TmsiStatus_presence=0):
+ """ATTACH REQUEST Section 9.4.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1) # 0000001
+ c = MsNetworkCapability()
+ d = AttachTypeAndCiphKeySeqNr()
+ f = DrxParameter()
+ g = MobileId()
+ h = RoutingAreaIdentification()
+ i = MsRadioAccessCapability()
+ packet = a / b / c / d / f / g / h / i
+ if PTmsiSignature_presence is 1:
+ j = PTmsiSignature(ieiPTS=0x19)
+ packet = packet / j
+ if GprsTimer_presence is 1:
+ k = GprsTimer(ieiGT=0x17)
+ packet = packet / k
+ if TmsiStatus_presence is 1:
+ l = TmsiStatus(ieiTS=0x9)
+ packet = packet / l
+ return packet
+
+
+def attachAccept(PTmsiSignature_presence=0, GprsTimer_presence=0,
+ MobileId_presence=0, MobileId_presence1=0,
+ GmmCause_presence=0):
+ """ATTACH ACCEPT Section 9.4.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x2) # 00000010
+ c = AttachResult()
+ d = ForceToStandby()
+ e = GprsTimer()
+ f = RadioPriorityAndSpareHalfOctets()
+ h = RoutingAreaIdentification()
+ packet = a / b / c / d / e / f / h
+ if PTmsiSignature_presence is 1:
+ i = PTmsiSignature(ieiPTS=0x19)
+ packet = packet / i
+ if GprsTimer_presence is 1:
+ j = GprsTimer(ieiGT=0x17)
+ packet = packet / j
+ if MobileId_presence is 1:
+ k = MobileIdHdr(ieiMI=0x18, eightBitMI=0x0)
+ packet = packet / k
+ if MobileId_presence1 is 1:
+ l = MobileIdHdr(ieiMI=0x23, eightBitMI=0x0)
+ packet = packet / l
+ if GmmCause_presence is 1:
+ m = GmmCause(ieiGC=0x25)
+ packet = packet / m
+ return packet
+
+
+def attachComplete():
+ """ATTACH COMPLETE Section 9.4.3"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x3) # 00000011
+ packet = a / b
+ return packet
+
+
+def attachReject():
+ """ATTACH REJECT Section 9.4.4"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x1) # 00000001
+ c = GmmCause()
+ packet = a / b / c
+ return packet
+
+
+def detachRequest(GmmCause_presence=0):
+ """DETACH REQUEST Section 9.4.5"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x5) # 00000101
+ c = DetachTypeAndForceToStandby()
+ packet = a / b / c
+ if GmmCause_presence is 1:
+ e = GmmCause(ieiGC=0x25)
+ packet = packet / e
+ return packet
+
+
+def detachRequestMsOriginating():
+ """DETACH REQUEST Section 9.4.5.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x5) # 00000101
+ c = DetachTypeAndSpareHalfOctets()
+ packet = a / b / c
+ return packet
+
+
+def detachAcceptMsTerminated():
+ """DETACH ACCEPT Section 9.4.6.1"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x6) # 00000110
+ packet = a / b
+ return packet
+
+
+def detachAcceptMsOriginating():
+ """DETACH ACCEPT Section 9.4.6.2"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x6) # 00000110
+ c = ForceToStandbyAndSpareHalfOctets()
+ packet = a / b / c
+ return packet
+
+
+def ptmsiReallocationCommand(PTmsiSignature_presence=0):
+ """P-TMSI REALLOCATION COMMAND Section 9.4.7"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x10) # 00010000
+ c = MobileId()
+ d = RoutingAreaIdentification()
+ e = ForceToStandbyAndSpareHalfOctets()
+ packet = a / b / c / d / e
+ if PTmsiSignature_presence is 1:
+ g = PTmsiSignature(ieiPTS=0x19)
+ packet = packet / g
+ return packet
+
+
+def ptmsiReallocationComplete():
+ """P-TMSI REALLOCATION COMPLETE Section 9.4.8"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x11) # 00010001
+ packet = a / b
+ return packet
+
+
+def authenticationAndCipheringRequest(
+ AuthenticationParameterRAND_presence=0,
+ CiphKeySeqNr_presence=0):
+ """AUTHENTICATION AND CIPHERING REQUEST Section 9.4.9"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x12) # 00010010
+ d = CipheringAlgorithmAndImeisvRequest()
+ e = ForceToStandbyAndAcReferenceNumber()
+ packet = a / b / d / e
+ if AuthenticationParameterRAND_presence is 1:
+ g = AuthenticationParameterRAND(ieiAPR=0x21)
+ packet = packet / g
+ if CiphKeySeqNr_presence is 1:
+ h = CiphKeySeqNrHdr(ieiCKSN=0x08, eightBitCKSN=0x0)
+ packet = packet / h
+ return packet
+
+
+def authenticationAndCipheringResponse(
+ AuthenticationParameterSRES_presence=0,
+ MobileId_presence=0):
+ """AUTHENTICATION AND CIPHERING RESPONSE Section 9.4.10"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x13) # 00010011
+ c = AcReferenceNumberAndSpareHalfOctets()
+ packet = a / b / c
+ if AuthenticationParameterSRES_presence is 1:
+ e = AuthenticationParameterSRES(ieiAPS=0x22)
+ packet = packet / e
+ if MobileId_presence is 1:
+ f = MobileIdHdr(ieiMI=0x23, eightBitMI=0x0)
+ packet = packet / f
+ return packet
+
+
+def authenticationAndCipheringReject():
+ """AUTHENTICATION AND CIPHERING REJECT Section 9.4.11"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x14) # 00010100
+ packet = a / b
+ return packet
+
+
+def identityRequest():
+ """IDENTITY REQUEST Section 9.4.12"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x15) # 00010101
+ c = IdentityType2AndforceToStandby()
+ packet = a / b / c
+ return packet
+
+
+def identityResponse():
+ """IDENTITY RESPONSE Section 9.4.13"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x16) # 00010110
+ c = MobileId()
+ packet = a / b / c
+ return packet
+
+
+def routingAreaUpdateRequest(PTmsiSignature_presence=0,
+ GprsTimer_presence=0,
+ DrxParameter_presence=0,
+ TmsiStatus_presence=0):
+ """ROUTING AREA UPDATE REQUEST Section 9.4.14"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x8) # 00001000
+ c = UpdateTypeAndCiphKeySeqNr()
+ e = RoutingAreaIdentification()
+ f = MsNetworkCapability()
+ packet = a / b / c / e / f
+ if PTmsiSignature_presence is 1:
+ g = PTmsiSignature(ieiPTS=0x19)
+ packet = packet / g
+ if GprsTimer_presence is 1:
+ h = GprsTimer(ieiGT=0x17)
+ packet = packet / h
+ if DrxParameter_presence is 1:
+ i = DrxParameter(ieiDP=0x27)
+ packet = packet / i
+ if TmsiStatus_presence is 1:
+ j = TmsiStatus(ieiTS=0x9)
+ packet = packet / j
+ return packet
+
+
+def routingAreaUpdateAccept(PTmsiSignature_presence=0,
+ MobileId_presence=0, MobileId_presence1=0,
+ ReceiveNpduNumbersList_presence=0,
+ GprsTimer_presence=0, GmmCause_presence=0):
+ """ROUTING AREA UPDATE ACCEPT Section 9.4.15"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x9) # 00001001
+ c = ForceToStandbyAndUpdateResult()
+ e = GprsTimer()
+ f = RoutingAreaIdentification()
+ packet = a / b / c / e / f
+ if PTmsiSignature_presence is 1:
+ g = PTmsiSignature(ieiPTS=0x19)
+ packet = packet / g
+ if MobileId_presence is 1:
+ h = MobileIdHdr(ieiMI=0x18, eightBitMI=0x0)
+ packet = packet / h
+ if MobileId_presence1 is 1:
+ i = MobileIdHdr(ieiMI=0x23, eightBitMI=0x0)
+ packet = packet / i
+ if ReceiveNpduNumbersList_presence is 1:
+ j = ReceiveNpduNumbersList(ieiRNNL=0x26)
+ packet = packet / j
+ if GprsTimer_presence is 1:
+ k = GprsTimer(ieiGT=0x17)
+ packet = packet / k
+ if GmmCause_presence is 1:
+ l = GmmCause(ieiGC=0x25)
+ packet = packet / l
+ return packet
+
+
+def routingAreaUpdateComplete(ReceiveNpduNumbersList_presence=0):
+ """ROUTING AREA UPDATE COMPLETE Section 9.4.16"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0xa) # 00001010
+ packet = a / b
+ if ReceiveNpduNumbersList_presence is 1:
+ c = ReceiveNpduNumbersList(ieiRNNL=0x26)
+ packet = packet / c
+ return packet
+
+
+def routingAreaUpdateReject():
+ """ROUTING AREA UPDATE REJECT Section 9.4.17"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0xb) # 00001011
+ c = GmmCause()
+ d = ForceToStandbyAndSpareHalfOctets()
+ packet = a / b / c / d
+ return packet
+
+
+def gmmStatus():
+ """GMM STATUS Section 9.4.18"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x20) # 00100000
+ c = GmmCause()
+ packet = a / b / c
+ return packet
+
+
+def gmmInformation(NetworkName_presence=0, NetworkName_presence1=0,
+ TimeZone_presence=0, TimeZoneAndTime_presence=0,
+ LsaIdentifier_presence=0):
+ """GMM INFORMATION Section 9.4.19"""
+ a = TpPd(pd=0x3)
+ b = MessageType(mesType=0x21) # 00100001
+ packet = a / b
+ if NetworkName_presence is 1:
+ c = NetworkNameHdr(ieiNN=0x43, eightBitNN=0x0)
+ packet = packet / c
+ if NetworkName_presence1 is 1:
+ d = NetworkNameHdr(ieiNN=0x45, eightBitNN=0x0)
+ packet = packet / d
+ if TimeZone_presence is 1:
+ e = TimeZoneHdr(ieiTZ=0x46, eightBitTZ=0x0)
+ packet = packet / e
+ if TimeZoneAndTime_presence is 1:
+ f = TimeZoneAndTimeHdr(ieiTZAT=0x47, eightBitTZAT=0x0)
+ packet = packet / f
+ if LsaIdentifier_presence is 1:
+ g = LsaIdentifierHdr(ieiLI=0x48, eightBitLI=0x0)
+ packet = packet / g
+ return packet
+
+#
+# 9.5 GPRS Session Management Messages
+#
+
+
+def activatePdpContextRequest(AccessPointName_presence=0,
+ ProtocolConfigurationOptions_presence=0):
+ """ACTIVATE PDP CONTEXT REQUEST Section 9.5.1"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x41) # 01000001
+ c = NetworkServiceAccessPointIdentifier()
+ d = LlcServiceAccessPointIdentifier()
+ e = QualityOfService()
+ f = PacketDataProtocolAddress()
+ packet = a / b / c / d / e / f
+ if AccessPointName_presence is 1:
+ g = AccessPointName(ieiAPN=0x28)
+ packet = packet / g
+ if ProtocolConfigurationOptions_presence is 1:
+ h = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / h
+ return packet
+
+
+def activatePdpContextAccept(PacketDataProtocolAddress_presence=0,
+ ProtocolConfigurationOptions_presence=0):
+ """ACTIVATE PDP CONTEXT ACCEPT Section 9.5.2"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x42) # 01000010
+ c = LlcServiceAccessPointIdentifier()
+ d = QualityOfService()
+ e = RadioPriorityAndSpareHalfOctets()
+ packet = a / b / c / d / e
+ if PacketDataProtocolAddress_presence is 1:
+ f = PacketDataProtocolAddress(ieiPDPA=0x2B)
+ packet = packet / f
+ if ProtocolConfigurationOptions_presence is 1:
+ g = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / g
+ return packet
+
+
+def activatePdpContextReject(ProtocolConfigurationOptions_presence=0):
+ """ACTIVATE PDP CONTEXT REJECT Section 9.5.3"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x43) # 01000011
+ c = SmCause()
+ packet = a / b / c
+ if ProtocolConfigurationOptions_presence is 1:
+ d = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / d
+ return packet
+
+
+def requestPdpContextActivation(AccessPointName_presence=0):
+ """REQUEST PDP CONTEXT ACTIVATION Section 9.5.4"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x44) # 01000100
+ c = PacketDataProtocolAddress()
+ packet = a / b / c
+ if AccessPointName_presence is 1:
+ d = AccessPointName(ieiAPN=0x28)
+ packet = packet / d
+ return packet
+
+
+def requestPdpContextActivationReject():
+ """REQUEST PDP CONTEXT ACTIVATION REJECT Section 9.5.5"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x45) # 01000101
+ c = SmCause()
+ packet = a / b / c
+ return packet
+
+
+def modifyPdpContextRequest():
+ """MODIFY PDP CONTEXT REQUEST Section 9.5.6"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x48) # 01001000
+ c = RadioPriorityAndSpareHalfOctets()
+ d = LlcServiceAccessPointIdentifier()
+ e = QualityOfService()
+ packet = a / b / c / d / e
+ return packet
+
+
+def modifyPdpContextAccept():
+ """MODIFY PDP CONTEXT ACCEPT Section 9.5.7"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x45) # 01000101
+ packet = a / b
+ return packet
+
+
+def deactivatePdpContextRequest():
+ """DEACTIVATE PDP CONTEXT REQUEST Section 9.5.8"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x46) # 01000110
+ c = SmCause()
+ packet = a / b / c
+ return packet
+
+
+def deactivatePdpContextAccept():
+ """DEACTIVATE PDP CONTEXT ACCEPT Section 9.5.9"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x47) # 01000111
+ packet = a / b
+ return packet
+
+
+def activateAaPdpContextRequest(AccessPointName_presence=0,
+ ProtocolConfigurationOptions_presence=0,
+ GprsTimer_presence=0):
+ """ACTIVATE AA PDP CONTEXT REQUEST Section 9.5.10"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x50) # 01010000
+ c = NetworkServiceAccessPointIdentifier()
+ d = LlcServiceAccessPointIdentifier()
+ e = QualityOfService()
+ f = PacketDataProtocolAddress()
+ packet = a / b / c / d / e / f
+ if AccessPointName_presence is 1:
+ g = AccessPointName(ieiAPN=0x28)
+ packet = packet / g
+ if ProtocolConfigurationOptions_presence is 1:
+ h = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / h
+ if GprsTimer_presence is 1:
+ i = GprsTimer(ieiGT=0x29)
+ packet = packet / i
+ return packet
+
+
+def activateAaPdpContextAccept(ProtocolConfigurationOptions_presence=0,
+ GprsTimer_presence=0):
+ """ACTIVATE AA PDP CONTEXT ACCEPT Section 9.5.11"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x51) # 01010001
+ c = LlcServiceAccessPointIdentifier()
+ d = QualityOfService()
+ e = MobileId()
+ f = PacketDataProtocolAddress()
+ g = RadioPriorityAndSpareHalfOctets()
+ packet = a / b / c / d / e / f / g
+ if ProtocolConfigurationOptions_presence is 1:
+ i = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / i
+ if GprsTimer_presence is 1:
+ j = GprsTimer(ieiGT=0x29)
+ packet = packet / j
+ return packet
+
+
+def activateAaPdpContextReject(ProtocolConfigurationOptions_presence=0):
+ """ACTIVATE AA PDP CONTEXT REJECT Section 9.5.12"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x52) # 01010010
+ c = SmCause()
+ packet = a / b / c
+ if ProtocolConfigurationOptions_presence is 1:
+ d = ProtocolConfigurationOptions(ieiPCO=0x27)
+ packet = packet / d
+ return packet
+
+
+def deactivateAaPdpContextRequest():
+ """DEACTIVATE AA PDP CONTEXT REQUEST Section 9.5.13"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x53) # 01010011
+ c = AaDeactivationCauseAndSpareHalfOctets()
+ packet = a / b / c
+ return packet
+
+
+def deactivateAaPdpContextAccept():
+ """DEACTIVATE AA PDP CONTEXT ACCEPT Section 9.5.14"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x54) # 01010100
+ packet = a / b
+ return packet
+
+
+def smStatus():
+ """SM STATUS Section 9.5.15"""
+ a = TpPd(pd=0x8)
+ b = MessageType(mesType=0x55) # 01010101
+ c = SmCause()
+ packet = a / b / c
+ return packet
+
+
+# ============================================#
+# Information Elements contents (Section 10) #
+# =========================================== #
+
+####
+# This section contains the elements we need to build the messages
+####
+
+#
+# Common information elements:
+#
+class CellIdentityHdr(Packet):
+ """ Cell identity Section 10.5.1.1 """
+ name = "Cell Identity"
+ fields_desc = [
+ BitField("eightBitCI", None, 1),
+ XBitField("ieiCI", None, 7),
+ ByteField("ciValue1", 0x0),
+ ByteField("ciValue2", 0x0)
+ ]
+
+
+class CiphKeySeqNrHdr(Packet):
+ """ Ciphering Key Sequence Number Section 10.5.1.2 """
+ name = "Cipher Key Sequence Number"
+ fields_desc = [
+ XBitField("ieiCKSN", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class CiphKeySeqNrAndSpareHalfOctets(Packet):
+ name = "Cipher Key Sequence Number and Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+# Fix 1/2 len problem
+class CiphKeySeqNrAndMacModeAndChannelCodingRequest(Packet):
+ name = "Cipher Key Sequence Number and Mac Mode And Channel Coding Request"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3),
+ BitField("macMode", 0x0, 2),
+ BitField("cs", 0x0, 2)
+ ]
+
+
+class LocalAreaIdHdr(Packet):
+ """ Local Area Identification Section 10.5.1.3 """
+ name = "Location Area Identification"
+ fields_desc = [
+ BitField("eightBitLAI", None, 1),
+ XBitField("ieiLAI", None, 7),
+ BitField("mccDigit2", 0x0, 4),
+ BitField("mccDigit1", 0x0, 4),
+ BitField("mncDigit3", 0x0, 4),
+ BitField("mccDigit3", 0x0, 4),
+ BitField("mncDigit2", 0x0, 4),
+ BitField("mncDigit1", 0x0, 4),
+ ByteField("lac1", 0x0),
+ ByteField("lac2", 0x0)
+ ]
+#
+# The Mobile Identity is a type 4 information element with a minimum
+# length of 3 octet and 11 octets length maximal.
+#
+
+
+# len 3 - 11
+class MobileIdHdr(Packet):
+ """ Mobile Identity Section 10.5.1.4 """
+ name = "Mobile Identity"
+ fields_desc = [
+ BitField("eightBitMI", 0x0, 1),
+ XBitField("ieiMI", 0x0, 7),
+
+ XByteField("lengthMI", None),
+
+ BitField("idDigit1", 0x0, 4),
+ BitField("oddEven", 0x0, 1),
+ BitField("typeOfId", 0x0, 3),
+
+ BitField("idDigit2_1", None, 4), # optional
+ BitField("idDigit2", None, 4),
+
+ BitField("idDigit3_1", None, 4),
+ BitField("idDigit3", None, 4),
+
+ BitField("idDigit4_1", None, 4),
+ BitField("idDigit4", None, 4),
+
+ BitField("idDigit5_1", None, 4),
+ BitField("idDigit5", None, 4),
+
+ BitField("idDigit6_1", None, 4),
+ BitField("idDigit6", None, 4),
+ BitField("idDigit7_1", None, 4),
+ BitField("idDigit7", None, 4),
+ BitField("idDigit8_1", None, 4),
+ BitField("idDigit8", None, 4),
+ BitField("idDigit9_1", None, 4),
+ BitField("idDigit9", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i, None)) # this list holds the values of
+# the variables, the INTERESSTING value!
+ res = adapt(3, 11, a, self.fields_desc)
+ if self.lengthMI is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ print(repr(p))
+ return p + pay
+
+
+class MobileStationClassmark1Hdr(Packet):
+ """ Mobile Station Classmark 1 Section 10.5.1.5 """
+ name = "Mobile Station Classmark 1"
+ fields_desc = [
+ BitField("eightBitiMSC1", None, 1),
+ XBitField("ieiMSC1", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("revisionLvl", 0x0, 2),
+ BitField("esInd", 0x0, 1),
+ BitField("a51", 0x0, 1),
+ BitField("rfPowerCap", 0x0, 3)
+ ]
+
+
+class MobileStationClassmark2Hdr(Packet):
+ """ Mobile Station Classmark 2 Section 10.5.1.6 """
+ name = "Mobile Station Classmark 2"
+ fields_desc = [
+ BitField("eightBitMSC2", None, 1),
+ XBitField("ieiMSC2", None, 7),
+ XByteField("lengthMSC2", 0x3),
+ BitField("spare", 0x0, 1),
+ BitField("revisionLvl", 0x0, 2),
+ BitField("esInd", 0x0, 1),
+ BitField("a51", 0x0, 1),
+ BitField("rfPowerCap", 0x0, 3),
+ BitField("spare1", 0x0, 1),
+ BitField("psCap", 0x0, 1),
+ BitField("ssScreenInd", 0x0, 2),
+ BitField("smCaPabi", 0x0, 1),
+ BitField("vbs", 0x0, 1),
+ BitField("vgcs", 0x0, 1),
+ BitField("fc", 0x0, 1),
+ BitField("cm3", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("lcsvaCap", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("soLsa", 0x0, 1),
+ BitField("cmsp", 0x0, 1),
+ BitField("a53", 0x0, 1),
+ BitField("a52", 0x0, 1)
+ ]
+
+
+# len max 14
+class MobileStationClassmark3(Packet):
+ """ Mobile Station Classmark 3 Section 10.5.1.7 """
+ name = "Mobile Station Classmark 3"
+ fields_desc = [
+ # FIXME
+ ByteField("ieiMSC3", 0x0),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0)
+ ]
+
+
+class SpareHalfOctets(Packet):
+ """ Spare Half Octet Section 10.5.1.8 """
+ name = "Spare Half Octet"
+ fields_desc = [
+ BitField("filler", None, 4),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class DescriptiveGroupOrBroadcastCallReferenceHdr(Packet):
+ """ Descriptive group or broadcast call reference Section 10.5.1.9 """
+ name = "Descriptive Group or Broadcast Call Reference"
+ fields_desc = [
+ BitField("eightBitDGOBCR", None, 1),
+ XBitField("ieiDGOBCR", None, 7),
+ BitField("binCallRef", 0x0, 27),
+ BitField("sf", 0x0, 1),
+ BitField("fa", 0x0, 1),
+ BitField("callPrio", 0x0, 3),
+ BitField("cipherInfo", 0x0, 4),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("spare4", 0x0, 1)
+ ]
+
+
+class GroupCipherKeyNumber(Packet):
+ """ Group Cipher Key Number reference Section 10.5.1.10 """
+ name = "Group Cipher Key Number"
+ fields_desc = [
+ XBitField("ieiGCKN", None, 4),
+ BitField("groupCipher", 0x0, 4)
+ ]
+
+
+class PdAndSapiHdr(Packet):
+ """ PD and SAPI $(CCBS)$ Section 10.5.1.10a """
+ name = "PD and SAPI $(CCBS)$"
+ fields_desc = [
+ BitField("eightBitPAS", None, 1),
+ XBitField("ieiPAS", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("sapi", 0x0, 2),
+ BitField("pd", 0x0, 4)
+ ]
+
+
+class PriorityLevelHdr(Packet):
+ """ Priority Level Section 10.5.1.11 """
+ name = "Priority Level"
+ fields_desc = [
+ XBitField("ieiPL", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("callPrio", 0x0, 3)
+ ]
+
+#
+# Radio Resource management information elements
+#
+
+
+# len 6 to max for L3 message (251)
+class BaRangeHdr(Packet):
+ """ BA Range Section 10.5.2.1a """
+ name = "BA Range"
+ fields_desc = [
+ BitField("eightBitBR", None, 1),
+ XBitField("ieiBR", None, 7),
+
+ XByteField("lengthBR", None),
+#error: byte format requires -128 <= number <= 127
+ ByteField("nrOfRanges", 0x0),
+# # rX = range X
+# # L o = Lower H i = higher
+# # H p = high Part Lp = low Part
+ ByteField("r1LoHp", 0x0),
+
+ BitField("r1LoLp", 0x0, 3),
+ BitField("r1HiHp", 0x0, 5),
+
+ BitField("r1HiLp", 0x0, 4),
+ BitField("r2LoHp", 0x0, 4),
+ # optional
+ BitField("r2LoLp", None, 5),
+ BitField("r2HiHp", None, 3),
+
+ ByteField("r2HiLp", None),
+ ByteField("r3LoHp", None),
+
+ BitField("r3LoLp", None, 5),
+ BitField("r3HiHp", None, 3),
+
+ ByteField("r3HiLp", None),
+ ByteField("r4LoHp", None),
+
+ BitField("r4LoLp", None, 5),
+ BitField("r4HiHp", None, 3),
+ ByteField("r4HiLp", None),
+ ByteField("r5LoHp", None),
+
+ BitField("r5LoLp", None, 5),
+ BitField("r5HiHp", None, 3),
+ ByteField("r5HiLp", None),
+ ByteField("r6LoHp", None),
+
+ BitField("r6LoLp", None, 5),
+ BitField("r6HiHp", None, 3),
+ ByteField("r6HiLp", None),
+ ByteField("r7LoHp", None),
+
+ BitField("r7LoLp", None, 5),
+ BitField("r7HiHp", None, 3),
+ ByteField("r7HiLp", None),
+ ByteField("r8LoHp", None),
+
+ BitField("r8LoLp", None, 5),
+ BitField("r8HiHp", None, 3),
+ ByteField("r8HiLp", None),
+ ByteField("r9LoHp", None),
+
+ BitField("r9LoLp", None, 5),
+ BitField("r9HiHp", None, 3),
+ ByteField("r9HiLp", None),
+ ByteField("r10LoHp", None),
+
+ BitField("r10LoLp", None, 5),
+ BitField("r10HiHp", None, 3),
+ ByteField("r10HiLp", None),
+ ByteField("r11LoHp", None),
+
+ BitField("r11LoLp", None, 5),
+ BitField("r11HiHp", None, 3),
+ ByteField("r11HiLp", None),
+ ByteField("r12LoHp", None),
+
+ BitField("r12LoLp", None, 5),
+ BitField("r12HiHp", None, 3),
+ ByteField("r12HiLp", None),
+ ByteField("r13LoHp", None),
+
+ BitField("r13LoLp", None, 5),
+ BitField("r13HiHp", None, 3),
+ ByteField("r13HiLp", None),
+ ByteField("r14LoHp", None),
+
+ BitField("r14LoLp", None, 5),
+ BitField("r14HiHp", None, 3),
+ ByteField("r14HiLp", None),
+ ByteField("r15LoHp", None),
+
+ BitField("r15LoLp", None, 5),
+ BitField("r15HiHp", None, 3),
+ ByteField("r15HiLp", None),
+ ByteField("r16LoHp", None),
+
+ BitField("r16LoLp", None, 5),
+ BitField("r16HiHp", None, 3),
+ ByteField("r16HiLp", None),
+ ByteField("r17LoHp", None),
+
+ BitField("r17LoLp", None, 5),
+ BitField("r17HiHp", None, 3),
+ ByteField("r17HiLp", None),
+ ByteField("r18LoHp", None),
+
+ BitField("r18LoLp", None, 5),
+ BitField("r18HiHp", None, 3),
+ ByteField("r18HiLp", None),
+ ByteField("r19LoHp", None),
+
+ BitField("r19LoLp", None, 5),
+ BitField("r19HiHp", None, 3),
+ ByteField("r19HiLp", None),
+ ByteField("r20LoHp", None),
+
+ BitField("r20LoLp", None, 5),
+ BitField("r20HiHp", None, 3),
+ ByteField("r20HiLp", None),
+ ByteField("r21LoHp", None),
+
+ BitField("r21LoLp", None, 5),
+ BitField("r21HiHp", None, 3),
+ ByteField("r21HiLp", None),
+ ByteField("r22LoHp", None),
+
+ BitField("r22LoLp", None, 5),
+ BitField("r22HiHp", None, 3),
+ ByteField("r22HiLp", None),
+ ByteField("r23LoHp", None),
+
+ BitField("r23LoLp", None, 5),
+ BitField("r23HiHp", None, 3),
+ ByteField("r23HiLp", None),
+ ByteField("r24LoHp", None),
+
+ BitField("r24LoLp", None, 5),
+ BitField("r24HiHp", None, 3),
+ ByteField("r24HiLp", None),
+ ByteField("r25LoHp", None),
+
+ BitField("r25LoLp", None, 5),
+ BitField("r25HiHp", None, 3),
+ ByteField("r25HiLp", None),
+ ByteField("r26LoHp", None),
+
+ BitField("r26LoLp", None, 5),
+ BitField("r26HiHp", None, 3),
+ ByteField("r26HiLp", None),
+ ByteField("r27LoHp", None),
+
+ BitField("r27LoLp", None, 5),
+ BitField("r27HiHp", None, 3),
+ ByteField("r27HiLp", None),
+ ByteField("r28LoHp", None),
+
+ BitField("r28LoLp", None, 5),
+ BitField("r28HiHp", None, 3),
+ ByteField("r28HiLp", None),
+ ByteField("r29LoHp", None),
+
+ BitField("r29LoLp", None, 5),
+ BitField("r29HiHp", None, 3),
+ ByteField("r29HiLp", None),
+ ByteField("r30LoHp", None),
+
+ BitField("r30LoLp", None, 5),
+ BitField("r30HiHp", None, 3),
+ ByteField("r30HiLp", None),
+ ByteField("r31LoHp", None),
+
+ BitField("r31LoLp", None, 5),
+ BitField("r31HiHp", None, 3),
+ ByteField("r31HiLp", None),
+ ByteField("r32LoHp", None),
+
+ BitField("r32LoLp", None, 5),
+ BitField("r32HiHp", None, 3),
+ ByteField("r32HiLp", None),
+ ByteField("r33LoHp", None),
+
+ BitField("r33LoLp", None, 5),
+ BitField("r33HiHp", None, 3),
+ ByteField("r33HiLp", None),
+ ByteField("r34LoHp", None),
+
+ BitField("r34LoLp", None, 5),
+ BitField("r34HiHp", None, 3),
+ ByteField("r34HiLp", None),
+ ByteField("r35LoHp", None),
+
+ BitField("r35LoLp", None, 5),
+ BitField("r35HiHp", None, 3),
+ ByteField("r35HiLp", None),
+ ByteField("r36LoHp", None),
+
+ BitField("r36LoLp", None, 5),
+ BitField("r36HiHp", None, 3),
+ ByteField("r36HiLp", None),
+ ByteField("r37LoHp", None),
+
+ BitField("r37LoLp", None, 5),
+ BitField("r37HiHp", None, 3),
+ ByteField("r37HiLp", None),
+ ByteField("r38LoHp", None),
+
+ BitField("r38LoLp", None, 5),
+ BitField("r38HiHp", None, 3),
+ ByteField("r38HiLp", None),
+ ByteField("r39LoHp", None),
+
+ BitField("r39LoLp", None, 5),
+ BitField("r39HiHp", None, 3),
+ ByteField("r39HiLp", None),
+ ByteField("r40LoHp", None),
+
+ BitField("r40LoLp", None, 5),
+ BitField("r40HiHp", None, 3),
+ ByteField("r40HiLp", None),
+ ByteField("r41LoHp", None),
+
+ BitField("r41LoLp", None, 5),
+ BitField("r41HiHp", None, 3),
+ ByteField("r41HiLp", None),
+ ByteField("r42LoHp", None),
+
+ BitField("r42LoLp", None, 5),
+ BitField("r42HiHp", None, 3),
+ ByteField("r42HiLp", None),
+ ByteField("r43LoHp", None),
+
+ BitField("r43LoLp", None, 5),
+ BitField("r43HiHp", None, 3),
+ ByteField("r43HiLp", None),
+ ByteField("r44LoHp", None),
+
+ BitField("r44LoLp", None, 5),
+ BitField("r44HiHp", None, 3),
+ ByteField("r44HiLp", None),
+ ByteField("r45LoHp", None),
+
+ BitField("r45LoLp", None, 5),
+ BitField("r45HiHp", None, 3),
+ ByteField("r45HiLp", None),
+ ByteField("r46LoHp", None),
+
+ BitField("r46LoLp", None, 5),
+ BitField("r46HiHp", None, 3),
+ ByteField("r46HiLp", None),
+ ByteField("r47LoHp", None),
+
+ BitField("r47LoLp", None, 5),
+ BitField("r47HiHp", None, 3),
+ ByteField("r47HiLp", None),
+ ByteField("r48LoHp", None),
+
+ BitField("r48LoLp", None, 5),
+ BitField("r48HiHp", None, 3),
+ ByteField("r48HiLp", None),
+ ByteField("r49LoHp", None),
+
+ BitField("r49LoLp", None, 5),
+ BitField("r49HiHp", None, 3),
+ ByteField("r49HiLp", None),
+ ByteField("r50LoHp", None),
+
+ BitField("r50LoLp", None, 5),
+ BitField("r50HiHp", None, 3),
+ ByteField("r50HiLp", None),
+ ByteField("r51LoHp", None),
+
+ BitField("r51LoLp", None, 5),
+ BitField("r51HiHp", None, 3),
+ ByteField("r51HiLp", None),
+ ByteField("r52LoHp", None),
+
+ BitField("r52LoLp", None, 5),
+ BitField("r52HiHp", None, 3),
+ ByteField("r52HiLp", None),
+ ByteField("r53LoHp", None),
+
+ BitField("r53LoLp", None, 5),
+ BitField("r53HiHp", None, 3),
+ ByteField("r53HiLp", None),
+ ByteField("r54LoHp", None),
+
+ BitField("r54LoLp", None, 5),
+ BitField("r54HiHp", None, 3),
+ ByteField("r54HiLp", None),
+ ByteField("r55LoHp", None),
+
+ BitField("r55LoLp", None, 5),
+ BitField("r55HiHp", None, 3),
+ ByteField("r55HiLp", None),
+ ByteField("r56LoHp", None),
+
+ BitField("r56LoLp", None, 5),
+ BitField("r56HiHp", None, 3),
+ ByteField("r56HiLp", None),
+ ByteField("r57LoHp", None),
+
+ BitField("r57LoLp", None, 5),
+ BitField("r57HiHp", None, 3),
+ ByteField("r57HiLp", None),
+ ByteField("r58LoHp", None),
+
+ BitField("r58LoLp", None, 5),
+ BitField("r58HiHp", None, 3),
+ ByteField("r58HiLp", None),
+ ByteField("r59LoHp", None),
+
+ BitField("r59LoLp", None, 5),
+ BitField("r59HiHp", None, 3),
+ ByteField("r59HiLp", None),
+ ByteField("r60LoHp", None),
+
+ BitField("r60LoLp", None, 5),
+ BitField("r60HiHp", None, 3),
+ ByteField("r60HiLp", None),
+ ByteField("r61LoHp", None),
+
+ BitField("r61LoLp", None, 5),
+ BitField("r61HiHp", None, 3),
+ ByteField("r61HiLp", None),
+ ByteField("r62LoHp", None),
+
+ BitField("r62LoLp", None, 5),
+ BitField("r62HiHp", None, 3),
+ ByteField("r62HiLp", None),
+ ByteField("r63LoHp", None),
+
+ BitField("r63LoLp", None, 5),
+ BitField("r63HiHp", None, 3),
+ ByteField("r63HiLp", None),
+ ByteField("r64LoHp", None),
+
+ BitField("r64LoLp", None, 5),
+ BitField("r64HiHp", None, 3),
+ ByteField("r64HiLp", None),
+ ByteField("r65LoHp", None),
+
+ BitField("r65LoLp", None, 5),
+ BitField("r65HiHp", None, 3),
+ ByteField("r65HiLp", None),
+ ByteField("r66LoHp", None),
+
+ BitField("r66LoLp", None, 5),
+ BitField("r66HiHp", None, 3),
+ ByteField("r66HiLp", None),
+ ByteField("r67LoHp", None),
+
+ BitField("r67LoLp", None, 5),
+ BitField("r67HiHp", None, 3),
+ ByteField("r67HiLp", None),
+ ByteField("r68LoHp", None),
+
+ BitField("r68LoLp", None, 5),
+ BitField("r68HiHp", None, 3),
+ ByteField("r68HiLp", None),
+ ByteField("r69LoHp", None),
+
+ BitField("r69LoLp", None, 5),
+ BitField("r69HiHp", None, 3),
+ ByteField("r69HiLp", None),
+ ByteField("r70LoHp", None),
+
+ BitField("r70LoLp", None, 5),
+ BitField("r70HiHp", None, 3),
+ ByteField("r70HiLp", None),
+ ByteField("r71LoHp", None),
+
+ BitField("r71LoLp", None, 5),
+ BitField("r71HiHp", None, 3),
+ ByteField("r71HiLp", None),
+ ByteField("r72LoHp", None),
+
+ BitField("r72LoLp", None, 5),
+ BitField("r72HiHp", None, 3),
+ ByteField("r72HiLp", None),
+ ByteField("r73LoHp", None),
+
+ BitField("r73LoLp", None, 5),
+ BitField("r73HiHp", None, 3),
+ ByteField("r73HiLp", None),
+ ByteField("r74LoHp", None),
+
+ BitField("r74LoLp", None, 5),
+ BitField("r74HiHp", None, 3),
+ ByteField("r74HiLp", None),
+ ByteField("r75LoHp", None),
+
+ BitField("r75LoLp", None, 5),
+ BitField("r75HiHp", None, 3),
+ ByteField("r75HiLp", None),
+ ByteField("r76LoHp", None),
+
+ BitField("r76LoLp", None, 5),
+ BitField("r76HiHp", None, 3),
+ ByteField("r76HiLp", None),
+ ByteField("r77LoHp", None),
+
+ BitField("r77LoLp", None, 5),
+ BitField("r77HiHp", None, 3),
+ ByteField("r77HiLp", None),
+ ByteField("r78LoHp", None),
+
+ BitField("r78LoLp", None, 5),
+ BitField("r78HiHp", None, 3),
+ ByteField("r78HiLp", None),
+ ByteField("r79LoHp", None),
+
+ BitField("r79LoLp", None, 5),
+ BitField("r79HiHp", None, 3),
+ ByteField("r79HiLp", None),
+ ByteField("r80LoHp", None),
+
+ BitField("r80LoLp", None, 5),
+ BitField("r80HiHp", None, 3),
+ ByteField("r80HiLp", None),
+ ByteField("r81LoHp", None),
+
+ BitField("r81LoLp", None, 5),
+ BitField("r81HiHp", None, 3),
+ ByteField("r81HiLp", None),
+ ByteField("r82LoHp", None),
+
+ BitField("r82LoLp", None, 5),
+ BitField("r82HiHp", None, 3),
+ ByteField("r82HiLp", None),
+ ByteField("r83LoHp", None),
+
+ BitField("r83LoLp", None, 5),
+ BitField("r83HiHp", None, 3),
+ ByteField("r83HiLp", None),
+ ByteField("r84LoHp", None),
+
+ BitField("r84LoLp", None, 5),
+ BitField("r84HiHp", None, 3),
+ ByteField("r84HiLp", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ print("i is %s" % (i,))
+ aList.append(self.fields_desc[i].name)
+ print("aList %s" % (len(aList)))
+ print("self.fields_desc %s" % (len(self.fields_desc)))
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(6, 251, a, self.fields_desc)
+ if self.lengthBR is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 3 to max for L3 message (251)
+class BaListPrefHdr(Packet):
+ """ BA List Pref Section 10.5.2.1c """
+ name = "BA List Pref"
+ fields_desc = [
+ # FIXME dynamic
+ BitField("eightBitBLP", None, 1),
+ XBitField("ieiBLP", None, 7),
+
+ XByteField("lengthBLP", None),
+
+ BitField("fixBit", 0x0, 1),
+ BitField("rangeLower", 0x0, 10),
+ BitField("fixBit2", 0x0, 1),
+ BitField("rangeUpper", 0x0, 10),
+ BitField("baFreq", 0x0, 10),
+ BitField("sparePad", 0x0, 8)
+ ]
+
+
+# len 17 || Have a look at the specs for the field format
+# Bit map 0 format
+# Range 1024 format
+# Range 512 format
+# Range 256 format
+# Range 128 format
+# Variable bit map format
+class CellChannelDescriptionHdr(Packet):
+ """ Cell Channel Description Section 10.5.2.1b """
+ name = "Cell Channel Description "
+ fields_desc = [
+ BitField("eightBitCCD", None, 1),
+ XBitField("ieiCCD", None, 7),
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ ByteField("bit120", 0x0),
+ ByteField("bit112", 0x0),
+ ByteField("bit104", 0x0),
+ ByteField("bit96", 0x0),
+ ByteField("bit88", 0x0),
+ ByteField("bit80", 0x0),
+ ByteField("bit72", 0x0),
+ ByteField("bit64", 0x0),
+ ByteField("bit56", 0x0),
+ ByteField("bit48", 0x0),
+ ByteField("bit40", 0x0),
+ ByteField("bit32", 0x0),
+ ByteField("bit24", 0x0),
+ ByteField("bit16", 0x0),
+ ByteField("bit8", 0x0)
+ ]
+
+
+class CellDescriptionHdr(Packet):
+ """ Cell Description Section 10.5.2.2 """
+ name = "Cell Description"
+ fields_desc = [
+ BitField("eightBitCD", None, 1),
+ XBitField("ieiCD", None, 7),
+ BitField("bcchHigh", 0x0, 2),
+ BitField("ncc", 0x0, 3),
+ BitField("bcc", 0x0, 3),
+ ByteField("bcchLow", 0x0)
+ ]
+
+
+class CellOptionsBCCHHdr(Packet):
+ """ Cell Options (BCCH) Section 10.5.2.3 """
+ name = "Cell Options (BCCH)"
+ fields_desc = [
+ BitField("eightBitCOB", None, 1),
+ XBitField("ieiCOB", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("pwrc", 0x0, 1),
+ BitField("dtx", 0x0, 2),
+ BitField("rLinkTout", 0x0, 4)
+ ]
+
+
+class CellOptionsSACCHHdr(Packet):
+ """ Cell Options (SACCH) Section 10.5.2.3a """
+ name = "Cell Options (SACCH)"
+ fields_desc = [
+ BitField("eightBitCOS", None, 1),
+ XBitField("ieiCOS", None, 7),
+ BitField("dtx", 0x0, 1),
+ BitField("pwrc", 0x0, 1),
+ BitField("dtx", 0x0, 1),
+ BitField("rLinkTout", 0x0, 4)
+ ]
+
+
+class CellSelectionParametersHdr(Packet):
+ """ Cell Selection Parameters Section 10.5.2.4 """
+ name = "Cell Selection Parameters"
+ fields_desc = [
+ BitField("eightBitCSP", None, 1),
+ XBitField("ieiCSP", None, 7),
+ BitField("cellReselect", 0x0, 3),
+ BitField("msTxPwrMax", 0x0, 5),
+ BitField("acs", None, 1),
+ BitField("neci", None, 1),
+ BitField("rxlenAccMin", None, 6)
+ ]
+
+
+class MacModeAndChannelCodingRequestHdr(Packet):
+ """ MAC Mode and Channel Coding Requested Section 10.5.2.4a """
+ name = "MAC Mode and Channel Coding Requested"
+ fields_desc = [
+ XBitField("ieiMMACCR", None, 4),
+ BitField("macMode", 0x0, 2),
+ BitField("cs", 0x0, 2)
+ ]
+
+
+class ChannelDescriptionHdr(Packet):
+ """ Channel Description Section 10.5.2.5 """
+ name = "Channel Description"
+ fields_desc = [
+ BitField("eightBitCD", None, 1),
+ XBitField("ieiCD", None, 7),
+
+ BitField("channelTyp", 0x0, 5),
+ BitField("tn", 0x0, 3),
+
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x1, 1),
+ # if h=1 maybe we find a better solution here...
+ BitField("maioHi", 0x0, 4),
+
+ BitField("maioLo", 0x0, 2),
+ BitField("hsn", 0x0, 6)
+ #BitField("spare", 0x0, 2),
+ #BitField("arfcnHigh", 0x0, 2),
+ #ByteField("arfcnLow", 0x0)
+ ]
+
+
+class ChannelDescription2Hdr(Packet):
+ """ Channel Description 2 Section 10.5.2.5a """
+ name = "Channel Description 2"
+ fields_desc = [
+ BitField("eightBitCD2", None, 1),
+ XBitField("ieiCD2", None, 7),
+ BitField("channelTyp", 0x0, 5),
+ BitField("tn", 0x0, 3),
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x0, 1),
+ # if h=1
+ # BitField("maioHi", 0x0, 4),
+ # BitField("maioLo", 0x0, 2),
+ # BitField("hsn", 0x0, 6)
+ BitField("spare", 0x0, 2),
+ BitField("arfcnHigh", 0x0, 2),
+ ByteField("arfcnLow", 0x0)
+ ]
+
+
+class ChannelModeHdr(Packet):
+ """ Channel Mode Section 10.5.2.6 """
+ name = "Channel Mode"
+ fields_desc = [
+ BitField("eightBitCM", None, 1),
+ XBitField("ieiCM", None, 7),
+ ByteField("mode", 0x0)
+ ]
+
+
+class ChannelMode2Hdr(Packet):
+ """ Channel Mode 2 Section 10.5.2.7 """
+ name = "Channel Mode 2"
+ fields_desc = [
+ BitField("eightBitCM2", None, 1),
+ XBitField("ieiCM2", None, 7),
+ ByteField("mode", 0x0)
+ ]
+
+
+class ChannelNeededHdr(Packet):
+ """ Channel Needed Section 10.5.2.8 """
+ name = "Channel Needed"
+ fields_desc = [
+ XBitField("ieiCN", None, 4),
+ BitField("channel2", 0x0, 2),
+ BitField("channel1", 0x0, 2),
+ ]
+
+
+class ChannelRequestDescriptionHdr(Packet):
+ """Channel Request Description Section 10.5.2.8a """
+ name = "Channel Request Description"
+ fields_desc = [
+ BitField("eightBitCRD", None, 1),
+ XBitField("ieiCRD", None, 7),
+ BitField("mt", 0x0, 1),
+ ConditionalField(BitField("spare", 0x0, 39),
+ lambda pkt: pkt.mt == 0),
+ ConditionalField(BitField("spare", 0x0, 3),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("priority", 0x0, 2),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("rlcMode", 0x0, 1),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("llcFrame", 0x1, 1),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("reqBandMsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("reqBandLsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("rlcMsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("rlcLsb", 0x0),
+ lambda pkt: pkt.mt == 1)
+ ]
+
+
+class CipherModeSettingHdr(Packet):
+ """Cipher Mode Setting Section 10.5.2.9 """
+ name = "Cipher Mode Setting"
+ fields_desc = [
+ XBitField("ieiCMS", None, 4),
+ BitField("algoId", 0x0, 3),
+ BitField("sc", 0x0, 1),
+ ]
+
+
+class CipherResponseHdr(Packet):
+ """Cipher Response Section 10.5.2.10 """
+ name = "Cipher Response"
+ fields_desc = [
+ XBitField("ieiCR", None, 4),
+ BitField("spare", 0x0, 3),
+ BitField("cr", 0x0, 1),
+ ]
+
+
+# This packet fixes the problem with the 1/2 Byte length. Concatenation
+# of cipherModeSetting and cipherResponse
+class CipherModeSettingAndcipherResponse(Packet):
+ name = "Cipher Mode Setting And Cipher Response"
+ fields_desc = [
+ BitField("algoId", 0x0, 3),
+ BitField("sc", 0x0, 1),
+ BitField("spare", 0x0, 3),
+ BitField("cr", 0x0, 1)
+ ]
+
+
+class ControlChannelDescriptionHdr(Packet):
+ """Control Channel Description Section 10.5.2.11 """
+ name = "Control Channel Description"
+ fields_desc = [
+ BitField("eightBitCCD", None, 1),
+ XBitField("ieiCCD", None, 7),
+
+ BitField("spare", 0x0, 1),
+ BitField("att", 0x0, 1),
+ BitField("bsAgBlksRes", 0x0, 3),
+ BitField("ccchConf", 0x0, 3),
+
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("spare4", 0x0, 1),
+ BitField("bsPaMfrms", 0x0, 3),
+
+ ByteField("t3212", 0x0)
+ ]
+
+
+class FrequencyChannelSequenceHdr(Packet):
+ """Frequency Channel Sequence Section 10.5.2.12"""
+ name = "Frequency Channel Sequence"
+ fields_desc = [
+ BitField("eightBitFCS", None, 1),
+ XBitField("ieiFCS", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("lowestArfcn", 0x0, 7),
+ BitField("skipArfcn01", 0x0, 4),
+ BitField("skipArfcn02", 0x0, 4),
+ BitField("skipArfcn03", 0x0, 4),
+ BitField("skipArfcn04", 0x0, 4),
+ BitField("skipArfcn05", 0x0, 4),
+ BitField("skipArfcn06", 0x0, 4),
+ BitField("skipArfcn07", 0x0, 4),
+ BitField("skipArfcn08", 0x0, 4),
+ BitField("skipArfcn09", 0x0, 4),
+ BitField("skipArfcn10", 0x0, 4),
+ BitField("skipArfcn11", 0x0, 4),
+ BitField("skipArfcn12", 0x0, 4),
+ BitField("skipArfcn13", 0x0, 4),
+ BitField("skipArfcn14", 0x0, 4),
+ BitField("skipArfcn15", 0x0, 4),
+ BitField("skipArfcn16", 0x0, 4)
+ ]
+
+
+class FrequencyListHdr(Packet):
+ """Frequency List Section 10.5.2.13"""
+ name = "Frequency List"
+ # Problem:
+ # There are several formats for the Frequency List information
+ # element, distinguished by the "format indicator" subfield.
+ # Some formats are frequency bit maps, the others use a special encoding
+ # scheme.
+ fields_desc = [
+ BitField("eightBitFL", None, 1),
+ XBitField("ieiFL", None, 7),
+ XByteField("lengthFL", None),
+
+ BitField("formatID", 0x0, 2),
+ BitField("spare", 0x0, 2),
+ BitField("arfcn124", 0x0, 1),
+ BitField("arfcn123", 0x0, 1),
+ BitField("arfcn122", 0x0, 1),
+ BitField("arfcn121", 0x0, 1),
+
+ ByteField("arfcn120", 0x0),
+ ByteField("arfcn112", 0x0),
+ ByteField("arfcn104", 0x0),
+ ByteField("arfcn96", 0x0),
+ ByteField("arfcn88", 0x0),
+ ByteField("arfcn80", 0x0),
+ ByteField("arfcn72", 0x0),
+ ByteField("arfcn64", 0x0),
+ ByteField("arfcn56", 0x0),
+ ByteField("arfcn48", 0x0),
+ ByteField("arfcn40", 0x0),
+ ByteField("arfcn32", 0x0),
+ ByteField("arfcn24", 0x0),
+ ByteField("arfcn16", 0x0),
+ ByteField("arfcn8", 0x0)
+ ]
+
+
+class FrequencyShortListHdr(Packet):
+ """Frequency Short List Section 10.5.2.14"""
+ name = "Frequency Short List"
+# len is 10
+#This element is encoded exactly as the Frequency List information element,
+#except that it has a fixed length instead of a
+#variable length and does not contain a length indicator and that it
+#shall not be encoded in bitmap 0 format.
+ fields_desc = [
+ ByteField("ieiFSL", 0x0),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0)
+ ]
+
+
+class FrequencyShortListHdr2(Packet):
+ """Frequency Short List2 Section 10.5.2.14a"""
+ name = "Frequency Short List 2"
+ fields_desc = [
+ ByteField("byte1", 0x0),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0)
+ ]
+
+
+# len 4 to 13
+class GroupChannelDescriptionHdr(Packet):
+ """Group Channel Description Section 10.5.2.14b"""
+ name = "Group Channel Description"
+ fields_desc = [
+ BitField("eightBitGCD", None, 1),
+ XBitField("ieiGCD", None, 7),
+
+ XByteField("lengthGCD", None),
+
+ BitField("channelType", 0x0, 5),
+ BitField("tn", 0x0, 3),
+
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x0, 1),
+ # if h == 0 the packet looks the following way:
+ ConditionalField(BitField("spare", 0x0, 2),
+ lambda pkt: pkt. h == 0x0),
+ ConditionalField(BitField("arfcnHi", 0x0, 2),
+ lambda pkt: pkt. h == 0x0),
+ ConditionalField(ByteField("arfcnLo", None),
+ lambda pkt: pkt. h == 0x0),
+ # if h == 1 the packet looks the following way:
+ ConditionalField(BitField("maioHi", 0x0, 4),
+ lambda pkt: pkt. h == 0x1),
+ ConditionalField(BitField("maioLo", None, 2),
+ lambda pkt: pkt. h == 0x1),
+ ConditionalField(BitField("hsn", None, 6),
+ lambda pkt: pkt. h == 0x1),
+ # finished with conditional fields
+ ByteField("maC6", None),
+ ByteField("maC7", None),
+ ByteField("maC8", None),
+ ByteField("maC9", None),
+ ByteField("maC10", None),
+ ByteField("maC11", None),
+ ByteField("maC12", None),
+ ByteField("maC13", None),
+ ByteField("maC14", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 13, a, self.fields_desc)
+ if self.lengthGCD is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class GprsResumptionHdr(Packet):
+ """GPRS Resumption Section 10.5.2.14c"""
+ name = "GPRS Resumption"
+ fields_desc = [
+ XBitField("ieiGR", None, 4),
+ BitField("spare", 0x0, 3),
+ BitField("ack", 0x0, 1)
+ ]
+
+
+class HandoverReferenceHdr(Packet):
+ """Handover Reference Section 10.5.2.15"""
+ name = "Handover Reference"
+ fields_desc = [
+ BitField("eightBitHR", None, 1),
+ XBitField("ieiHR", None, 7),
+ ByteField("handoverRef", 0x0)
+ ]
+
+
+# len 1-12
+class IaRestOctets(Packet):
+ """IA Rest Octets Section 10.5.2.16"""
+ name = "IA Rest Octets"
+ fields_desc = [
+ ByteField("ieiIRO", 0x0),
+ # FIXME brainfuck packet
+ XByteField("lengthIRO", None),
+ ByteField("byte2", None),
+ ByteField("byte3", None),
+ ByteField("byte4", None),
+ ByteField("byte5", None),
+ ByteField("byte6", None),
+ ByteField("byte7", None),
+ ByteField("byte8", None),
+ ByteField("byte9", None),
+ ByteField("byte10", None),
+ ByteField("byte11", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 12, a, self.fields_desc)
+ if self.lengthIRO is None:
+ if res[1] < 0: # FIXME better fix
+ res[1] = 0
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class IraRestOctetsHdr(Packet):
+ """IAR Rest Octets Section 10.5.2.17"""
+ name = "IAR Rest Octets"
+ fields_desc = [
+ BitField("eightBitIRO", None, 1),
+ XBitField("ieiIRO", None, 7),
+ BitField("spare01", 0x0, 1),
+ BitField("spare02", 0x0, 1),
+ BitField("spare03", 0x1, 1),
+ BitField("spare04", 0x0, 1),
+ BitField("spare05", 0x1, 1),
+ BitField("spare06", 0x0, 1),
+ BitField("spare07", 0x1, 1),
+ BitField("spare08", 0x1, 1),
+ BitField("spare09", 0x0, 1),
+ BitField("spare10", 0x0, 1),
+ BitField("spare11", 0x1, 1),
+ BitField("spare12", 0x0, 1),
+ BitField("spare13", 0x1, 1),
+ BitField("spare14", 0x0, 1),
+ BitField("spare15", 0x1, 1),
+ BitField("spare16", 0x1, 1),
+ BitField("spare17", 0x0, 1),
+ BitField("spare18", 0x0, 1),
+ BitField("spare19", 0x1, 1),
+ BitField("spare20", 0x0, 1),
+ BitField("spare21", 0x1, 1),
+ BitField("spare22", 0x0, 1),
+ BitField("spare23", 0x1, 1),
+ BitField("spare24", 0x1, 1)
+ ]
+
+
+# len is 1 to 5 what do we do with the variable size? no lenght
+# field?! WTF
+class IaxRestOctetsHdr(Packet):
+ """IAX Rest Octets Section 10.5.2.18"""
+ name = "IAX Rest Octets"
+ fields_desc = [
+ BitField("eightBitIRO", None, 1),
+ XBitField("ieiIRO", None, 7),
+ BitField("spare01", 0x0, 1),
+ BitField("spare02", 0x0, 1),
+ BitField("spare03", 0x1, 1),
+ BitField("spare04", 0x0, 1),
+ BitField("spare05", 0x1, 1),
+ BitField("spare06", 0x0, 1),
+ BitField("spare07", 0x1, 1),
+ BitField("spare08", 0x1, 1),
+ ByteField("spareB1", None),
+ ByteField("spareB2", None),
+ ByteField("spareB3", None)
+ ]
+
+
+class L2PseudoLengthHdr(Packet):
+ """L2 Pseudo Length Section 10.5.2.19"""
+ name = "L2 Pseudo Length"
+ fields_desc = [
+ BitField("eightBitPL", None, 1),
+ XBitField("ieiPL", None, 7),
+ BitField("l2pLength", None, 6),
+ BitField("bit2", 0x0, 1),
+ BitField("bit1", 0x1, 1)
+ ]
+
+
+class MeasurementResultsHdr(Packet):
+ """Measurement Results Section 10.5.2.20"""
+ name = "Measurement Results"
+ fields_desc = [
+ BitField("eightBitMR", None, 1),
+ XBitField("ieiMR", None, 7),
+ BitField("baUsed", 0x0, 1),
+ BitField("dtxUsed", 0x0, 1),
+ BitField("rxLevFull", 0x0, 6),
+ BitField("spare", 0x0, 1),
+ BitField("measValid", 0x0, 1),
+ BitField("rxLevSub", 0x0, 6),
+ BitField("spare0", 0x0, 1),
+ BitField("rxqualFull", 0x0, 3),
+ BitField("rxqualSub", 0x0, 3),
+ BitField("noNcellHi", 0x0, 1),
+ BitField("noNcellLo", 0x0, 2),
+ BitField("rxlevC1", 0x0, 6),
+ BitField("bcchC1", 0x0, 5),
+ BitField("bsicC1Hi", 0x0, 3),
+ BitField("bsicC1Lo", 0x0, 3),
+ BitField("rxlevC2", 0x0, 5),
+ BitField("rxlevC2Lo", 0x0, 1),
+ BitField("bcchC2", 0x0, 5),
+ BitField("bsicC1Hi", 0x0, 2),
+ BitField("bscicC2Lo", 0x0, 4),
+ BitField("bscicC2Hi", 0x0, 4),
+
+ BitField("rxlevC3Lo", 0x0, 2),
+ BitField("bcchC3", 0x0, 5),
+ BitField("rxlevC3Hi", 0x0, 1),
+
+ BitField("bsicC3Lo", 0x0, 5),
+ BitField("bsicC3Hi", 0x0, 3),
+
+ BitField("rxlevC4Lo", 0x0, 3),
+ BitField("bcchC4", 0x0, 5),
+
+ BitField("bsicC4", 0x0, 6),
+ BitField("rxlevC5Hi", 0x0, 2),
+
+ BitField("rxlevC5Lo", 0x0, 4),
+ BitField("bcchC5Hi", 0x0, 4),
+
+ BitField("bcchC5Lo", 0x0, 1),
+ BitField("bsicC5", 0x0, 6),
+ BitField("rxlevC6", 0x0, 1),
+
+ BitField("rxlevC6Lo", 0x0, 5),
+ BitField("bcchC6Hi", 0x0, 3),
+
+ BitField("bcchC6Lo", 0x0, 3),
+ BitField("bsicC6", 0x0, 5)
+ ]
+
+
+class GprsMeasurementResultsHdr(Packet):
+ """GPRS Measurement Results Section 10.5.2.20a"""
+ name = "GPRS Measurement Results"
+ fields_desc = [
+ BitField("eightBitGMR", None, 1),
+ XBitField("ieiGMR", None, 7),
+ BitField("cValue", 0x0, 6),
+ BitField("rxqualHi", 0x0, 2),
+ BitField("rxqL", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("signVar", 0x0, 6)
+ ]
+
+
+# len 3 to 10
+class MobileAllocationHdr(Packet):
+ """Mobile Allocation Section 10.5.2.21"""
+ name = "Mobile Allocation"
+ fields_desc = [
+ BitField("eightBitMA", None, 1),
+ XBitField("ieiMA", None, 7),
+ XByteField("lengthMA", None),
+ ByteField("maC64", 0x12),
+ ByteField("maC56", None), # optional fields start here
+ ByteField("maC48", None),
+ ByteField("maC40", None),
+ ByteField("maC32", None),
+ ByteField("maC24", None),
+ ByteField("maC16", None),
+ ByteField("maC8", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 10, a, self.fields_desc)
+ if self.lengthMA is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MobileTimeDifferenceHdr(Packet):
+ """Mobile Time Difference Section 10.5.2.21a"""
+ name = "Mobile Time Difference"
+ fields_desc = [
+ BitField("eightBitMTD", None, 1),
+ XBitField("ieiMTD", None, 7),
+ XByteField("lengthMTD", 0x5),
+ ByteField("valueHi", 0x0),
+ ByteField("valueCnt", 0x0),
+ BitField("valueLow", 0x0, 5),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1)
+ ]
+
+
+# min 4 octets max 8
+class MultiRateConfigurationHdr(Packet):
+ """ MultiRate configuration Section 10.5.2.21aa"""
+ name = "MultiRate Configuration"
+ fields_desc = [
+ BitField("eightBitMRC", None, 1),
+ XBitField("ieiMRC", None, 7),
+
+ XByteField("lengthMRC", None),
+
+ BitField("mrVersion", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("icmi", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("startMode", 0x0, 2),
+
+ ByteField("amrCodec", 0x0),
+
+ BitField("spare", None, 2),
+ BitField("threshold1", None, 6),
+
+ BitField("hysteresis1", None, 4),
+ BitField("threshold2", None, 4),
+
+ BitField("threshold2cnt", None, 2),
+ BitField("hysteresis2", None, 4),
+ BitField("threshold3", None, 2),
+
+ BitField("threshold3cnt", None, 4),
+ BitField("hysteresis3", None, 4)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 8, a, self.fields_desc)
+ if self.lengthMRC is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 3 to 12
+class MultislotAllocationHdr(Packet):
+ """Multislot Allocation Section 10.5.2.21b"""
+ name = "Multislot Allocation"
+ fields_desc = [
+ BitField("eightBitMSA", None, 1),
+ XBitField("ieiMSA", None, 7),
+ XByteField("lengthMSA", None),
+ BitField("ext0", 0x1, 1),
+ BitField("da", 0x0, 7),
+ ConditionalField(BitField("ext1", 0x1, 1), # optional
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("ua", 0x0, 7),
+ lambda pkt: pkt.ext0 == 0),
+ ByteField("chan1", None),
+ ByteField("chan2", None),
+ ByteField("chan3", None),
+ ByteField("chan4", None),
+ ByteField("chan5", None),
+ ByteField("chan6", None),
+ ByteField("chan7", None),
+ ByteField("chan8", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 12, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthMSA is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+
+
+class NcModeHdr(Packet):
+ """NC mode Section 10.5.2.21c"""
+ name = "NC Mode"
+ fields_desc = [
+ XBitField("ieiNM", None, 4),
+ BitField("spare", 0x0, 2),
+ BitField("ncMode", 0x0, 2)
+ ]
+
+
+# Fix for len problem
+# concatenation NC Mode And Spare Half Octets
+class NcModeAndSpareHalfOctets(Packet):
+ name = "NC Mode And Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x0, 2),
+ BitField("ncMode", 0x0, 2),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class NeighbourCellsDescriptionHdr(Packet):
+ """Neighbour Cells Description Section 10.5.2.22"""
+ name = "Neighbour Cells Description"
+ fields_desc = [
+ BitField("eightBitNCD", None, 1),
+ XBitField("ieiNCD", None, 7),
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("extInd", 0x0, 1),
+ BitField("baInd", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ BitField("120bits", 0x0, 120)
+ ]
+
+
+class NeighbourCellsDescription2Hdr(Packet):
+ """Neighbour Cells Description 2 Section 10.5.2.22a"""
+ name = "Neighbour Cells Description 2"
+ fields_desc = [
+ BitField("eightBitNCD2", None, 1),
+ XBitField("ieiNCD2", None, 7),
+ BitField("bit128", 0x0, 1),
+ BitField("multiband", 0x0, 2),
+ BitField("baInd", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ BitField("120bits", 0x0, 120)
+ ]
+
+
+class NtNRestOctets(Packet):
+ """NT/N Rest Octets Section 10.5.2.22c"""
+ name = "NT/N Rest Octets"
+ fields_desc = [
+ BitField("nln", 0x0, 2),
+ BitField("ncnInfo", 0x0, 4),
+ BitField("spare", 0x0, 2)
+ ]
+
+
+#
+# The following packet has no length info!
+#
+# len 1-18
+class P1RestOctets(Packet):
+ """P1 Rest Octets Section 10.5.2.23"""
+ name = "P1 Rest Octets"
+ fields_desc = [
+ BitField("nln", 0x0, 2),
+ BitField("nlnStatus", 0x0, 1),
+ BitField("prio1", 0x0, 3),
+ BitField("prio2", 0x0, 3),
+ # optional
+ BitField("pageIndication1", 0x0, 1),
+ BitField("pageIndication2", 0x0, 1),
+ BitField("spare", 0x0, 5),
+ ByteField("spareB1", None),
+ ByteField("spareB2", None),
+ ByteField("spareB3", None),
+ ByteField("spareB4", None),
+ ByteField("spareB5", None),
+ ByteField("spareB6", None),
+ ByteField("spareB7", None),
+ ByteField("spareB8", None),
+ ByteField("spareB9", None),
+ ByteField("spareB10", None),
+ ByteField("spareB11", None),
+ ByteField("spareB12", None),
+ ByteField("spareB13", None),
+ ByteField("spareB14", None),
+ ByteField("spareB15", None),
+ ByteField("spareB16", None),
+ ]
+
+
+# len 2-12
+class P2RestOctets(Packet):
+ """P2 Rest Octets Section 10.5.2.24"""
+ name = "P2 Rest Octets"
+ fields_desc = [
+ BitField("cn3", 0x0, 2),
+ BitField("nln", 0x0, 2),
+ BitField("nlnStatus", 0x0, 1),
+ BitField("prio1", 0x0, 3),
+
+ BitField("prio2", 0x0, 3),
+ BitField("prio3", 0x0, 3),
+ BitField("pageIndication3", 0x0, 1),
+ BitField("spare", 0x0, 1),
+
+ # optinal (No length field!)
+ ByteField("spareB1", None),
+ ByteField("spareB2", None),
+ ByteField("spareB3", None),
+ ByteField("spareB4", None),
+
+ ByteField("spareB5", None),
+ ByteField("spareB6", None),
+ ByteField("spareB7", None),
+ ByteField("spareB8", None),
+
+ ByteField("spareB9", None),
+ ByteField("spareB10", None)
+ ]
+
+
+# len 4
+class P3RestOctets(Packet):
+ """P3 Rest Octets Section 10.5.2.25"""
+ name = "P3 Rest Octets"
+ fields_desc = [
+ BitField("cn3", 0x0, 2),
+ BitField("cn4", 0x0, 2),
+ BitField("nln", 0x0, 2),
+ BitField("nlnStatus", 0x0, 1),
+ BitField("prio1", 0x0, 3),
+ BitField("prio2", 0x0, 3),
+ BitField("prio3", 0x0, 3),
+ BitField("prio4", 0x0, 3),
+ BitField("spare", 0x0, 5)
+ ]
+
+
+# len 4
+# strange packet, lots of valid formats
+
+# ideas for the dynamic packets:
+# 1] for user interaction: Create an interactive "builder" based on a
+# Q/A process (not very scapy like)
+# 2] for usage in scripts, create an alternative packet for every
+# possible packet layout
+#
+
+
+class PacketChannelDescription(Packet):
+ """Packet Channel Description Section 10.5.2.25a"""
+ name = "Packet Channel Description"
+ fields_desc = [
+ ByteField("ieiPCD", None),
+ BitField("chanType", 0x0, 5), # This packet has multiple
+ # possible layouts. I moddeled the first one
+ BitField("tn", 0x0, 3), # maybe build an
+ #"interactive" builder. Like
+ # a Q/A then propose a
+ # packet?
+ BitField("tsc", 0x0, 3),
+ BitField("chooser1", 0x0, 1),
+ BitField("chooser2", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("arfcn", 0x0, 10),
+ ]
+
+
+class DedicatedModeOrTBFHdr(Packet):
+ """Dedicated mode or TBF Section 10.5.2.25b"""
+ name = "Dedicated Mode or TBF"
+ fields_desc = [
+ XBitField("ieiDMOT", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("tma", 0x0, 1),
+ BitField("downlink", 0x0, 1),
+ BitField("td", 0x0, 1)
+ ]
+
+
+# FIXME add implementation
+class RrPacketUplinkAssignment(Packet):
+ """RR Packet Uplink Assignment Section 10.5.2.25c"""
+ name = "RR Packet Uplink Assignment"
+ fields_desc = [
+ # Fill me
+ ]
+
+
+class PageModeHdr(Packet):
+ """Page Mode Section 10.5.2.26"""
+ name = "Page Mode"
+ fields_desc = [
+ XBitField("ieiPM", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("pm", 0x0, 2)
+ ]
+
+
+# Fix for 1/2 len problem
+# concatenation: pageMode and dedicatedModeOrTBF
+class PageModeAndDedicatedModeOrTBF(Packet):
+ name = "Page Mode and Dedicated Mode Or TBF"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("pm", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("tma", 0x0, 1),
+ BitField("downlink", 0x0, 1),
+ BitField("td", 0x0, 1)
+ ]
+
+
+# Fix for 1/2 len problem
+# concatenation: pageMode and spareHalfOctets
+class PageModeAndSpareHalfOctets(Packet):
+ name = "Page Mode and Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("pm", 0x0, 2),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+# Fix for 1/2 len problem
+# concatenation: pageMode and Channel Needed
+class PageModeAndChannelNeeded(Packet):
+ name = "Page Mode and Channel Needed"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("pm", 0x0, 2),
+ BitField("channel2", 0x0, 2),
+ BitField("channel1", 0x0, 2)
+ ]
+
+
+class NccPermittedHdr(Packet):
+ """NCC Permitted Section 10.5.2.27"""
+ name = "NCC Permited"
+ fields_desc = [
+ BitField("eightBitNP", None, 1),
+ XBitField("ieiNP", None, 7),
+ ByteField("nccPerm", 0x0)
+ ]
+
+
+class PowerCommandHdr(Packet):
+ """Power Command Section 10.5.2.28"""
+ name = "Power Command"
+ fields_desc = [
+ BitField("eightBitPC", None, 1),
+ XBitField("ieiPC", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("powerLvl", 0x0, 5)
+ ]
+
+
+class PowerCommandAndAccessTypeHdr(Packet):
+ """Power Command and access type Section 10.5.2.28a"""
+ name = "Power Command and Access Type"
+ fields_desc = [
+ BitField("eightBitPCAAT", None, 1),
+ XBitField("ieiPCAAT", None, 7),
+ BitField("atc", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("powerLvl", 0x0, 5)
+ ]
+
+
+class RachControlParametersHdr(Packet):
+ """RACH Control Parameters Section 10.5.2.29"""
+ name = "RACH Control Parameters"
+ fields_desc = [
+ BitField("eightBitRCP", None, 1),
+ XBitField("ieiRCP", None, 7),
+ BitField("maxRetrans", 0x0, 2),
+ BitField("txInteger", 0x0, 4),
+ BitField("cellBarrAccess", 0x0, 1),
+ BitField("re", 0x0, 1),
+ BitField("ACC15", 0x0, 1),
+ BitField("ACC14", 0x0, 1),
+ BitField("ACC13", 0x0, 1),
+ BitField("ACC12", 0x0, 1),
+ BitField("ACC11", 0x0, 1),
+ BitField("ACC10", 0x0, 1),
+ BitField("ACC09", 0x0, 1),
+ BitField("ACC08", 0x0, 1),
+ BitField("ACC07", 0x0, 1),
+ BitField("ACC06", 0x0, 1),
+ BitField("ACC05", 0x0, 1),
+ BitField("ACC04", 0x0, 1),
+ BitField("ACC03", 0x0, 1),
+ BitField("ACC02", 0x0, 1),
+ BitField("ACC01", 0x0, 1),
+ BitField("ACC00", 0x0, 1),
+ ]
+
+
+class RequestReferenceHdr(Packet):
+ """Request Reference Section 10.5.2.30"""
+ name = "Request Reference"
+ fields_desc = [
+ BitField("eightBitRR", None, 1),
+ XBitField("ieiRR", None, 7),
+ ByteField("ra", 0x0),
+ BitField("t1", 0x0, 5),
+ BitField("t3Hi", 0x0, 3),
+ BitField("t3Lo", 0x0, 3),
+ BitField("t2", 0x0, 5)
+ ]
+
+
+class RrCauseHdr(Packet):
+ """RR Cause Section 10.5.2.31"""
+ name = "RR Cause"
+ fields_desc = [
+ BitField("eightBitRC", None, 1),
+ XBitField("ieiRC", None, 7),
+ ByteField("rrCause", 0x0)
+ ]
+
+
+class Si1RestOctets(Packet):
+ """SI 1 Rest Octets Section 10.5.2.32"""
+ name = "SI 1 Rest Octets"
+ fields_desc = [
+ ByteField("nchPos", 0x0)
+ ]
+
+
+class Si2bisRestOctets(Packet):
+ """SI 2bis Rest Octets Section 10.5.2.33"""
+ name = "SI 2bis Rest Octets"
+ fields_desc = [
+ ByteField("spare", 0x0)
+ ]
+
+
+class Si2terRestOctets(Packet):
+ """SI 2ter Rest Octets Section 10.5.2.33a"""
+ name = "SI 2ter Rest Octets"
+ fields_desc = [
+ ByteField("spare1", 0x0),
+ ByteField("spare2", 0x0),
+ ByteField("spare3", 0x0),
+ ByteField("spare4", 0x0)
+ ]
+
+
+# len 5
+class Si3RestOctets(Packet):
+ """SI 3 Rest Octets Section 10.5.2.34"""
+ name = "SI 3 Rest Octets"
+ fields_desc = [
+ ByteField("byte1", 0x0),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0)
+ ]
+
+
+# len 1 to 11
+class Si4RestOctets(Packet):
+ """SI 4 Rest Octets Section 10.5.2.35"""
+ name = "SI 4 Rest Octets"
+ fields_desc = [
+ XByteField("lengthSI4", None),
+ ByteField("byte2", None),
+ ByteField("byte3", None),
+ ByteField("byte4", None),
+ ByteField("byte5", None),
+ ByteField("byte6", None),
+ ByteField("byte7", None),
+ ByteField("byte8", None),
+ ByteField("byte9", None),
+ ByteField("byte10", None),
+ ByteField("byte11", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 11, a, self.fields_desc, 1)
+ if self.lengthSI4 is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if len(p) is 1: # length of this packet can be 0, but packet is
+ p = '' # but the IE is manadatory 0_o
+ return p + pay
+
+
+class Si6RestOctets(Packet):
+ """SI 6 Rest Octets Section 10.5.2.35a"""
+ name = "SI 4 Rest Octets"
+ fields_desc = [
+ # FIXME
+ ]
+
+
+# len 21
+class Si7RestOctets(Packet):
+ """SI 7 Rest Octets Section 10.5.2.36"""
+ name = "SI 7 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI7", 0x15),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0),
+ ByteField("byte18", 0x0),
+ ByteField("byte19", 0x0),
+ ByteField("byte20", 0x0),
+ ByteField("byte21", 0x0)
+ ]
+
+
+# len 21
+class Si8RestOctets(Packet):
+ """SI 8 Rest Octets Section 10.5.2.37"""
+ name = "SI 8 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI8", 0x15),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0),
+ ByteField("byte18", 0x0),
+ ByteField("byte19", 0x0),
+ ByteField("byte20", 0x0),
+ ByteField("byte21", 0x0)
+ ]
+
+
+#len 17
+class Si9RestOctets(Packet):
+ """SI 9 Rest Octets Section 10.5.2.37a"""
+ name = "SI 9 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI9", 0x11),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0)
+ ]
+
+
+# len 21
+class Si13RestOctets(Packet):
+ """SI 13 Rest Octets Section 10.5.2.37b"""
+ name = "SI 13 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI3", 0x15),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0),
+ ByteField("byte18", 0x0),
+ ByteField("byte19", 0x0),
+ ByteField("byte20", 0x0),
+ ByteField("byte21", 0x0)
+ ]
+
+
+# 10.5.2.37c [spare]
+# 10.5.2.37d [spare]
+
+
+# len 21
+class Si16RestOctets(Packet):
+ """SI 16 Rest Octets Section 10.5.2.37e"""
+ name = "SI 16 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI16", 0x15),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0),
+ ByteField("byte18", 0x0),
+ ByteField("byte19", 0x0),
+ ByteField("byte20", 0x0),
+ ByteField("byte21", 0x0)
+ ]
+
+
+# len 21
+class Si17RestOctets(Packet):
+ """SI 17 Rest Octets Section 10.5.2.37f"""
+ name = "SI 17 Rest Octets"
+ fields_desc = [
+ # FIXME
+ XByteField("lengthSI17", 0x15),
+ ByteField("byte2", 0x0),
+ ByteField("byte3", 0x0),
+ ByteField("byte4", 0x0),
+ ByteField("byte5", 0x0),
+ ByteField("byte6", 0x0),
+ ByteField("byte7", 0x0),
+ ByteField("byte8", 0x0),
+ ByteField("byte9", 0x0),
+ ByteField("byte10", 0x0),
+ ByteField("byte11", 0x0),
+ ByteField("byte12", 0x0),
+ ByteField("byte13", 0x0),
+ ByteField("byte14", 0x0),
+ ByteField("byte15", 0x0),
+ ByteField("byte16", 0x0),
+ ByteField("byte17", 0x0),
+ ByteField("byte18", 0x0),
+ ByteField("byte19", 0x0),
+ ByteField("byte20", 0x0),
+ ByteField("byte21", 0x0)
+ ]
+
+
+class StartingTimeHdr(Packet):
+ """Starting Time Section 10.5.2.38"""
+ name = "Starting Time"
+ fields_desc = [
+ BitField("eightBitST", None, 1),
+ XBitField("ieiST", None, 7),
+ ByteField("ra", 0x0),
+ BitField("t1", 0x0, 5),
+ BitField("t3Hi", 0x0, 3),
+ BitField("t3Lo", 0x0, 3),
+ BitField("t2", 0x0, 5)
+ ]
+
+
+class SynchronizationIndicationHdr(Packet):
+ """Synchronization Indication Section 10.5.2.39"""
+ name = "Synchronization Indication"
+ fields_desc = [
+ XBitField("ieiSI", None, 4),
+ BitField("nci", 0x0, 1),
+ BitField("rot", 0x0, 1),
+ BitField("si", 0x0, 2)
+ ]
+
+
+class TimingAdvanceHdr(Packet):
+ """Timing Advance Section 10.5.2.40"""
+ name = "Timing Advance"
+ fields_desc = [
+ BitField("eightBitTA", None, 1),
+ XBitField("ieiTA", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("timingVal", 0x0, 6)
+ ]
+
+
+class TimeDifferenceHdr(Packet):
+ """ Time Difference Section 10.5.2.41"""
+ name = "Time Difference"
+ fields_desc = [
+ BitField("eightBitTD", None, 1),
+ XBitField("ieiTD", None, 7),
+ XByteField("lengthTD", 0x3),
+ ByteField("timeValue", 0x0)
+ ]
+
+
+class TlliHdr(Packet):
+ """ TLLI Section Section 10.5.2.41a"""
+ name = "TLLI"
+ fields_desc = [
+ BitField("eightBitT", None, 1),
+ XBitField("ieiT", None, 7),
+ ByteField("value", 0x0),
+ ByteField("value1", 0x0),
+ ByteField("value2", 0x0),
+ ByteField("value3", 0x0)
+ ]
+
+
+class TmsiPTmsiHdr(Packet):
+ """ TMSI/P-TMSI Section 10.5.2.42"""
+ name = "TMSI/P-TMSI"
+ fields_desc = [
+ BitField("eightBitTPT", None, 1),
+ XBitField("ieiTPT", None, 7),
+ ByteField("value", 0x0),
+ ByteField("value1", 0x0),
+ ByteField("value2", 0x0),
+ ByteField("value3", 0x0)
+ ]
+
+
+class VgcsTargetModeIdenticationHdr(Packet):
+ """ VGCS target Mode Indication 10.5.2.42a"""
+ name = "VGCS Target Mode Indication"
+ fields_desc = [
+ BitField("eightBitVTMI", None, 1),
+ XBitField("ieiVTMI", None, 7),
+ XByteField("lengthVTMI", 0x2),
+ BitField("targerMode", 0x0, 2),
+ BitField("cipherKeyNb", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1)
+ ]
+
+
+class WaitIndicationHdr(Packet):
+ """ Wait Indication Section 10.5.2.43"""
+ name = "Wait Indication"
+ fields_desc = [ # asciiart of specs strange
+ BitField("eightBitWI", None, 1),
+ XBitField("ieiWI", None, 7),
+ ByteField("timeoutVal", 0x0)
+ ]
+
+
+# len 17
+class ExtendedMeasurementResultsHdr(Packet):
+ """EXTENDED MEASUREMENT RESULTS Section 10.5.2.45"""
+ name = "Extended Measurement Results"
+ fields_desc = [
+ BitField("eightBitEMR", None, 1),
+ XBitField("ieiEMR", None, 7),
+
+ BitField("scUsed", None, 1),
+ BitField("dtxUsed", None, 1),
+ BitField("rxLevC0", None, 6),
+
+ BitField("rxLevC1", None, 6),
+ BitField("rxLevC2Hi", None, 2),
+
+ BitField("rxLevC2Lo", None, 4),
+ BitField("rxLevC3Hi", None, 4),
+
+ BitField("rxLevC3Lo", None, 3),
+ BitField("rxLevC4", None, 5),
+
+ BitField("rxLevC5", None, 6),
+ BitField("rxLevC6Hi", None, 2),
+
+ BitField("rxLevC6Lo", None, 4),
+ BitField("rxLevC7Hi", None, 4),
+
+ BitField("rxLevC7Lo", None, 2),
+ BitField("rxLevC8", None, 6),
+
+ BitField("rxLevC9", None, 6),
+ BitField("rxLevC10Hi", None, 2),
+
+ BitField("rxLevC10Lo", None, 4),
+ BitField("rxLevC11Hi", None, 4),
+
+ BitField("rxLevC13Lo", None, 2),
+ BitField("rxLevC12", None, 6),
+
+ BitField("rxLevC13", None, 6),
+ BitField("rxLevC14Hi", None, 2),
+
+ BitField("rxLevC14Lo", None, 4),
+ BitField("rxLevC15Hi", None, 4),
+
+ BitField("rxLevC15Lo", None, 2),
+ BitField("rxLevC16", None, 6),
+
+
+ BitField("rxLevC17", None, 6),
+ BitField("rxLevC18Hi", None, 2),
+
+ BitField("rxLevC18Lo", None, 4),
+ BitField("rxLevC19Hi", None, 4),
+
+ BitField("rxLevC19Lo", None, 2),
+ BitField("rxLevC20", None, 6)
+ ]
+
+
+# len 17
+class ExtendedMeasurementFrequencyListHdr(Packet):
+ """Extended Measurement Frequency List Section 10.5.2.46"""
+ name = "Extended Measurement Frequency List"
+ fields_desc = [
+ BitField("eightBitEMFL", None, 1),
+ XBitField("ieiEMFL", None, 7),
+
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("seqCode", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+
+ BitField("bitsRest", 0x0, 128)
+ ]
+
+
+class SuspensionCauseHdr(Packet):
+ """Suspension Cause Section 10.5.2.47"""
+ name = "Suspension Cause"
+ fields_desc = [
+ BitField("eightBitSC", None, 1),
+ XBitField("ieiSC", None, 7),
+ ByteField("suspVal", 0x0)
+ ]
+
+
+class ApduIDHdr(Packet):
+ """APDU Flags Section 10.5.2.48"""
+ name = "Apdu Id"
+ fields_desc = [
+ XBitField("ieiAI", None, 4),
+ BitField("id", None, 4)
+ ]
+
+
+class ApduFlagsHdr(Packet):
+ """APDU Flags Section 10.5.2.49"""
+ name = "Apdu Flags"
+ fields_desc = [
+ XBitField("iei", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("cr", 0x0, 1),
+ BitField("firstSeg", 0x0, 1),
+ BitField("lastSeg", 0x0, 1)
+ ]
+
+
+# Fix 1/2 len problem
+class ApduIDAndApduFlags(Packet):
+ name = "Apu Id and Apdu Flags"
+ fields_desc = [
+ BitField("id", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("cr", 0x0, 1),
+ BitField("firstSeg", 0x0, 1),
+ BitField("lastSeg", 0x0, 1)
+ ]
+
+
+# len 2 to max L3 (251) (done)
+class ApduDataHdr(Packet):
+ """APDU Data Section 10.5.2.50"""
+ name = "Apdu Data"
+ fields_desc = [
+ BitField("eightBitAD", None, 1),
+ XBitField("ieiAD", None, 7),
+ XByteField("lengthAD", None),
+ #optional
+ ByteField("apuInfo1", None),
+ ByteField("apuInfo2", None),
+ ByteField("apuInfo3", None),
+ ByteField("apuInfo4", None),
+ ByteField("apuInfo5", None),
+ ByteField("apuInfo6", None),
+ ByteField("apuInfo7", None),
+ ByteField("apuInfo8", None),
+ ByteField("apuInfo9", None),
+ ByteField("apuInfo10", None),
+ ByteField("apuInfo11", None),
+ ByteField("apuInfo12", None),
+ ByteField("apuInfo13", None),
+ ByteField("apuInfo14", None),
+ ByteField("apuInfo15", None),
+ ByteField("apuInfo16", None),
+ ByteField("apuInfo17", None),
+ ByteField("apuInfo18", None),
+ ByteField("apuInfo19", None),
+ ByteField("apuInfo20", None),
+ ByteField("apuInfo21", None),
+ ByteField("apuInfo22", None),
+ ByteField("apuInfo23", None),
+ ByteField("apuInfo24", None),
+ ByteField("apuInfo25", None),
+ ByteField("apuInfo26", None),
+ ByteField("apuInfo27", None),
+ ByteField("apuInfo28", None),
+ ByteField("apuInfo29", None),
+ ByteField("apuInfo30", None),
+ ByteField("apuInfo31", None),
+ ByteField("apuInfo32", None),
+ ByteField("apuInfo33", None),
+ ByteField("apuInfo34", None),
+ ByteField("apuInfo35", None),
+ ByteField("apuInfo36", None),
+ ByteField("apuInfo37", None),
+ ByteField("apuInfo38", None),
+ ByteField("apuInfo39", None),
+ ByteField("apuInfo40", None),
+ ByteField("apuInfo41", None),
+ ByteField("apuInfo42", None),
+ ByteField("apuInfo43", None),
+ ByteField("apuInfo44", None),
+ ByteField("apuInfo45", None),
+ ByteField("apuInfo46", None),
+ ByteField("apuInfo47", None),
+ ByteField("apuInfo48", None),
+ ByteField("apuInfo49", None),
+ ByteField("apuInfo50", None),
+ ByteField("apuInfo51", None),
+ ByteField("apuInfo52", None),
+ ByteField("apuInfo53", None),
+ ByteField("apuInfo54", None),
+ ByteField("apuInfo55", None),
+ ByteField("apuInfo56", None),
+ ByteField("apuInfo57", None),
+ ByteField("apuInfo58", None),
+ ByteField("apuInfo59", None),
+ ByteField("apuInfo60", None),
+ ByteField("apuInfo61", None),
+ ByteField("apuInfo62", None),
+ ByteField("apuInfo63", None),
+ ByteField("apuInfo64", None),
+ ByteField("apuInfo65", None),
+ ByteField("apuInfo66", None),
+ ByteField("apuInfo67", None),
+ ByteField("apuInfo68", None),
+ ByteField("apuInfo69", None),
+ ByteField("apuInfo70", None),
+ ByteField("apuInfo71", None),
+ ByteField("apuInfo72", None),
+ ByteField("apuInfo73", None),
+ ByteField("apuInfo74", None),
+ ByteField("apuInfo75", None),
+ ByteField("apuInfo76", None),
+ ByteField("apuInfo77", None),
+ ByteField("apuInfo78", None),
+ ByteField("apuInfo79", None),
+ ByteField("apuInfo80", None),
+ ByteField("apuInfo81", None),
+ ByteField("apuInfo82", None),
+ ByteField("apuInfo83", None),
+ ByteField("apuInfo84", None),
+ ByteField("apuInfo85", None),
+ ByteField("apuInfo86", None),
+ ByteField("apuInfo87", None),
+ ByteField("apuInfo88", None),
+ ByteField("apuInfo89", None),
+ ByteField("apuInfo90", None),
+ ByteField("apuInfo91", None),
+ ByteField("apuInfo92", None),
+ ByteField("apuInfo93", None),
+ ByteField("apuInfo94", None),
+ ByteField("apuInfo95", None),
+ ByteField("apuInfo96", None),
+ ByteField("apuInfo97", None),
+ ByteField("apuInfo98", None),
+ ByteField("apuInfo99", None),
+ ByteField("apuInfo100", None),
+ ByteField("apuInfo101", None),
+ ByteField("apuInfo102", None),
+ ByteField("apuInfo103", None),
+ ByteField("apuInfo104", None),
+ ByteField("apuInfo105", None),
+ ByteField("apuInfo106", None),
+ ByteField("apuInfo107", None),
+ ByteField("apuInfo108", None),
+ ByteField("apuInfo109", None),
+ ByteField("apuInfo110", None),
+ ByteField("apuInfo111", None),
+ ByteField("apuInfo112", None),
+ ByteField("apuInfo113", None),
+ ByteField("apuInfo114", None),
+ ByteField("apuInfo115", None),
+ ByteField("apuInfo116", None),
+ ByteField("apuInfo117", None),
+ ByteField("apuInfo118", None),
+ ByteField("apuInfo119", None),
+ ByteField("apuInfo120", None),
+ ByteField("apuInfo121", None),
+ ByteField("apuInfo122", None),
+ ByteField("apuInfo123", None),
+ ByteField("apuInfo124", None),
+ ByteField("apuInfo125", None),
+ ByteField("apuInfo126", None),
+ ByteField("apuInfo127", None),
+ ByteField("apuInfo128", None),
+ ByteField("apuInfo129", None),
+ ByteField("apuInfo130", None),
+ ByteField("apuInfo131", None),
+ ByteField("apuInfo132", None),
+ ByteField("apuInfo133", None),
+ ByteField("apuInfo134", None),
+ ByteField("apuInfo135", None),
+ ByteField("apuInfo136", None),
+ ByteField("apuInfo137", None),
+ ByteField("apuInfo138", None),
+ ByteField("apuInfo139", None),
+ ByteField("apuInfo140", None),
+ ByteField("apuInfo141", None),
+ ByteField("apuInfo142", None),
+ ByteField("apuInfo143", None),
+ ByteField("apuInfo144", None),
+ ByteField("apuInfo145", None),
+ ByteField("apuInfo146", None),
+ ByteField("apuInfo147", None),
+ ByteField("apuInfo148", None),
+ ByteField("apuInfo149", None),
+ ByteField("apuInfo150", None),
+ ByteField("apuInfo151", None),
+ ByteField("apuInfo152", None),
+ ByteField("apuInfo153", None),
+ ByteField("apuInfo154", None),
+ ByteField("apuInfo155", None),
+ ByteField("apuInfo156", None),
+ ByteField("apuInfo157", None),
+ ByteField("apuInfo158", None),
+ ByteField("apuInfo159", None),
+ ByteField("apuInfo160", None),
+ ByteField("apuInfo161", None),
+ ByteField("apuInfo162", None),
+ ByteField("apuInfo163", None),
+ ByteField("apuInfo164", None),
+ ByteField("apuInfo165", None),
+ ByteField("apuInfo166", None),
+ ByteField("apuInfo167", None),
+ ByteField("apuInfo168", None),
+ ByteField("apuInfo169", None),
+ ByteField("apuInfo170", None),
+ ByteField("apuInfo171", None),
+ ByteField("apuInfo172", None),
+ ByteField("apuInfo173", None),
+ ByteField("apuInfo174", None),
+ ByteField("apuInfo175", None),
+ ByteField("apuInfo176", None),
+ ByteField("apuInfo177", None),
+ ByteField("apuInfo178", None),
+ ByteField("apuInfo179", None),
+ ByteField("apuInfo180", None),
+ ByteField("apuInfo181", None),
+ ByteField("apuInfo182", None),
+ ByteField("apuInfo183", None),
+ ByteField("apuInfo184", None),
+ ByteField("apuInfo185", None),
+ ByteField("apuInfo186", None),
+ ByteField("apuInfo187", None),
+ ByteField("apuInfo188", None),
+ ByteField("apuInfo189", None),
+ ByteField("apuInfo190", None),
+ ByteField("apuInfo191", None),
+ ByteField("apuInfo192", None),
+ ByteField("apuInfo193", None),
+ ByteField("apuInfo194", None),
+ ByteField("apuInfo195", None),
+ ByteField("apuInfo196", None),
+ ByteField("apuInfo197", None),
+ ByteField("apuInfo198", None),
+ ByteField("apuInfo199", None),
+ ByteField("apuInfo200", None),
+ ByteField("apuInfo201", None),
+ ByteField("apuInfo202", None),
+ ByteField("apuInfo203", None),
+ ByteField("apuInfo204", None),
+ ByteField("apuInfo205", None),
+ ByteField("apuInfo206", None),
+ ByteField("apuInfo207", None),
+ ByteField("apuInfo208", None),
+ ByteField("apuInfo209", None),
+ ByteField("apuInfo210", None),
+ ByteField("apuInfo211", None),
+ ByteField("apuInfo212", None),
+ ByteField("apuInfo213", None),
+ ByteField("apuInfo214", None),
+ ByteField("apuInfo215", None),
+ ByteField("apuInfo216", None),
+ ByteField("apuInfo217", None),
+ ByteField("apuInfo218", None),
+ ByteField("apuInfo219", None),
+ ByteField("apuInfo220", None),
+ ByteField("apuInfo221", None),
+ ByteField("apuInfo222", None),
+ ByteField("apuInfo223", None),
+ ByteField("apuInfo224", None),
+ ByteField("apuInfo225", None),
+ ByteField("apuInfo226", None),
+ ByteField("apuInfo227", None),
+ ByteField("apuInfo228", None),
+ ByteField("apuInfo229", None),
+ ByteField("apuInfo230", None),
+ ByteField("apuInfo231", None),
+ ByteField("apuInfo232", None),
+ ByteField("apuInfo233", None),
+ ByteField("apuInfo234", None),
+ ByteField("apuInfo235", None),
+ ByteField("apuInfo236", None),
+ ByteField("apuInfo237", None),
+ ByteField("apuInfo238", None),
+ ByteField("apuInfo239", None),
+ ByteField("apuInfo240", None),
+ ByteField("apuInfo241", None),
+ ByteField("apuInfo242", None),
+ ByteField("apuInfo243", None),
+ ByteField("apuInfo244", None),
+ ByteField("apuInfo245", None),
+ ByteField("apuInfo246", None),
+ ByteField("apuInfo247", None),
+ ByteField("apuInfo248", None),
+ ByteField("apuInfo249", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 251, a, self.fields_desc)
+ if self.lengthAD is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+#
+# 10.5.3 Mobility management information elements
+#
+
+
+class AuthenticationParameterRAND(Packet):
+ """Authentication parameter RAND Section 10.5.3.1"""
+ name = "Authentication Parameter Rand"
+ fields_desc = [
+ ByteField("ieiAPR", None),
+ BitField("randValue", 0x0, 128)
+ ]
+
+
+class AuthenticationParameterSRES(Packet):
+ """Authentication parameter SRES Section 10.5.3.2"""
+ name = "Authentication Parameter Sres"
+ fields_desc = [
+ ByteField("ieiAPS", None),
+ BitField("sresValue", 0x0, 40)
+ ]
+
+
+class CmServiceType(Packet):
+ """CM service type Section 10.5.3.3"""
+ name = "CM Service Type"
+ fields_desc = [
+ XBitField("ieiCST", 0x0, 4),
+ BitField("serviceType", 0x0, 4)
+ ]
+
+
+class CmServiceTypeAndCiphKeySeqNr(Packet):
+ name = "CM Service Type and Cipher Key Sequence Number"
+ fields_desc = [
+ BitField("keySeq", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("serviceType", 0x0, 4)
+ ]
+
+
+class IdentityType(Packet):
+ """Identity type Section 10.5.3.4"""
+ name = "Identity Type"
+ fields_desc = [
+ XBitField("ieiIT", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("idType", 0x1, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class IdentityTypeAndSpareHalfOctet(Packet):
+ name = "Identity Type and Spare Half Octet"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("idType", 0x1, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class LocationUpdatingType(Packet):
+ """Location updating type Section 10.5.3.5"""
+ name = "Location Updating Type"
+ fields_desc = [
+ XBitField("ieiLUT", 0x0, 4),
+ BitField("for", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("lut", 0x0, 2)
+ ]
+
+
+class LocationUpdatingTypeAndCiphKeySeqNr(Packet):
+ name = "Location Updating Type and Cipher Key Sequence Number"
+ fields_desc = [
+ BitField("for", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("lut", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3)
+ ]
+
+
+# len 3 to L3 max (251) (done)
+class NetworkNameHdr(Packet):
+ """Network Name Section 10.5.3.5a"""
+ name = "Network Name"
+ fields_desc = [
+ BitField("eightBitNN", None, 1),
+ XBitField("ieiNN", None, 7),
+
+ XByteField("lengthNN", None),
+
+ BitField("ext1", 0x1, 1),
+ BitField("codingScheme", 0x0, 3),
+ BitField("addCi", 0x0, 1),
+ BitField("nbSpare", 0x0, 3),
+ # optional
+ ByteField("txtString1", None),
+ ByteField("txtString2", None),
+ ByteField("txtString3", None),
+ ByteField("txtString4", None),
+ ByteField("txtString5", None),
+ ByteField("txtString6", None),
+ ByteField("txtString7", None),
+ ByteField("txtString8", None),
+ ByteField("txtString9", None),
+ ByteField("txtString10", None),
+ ByteField("txtString11", None),
+ ByteField("txtString12", None),
+ ByteField("txtString13", None),
+ ByteField("txtString14", None),
+ ByteField("txtString15", None),
+ ByteField("txtString16", None),
+ ByteField("txtString17", None),
+ ByteField("txtString18", None),
+ ByteField("txtString19", None),
+ ByteField("txtString20", None),
+ ByteField("txtString21", None),
+ ByteField("txtString22", None),
+ ByteField("txtString23", None),
+ ByteField("txtString24", None),
+ ByteField("txtString25", None),
+ ByteField("txtString26", None),
+ ByteField("txtString27", None),
+ ByteField("txtString28", None),
+ ByteField("txtString29", None),
+ ByteField("txtString30", None),
+ ByteField("txtString31", None),
+ ByteField("txtString32", None),
+ ByteField("txtString33", None),
+ ByteField("txtString34", None),
+ ByteField("txtString35", None),
+ ByteField("txtString36", None),
+ ByteField("txtString37", None),
+ ByteField("txtString38", None),
+ ByteField("txtString39", None),
+ ByteField("txtString40", None),
+ ByteField("txtString41", None),
+ ByteField("txtString42", None),
+ ByteField("txtString43", None),
+ ByteField("txtString44", None),
+ ByteField("txtString45", None),
+ ByteField("txtString46", None),
+ ByteField("txtString47", None),
+ ByteField("txtString48", None),
+ ByteField("txtString49", None),
+ ByteField("txtString50", None),
+ ByteField("txtString51", None),
+ ByteField("txtString52", None),
+ ByteField("txtString53", None),
+ ByteField("txtString54", None),
+ ByteField("txtString55", None),
+ ByteField("txtString56", None),
+ ByteField("txtString57", None),
+ ByteField("txtString58", None),
+ ByteField("txtString59", None),
+ ByteField("txtString60", None),
+ ByteField("txtString61", None),
+ ByteField("txtString62", None),
+ ByteField("txtString63", None),
+ ByteField("txtString64", None),
+ ByteField("txtString65", None),
+ ByteField("txtString66", None),
+ ByteField("txtString67", None),
+ ByteField("txtString68", None),
+ ByteField("txtString69", None),
+ ByteField("txtString70", None),
+ ByteField("txtString71", None),
+ ByteField("txtString72", None),
+ ByteField("txtString73", None),
+ ByteField("txtString74", None),
+ ByteField("txtString75", None),
+ ByteField("txtString76", None),
+ ByteField("txtString77", None),
+ ByteField("txtString78", None),
+ ByteField("txtString79", None),
+ ByteField("txtString80", None),
+ ByteField("txtString81", None),
+ ByteField("txtString82", None),
+ ByteField("txtString83", None),
+ ByteField("txtString84", None),
+ ByteField("txtString85", None),
+ ByteField("txtString86", None),
+ ByteField("txtString87", None),
+ ByteField("txtString88", None),
+ ByteField("txtString89", None),
+ ByteField("txtString90", None),
+ ByteField("txtString91", None),
+ ByteField("txtString92", None),
+ ByteField("txtString93", None),
+ ByteField("txtString94", None),
+ ByteField("txtString95", None),
+ ByteField("txtString96", None),
+ ByteField("txtString97", None),
+ ByteField("txtString98", None),
+ ByteField("txtString99", None),
+ ByteField("txtString100", None),
+ ByteField("txtString101", None),
+ ByteField("txtString102", None),
+ ByteField("txtString103", None),
+ ByteField("txtString104", None),
+ ByteField("txtString105", None),
+ ByteField("txtString106", None),
+ ByteField("txtString107", None),
+ ByteField("txtString108", None),
+ ByteField("txtString109", None),
+ ByteField("txtString110", None),
+ ByteField("txtString111", None),
+ ByteField("txtString112", None),
+ ByteField("txtString113", None),
+ ByteField("txtString114", None),
+ ByteField("txtString115", None),
+ ByteField("txtString116", None),
+ ByteField("txtString117", None),
+ ByteField("txtString118", None),
+ ByteField("txtString119", None),
+ ByteField("txtString120", None),
+ ByteField("txtString121", None),
+ ByteField("txtString122", None),
+ ByteField("txtString123", None),
+ ByteField("txtString124", None),
+ ByteField("txtString125", None),
+ ByteField("txtString126", None),
+ ByteField("txtString127", None),
+ ByteField("txtString128", None),
+ ByteField("txtString129", None),
+ ByteField("txtString130", None),
+ ByteField("txtString131", None),
+ ByteField("txtString132", None),
+ ByteField("txtString133", None),
+ ByteField("txtString134", None),
+ ByteField("txtString135", None),
+ ByteField("txtString136", None),
+ ByteField("txtString137", None),
+ ByteField("txtString138", None),
+ ByteField("txtString139", None),
+ ByteField("txtString140", None),
+ ByteField("txtString141", None),
+ ByteField("txtString142", None),
+ ByteField("txtString143", None),
+ ByteField("txtString144", None),
+ ByteField("txtString145", None),
+ ByteField("txtString146", None),
+ ByteField("txtString147", None),
+ ByteField("txtString148", None),
+ ByteField("txtString149", None),
+ ByteField("txtString150", None),
+ ByteField("txtString151", None),
+ ByteField("txtString152", None),
+ ByteField("txtString153", None),
+ ByteField("txtString154", None),
+ ByteField("txtString155", None),
+ ByteField("txtString156", None),
+ ByteField("txtString157", None),
+ ByteField("txtString158", None),
+ ByteField("txtString159", None),
+ ByteField("txtString160", None),
+ ByteField("txtString161", None),
+ ByteField("txtString162", None),
+ ByteField("txtString163", None),
+ ByteField("txtString164", None),
+ ByteField("txtString165", None),
+ ByteField("txtString166", None),
+ ByteField("txtString167", None),
+ ByteField("txtString168", None),
+ ByteField("txtString169", None),
+ ByteField("txtString170", None),
+ ByteField("txtString171", None),
+ ByteField("txtString172", None),
+ ByteField("txtString173", None),
+ ByteField("txtString174", None),
+ ByteField("txtString175", None),
+ ByteField("txtString176", None),
+ ByteField("txtString177", None),
+ ByteField("txtString178", None),
+ ByteField("txtString179", None),
+ ByteField("txtString180", None),
+ ByteField("txtString181", None),
+ ByteField("txtString182", None),
+ ByteField("txtString183", None),
+ ByteField("txtString184", None),
+ ByteField("txtString185", None),
+ ByteField("txtString186", None),
+ ByteField("txtString187", None),
+ ByteField("txtString188", None),
+ ByteField("txtString189", None),
+ ByteField("txtString190", None),
+ ByteField("txtString191", None),
+ ByteField("txtString192", None),
+ ByteField("txtString193", None),
+ ByteField("txtString194", None),
+ ByteField("txtString195", None),
+ ByteField("txtString196", None),
+ ByteField("txtString197", None),
+ ByteField("txtString198", None),
+ ByteField("txtString199", None),
+ ByteField("txtString200", None),
+ ByteField("txtString201", None),
+ ByteField("txtString202", None),
+ ByteField("txtString203", None),
+ ByteField("txtString204", None),
+ ByteField("txtString205", None),
+ ByteField("txtString206", None),
+ ByteField("txtString207", None),
+ ByteField("txtString208", None),
+ ByteField("txtString209", None),
+ ByteField("txtString210", None),
+ ByteField("txtString211", None),
+ ByteField("txtString212", None),
+ ByteField("txtString213", None),
+ ByteField("txtString214", None),
+ ByteField("txtString215", None),
+ ByteField("txtString216", None),
+ ByteField("txtString217", None),
+ ByteField("txtString218", None),
+ ByteField("txtString219", None),
+ ByteField("txtString220", None),
+ ByteField("txtString221", None),
+ ByteField("txtString222", None),
+ ByteField("txtString223", None),
+ ByteField("txtString224", None),
+ ByteField("txtString225", None),
+ ByteField("txtString226", None),
+ ByteField("txtString227", None),
+ ByteField("txtString228", None),
+ ByteField("txtString229", None),
+ ByteField("txtString230", None),
+ ByteField("txtString231", None),
+ ByteField("txtString232", None),
+ ByteField("txtString233", None),
+ ByteField("txtString234", None),
+ ByteField("txtString235", None),
+ ByteField("txtString236", None),
+ ByteField("txtString237", None),
+ ByteField("txtString238", None),
+ ByteField("txtString239", None),
+ ByteField("txtString240", None),
+ ByteField("txtString241", None),
+ ByteField("txtString242", None),
+ ByteField("txtString243", None),
+ ByteField("txtString244", None),
+ ByteField("txtString245", None),
+ ByteField("txtString246", None),
+ ByteField("txtString247", None),
+ ByteField("txtString248", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 251, a, self.fields_desc)
+ if self.lengthNN is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class RejectCause(Packet):
+ """Reject cause Section 10.5.3.6"""
+ name = "Reject Cause"
+ fields_desc = [
+ ByteField("ieiRC", 0x0),
+ ByteField("rejCause", 0x0)
+ ]
+
+
+class FollowOnProceed(Packet):
+ """Follow-on Proceed Section 10.5.3.7"""
+ name = "Follow-on Proceed"
+ fields_desc = [
+ ByteField("ieiFOP", 0x0),
+ ]
+
+
+class TimeZoneHdr(Packet):
+ """Time Zone Section 10.5.3.8"""
+ name = "Time Zone"
+ fields_desc = [
+ BitField("eightBitTZ", None, 1),
+ XBitField("ieiTZ", None, 7),
+ ByteField("timeZone", 0x0),
+ ]
+
+
+class TimeZoneAndTimeHdr(Packet):
+ """Time Zone and Time Section 10.5.3.9"""
+ name = "Time Zone and Time"
+ fields_desc = [
+ BitField("eightBitTZAT", None, 1),
+ XBitField("ieiTZAT", None, 7),
+ ByteField("year", 0x0),
+ ByteField("month", 0x0),
+ ByteField("day", 0x0),
+ ByteField("hour", 0x0),
+ ByteField("minute", 0x0),
+ ByteField("second", 0x0),
+ ByteField("timeZone", 0x0)
+ ]
+
+
+class CtsPermissionHdr(Packet):
+ """CTS permission Section 10.5.3.10"""
+ name = "Cts Permission"
+ fields_desc = [
+ BitField("eightBitCP", None, 1),
+ XBitField("ieiCP", None, 7),
+ ]
+
+
+class LsaIdentifierHdr(Packet):
+ """LSA Identifier Section 10.5.3.11"""
+ name = "Lsa Identifier"
+ fields_desc = [
+ BitField("eightBitLI", None, 1),
+ XBitField("ieiLI", None, 7),
+ ByteField("lsaID", 0x0),
+ ByteField("lsaID1", 0x0),
+ ByteField("lsaID2", 0x0)
+ ]
+
+
+#
+# 10.5.4 Call control information elements
+#
+
+#10.5.4.1 Extensions of codesets
+# This is only text and no packet
+
+class LockingShiftProcedureHdr(Packet):
+ """Locking shift procedure Section 10.5.4.2"""
+ name = "Locking Shift Procedure"
+ fields_desc = [
+ XBitField("ieiLSP", None, 4),
+ BitField("lockShift", 0x0, 1),
+ BitField("codesetId", 0x0, 3)
+ ]
+
+
+class NonLockingShiftProcedureHdr(Packet):
+ """Non-locking shift procedure Section 10.5.4.3"""
+ name = "Non-locking Shift Procedure"
+ fields_desc = [
+ XBitField("ieiNLSP", None, 4),
+ BitField("nonLockShift", 0x1, 1),
+ BitField("codesetId", 0x0, 3)
+ ]
+
+
+class AuxiliaryStatesHdr(Packet):
+ """Auxiliary states Section 10.5.4.4"""
+ name = "Auxiliary States"
+ fields_desc = [
+ BitField("eightBitAS", None, 1),
+ XBitField("ieiAS", None, 7),
+ XByteField("lengthAS", 0x3),
+ BitField("ext", 0x1, 1),
+ BitField("spare", 0x0, 3),
+ BitField("holdState", 0x0, 2),
+ BitField("mptyState", 0x0, 2)
+ ]
+
+
+# len 3 to 15
+class BearerCapabilityHdr(Packet):
+ """Bearer capability Section 10.5.4.5"""
+ name = "Bearer Capability"
+ fields_desc = [
+ BitField("eightBitBC", None, 1),
+ XBitField("ieiBC", None, 7),
+
+ XByteField("lengthBC", None),
+
+ BitField("ext0", 0x1, 1),
+ BitField("radioChReq", 0x1, 2),
+ BitField("codingStd", 0x0, 1),
+ BitField("transMode", 0x0, 1),
+ BitField("infoTransCa", 0x0, 3),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("coding", None, 1),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("spare", None, 2),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("speechVers", 0x0, 4),
+ lambda pkt: pkt.ext0 == 0),
+
+ ConditionalField(BitField("ext2", 0x1, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("compress", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("structure", None, 2),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("dupMode", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("config", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("nirr", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("establi", 0x0, 1),
+ lambda pkt: pkt.ext1 == 0),
+
+ BitField("ext3", None, 1),
+ BitField("accessId", None, 2),
+ BitField("rateAda", None, 2),
+ BitField("signaling", None, 3),
+
+ ConditionalField(BitField("ext4", None, 1),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("otherITC", None, 2),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("otherRate", None, 2),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("spare1", 0x0, 3),
+ lambda pkt: pkt.ext3 == 0),
+
+ ConditionalField(BitField("ext5", 0x1, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("hdr", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("multiFr", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("mode", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("lli", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("assig", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("inbNeg", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("spare2", 0x0, 1),
+ lambda pkt: pkt.ext4 == 0),
+
+ BitField("ext6", None, 1),
+ BitField("layer1Id", None, 2),
+ BitField("userInf", None, 4),
+ BitField("sync", None, 1),
+
+ ConditionalField(BitField("ext7", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("stopBit", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("negoc", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("nbDataBit", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("userRate", None, 4),
+ lambda pkt: pkt.ext6 == 0),
+
+ ConditionalField(BitField("ext8", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("interRate", None, 2),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("nicTX", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("nicRX", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("parity", None, 3),
+ lambda pkt: pkt.ext7 == 0),
+
+ ConditionalField(BitField("ext9", None, 1),
+ lambda pkt: pkt.ext8 == 0),
+ ConditionalField(BitField("connEle", None, 2),
+ lambda pkt: pkt.ext8 == 0),
+ ConditionalField(BitField("modemType", None, 5),
+ lambda pkt: pkt.ext8 == 0),
+
+ ConditionalField(BitField("ext10", None, 1),
+ lambda pkt: pkt.ext9 == 0),
+ ConditionalField(BitField("otherModemType", None, 2),
+ lambda pkt: pkt.ext9 == 0),
+ ConditionalField(BitField("netUserRate", None, 5),
+ lambda pkt: pkt.ext9 == 0),
+
+ ConditionalField(BitField("ext11", None, 1),
+ lambda pkt: pkt.ext10 == 0),
+ ConditionalField(BitField("chanCoding", None, 4),
+ lambda pkt: pkt.ext10 == 0),
+ ConditionalField(BitField("maxTrafficChan", None, 3),
+ lambda pkt: pkt.ext10 == 0),
+
+ ConditionalField(BitField("ext12", None, 1),
+ lambda pkt: pkt.ext11 == 0),
+ ConditionalField(BitField("uimi", None, 3),
+ lambda pkt: pkt.ext11 == 0),
+ ConditionalField(BitField("airInterfaceUserRate", None, 4),
+ lambda pkt: pkt.ext11 == 0),
+
+ ConditionalField(BitField("ext13", 0x1, 1),
+ lambda pkt: pkt.ext12 == 0),
+ ConditionalField(BitField("layer2Ch", None, 2),
+ lambda pkt: pkt.ext12 == 0),
+ ConditionalField(BitField("userInfoL2", 0x0, 5),
+ lambda pkt: pkt.ext12 == 0)
+ ]
+
+# We have a bug here. packet is not working if used in message
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 15, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ # avoids a bug. find better way
+ if len(p) is 5:
+ p = p[:-2]
+ if self.lengthBC is None:
+ print("len von a %s" % (len(p),))
+ p = p[:1] + struct.pack(">B", len(p)-3) + p[2:]
+ return p + pay
+
+
+class CallControlCapabilitiesHdr(Packet):
+ """Call Control Capabilities Section 10.5.4.5a"""
+ name = "Call Control Capabilities"
+ fields_desc = [
+ BitField("eightBitCCC", None, 1),
+ XBitField("ieiCCC", None, 7),
+ XByteField("lengthCCC", 0x3),
+ BitField("spare", 0x0, 6),
+ BitField("pcp", 0x0, 1),
+ BitField("dtmf", 0x0, 1)
+ ]
+
+
+class CallStateHdr(Packet):
+ """Call State Section 10.5.4.6"""
+ name = "Call State"
+ fields_desc = [
+ BitField("eightBitCS", None, 1),
+ XBitField("ieiCS", None, 7),
+ BitField("codingStd", 0x0, 2),
+ BitField("stateValue", 0x0, 6)
+ ]
+
+
+# len 3 to 43
+class CalledPartyBcdNumberHdr(Packet):
+ """Called party BCD number Section 10.5.4.7"""
+ name = "Called Party BCD Number"
+ fields_desc = [
+ BitField("eightBitCPBN", None, 1),
+ XBitField("ieiCPBN", None, 7),
+ XByteField("lengthCPBN", None),
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("nbPlanId", 0x0, 4),
+ # optional
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+
+ BitField("nbDigit22", None, 4),
+ BitField("nbDigit21", None, 4),
+ BitField("nbDigit24", None, 4),
+ BitField("nbDigit23", None, 4),
+
+ BitField("nbDigit26", None, 4),
+ BitField("nbDigit25", None, 4),
+ BitField("nbDigit28", None, 4),
+ BitField("nbDigit27", None, 4),
+
+ BitField("nbDigit30", None, 4),
+ BitField("nbDigit29", None, 4),
+ BitField("nbDigit32", None, 4),
+ BitField("nbDigit31", None, 4),
+
+ BitField("nbDigit34", None, 4),
+ BitField("nbDigit33", None, 4),
+ BitField("nbDigit36", None, 4),
+ BitField("nbDigit35", None, 4),
+
+ BitField("nbDigit38", None, 4),
+ BitField("nbDigit37", None, 4),
+ BitField("nbDigit40", None, 4),
+ BitField("nbDigit39", None, 4),
+# ^^^^^^ 20 first optional bytes ^^^^^^^^^^^^^^^
+ BitField("nbDigit42", None, 4),
+ BitField("nbDigit41", None, 4),
+ BitField("nbDigit44", None, 4),
+ BitField("nbDigit43", None, 4),
+
+ BitField("nbDigit46", None, 4),
+ BitField("nbDigit45", None, 4),
+ BitField("nbDigit48", None, 4),
+ BitField("nbDigit47", None, 4),
+
+ BitField("nbDigit50", None, 4),
+ BitField("nbDigit49", None, 4),
+ BitField("nbDigit52", None, 4),
+ BitField("nbDigit51", None, 4),
+
+ BitField("nbDigit54", None, 4),
+ BitField("nbDigit53", None, 4),
+ BitField("nbDigit56", None, 4),
+ BitField("nbDigit55", None, 4),
+
+ BitField("nbDigit58", None, 4),
+ BitField("nbDigit57", None, 4),
+ BitField("nbDigit60", None, 4),
+ BitField("nbDigit59", None, 4),
+
+ BitField("nbDigit62", None, 4),
+ BitField("nbDigit61", None, 4),
+ BitField("nbDigit64", None, 4),
+ BitField("nbDigit63", None, 4),
+
+ BitField("nbDigit66", None, 4),
+ BitField("nbDigit65", None, 4),
+ BitField("nbDigit68", None, 4),
+ BitField("nbDigit67", None, 4),
+
+ BitField("nbDigit70", None, 4),
+ BitField("nbDigit69", None, 4),
+ BitField("nbDigit72", None, 4),
+ BitField("nbDigit71", None, 4),
+
+ BitField("nbDigit74", None, 4),
+ BitField("nbDigit73", None, 4),
+ BitField("nbDigit76", None, 4),
+ BitField("nbDigit75", None, 4),
+
+ BitField("nbDigit78", None, 4),
+ BitField("nbDigit77", None, 4),
+ BitField("nbDigit80", None, 4),
+ BitField("nbDigit79", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 43, a, self.fields_desc, 2)
+ if self.lengthCPBN is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 2 to 23
+class CalledPartySubaddressHdr(Packet):
+ """Called party subaddress Section 10.5.4.8"""
+ name = "Called Party Subaddress"
+ fields_desc = [
+ BitField("eightBitCPS", None, 1),
+ XBitField("ieiCPS", None, 7),
+ XByteField("lengthCPS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("subAddr", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 23, a, self.fields_desc)
+ if self.lengthCPS is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 3 to 14
+class CallingPartyBcdNumberHdr(Packet):
+ """Called party subaddress Section 10.5.4.9"""
+ name = "Called Party Subaddress"
+ fields_desc = [
+ BitField("eightBitCPBN", None, 1),
+ XBitField("ieiCPBN", None, 7),
+ XByteField("lengthCPBN", None),
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("nbPlanId", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", None, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", None, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", 0x0, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 14, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthCPBN is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+
+
+# len 2 to 23
+class CallingPartySubaddressHdr(Packet):
+ """Calling party subaddress Section 10.5.4.10"""
+ name = "Calling Party Subaddress"
+ fields_desc = [
+ BitField("eightBitCPS", None, 1),
+ XBitField("ieiCPS", None, 7),
+ XByteField("lengthCPS", None),
+ # optional
+ BitField("ext1", None, 1),
+ BitField("typeAddr", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 23, a, self.fields_desc)
+ if self.lengthCPS is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 4 to 32
+class CauseHdr(Packet):
+ """Cause Section 10.5.4.11"""
+ name = "Cause"
+ fields_desc = [
+ BitField("eightBitC", None, 1),
+ XBitField("ieiC", None, 7),
+
+ XByteField("lengthC", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("codingStd", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("location", 0x0, 4),
+
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("recommendation", 0x0, 7),
+ lambda pkt: pkt.ext == 0),
+ # optional
+ BitField("ext2", None, 1),
+ BitField("causeValue", None, 7),
+
+ ByteField("diagnositc0", None),
+ ByteField("diagnositc1", None),
+ ByteField("diagnositc2", None),
+ ByteField("diagnositc3", None),
+ ByteField("diagnositc4", None),
+ ByteField("diagnositc5", None),
+ ByteField("diagnositc6", None),
+ ByteField("diagnositc7", None),
+ ByteField("diagnositc8", None),
+ ByteField("diagnositc9", None),
+ ByteField("diagnositc10", None),
+ ByteField("diagnositc11", None),
+ ByteField("diagnositc12", None),
+ ByteField("diagnositc13", None),
+ ByteField("diagnositc14", None),
+ ByteField("diagnositc15", None),
+ ByteField("diagnositc16", None),
+ ByteField("diagnositc17", None),
+ ByteField("diagnositc18", None),
+ ByteField("diagnositc19", None),
+ ByteField("diagnositc20", None),
+ ByteField("diagnositc21", None),
+ ByteField("diagnositc22", None),
+ ByteField("diagnositc23", None),
+ ByteField("diagnositc24", None),
+ ByteField("diagnositc25", None),
+ ByteField("diagnositc26", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 32, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthC is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+
+
+class ClirSuppressionHdr(Packet):
+ """CLIR suppression Section 10.5.4.11a"""
+ name = "Clir Suppression"
+ fields_desc = [
+ BitField("eightBitCS", None, 1),
+ XBitField("ieiCS", None, 7),
+ ]
+
+
+class ClirInvocationHdr(Packet):
+ """CLIR invocation Section 10.5.4.11b"""
+ name = "Clir Invocation"
+ fields_desc = [
+ BitField("eightBitCI", None, 1),
+ XBitField("ieiCI", None, 7),
+ ]
+
+
+class CongestionLevelHdr(Packet):
+ """Congestion level Section 10.5.4.12"""
+ name = "Congestion Level"
+ fields_desc = [
+ XBitField("ieiCL", None, 4),
+ BitField("notDef", 0x0, 4)
+ ]
+
+
+# Fix 1/2 len problem
+class CongestionLevelAndSpareHalfOctets(Packet):
+ name = "Congestion Level and Spare Half Octets"
+ fields_desc = [
+ BitField("ieiCL", 0x0, 4),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+# len 3 to 14
+class ConnectedNumberHdr(Packet):
+ """Connected number Section 10.5.4.13"""
+ name = "Connected Number"
+ fields_desc = [
+ BitField("eightBitCN", None, 1),
+ XBitField("ieiCN", None, 7),
+
+ XByteField("lengthCN", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("typePlanId", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", None, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", None, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", None, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ sum1 = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 14, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthCN is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+
+
+# len 2 to 23
+class ConnectedSubaddressHdr(Packet):
+ """Connected subaddress Section 10.5.4.14"""
+ name = "Connected Subaddress"
+ fields_desc = [
+ BitField("eightBitCS", None, 1),
+ XBitField("ieiCS", None, 7),
+
+ XByteField("lengthCS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("typeOfSub", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 23, a, self.fields_desc)
+ if self.lengthCS is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 2 to L3 (251) (done)
+class FacilityHdr(Packet):
+ """Facility Section 10.5.4.15"""
+ name = "Facility"
+ fields_desc = [
+ BitField("eightBitF", None, 1),
+ XBitField("ieiF", None, 7),
+ XByteField("lengthF", None),
+ # optional
+ ByteField("facilityInfo1", None),
+ ByteField("facilityInfo2", None),
+ ByteField("facilityInfo3", None),
+ ByteField("facilityInfo4", None),
+ ByteField("facilityInfo5", None),
+ ByteField("facilityInfo6", None),
+ ByteField("facilityInfo7", None),
+ ByteField("facilityInfo8", None),
+ ByteField("facilityInfo9", None),
+ ByteField("facilityInfo10", None),
+ ByteField("facilityInfo11", None),
+ ByteField("facilityInfo12", None),
+ ByteField("facilityInfo13", None),
+ ByteField("facilityInfo14", None),
+ ByteField("facilityInfo15", None),
+ ByteField("facilityInfo16", None),
+ ByteField("facilityInfo17", None),
+ ByteField("facilityInfo18", None),
+ ByteField("facilityInfo19", None),
+ ByteField("facilityInfo20", None),
+ ByteField("facilityInfo21", None),
+ ByteField("facilityInfo22", None),
+ ByteField("facilityInfo23", None),
+ ByteField("facilityInfo24", None),
+ ByteField("facilityInfo25", None),
+ ByteField("facilityInfo26", None),
+ ByteField("facilityInfo27", None),
+ ByteField("facilityInfo28", None),
+ ByteField("facilityInfo29", None),
+ ByteField("facilityInfo30", None),
+ ByteField("facilityInfo31", None),
+ ByteField("facilityInfo32", None),
+ ByteField("facilityInfo33", None),
+ ByteField("facilityInfo34", None),
+ ByteField("facilityInfo35", None),
+ ByteField("facilityInfo36", None),
+ ByteField("facilityInfo37", None),
+ ByteField("facilityInfo38", None),
+ ByteField("facilityInfo39", None),
+ ByteField("facilityInfo40", None),
+ ByteField("facilityInfo41", None),
+ ByteField("facilityInfo42", None),
+ ByteField("facilityInfo43", None),
+ ByteField("facilityInfo44", None),
+ ByteField("facilityInfo45", None),
+ ByteField("facilityInfo46", None),
+ ByteField("facilityInfo47", None),
+ ByteField("facilityInfo48", None),
+ ByteField("facilityInfo49", None),
+ ByteField("facilityInfo50", None),
+ ByteField("facilityInfo51", None),
+ ByteField("facilityInfo52", None),
+ ByteField("facilityInfo53", None),
+ ByteField("facilityInfo54", None),
+ ByteField("facilityInfo55", None),
+ ByteField("facilityInfo56", None),
+ ByteField("facilityInfo57", None),
+ ByteField("facilityInfo58", None),
+ ByteField("facilityInfo59", None),
+ ByteField("facilityInfo60", None),
+ ByteField("facilityInfo61", None),
+ ByteField("facilityInfo62", None),
+ ByteField("facilityInfo63", None),
+ ByteField("facilityInfo64", None),
+ ByteField("facilityInfo65", None),
+ ByteField("facilityInfo66", None),
+ ByteField("facilityInfo67", None),
+ ByteField("facilityInfo68", None),
+ ByteField("facilityInfo69", None),
+ ByteField("facilityInfo70", None),
+ ByteField("facilityInfo71", None),
+ ByteField("facilityInfo72", None),
+ ByteField("facilityInfo73", None),
+ ByteField("facilityInfo74", None),
+ ByteField("facilityInfo75", None),
+ ByteField("facilityInfo76", None),
+ ByteField("facilityInfo77", None),
+ ByteField("facilityInfo78", None),
+ ByteField("facilityInfo79", None),
+ ByteField("facilityInfo80", None),
+ ByteField("facilityInfo81", None),
+ ByteField("facilityInfo82", None),
+ ByteField("facilityInfo83", None),
+ ByteField("facilityInfo84", None),
+ ByteField("facilityInfo85", None),
+ ByteField("facilityInfo86", None),
+ ByteField("facilityInfo87", None),
+ ByteField("facilityInfo88", None),
+ ByteField("facilityInfo89", None),
+ ByteField("facilityInfo90", None),
+ ByteField("facilityInfo91", None),
+ ByteField("facilityInfo92", None),
+ ByteField("facilityInfo93", None),
+ ByteField("facilityInfo94", None),
+ ByteField("facilityInfo95", None),
+ ByteField("facilityInfo96", None),
+ ByteField("facilityInfo97", None),
+ ByteField("facilityInfo98", None),
+ ByteField("facilityInfo99", None),
+ ByteField("facilityInfo100", None),
+ ByteField("facilityInfo101", None),
+ ByteField("facilityInfo102", None),
+ ByteField("facilityInfo103", None),
+ ByteField("facilityInfo104", None),
+ ByteField("facilityInfo105", None),
+ ByteField("facilityInfo106", None),
+ ByteField("facilityInfo107", None),
+ ByteField("facilityInfo108", None),
+ ByteField("facilityInfo109", None),
+ ByteField("facilityInfo110", None),
+ ByteField("facilityInfo111", None),
+ ByteField("facilityInfo112", None),
+ ByteField("facilityInfo113", None),
+ ByteField("facilityInfo114", None),
+ ByteField("facilityInfo115", None),
+ ByteField("facilityInfo116", None),
+ ByteField("facilityInfo117", None),
+ ByteField("facilityInfo118", None),
+ ByteField("facilityInfo119", None),
+ ByteField("facilityInfo120", None),
+ ByteField("facilityInfo121", None),
+ ByteField("facilityInfo122", None),
+ ByteField("facilityInfo123", None),
+ ByteField("facilityInfo124", None),
+ ByteField("facilityInfo125", None),
+ ByteField("facilityInfo126", None),
+ ByteField("facilityInfo127", None),
+ ByteField("facilityInfo128", None),
+ ByteField("facilityInfo129", None),
+ ByteField("facilityInfo130", None),
+ ByteField("facilityInfo131", None),
+ ByteField("facilityInfo132", None),
+ ByteField("facilityInfo133", None),
+ ByteField("facilityInfo134", None),
+ ByteField("facilityInfo135", None),
+ ByteField("facilityInfo136", None),
+ ByteField("facilityInfo137", None),
+ ByteField("facilityInfo138", None),
+ ByteField("facilityInfo139", None),
+ ByteField("facilityInfo140", None),
+ ByteField("facilityInfo141", None),
+ ByteField("facilityInfo142", None),
+ ByteField("facilityInfo143", None),
+ ByteField("facilityInfo144", None),
+ ByteField("facilityInfo145", None),
+ ByteField("facilityInfo146", None),
+ ByteField("facilityInfo147", None),
+ ByteField("facilityInfo148", None),
+ ByteField("facilityInfo149", None),
+ ByteField("facilityInfo150", None),
+ ByteField("facilityInfo151", None),
+ ByteField("facilityInfo152", None),
+ ByteField("facilityInfo153", None),
+ ByteField("facilityInfo154", None),
+ ByteField("facilityInfo155", None),
+ ByteField("facilityInfo156", None),
+ ByteField("facilityInfo157", None),
+ ByteField("facilityInfo158", None),
+ ByteField("facilityInfo159", None),
+ ByteField("facilityInfo160", None),
+ ByteField("facilityInfo161", None),
+ ByteField("facilityInfo162", None),
+ ByteField("facilityInfo163", None),
+ ByteField("facilityInfo164", None),
+ ByteField("facilityInfo165", None),
+ ByteField("facilityInfo166", None),
+ ByteField("facilityInfo167", None),
+ ByteField("facilityInfo168", None),
+ ByteField("facilityInfo169", None),
+ ByteField("facilityInfo170", None),
+ ByteField("facilityInfo171", None),
+ ByteField("facilityInfo172", None),
+ ByteField("facilityInfo173", None),
+ ByteField("facilityInfo174", None),
+ ByteField("facilityInfo175", None),
+ ByteField("facilityInfo176", None),
+ ByteField("facilityInfo177", None),
+ ByteField("facilityInfo178", None),
+ ByteField("facilityInfo179", None),
+ ByteField("facilityInfo180", None),
+ ByteField("facilityInfo181", None),
+ ByteField("facilityInfo182", None),
+ ByteField("facilityInfo183", None),
+ ByteField("facilityInfo184", None),
+ ByteField("facilityInfo185", None),
+ ByteField("facilityInfo186", None),
+ ByteField("facilityInfo187", None),
+ ByteField("facilityInfo188", None),
+ ByteField("facilityInfo189", None),
+ ByteField("facilityInfo190", None),
+ ByteField("facilityInfo191", None),
+ ByteField("facilityInfo192", None),
+ ByteField("facilityInfo193", None),
+ ByteField("facilityInfo194", None),
+ ByteField("facilityInfo195", None),
+ ByteField("facilityInfo196", None),
+ ByteField("facilityInfo197", None),
+ ByteField("facilityInfo198", None),
+ ByteField("facilityInfo199", None),
+ ByteField("facilityInfo200", None),
+ ByteField("facilityInfo201", None),
+ ByteField("facilityInfo202", None),
+ ByteField("facilityInfo203", None),
+ ByteField("facilityInfo204", None),
+ ByteField("facilityInfo205", None),
+ ByteField("facilityInfo206", None),
+ ByteField("facilityInfo207", None),
+ ByteField("facilityInfo208", None),
+ ByteField("facilityInfo209", None),
+ ByteField("facilityInfo210", None),
+ ByteField("facilityInfo211", None),
+ ByteField("facilityInfo212", None),
+ ByteField("facilityInfo213", None),
+ ByteField("facilityInfo214", None),
+ ByteField("facilityInfo215", None),
+ ByteField("facilityInfo216", None),
+ ByteField("facilityInfo217", None),
+ ByteField("facilityInfo218", None),
+ ByteField("facilityInfo219", None),
+ ByteField("facilityInfo220", None),
+ ByteField("facilityInfo221", None),
+ ByteField("facilityInfo222", None),
+ ByteField("facilityInfo223", None),
+ ByteField("facilityInfo224", None),
+ ByteField("facilityInfo225", None),
+ ByteField("facilityInfo226", None),
+ ByteField("facilityInfo227", None),
+ ByteField("facilityInfo228", None),
+ ByteField("facilityInfo229", None),
+ ByteField("facilityInfo230", None),
+ ByteField("facilityInfo231", None),
+ ByteField("facilityInfo232", None),
+ ByteField("facilityInfo233", None),
+ ByteField("facilityInfo234", None),
+ ByteField("facilityInfo235", None),
+ ByteField("facilityInfo236", None),
+ ByteField("facilityInfo237", None),
+ ByteField("facilityInfo238", None),
+ ByteField("facilityInfo239", None),
+ ByteField("facilityInfo240", None),
+ ByteField("facilityInfo241", None),
+ ByteField("facilityInfo242", None),
+ ByteField("facilityInfo243", None),
+ ByteField("facilityInfo244", None),
+ ByteField("facilityInfo245", None),
+ ByteField("facilityInfo246", None),
+ ByteField("facilityInfo247", None),
+ ByteField("facilityInfo248", None),
+ ByteField("facilityInfo249", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 251, a, self.fields_desc)
+ if self.lengthF is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+#len 2 to 5
+class HighLayerCompatibilityHdr(Packet):
+ """High layer compatibility Section 10.5.4.16"""
+ name = "High Layer Compatibility"
+ fields_desc = [
+ BitField("eightBitHLC", None, 1),
+ XBitField("ieiHLC", None, 7),
+
+ XByteField("lengthHLC", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("codingStd", None, 2),
+ BitField("interpret", None, 3),
+ BitField("presMeth", None, 2),
+
+ BitField("ext1", None, 1),
+ BitField("highLayerId", None, 7),
+
+ ConditionalField(BitField("ext2", 0x1, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("exHiLayerId", 0x0, 7),
+ lambda pkt: pkt.ext1 == 0)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 5, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthHLC is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+#
+# 10.5.4.16.1 Static conditions for the high layer
+# compatibility IE contents
+#
+
+
+class KeypadFacilityHdr(Packet):
+ """Keypad facility Section 10.5.4.17"""
+ name = "Keypad Facility"
+ fields_desc = [
+ BitField("eightBitKF", None, 1),
+ XBitField("ieiKF", None, 7),
+ BitField("spare", 0x0, 1),
+ BitField("keyPadInfo", 0x0, 7)
+ ]
+
+
+# len 2 to 15
+class LowLayerCompatibilityHdr(Packet):
+ """Low layer compatibility Section 10.5.4.18"""
+ name = "Low Layer Compatibility"
+ fields_desc = [
+ BitField("eightBitLLC", None, 1),
+ XBitField("ieiLLC", None, 7),
+
+ XByteField("lengthLLC", None),
+ # optional
+ ByteField("rest0", None),
+ ByteField("rest1", None),
+ ByteField("rest2", None),
+ ByteField("rest3", None),
+ ByteField("rest4", None),
+ ByteField("rest5", None),
+ ByteField("rest6", None),
+ ByteField("rest7", None),
+ ByteField("rest8", None),
+ ByteField("rest9", None),
+ ByteField("rest10", None),
+ ByteField("rest11", None),
+ ByteField("rest12", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 15, a, self.fields_desc)
+ if self.lengthLLC is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MoreDataHdr(Packet):
+ """More data Section 10.5.4.19"""
+ name = "More Data"
+ fields_desc = [
+ BitField("eightBitMD", None, 1),
+ XBitField("ieiMD", None, 7),
+ ]
+
+
+class NotificationIndicatorHdr(Packet):
+ """Notification indicator Section 10.5.4.20"""
+ name = "Notification Indicator"
+ fields_desc = [
+ BitField("eightBitNI", None, 1),
+ XBitField("ieiNI", None, 7),
+ BitField("ext", 0x1, 1),
+ BitField("notifDesc", 0x0, 7)
+ ]
+
+
+class ProgressIndicatorHdr(Packet):
+ """Progress indicator Section 10.5.4.21"""
+ name = "Progress Indicator"
+ fields_desc = [
+ BitField("eightBitPI", None, 1),
+ XBitField("ieiPI", None, 7),
+ XByteField("lengthPI", 0x2),
+ BitField("ext", 0x1, 1),
+ BitField("codingStd", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("location", 0x0, 4),
+ BitField("ext1", 0x1, 1),
+ BitField("progressDesc", 0x0, 7)
+ ]
+
+
+class RecallTypeHdr(Packet):
+ """Recall type $(CCBS)$ Section 10.5.4.21a"""
+ name = "Recall Type $(CCBS)$"
+ fields_desc = [
+ BitField("eightBitRT", None, 1),
+ XBitField("ieiRT", None, 7),
+ BitField("spare", 0x0, 5),
+ BitField("recallType", 0x0, 3)
+ ]
+
+
+# len 3 to 19
+class RedirectingPartyBcdNumberHdr(Packet):
+ """Redirecting party BCD number Section 10.5.4.21b"""
+ name = "Redirecting Party BCD Number"
+ fields_desc = [
+ BitField("eightBitRPBN", None, 1),
+ XBitField("ieiRPBN", None, 7),
+
+ XByteField("lengthRPBN", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("numberingPlan", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", None, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", None, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", None, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+
+ BitField("nbDigit22", None, 4),
+ BitField("nbDigit21", None, 4),
+
+ BitField("nbDigit24", None, 4),
+ BitField("nbDigit23", None, 4),
+
+ BitField("nbDigit26", None, 4),
+ BitField("nbDigit25", None, 4),
+
+ BitField("nbDigit28", None, 4),
+ BitField("nbDigit27", None, 4),
+
+ BitField("nbDigit30", None, 4),
+ BitField("nbDigit29", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 19, a, self.fields_desc)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthRPBN is None:
+ p = p[:1] + struct.pack(">B", len(p)-2) + p[2:]
+ return p + pay
+
+
+# length 2 to 23
+class RedirectingPartySubaddressHdr(Packet):
+ """Redirecting party subaddress Section 10.5.4.21c"""
+ name = "Redirecting Party BCD Number"
+ fields_desc = [
+ BitField("eightBitRPS", None, 1),
+ XBitField("ieiRPS", None, 7),
+
+ XByteField("lengthRPS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("typeSub", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 23, a, self.fields_desc)
+ if self.lengthRPS is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class RepeatIndicatorHdr(Packet):
+ """Repeat indicator Section 10.5.4.22"""
+ name = "Repeat Indicator"
+ fields_desc = [
+ XBitField("ieiRI", None, 4),
+ BitField("repeatIndic", 0x0, 4)
+ ]
+
+
+class ReverseCallSetupDirectionHdr(Packet):
+ """Reverse call setup direction Section 10.5.4.22a"""
+ name = "Reverse Call Setup Direction"
+ fields_desc = [
+ ByteField("ieiRCSD", 0x0)
+ ]
+
+
+# no upper length min 2(max for L3) (251)
+class SetupContainerHdr(Packet):
+ """SETUP Container $(CCBS)$ Section 10.5.4.22b"""
+ name = "Setup Container $(CCBS)$"
+ fields_desc = [
+ BitField("eightBitSC", None, 1),
+ XBitField("ieiSC", None, 7),
+ XByteField("lengthSC", None),
+ # optional
+ ByteField("mess1", None),
+ ByteField("mess2", None),
+ ByteField("mess3", None),
+ ByteField("mess4", None),
+ ByteField("mess5", None),
+ ByteField("mess6", None),
+ ByteField("mess7", None),
+ ByteField("mess8", None),
+ ByteField("mess9", None),
+ ByteField("mess10", None),
+ ByteField("mess11", None),
+ ByteField("mess12", None),
+ ByteField("mess13", None),
+ ByteField("mess14", None),
+ ByteField("mess15", None),
+ ByteField("mess16", None),
+ ByteField("mess17", None),
+ ByteField("mess18", None),
+ ByteField("mess19", None),
+ ByteField("mess20", None),
+ ByteField("mess21", None),
+ ByteField("mess22", None),
+ ByteField("mess23", None),
+ ByteField("mess24", None),
+ ByteField("mess25", None),
+ ByteField("mess26", None),
+ ByteField("mess27", None),
+ ByteField("mess28", None),
+ ByteField("mess29", None),
+ ByteField("mess30", None),
+ ByteField("mess31", None),
+ ByteField("mess32", None),
+ ByteField("mess33", None),
+ ByteField("mess34", None),
+ ByteField("mess35", None),
+ ByteField("mess36", None),
+ ByteField("mess37", None),
+ ByteField("mess38", None),
+ ByteField("mess39", None),
+ ByteField("mess40", None),
+ ByteField("mess41", None),
+ ByteField("mess42", None),
+ ByteField("mess43", None),
+ ByteField("mess44", None),
+ ByteField("mess45", None),
+ ByteField("mess46", None),
+ ByteField("mess47", None),
+ ByteField("mess48", None),
+ ByteField("mess49", None),
+ ByteField("mess50", None),
+ ByteField("mess51", None),
+ ByteField("mess52", None),
+ ByteField("mess53", None),
+ ByteField("mess54", None),
+ ByteField("mess55", None),
+ ByteField("mess56", None),
+ ByteField("mess57", None),
+ ByteField("mess58", None),
+ ByteField("mess59", None),
+ ByteField("mess60", None),
+ ByteField("mess61", None),
+ ByteField("mess62", None),
+ ByteField("mess63", None),
+ ByteField("mess64", None),
+ ByteField("mess65", None),
+ ByteField("mess66", None),
+ ByteField("mess67", None),
+ ByteField("mess68", None),
+ ByteField("mess69", None),
+ ByteField("mess70", None),
+ ByteField("mess71", None),
+ ByteField("mess72", None),
+ ByteField("mess73", None),
+ ByteField("mess74", None),
+ ByteField("mess75", None),
+ ByteField("mess76", None),
+ ByteField("mess77", None),
+ ByteField("mess78", None),
+ ByteField("mess79", None),
+ ByteField("mess80", None),
+ ByteField("mess81", None),
+ ByteField("mess82", None),
+ ByteField("mess83", None),
+ ByteField("mess84", None),
+ ByteField("mess85", None),
+ ByteField("mess86", None),
+ ByteField("mess87", None),
+ ByteField("mess88", None),
+ ByteField("mess89", None),
+ ByteField("mess90", None),
+ ByteField("mess91", None),
+ ByteField("mess92", None),
+ ByteField("mess93", None),
+ ByteField("mess94", None),
+ ByteField("mess95", None),
+ ByteField("mess96", None),
+ ByteField("mess97", None),
+ ByteField("mess98", None),
+ ByteField("mess99", None),
+ ByteField("mess100", None),
+ ByteField("mess101", None),
+ ByteField("mess102", None),
+ ByteField("mess103", None),
+ ByteField("mess104", None),
+ ByteField("mess105", None),
+ ByteField("mess106", None),
+ ByteField("mess107", None),
+ ByteField("mess108", None),
+ ByteField("mess109", None),
+ ByteField("mess110", None),
+ ByteField("mess111", None),
+ ByteField("mess112", None),
+ ByteField("mess113", None),
+ ByteField("mess114", None),
+ ByteField("mess115", None),
+ ByteField("mess116", None),
+ ByteField("mess117", None),
+ ByteField("mess118", None),
+ ByteField("mess119", None),
+ ByteField("mess120", None),
+ ByteField("mess121", None),
+ ByteField("mess122", None),
+ ByteField("mess123", None),
+ ByteField("mess124", None),
+ ByteField("mess125", None),
+ ByteField("mess126", None),
+ ByteField("mess127", None),
+ ByteField("mess128", None),
+ ByteField("mess129", None),
+ ByteField("mess130", None),
+ ByteField("mess131", None),
+ ByteField("mess132", None),
+ ByteField("mess133", None),
+ ByteField("mess134", None),
+ ByteField("mess135", None),
+ ByteField("mess136", None),
+ ByteField("mess137", None),
+ ByteField("mess138", None),
+ ByteField("mess139", None),
+ ByteField("mess140", None),
+ ByteField("mess141", None),
+ ByteField("mess142", None),
+ ByteField("mess143", None),
+ ByteField("mess144", None),
+ ByteField("mess145", None),
+ ByteField("mess146", None),
+ ByteField("mess147", None),
+ ByteField("mess148", None),
+ ByteField("mess149", None),
+ ByteField("mess150", None),
+ ByteField("mess151", None),
+ ByteField("mess152", None),
+ ByteField("mess153", None),
+ ByteField("mess154", None),
+ ByteField("mess155", None),
+ ByteField("mess156", None),
+ ByteField("mess157", None),
+ ByteField("mess158", None),
+ ByteField("mess159", None),
+ ByteField("mess160", None),
+ ByteField("mess161", None),
+ ByteField("mess162", None),
+ ByteField("mess163", None),
+ ByteField("mess164", None),
+ ByteField("mess165", None),
+ ByteField("mess166", None),
+ ByteField("mess167", None),
+ ByteField("mess168", None),
+ ByteField("mess169", None),
+ ByteField("mess170", None),
+ ByteField("mess171", None),
+ ByteField("mess172", None),
+ ByteField("mess173", None),
+ ByteField("mess174", None),
+ ByteField("mess175", None),
+ ByteField("mess176", None),
+ ByteField("mess177", None),
+ ByteField("mess178", None),
+ ByteField("mess179", None),
+ ByteField("mess180", None),
+ ByteField("mess181", None),
+ ByteField("mess182", None),
+ ByteField("mess183", None),
+ ByteField("mess184", None),
+ ByteField("mess185", None),
+ ByteField("mess186", None),
+ ByteField("mess187", None),
+ ByteField("mess188", None),
+ ByteField("mess189", None),
+ ByteField("mess190", None),
+ ByteField("mess191", None),
+ ByteField("mess192", None),
+ ByteField("mess193", None),
+ ByteField("mess194", None),
+ ByteField("mess195", None),
+ ByteField("mess196", None),
+ ByteField("mess197", None),
+ ByteField("mess198", None),
+ ByteField("mess199", None),
+ ByteField("mess200", None),
+ ByteField("mess201", None),
+ ByteField("mess202", None),
+ ByteField("mess203", None),
+ ByteField("mess204", None),
+ ByteField("mess205", None),
+ ByteField("mess206", None),
+ ByteField("mess207", None),
+ ByteField("mess208", None),
+ ByteField("mess209", None),
+ ByteField("mess210", None),
+ ByteField("mess211", None),
+ ByteField("mess212", None),
+ ByteField("mess213", None),
+ ByteField("mess214", None),
+ ByteField("mess215", None),
+ ByteField("mess216", None),
+ ByteField("mess217", None),
+ ByteField("mess218", None),
+ ByteField("mess219", None),
+ ByteField("mess220", None),
+ ByteField("mess221", None),
+ ByteField("mess222", None),
+ ByteField("mess223", None),
+ ByteField("mess224", None),
+ ByteField("mess225", None),
+ ByteField("mess226", None),
+ ByteField("mess227", None),
+ ByteField("mess228", None),
+ ByteField("mess229", None),
+ ByteField("mess230", None),
+ ByteField("mess231", None),
+ ByteField("mess232", None),
+ ByteField("mess233", None),
+ ByteField("mess234", None),
+ ByteField("mess235", None),
+ ByteField("mess236", None),
+ ByteField("mess237", None),
+ ByteField("mess238", None),
+ ByteField("mess239", None),
+ ByteField("mess240", None),
+ ByteField("mess241", None),
+ ByteField("mess242", None),
+ ByteField("mess243", None),
+ ByteField("mess244", None),
+ ByteField("mess245", None),
+ ByteField("mess246", None),
+ ByteField("mess247", None),
+ ByteField("mess248", None),
+ ByteField("mess249", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 251, a, self.fields_desc)
+ if self.lengthSC is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class SignalHdr(Packet):
+ """Signal Section 10.5.4.23"""
+ name = "Signal"
+ fields_desc = [
+ BitField("eightBitS", None, 1),
+ XBitField("ieiS", None, 7),
+ ByteField("sigValue", 0x0)
+ ]
+
+
+# length 2 to max for L3 message (251)
+class SsVersionIndicatorHdr(Packet):
+ """SS Version Indicator Section 10.5.4.24"""
+ name = "SS Version Indicator"
+ fields_desc = [
+ BitField("eightBitSVI", None, 1),
+ XBitField("ieiSVI", None, 7),
+ XByteField("lengthSVI", None),
+ # optional
+ ByteField("info1", None),
+ ByteField("info2", None),
+ ByteField("info3", None),
+ ByteField("info4", None),
+ ByteField("info5", None),
+ ByteField("info6", None),
+ ByteField("info7", None),
+ ByteField("info8", None),
+ ByteField("info9", None),
+ ByteField("info10", None),
+ ByteField("info11", None),
+ ByteField("info12", None),
+ ByteField("info13", None),
+ ByteField("info14", None),
+ ByteField("info15", None),
+ ByteField("info16", None),
+ ByteField("info17", None),
+ ByteField("info18", None),
+ ByteField("info19", None),
+ ByteField("info20", None),
+ ByteField("info21", None),
+ ByteField("info22", None),
+ ByteField("info23", None),
+ ByteField("info24", None),
+ ByteField("info25", None),
+ ByteField("info26", None),
+ ByteField("info27", None),
+ ByteField("info28", None),
+ ByteField("info29", None),
+ ByteField("info30", None),
+ ByteField("info31", None),
+ ByteField("info32", None),
+ ByteField("info33", None),
+ ByteField("info34", None),
+ ByteField("info35", None),
+ ByteField("info36", None),
+ ByteField("info37", None),
+ ByteField("info38", None),
+ ByteField("info39", None),
+ ByteField("info40", None),
+ ByteField("info41", None),
+ ByteField("info42", None),
+ ByteField("info43", None),
+ ByteField("info44", None),
+ ByteField("info45", None),
+ ByteField("info46", None),
+ ByteField("info47", None),
+ ByteField("info48", None),
+ ByteField("info49", None),
+ ByteField("info50", None),
+ ByteField("info51", None),
+ ByteField("info52", None),
+ ByteField("info53", None),
+ ByteField("info54", None),
+ ByteField("info55", None),
+ ByteField("info56", None),
+ ByteField("info57", None),
+ ByteField("info58", None),
+ ByteField("info59", None),
+ ByteField("info60", None),
+ ByteField("info61", None),
+ ByteField("info62", None),
+ ByteField("info63", None),
+ ByteField("info64", None),
+ ByteField("info65", None),
+ ByteField("info66", None),
+ ByteField("info67", None),
+ ByteField("info68", None),
+ ByteField("info69", None),
+ ByteField("info70", None),
+ ByteField("info71", None),
+ ByteField("info72", None),
+ ByteField("info73", None),
+ ByteField("info74", None),
+ ByteField("info75", None),
+ ByteField("info76", None),
+ ByteField("info77", None),
+ ByteField("info78", None),
+ ByteField("info79", None),
+ ByteField("info80", None),
+ ByteField("info81", None),
+ ByteField("info82", None),
+ ByteField("info83", None),
+ ByteField("info84", None),
+ ByteField("info85", None),
+ ByteField("info86", None),
+ ByteField("info87", None),
+ ByteField("info88", None),
+ ByteField("info89", None),
+ ByteField("info90", None),
+ ByteField("info91", None),
+ ByteField("info92", None),
+ ByteField("info93", None),
+ ByteField("info94", None),
+ ByteField("info95", None),
+ ByteField("info96", None),
+ ByteField("info97", None),
+ ByteField("info98", None),
+ ByteField("info99", None),
+ ByteField("info100", None),
+ ByteField("info101", None),
+ ByteField("info102", None),
+ ByteField("info103", None),
+ ByteField("info104", None),
+ ByteField("info105", None),
+ ByteField("info106", None),
+ ByteField("info107", None),
+ ByteField("info108", None),
+ ByteField("info109", None),
+ ByteField("info110", None),
+ ByteField("info111", None),
+ ByteField("info112", None),
+ ByteField("info113", None),
+ ByteField("info114", None),
+ ByteField("info115", None),
+ ByteField("info116", None),
+ ByteField("info117", None),
+ ByteField("info118", None),
+ ByteField("info119", None),
+ ByteField("info120", None),
+ ByteField("info121", None),
+ ByteField("info122", None),
+ ByteField("info123", None),
+ ByteField("info124", None),
+ ByteField("info125", None),
+ ByteField("info126", None),
+ ByteField("info127", None),
+ ByteField("info128", None),
+ ByteField("info129", None),
+ ByteField("info130", None),
+ ByteField("info131", None),
+ ByteField("info132", None),
+ ByteField("info133", None),
+ ByteField("info134", None),
+ ByteField("info135", None),
+ ByteField("info136", None),
+ ByteField("info137", None),
+ ByteField("info138", None),
+ ByteField("info139", None),
+ ByteField("info140", None),
+ ByteField("info141", None),
+ ByteField("info142", None),
+ ByteField("info143", None),
+ ByteField("info144", None),
+ ByteField("info145", None),
+ ByteField("info146", None),
+ ByteField("info147", None),
+ ByteField("info148", None),
+ ByteField("info149", None),
+ ByteField("info150", None),
+ ByteField("info151", None),
+ ByteField("info152", None),
+ ByteField("info153", None),
+ ByteField("info154", None),
+ ByteField("info155", None),
+ ByteField("info156", None),
+ ByteField("info157", None),
+ ByteField("info158", None),
+ ByteField("info159", None),
+ ByteField("info160", None),
+ ByteField("info161", None),
+ ByteField("info162", None),
+ ByteField("info163", None),
+ ByteField("info164", None),
+ ByteField("info165", None),
+ ByteField("info166", None),
+ ByteField("info167", None),
+ ByteField("info168", None),
+ ByteField("info169", None),
+ ByteField("info170", None),
+ ByteField("info171", None),
+ ByteField("info172", None),
+ ByteField("info173", None),
+ ByteField("info174", None),
+ ByteField("info175", None),
+ ByteField("info176", None),
+ ByteField("info177", None),
+ ByteField("info178", None),
+ ByteField("info179", None),
+ ByteField("info180", None),
+ ByteField("info181", None),
+ ByteField("info182", None),
+ ByteField("info183", None),
+ ByteField("info184", None),
+ ByteField("info185", None),
+ ByteField("info186", None),
+ ByteField("info187", None),
+ ByteField("info188", None),
+ ByteField("info189", None),
+ ByteField("info190", None),
+ ByteField("info191", None),
+ ByteField("info192", None),
+ ByteField("info193", None),
+ ByteField("info194", None),
+ ByteField("info195", None),
+ ByteField("info196", None),
+ ByteField("info197", None),
+ ByteField("info198", None),
+ ByteField("info199", None),
+ ByteField("info200", None),
+ ByteField("info201", None),
+ ByteField("info202", None),
+ ByteField("info203", None),
+ ByteField("info204", None),
+ ByteField("info205", None),
+ ByteField("info206", None),
+ ByteField("info207", None),
+ ByteField("info208", None),
+ ByteField("info209", None),
+ ByteField("info210", None),
+ ByteField("info211", None),
+ ByteField("info212", None),
+ ByteField("info213", None),
+ ByteField("info214", None),
+ ByteField("info215", None),
+ ByteField("info216", None),
+ ByteField("info217", None),
+ ByteField("info218", None),
+ ByteField("info219", None),
+ ByteField("info220", None),
+ ByteField("info221", None),
+ ByteField("info222", None),
+ ByteField("info223", None),
+ ByteField("info224", None),
+ ByteField("info225", None),
+ ByteField("info226", None),
+ ByteField("info227", None),
+ ByteField("info228", None),
+ ByteField("info229", None),
+ ByteField("info230", None),
+ ByteField("info231", None),
+ ByteField("info232", None),
+ ByteField("info233", None),
+ ByteField("info234", None),
+ ByteField("info235", None),
+ ByteField("info236", None),
+ ByteField("info237", None),
+ ByteField("info238", None),
+ ByteField("info239", None),
+ ByteField("info240", None),
+ ByteField("info241", None),
+ ByteField("info242", None),
+ ByteField("info243", None),
+ ByteField("info244", None),
+ ByteField("info245", None),
+ ByteField("info246", None),
+ ByteField("info247", None),
+ ByteField("info248", None),
+ ByteField("info249", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 251, a, self.fields_desc)
+ if self.lengthSVI is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# length 3 to 35 or 131
+class UserUserHdr(Packet):
+ """User-user Section 10.5.4.25"""
+ name = "User-User"
+ fields_desc = [
+ BitField("eightBitUU", None, 1),
+ XBitField("ieiUU", None, 7),
+
+ XByteField("lengthUU", None), # dynamic length of field depending
+ # of the type of message
+ # let user decide which length he
+ # wants to take
+ # => more fuzzing options
+ ByteField("userUserPD", 0x0),
+ # optional
+ ByteField("userUserInfo1", None),
+ ByteField("userUserInfo2", None),
+ ByteField("userUserInfo3", None),
+ ByteField("userUserInfo4", None),
+ ByteField("userUserInfo5", None),
+ ByteField("userUserInfo6", None),
+ ByteField("userUserInfo7", None),
+ ByteField("userUserInfo8", None),
+ ByteField("userUserInfo9", None),
+ ByteField("userUserInfo10", None),
+ ByteField("userUserInfo11", None),
+ ByteField("userUserInfo12", None),
+ ByteField("userUserInfo13", None),
+ ByteField("userUserInfo14", None),
+ ByteField("userUserInfo15", None),
+ ByteField("userUserInfo16", None),
+ ByteField("userUserInfo17", None),
+ ByteField("userUserInfo18", None),
+ ByteField("userUserInfo19", None),
+ ByteField("userUserInfo20", None),
+ ByteField("userUserInfo21", None),
+ ByteField("userUserInfo22", None),
+ ByteField("userUserInfo23", None),
+ ByteField("userUserInfo24", None),
+ ByteField("userUserInfo25", None),
+ ByteField("userUserInfo26", None),
+ ByteField("userUserInfo27", None),
+ ByteField("userUserInfo28", None),
+ ByteField("userUserInfo29", None),
+ ByteField("userUserInfo30", None),
+ ByteField("userUserInfo31", None),
+ ByteField("userUserInfo32", None),
+ # long packet
+ ByteField("userUserInfo33", None),
+ ByteField("userUserInfo34", None),
+ ByteField("userUserInfo35", None),
+ ByteField("userUserInfo36", None),
+ ByteField("userUserInfo37", None),
+ ByteField("userUserInfo38", None),
+ ByteField("userUserInfo39", None),
+ ByteField("userUserInfo40", None),
+ ByteField("userUserInfo41", None),
+ ByteField("userUserInfo42", None),
+ ByteField("userUserInfo43", None),
+ ByteField("userUserInfo44", None),
+ ByteField("userUserInfo45", None),
+ ByteField("userUserInfo46", None),
+ ByteField("userUserInfo47", None),
+ ByteField("userUserInfo48", None),
+ ByteField("userUserInfo49", None),
+ ByteField("userUserInfo50", None),
+ ByteField("userUserInfo51", None),
+ ByteField("userUserInfo52", None),
+ ByteField("userUserInfo53", None),
+ ByteField("userUserInfo54", None),
+ ByteField("userUserInfo55", None),
+ ByteField("userUserInfo56", None),
+ ByteField("userUserInfo57", None),
+ ByteField("userUserInfo58", None),
+ ByteField("userUserInfo59", None),
+ ByteField("userUserInfo60", None),
+ ByteField("userUserInfo61", None),
+ ByteField("userUserInfo62", None),
+ ByteField("userUserInfo63", None),
+ ByteField("userUserInfo64", None),
+ ByteField("userUserInfo65", None),
+ ByteField("userUserInfo66", None),
+ ByteField("userUserInfo67", None),
+ ByteField("userUserInfo68", None),
+ ByteField("userUserInfo69", None),
+ ByteField("userUserInfo70", None),
+ ByteField("userUserInfo71", None),
+ ByteField("userUserInfo72", None),
+ ByteField("userUserInfo73", None),
+ ByteField("userUserInfo74", None),
+ ByteField("userUserInfo75", None),
+ ByteField("userUserInfo76", None),
+ ByteField("userUserInfo77", None),
+ ByteField("userUserInfo78", None),
+ ByteField("userUserInfo79", None),
+ ByteField("userUserInfo80", None),
+ ByteField("userUserInfo81", None),
+ ByteField("userUserInfo82", None),
+ ByteField("userUserInfo83", None),
+ ByteField("userUserInfo84", None),
+ ByteField("userUserInfo85", None),
+ ByteField("userUserInfo86", None),
+ ByteField("userUserInfo87", None),
+ ByteField("userUserInfo88", None),
+ ByteField("userUserInfo89", None),
+ ByteField("userUserInfo90", None),
+ ByteField("userUserInfo91", None),
+ ByteField("userUserInfo92", None),
+ ByteField("userUserInfo93", None),
+ ByteField("userUserInfo94", None),
+ ByteField("userUserInfo95", None),
+ ByteField("userUserInfo96", None),
+ ByteField("userUserInfo97", None),
+ ByteField("userUserInfo98", None),
+ ByteField("userUserInfo99", None),
+ ByteField("userUserInfo100", None),
+ ByteField("userUserInfo101", None),
+ ByteField("userUserInfo102", None),
+ ByteField("userUserInfo103", None),
+ ByteField("userUserInfo104", None),
+ ByteField("userUserInfo105", None),
+ ByteField("userUserInfo106", None),
+ ByteField("userUserInfo107", None),
+ ByteField("userUserInfo108", None),
+ ByteField("userUserInfo109", None),
+ ByteField("userUserInfo110", None),
+ ByteField("userUserInfo111", None),
+ ByteField("userUserInfo112", None),
+ ByteField("userUserInfo113", None),
+ ByteField("userUserInfo114", None),
+ ByteField("userUserInfo115", None),
+ ByteField("userUserInfo116", None),
+ ByteField("userUserInfo117", None),
+ ByteField("userUserInfo118", None),
+ ByteField("userUserInfo119", None),
+ ByteField("userUserInfo120", None),
+ ByteField("userUserInfo121", None),
+ ByteField("userUserInfo122", None),
+ ByteField("userUserInfo123", None),
+ ByteField("userUserInfo124", None),
+ ByteField("userUserInfo125", None),
+ ByteField("userUserInfo126", None),
+ ByteField("userUserInfo127", None),
+ ByteField("userUserInfo128", None),
+ ByteField("userUserInfo129", None),
+ ByteField("userUserInfo130", None),
+ ByteField("userUserInfo131", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 131, a, self.fields_desc)
+ if self.lengthUU is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class AlertingPatternHdr(Packet):
+ """Alerting Pattern 10.5.4.26"""
+ name = "Alerting Pattern"
+ fields_desc = [
+ BitField("eightBitAP", None, 1),
+ XBitField("ieiAP", None, 7),
+ XByteField("lengthAP", 0x3),
+ BitField("spare", 0x0, 4),
+ BitField("alertingValue", 0x0, 4)
+ ]
+
+
+class AllowedActionsHdr(Packet):
+ """Allowed actions $(CCBS)$ Section 10.5.4.26"""
+ name = "Allowed Actions $(CCBS)$"
+ fields_desc = [
+ BitField("eightBitAA", None, 1),
+ XBitField("ieiAA", None, 7),
+ XByteField("lengthAP", 0x3),
+ BitField("CCBS", 0x0, 1),
+ BitField("spare", 0x0, 7)
+ ]
+
+
+#
+# 10.5.5 GPRS mobility management information elements
+#
+
+class AttachResult(Packet):
+ """Attach result Section 10.5.5.1"""
+ name = "Attach Result"
+ fields_desc = [
+ XBitField("ieiAR", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("result", 0x1, 3)
+ ]
+
+
+class AttachTypeHdr(Packet):
+ """Attach type Section 10.5.5.2"""
+ name = "Attach Type"
+ fields_desc = [
+ XBitField("ieiAT", None, 4),
+ BitField("spare", 0x0, 1),
+ BitField("type", 0x1, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class AttachTypeAndCiphKeySeqNr(Packet):
+ name = "Attach Type and Cipher Key Sequence Number"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("type", 0x1, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class CipheringAlgorithm(Packet):
+ """Ciphering algorithm Section 10.5.5.3"""
+ name = "Ciphering Algorithm"
+ fields_desc = [
+ XBitField("ieiCA", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("type", 0x1, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class CipheringAlgorithmAndImeisvRequest(Packet):
+ name = "Ciphering Algorithm and Imeisv Request"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("type", 0x1, 3),
+ BitField("spare", 0x0, 1),
+ BitField("imeisvVal", 0x0, 3)
+ ]
+
+
+# [Spare]
+class TmsiStatus(Packet):
+ """[Spare] TMSI status Section 10.5.5.4"""
+ name = "[Spare] TMSI Status"
+ fields_desc = [
+ XBitField("ieiTS", None, 4),
+ BitField("spare", 0x0, 3),
+ BitField("flag", 0x1, 1)
+ ]
+
+
+class DetachType(Packet):
+ """Detach type Section 10.5.5.5"""
+ name = "Detach Type"
+ fields_desc = [
+ XBitField("ieiDT", 0x0, 4),
+ BitField("poweroff", 0x0, 1),
+ BitField("type", 0x1, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class DetachTypeAndForceToStandby(Packet):
+ name = "Detach Type and Force To Standby"
+ fields_desc = [
+ BitField("poweroff", 0x0, 1),
+ BitField("type", 0x1, 3),
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class DetachTypeAndSpareHalfOctets(Packet):
+ name = "Detach Type and Spare Half Octets"
+ fields_desc = [
+ BitField("poweroff", 0x0, 1),
+ BitField("type", 0x1, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class DrxParameter(Packet):
+ """DRX parameter Section 10.5.5.6"""
+ name = "DRX Parameter"
+ fields_desc = [
+ ByteField("ieiDP", 0x0),
+ ByteField("splitPG", 0x0),
+ BitField("spare", 0x0, 4),
+ BitField("splitCCCH", 0x0, 1),
+ BitField("NonDrxTimer", 0x1, 3)
+ ]
+
+
+class ForceToStandby(Packet):
+ """Force to standby Section 10.5.5.7"""
+ name = "Force To Standby"
+ fields_desc = [
+ XBitField("ieiFTS", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class ForceToStandbyAndAcReferenceNumber(Packet):
+ name = "Force To Standby And Ac Reference Number"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3),
+ BitField("acRefVal", 0x0, 4)
+ ]
+
+
+# Fix 1/2 len problem
+class ForceToStandbyAndUpdateResult(Packet):
+ name = "Force To Standby And Update Result"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("updateResVal", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class ForceToStandbyAndSpareHalfOctets(Packet):
+ name = "Force To Standby And Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class PTmsiSignature(Packet):
+ """P-TMSI signature Section 10.5.5.8"""
+ name = "P-TMSI Signature"
+ fields_desc = [
+ ByteField("ieiPTS", 0x0),
+ BitField("sgnature", 0x0, 24)
+ ]
+
+
+class IdentityType2(Packet):
+ """Identity type 2 Section 10.5.5.9"""
+ name = "Identity Type 2"
+ fields_desc = [
+ XBitField("ieiIT2", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("typeOfIdentity", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class IdentityType2AndforceToStandby(Packet):
+ name = "Identity Type 2 and Force to Standby"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("typeOfIdentity", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("forceStandby", 0x0, 3)
+ ]
+
+
+class ImeisvRequest(Packet):
+ """IMEISV request Section 10.5.5.10"""
+ name = "IMEISV Request"
+ fields_desc = [
+ XBitField("ieiIR", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("imeisvVal", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class ImeisvRequestAndForceToStandby(Packet):
+ name = "IMEISV Request and Force To Standby"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("imeisvVal", 0x0, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+# length 4 to 19
+class ReceiveNpduNumbersList(Packet):
+ """Receive N-PDU Numbers list Section 10.5.5.11"""
+ name = "Receive N-PDU Numbers list"
+ fields_desc = [
+ ByteField("ieiRNNL", 0x0),
+
+ XByteField("lengthRNNL", None),
+
+ BitField("nbList0", 0x0, 16),
+ # optional
+ ByteField("nbList1", None),
+ ByteField("nbList2", None),
+ ByteField("nbList3", None),
+ ByteField("nbList4", None),
+ ByteField("nbList5", None),
+ ByteField("nbList6", None),
+ ByteField("nbList7", None),
+ ByteField("nbList8", None),
+ ByteField("nbList9", None),
+ ByteField("nbList10", None),
+ ByteField("nbList11", None),
+ ByteField("nbList12", None),
+ ByteField("nbList13", None),
+ ByteField("nbList14", None),
+ ByteField("nbList15", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 19, a, self.fields_desc)
+ if self.lengthRNNL is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MsNetworkCapability(Packet):
+ """MS network capability Section 10.5.5.12"""
+ name = "MS Network Capability"
+ fields_desc = [
+ ByteField("ieiMNC", 0x0),
+ XByteField("lengthMNC", 0x3),
+ ByteField("msNetValue", 0x0)
+ ]
+
+
+# length 6 to 14
+class MsRadioAccessCapability(Packet):
+ """MS Radio Access capability Section 10.5.5.12a"""
+ name = "MS Radio Access Capability"
+ fields_desc = [
+ ByteField("ieiMRAC", 0x24),
+
+ XByteField("lengthMRAC", None),
+
+ BitField("spare1", 0x0, 1), # ...
+
+ BitField("accessCap", 0x0, 4),
+ BitField("accessTechType", 0x0, 4),
+ # access capability
+ BitField("bool", 0x0, 1),
+ BitField("lengthContent", 0x0, 7),
+ BitField("spare1", 0x0, 1), # ...
+ # content
+ BitField("pwrCap", 0x0, 3),
+ BitField("bool1", 0x0, 1),
+ BitField("a51", 0x0, 1),
+ BitField("a52", 0x0, 1),
+ BitField("a53", 0x0, 1),
+ BitField("a54", 0x0, 1),
+
+ BitField("a55", 0x0, 1),
+ BitField("a56", 0x0, 1),
+ BitField("a57", 0x0, 1),
+ BitField("esInd", 0x0, 1),
+ BitField("ps", 0x0, 1),
+ BitField("vgcs", 0x0, 1),
+ BitField("vbs", 0x0, 1),
+ BitField("bool2", 0x0, 1),
+ # multislot
+ BitField("bool3", 0x0, 1),
+ BitField("hscsd", 0x0, 5),
+
+ BitField("bool4", 0x0, 1),
+ BitField("gprs", 0x0, 5),
+ BitField("gprsExt", 0x0, 1),
+ BitField("bool5", 0x0, 1),
+
+ BitField("smsVal", 0x0, 4),
+ BitField("smVal", 0x0, 4)
+ ]
+
+
+# 10.5.5.13 Spare
+# This is intentionally left spare.
+
+class GmmCause(Packet):
+ """GMM cause Section 10.5.5.14"""
+ name = "GMM Cause"
+ fields_desc = [
+ ByteField("ieiGC", 0x0),
+ ByteField("causeValue", 0x0)
+ ]
+
+
+class RoutingAreaIdentification(Packet):
+ """Routing area identification Section 10.5.5.15"""
+ name = "Routing Area Identification"
+ fields_desc = [
+ ByteField("ieiRAI", 0x0),
+ BitField("mccDigit2", 0x0, 4),
+ BitField("mccDigit1", 0x0, 4),
+ BitField("mncDigit3", 0x0, 4),
+ BitField("mccDigit3", 0x0, 4),
+ BitField("mccDigit2", 0x0, 4),
+ BitField("mccDigit1", 0x0, 4),
+ ByteField("LAC", 0x0),
+ ByteField("LAC1", 0x0),
+ ByteField("LAC", 0x0)
+ ]
+# 10.5.5.16 Spare
+# This is intentionally left spare.
+
+
+class UpdateResult(Packet):
+ """Update result Section 10.5.5.17"""
+ name = "Update Result"
+ fields_desc = [
+ XBitField("ieiUR", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("updateResVal", 0x0, 3)
+ ]
+
+
+class UpdateType(Packet):
+ """Update type Section 10.5.5.18"""
+ name = "Update Type"
+ fields_desc = [
+ XBitField("ieiUT", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("updateTypeVal", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class UpdateTypeAndCiphKeySeqNr(Packet):
+ name = "Update Type and Cipher Key Sequence Number"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("updateTypeVal", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3)
+ ]
+
+
+class AcReferenceNumber(Packet):
+ """A&C reference number Section 10.5.5.19"""
+ name = "A&C Reference Number"
+ fields_desc = [
+ XBitField("ieiARN", 0x0, 4),
+ BitField("acRefVal", 0x0, 4)
+ ]
+
+
+# Fix 1/2 len problem
+class AcReferenceNumberAndSpareHalfOctets(Packet):
+ name = "A&C Reference Number and Spare Half Octets"
+ fields_desc = [
+ BitField("acRefVal", 0x0, 4),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+#
+# 10.5.6 Session management information elements
+#
+# length 3 to 102
+
+
+class AccessPointName(Packet):
+ """Access Point Name Section 10.5.6.1"""
+ name = "Access Point Name"
+ fields_desc = [
+ ByteField("ieiAPN", 0x0),
+ XByteField("lengthAPN", None),
+ ByteField("apName", 0x0),
+ # optional
+ ByteField("apName1", None),
+ ByteField("apName2", None),
+ ByteField("apName3", None),
+ ByteField("apName4", None),
+ ByteField("apName5", None),
+ ByteField("apName6", None),
+ ByteField("apName7", None),
+ ByteField("apName8", None),
+ ByteField("apName9", None),
+ ByteField("apName10", None),
+ ByteField("apName11", None),
+ ByteField("apName12", None),
+ ByteField("apName13", None),
+ ByteField("apName14", None),
+ ByteField("apName15", None),
+ ByteField("apName16", None),
+ ByteField("apName17", None),
+ ByteField("apName18", None),
+ ByteField("apName19", None),
+ ByteField("apName20", None),
+ ByteField("apName21", None),
+ ByteField("apName22", None),
+ ByteField("apName23", None),
+ ByteField("apName24", None),
+ ByteField("apName25", None),
+ ByteField("apName26", None),
+ ByteField("apName27", None),
+ ByteField("apName28", None),
+ ByteField("apName29", None),
+ ByteField("apName30", None),
+ ByteField("apName31", None),
+ ByteField("apName32", None),
+ ByteField("apName33", None),
+ ByteField("apName34", None),
+ ByteField("apName35", None),
+ ByteField("apName36", None),
+ ByteField("apName37", None),
+ ByteField("apName38", None),
+ ByteField("apName39", None),
+ ByteField("apName40", None),
+ ByteField("apName41", None),
+ ByteField("apName42", None),
+ ByteField("apName43", None),
+ ByteField("apName44", None),
+ ByteField("apName45", None),
+ ByteField("apName46", None),
+ ByteField("apName47", None),
+ ByteField("apName48", None),
+ ByteField("apName49", None),
+ ByteField("apName50", None),
+ ByteField("apName51", None),
+ ByteField("apName52", None),
+ ByteField("apName53", None),
+ ByteField("apName54", None),
+ ByteField("apName55", None),
+ ByteField("apName56", None),
+ ByteField("apName57", None),
+ ByteField("apName58", None),
+ ByteField("apName59", None),
+ ByteField("apName60", None),
+ ByteField("apName61", None),
+ ByteField("apName62", None),
+ ByteField("apName63", None),
+ ByteField("apName64", None),
+ ByteField("apName65", None),
+ ByteField("apName66", None),
+ ByteField("apName67", None),
+ ByteField("apName68", None),
+ ByteField("apName69", None),
+ ByteField("apName70", None),
+ ByteField("apName71", None),
+ ByteField("apName72", None),
+ ByteField("apName73", None),
+ ByteField("apName74", None),
+ ByteField("apName75", None),
+ ByteField("apName76", None),
+ ByteField("apName77", None),
+ ByteField("apName78", None),
+ ByteField("apName79", None),
+ ByteField("apName80", None),
+ ByteField("apName81", None),
+ ByteField("apName82", None),
+ ByteField("apName83", None),
+ ByteField("apName84", None),
+ ByteField("apName85", None),
+ ByteField("apName86", None),
+ ByteField("apName87", None),
+ ByteField("apName88", None),
+ ByteField("apName89", None),
+ ByteField("apName90", None),
+ ByteField("apName91", None),
+ ByteField("apName92", None),
+ ByteField("apName93", None),
+ ByteField("apName94", None),
+ ByteField("apName95", None),
+ ByteField("apName96", None),
+ ByteField("apName97", None),
+ ByteField("apName98", None),
+ ByteField("apName99", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 102, a, self.fields_desc)
+ if self.lengthAPN is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class NetworkServiceAccessPointIdentifier(Packet):
+ """Network service access point identifier Section 10.5.6.2"""
+ name = "Network Service Access Point Identifier"
+ fields_desc = [
+ ByteField("ieiNSAPI", 0x0),
+ BitField("spare", 0x0, 4),
+ BitField("nsapiVal", 0x0, 4)
+ ]
+
+
+# length 2 to 253
+class ProtocolConfigurationOptions(Packet):
+ """Protocol configuration options Section 10.5.6.3"""
+ name = "Protocol Configuration Options"
+ fields_desc = [
+ ByteField("ieiPCO", 0x0),
+
+ XByteField("lengthPCO", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("spare", None, 4),
+ BitField("configProto", None, 3),
+
+ ByteField("protoId1", None),
+ ByteField("lenProto1", None),
+ ByteField("proto1Content", None),
+
+ ByteField("protoId2", None),
+ ByteField("lenProto2", None),
+ ByteField("proto2Content", None),
+
+ ByteField("protoId3", None),
+ ByteField("lenProto3", None),
+ ByteField("proto3Content", None),
+
+ ByteField("protoId4", None),
+ ByteField("lenProto4", None),
+ ByteField("proto4Content", None),
+
+
+ ByteField("protoId5", None),
+ ByteField("lenProto5", None),
+ ByteField("proto5Content", None),
+
+ ByteField("protoId6", None),
+ ByteField("lenProto6", None),
+ ByteField("proto6Content", None),
+
+ ByteField("protoId7", None),
+ ByteField("lenProto7", None),
+ ByteField("proto7Content", None),
+
+ ByteField("protoId8", None),
+ ByteField("lenProto8", None),
+ ByteField("proto8Content", None),
+
+ ByteField("protoId9", None),
+ ByteField("lenProto9", None),
+ ByteField("proto9Content", None),
+
+ ByteField("protoId10", None),
+ ByteField("lenProto10", None),
+ ByteField("proto10Content", None),
+
+ ByteField("protoId11", None),
+ ByteField("lenProto11", None),
+ ByteField("proto11Content", None),
+
+ ByteField("protoId12", None),
+ ByteField("lenProto12", None),
+ ByteField("proto12Content", None),
+
+ ByteField("protoId13", None),
+ ByteField("lenProto13", None),
+ ByteField("proto13Content", None),
+
+ ByteField("protoId14", None),
+ ByteField("lenProto14", None),
+ ByteField("proto14Content", None),
+
+ ByteField("protoId15", None),
+ ByteField("lenProto15", None),
+ ByteField("proto15Content", None),
+
+ ByteField("protoId16", None),
+ ByteField("lenProto16", None),
+ ByteField("proto16Content", None),
+
+ ByteField("protoId17", None),
+ ByteField("lenProto17", None),
+ ByteField("proto17Content", None),
+
+ ByteField("protoId18", None),
+ ByteField("lenProto18", None),
+ ByteField("proto18Content", None),
+
+ ByteField("protoId19", None),
+ ByteField("lenProto19", None),
+ ByteField("proto19Content", None),
+
+ ByteField("protoId20", None),
+ ByteField("lenProto20", None),
+ ByteField("proto20Content", None),
+
+ ByteField("protoId21", None),
+ ByteField("lenProto21", None),
+ ByteField("proto21Content", None),
+
+ ByteField("protoId22", None),
+ ByteField("lenProto22", None),
+ ByteField("proto22Content", None),
+
+ ByteField("protoId23", None),
+ ByteField("lenProto23", None),
+ ByteField("proto23Content", None),
+
+ ByteField("protoId24", None),
+ ByteField("lenProto24", None),
+ ByteField("proto24Content", None),
+
+ ByteField("protoId25", None),
+ ByteField("lenProto25", None),
+ ByteField("proto25Content", None),
+
+ ByteField("protoId26", None),
+ ByteField("lenProto26", None),
+ ByteField("proto26Content", None),
+
+ ByteField("protoId27", None),
+ ByteField("lenProto27", None),
+ ByteField("proto27Content", None),
+
+ ByteField("protoId28", None),
+ ByteField("lenProto28", None),
+ ByteField("proto28Content", None),
+
+ ByteField("protoId29", None),
+ ByteField("lenProto29", None),
+ ByteField("proto29Content", None),
+
+ ByteField("protoId30", None),
+ ByteField("lenProto30", None),
+ ByteField("proto30Content", None),
+
+ ByteField("protoId31", None),
+ ByteField("lenProto31", None),
+ ByteField("proto31Content", None),
+
+ ByteField("protoId32", None),
+ ByteField("lenProto32", None),
+ ByteField("proto32Content", None),
+
+ ByteField("protoId33", None),
+ ByteField("lenProto33", None),
+ ByteField("proto33Content", None),
+
+ ByteField("protoId34", None),
+ ByteField("lenProto34", None),
+ ByteField("proto34Content", None),
+
+ ByteField("protoId35", None),
+ ByteField("lenProto35", None),
+ ByteField("proto35Content", None),
+
+ ByteField("protoId36", None),
+ ByteField("lenProto36", None),
+ ByteField("proto36Content", None),
+
+ ByteField("protoId37", None),
+ ByteField("lenProto37", None),
+ ByteField("proto37Content", None),
+
+ ByteField("protoId38", None),
+ ByteField("lenProto38", None),
+ ByteField("proto38Content", None),
+
+ ByteField("protoId39", None),
+ ByteField("lenProto39", None),
+ ByteField("proto39Content", None),
+
+ ByteField("protoId40", None),
+ ByteField("lenProto40", None),
+ ByteField("proto40Content", None),
+
+ ByteField("protoId41", None),
+ ByteField("lenProto41", None),
+ ByteField("proto41Content", None),
+
+ ByteField("protoId42", None),
+ ByteField("lenProto42", None),
+ ByteField("proto42Content", None),
+
+ ByteField("protoId43", None),
+ ByteField("lenProto43", None),
+ ByteField("proto43Content", None),
+
+ ByteField("protoId44", None),
+ ByteField("lenProto44", None),
+ ByteField("proto44Content", None),
+
+ ByteField("protoId45", None),
+ ByteField("lenProto45", None),
+ ByteField("proto45Content", None),
+
+ ByteField("protoId46", None),
+ ByteField("lenProto46", None),
+ ByteField("proto46Content", None),
+
+ ByteField("protoId47", None),
+ ByteField("lenProto47", None),
+ ByteField("proto47Content", None),
+
+ ByteField("protoId48", None),
+ ByteField("lenProto48", None),
+ ByteField("proto48Content", None),
+
+ ByteField("protoId49", None),
+ ByteField("lenProto49", None),
+ ByteField("proto49Content", None),
+
+ ByteField("protoId50", None),
+ ByteField("lenProto50", None),
+ ByteField("proto50Content", None),
+
+ ByteField("protoId51", None),
+ ByteField("lenProto51", None),
+ ByteField("proto51Content", None),
+
+ ByteField("protoId52", None),
+ ByteField("lenProto52", None),
+ ByteField("proto52Content", None),
+
+ ByteField("protoId53", None),
+ ByteField("lenProto53", None),
+ ByteField("proto53Content", None),
+
+ ByteField("protoId54", None),
+ ByteField("lenProto54", None),
+ ByteField("proto54Content", None),
+
+ ByteField("protoId55", None),
+ ByteField("lenProto55", None),
+ ByteField("proto55Content", None),
+
+ ByteField("protoId56", None),
+ ByteField("lenProto56", None),
+ ByteField("proto56Content", None),
+
+ ByteField("protoId57", None),
+ ByteField("lenProto57", None),
+ ByteField("proto57Content", None),
+
+ ByteField("protoId58", None),
+ ByteField("lenProto58", None),
+ ByteField("proto58Content", None),
+
+ ByteField("protoId59", None),
+ ByteField("lenProto59", None),
+ ByteField("proto59Content", None),
+
+ ByteField("protoId60", None),
+ ByteField("lenProto60", None),
+ ByteField("proto60Content", None),
+
+ ByteField("protoId61", None),
+ ByteField("lenProto61", None),
+ ByteField("proto61Content", None),
+
+ ByteField("protoId62", None),
+ ByteField("lenProto62", None),
+ ByteField("proto62Content", None),
+
+ ByteField("protoId63", None),
+ ByteField("lenProto63", None),
+ ByteField("proto63Content", None),
+
+ ByteField("protoId64", None),
+ ByteField("lenProto64", None),
+ ByteField("proto64Content", None),
+
+ ByteField("protoId65", None),
+ ByteField("lenProto65", None),
+ ByteField("proto65Content", None),
+
+ ByteField("protoId66", None),
+ ByteField("lenProto66", None),
+ ByteField("proto66Content", None),
+
+ ByteField("protoId67", None),
+ ByteField("lenProto67", None),
+ ByteField("proto67Content", None),
+
+ ByteField("protoId68", None),
+ ByteField("lenProto68", None),
+ ByteField("proto68Content", None),
+
+ ByteField("protoId69", None),
+ ByteField("lenProto69", None),
+ ByteField("proto69Content", None),
+
+ ByteField("protoId70", None),
+ ByteField("lenProto70", None),
+ ByteField("proto70Content", None),
+
+ ByteField("protoId71", None),
+ ByteField("lenProto71", None),
+ ByteField("proto71Content", None),
+
+ ByteField("protoId72", None),
+ ByteField("lenProto72", None),
+ ByteField("proto72Content", None),
+
+ ByteField("protoId73", None),
+ ByteField("lenProto73", None),
+ ByteField("proto73Content", None),
+
+ ByteField("protoId74", None),
+ ByteField("lenProto74", None),
+ ByteField("proto74Content", None),
+
+ ByteField("protoId75", None),
+ ByteField("lenProto75", None),
+ ByteField("proto75Content", None),
+
+ ByteField("protoId76", None),
+ ByteField("lenProto76", None),
+ ByteField("proto76Content", None),
+
+ ByteField("protoId77", None),
+ ByteField("lenProto77", None),
+ ByteField("proto77Content", None),
+
+ ByteField("protoId78", None),
+ ByteField("lenProto78", None),
+ ByteField("proto78Content", None),
+
+ ByteField("protoId79", None),
+ ByteField("lenProto79", None),
+ ByteField("proto79Content", None),
+
+ ByteField("protoId80", None),
+ ByteField("lenProto80", None),
+ ByteField("proto80Content", None),
+
+ ByteField("protoId81", None),
+ ByteField("lenProto81", None),
+ ByteField("proto81Content", None),
+
+ ByteField("protoId82", None),
+ ByteField("lenProto82", None),
+ ByteField("proto82Content", None),
+
+ ByteField("protoId83", None),
+ ByteField("lenProto83", None),
+ ByteField("proto83Content", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 253, a, self.fields_desc)
+ if self.lengthPCO is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 4 to 20
+class PacketDataProtocolAddress(Packet):
+ """Packet data protocol address Section 10.5.6.4"""
+ name = "Packet Data Protocol Address"
+ fields_desc = [
+ ByteField("ieiPDPA", 0x0),
+
+ XByteField("lengthPDPA", None),
+
+ BitField("spare", 0x0, 4),
+ BitField("pdpTypeOrga", 0x0, 4),
+
+ ByteField("pdpTypeNb", 0x0),
+ # optional
+ ByteField("addressInfo1", None),
+ ByteField("addressInfo2", None),
+ ByteField("addressInfo3", None),
+ ByteField("addressInfo4", None),
+ ByteField("addressInfo5", None),
+ ByteField("addressInfo6", None),
+ ByteField("addressInfo7", None),
+ ByteField("addressInfo8", None),
+ ByteField("addressInfo9", None),
+ ByteField("addressInfo10", None),
+ ByteField("addressInfo11", None),
+ ByteField("addressInfo12", None),
+ ByteField("addressInfo13", None),
+ ByteField("addressInfo14", None),
+ ByteField("addressInfo15", None),
+ ByteField("addressInfo16", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 20, a, self.fields_desc)
+ if self.lengthPDPA is None:
+ p = p[:1] + struct.pack(">B", res[1]) + p[2:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class QualityOfService(Packet):
+ """Quality of service Section 10.5.6.5"""
+ name = "Quality of Service"
+ fields_desc = [
+ ByteField("ieiQOS", 0x0),
+ XByteField("lengthQOS", 0x5),
+
+ BitField("spare", 0x0, 2),
+ BitField("delayClass", 0x0, 3),
+ BitField("reliaClass", 0x0, 3),
+
+ BitField("peak", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("precedenceCl", 0x0, 3),
+
+ BitField("spare", 0x0, 3),
+ BitField("mean", 0x0, 5)
+ ]
+
+
+class SmCause(Packet):
+ """SM cause Section 10.5.6.6"""
+ name = "SM Cause"
+ fields_desc = [
+ ByteField("ieiSC", 0x0),
+ ByteField("causeVal", 0x0)
+ ]
+
+# 10.5.6.7 Spare
+# This is intentionally left spare.
+
+
+class AaDeactivationCause(Packet):
+ """AA deactivation cause Section 10.5.6.8"""
+ name = "AA Deactivation Cause"
+ fields_desc = [
+ XBitField("ieiADC", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("aaVal", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class AaDeactivationCauseAndSpareHalfOctets(Packet):
+ name = "AA Deactivation Cause and Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("aaVal", 0x0, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class LlcServiceAccessPointIdentifier(Packet):
+ """LLC service access point identifier Section 10.5.6.9"""
+ name = "LLC Service Access Point Identifier"
+ fields_desc = [
+ ByteField("ieiLSAPI", None),
+ BitField("spare", 0x0, 4),
+ BitField("llcVal", 0x0, 4)
+ ]
+
+
+#
+# 10.5.7 GPRS Common information elements
+#
+
+# 10.5.7.1 [Spare]
+
+class RadioPriority(Packet):
+ """Radio priority Section 10.5.7.2"""
+ name = "Radio Priority"
+ fields_desc = [
+ XBitField("ieiRP", 0x0, 4),
+ BitField("spare", 0x1, 1),
+ BitField("rplv", 0x0, 3)
+ ]
+
+
+# Fix 1/2 len problem
+class RadioPriorityAndSpareHalfOctets(Packet):
+ name = "Radio Priority and Spare Half Octets"
+ fields_desc = [
+ BitField("spare", 0x1, 1),
+ BitField("rplv", 0x0, 3),
+ BitField("spareHalfOctets", 0x0, 4)
+ ]
+
+
+class GprsTimer(Packet):
+ """GPRS Timer Section 10.5.7.3"""
+ name = "GPRS Timer"
+ fields_desc = [
+ ByteField("ieiGT", 0x0),
+ BitField("unit", 0x0, 3),
+ BitField("timerVal", 0x0, 5)
+ ]
+
+
+class CellIdentity(Packet):
+ """ Cell identity Section 10.5.1.1 """
+ name = "Cell Identity"
+ fields_desc = [
+ ByteField("ciValue1", 0x0),
+ ByteField("ciValue2", 0x0)
+ ]
+
+
+class CiphKeySeqNr(Packet):
+ """ Ciphering Key Sequence Number Section 10.5.1.2 """
+ name = "Cipher Key Sequence Number"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("keySeq", 0x0, 3)
+ ]
+
+
+class LocalAreaId(Packet):
+ """ Local Area Identification Section 10.5.1.3 """
+ name = "Location Area Identification"
+ fields_desc = [
+ BitField("mccDigit2", 0x0, 4),
+ BitField("mccDigit1", 0x0, 4),
+ BitField("mncDigit3", 0x0, 4),
+ BitField("mccDigit3", 0x0, 4),
+ BitField("mncDigit2", 0x0, 4),
+ BitField("mncDigit1", 0x0, 4),
+ ByteField("lac1", 0x0),
+ ByteField("lac2", 0x0)
+ ]
+#
+# The Mobile Identity is a type 4 information element with a minimum
+# length of 3 octet and 11 octets length maximal.
+#
+
+
+# len 3 - 11
+class MobileId(Packet):
+ """ Mobile Identity Section 10.5.1.4 """
+ name = "Mobile Identity"
+ fields_desc = [
+ XByteField("lengthMI", None),
+ BitField("idDigit1", 0x0, 4),
+ BitField("oddEven", 0x0, 1),
+ BitField("typeOfId", 0x0, 3),
+
+ BitField("idDigit2_1", None, 4), # optional
+ BitField("idDigit2", None, 4),
+ BitField("idDigit3_1", None, 4),
+ BitField("idDigit3", None, 4),
+ BitField("idDigit4_1", None, 4),
+ BitField("idDigit4", None, 4),
+ BitField("idDigit5_1", None, 4),
+ BitField("idDigit5", None, 4),
+ BitField("idDigit6_1", None, 4),
+ BitField("idDigit6", None, 4),
+ BitField("idDigit7_1", None, 4),
+ BitField("idDigit7", None, 4),
+ BitField("idDigit8_1", None, 4),
+ BitField("idDigit8", None, 4),
+ BitField("idDigit9_1", None, 4),
+ BitField("idDigit9", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 10, a, self.fields_desc, 1)
+ if self.lengthMI is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MobileStationClassmark1(Packet):
+ """ Mobile Station Classmark 1 Section 10.5.1.5 """
+ name = "Mobile Station Classmark 1"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("revisionLvl", 0x0, 2),
+ BitField("esInd", 0x0, 1),
+ BitField("a51", 0x0, 1),
+ BitField("rfPowerCap", 0x0, 3)
+ ]
+
+
+class MobileStationClassmark2(Packet):
+ """ Mobile Station Classmark 2 Section 10.5.1.6 """
+ name = "Mobile Station Classmark 2"
+ fields_desc = [
+ XByteField("lengthMSC2", 0x3),
+ BitField("spare", 0x0, 1),
+ BitField("revisionLvl", 0x0, 2),
+ BitField("esInd", 0x0, 1),
+ BitField("a51", 0x0, 1),
+ BitField("rfPowerCap", 0x0, 3),
+ BitField("spare1", 0x0, 1),
+ BitField("psCap", 0x0, 1),
+ BitField("ssScreenInd", 0x0, 2),
+ BitField("smCaPabi", 0x0, 1),
+ BitField("vbs", 0x0, 1),
+ BitField("vgcs", 0x0, 1),
+ BitField("fc", 0x0, 1),
+ BitField("cm3", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("lcsvaCap", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("soLsa", 0x0, 1),
+ BitField("cmsp", 0x0, 1),
+ BitField("a53", 0x0, 1),
+ BitField("a52", 0x0, 1)
+ ]
+
+
+class DescriptiveGroupOrBroadcastCallReference(Packet):
+ """ Descriptive group or broadcast call reference Section 10.5.1.9 """
+ name = "Descriptive Group or Broadcast Call Reference"
+ fields_desc = [
+ BitField("binCallRef", 0x0, 27),
+ BitField("sf", 0x0, 1),
+ BitField("fa", 0x0, 1),
+ BitField("callPrio", 0x0, 3),
+ BitField("cipherInfo", 0x0, 4),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("spare4", 0x0, 1)
+ ]
+
+
+class PdAndSapi(Packet):
+ """ PD and SAPI $(CCBS)$ Section 10.5.1.10a """
+ name = "PD and SAPI $(CCBS)$"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("sapi", 0x0, 2),
+ BitField("pd", 0x0, 4)
+ ]
+
+
+class PriorityLevel(Packet):
+ """ Priority Level Section 10.5.1.11 """
+ name = "Priority Level"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("callPrio", 0x0, 3)
+ ]
+
+#
+# Radio Resource management information elements
+#
+
+
+# len 6 to max for L3 message (251)
+class BaRange(Packet):
+ """ BA Range Section 10.5.2.1a """
+ name = "BA Range"
+ fields_desc = [
+
+ XByteField("lengthBR", None),
+#error: byte format requires -128 <= number <= 127
+ ByteField("nrOfRanges", 0x0),
+# # rX = range X
+# # L o = Lower H i = higher
+# # H p = high Part Lp = low Part
+ ByteField("r1LoHp", 0x0),
+
+ BitField("r1LoLp", 0x0, 3),
+ BitField("r1HiHp", 0x0, 5),
+
+ BitField("r1HiLp", 0x0, 4),
+ BitField("r2LoHp", 0x0, 4),
+ # optional
+ BitField("r2LoLp", None, 5),
+ BitField("r2HiHp", None, 3),
+
+ ByteField("r2HiLp", None),
+ ByteField("r3LoHp", None),
+
+ BitField("r3LoLp", None, 5),
+ BitField("r3HiHp", None, 3),
+
+ ByteField("r3HiLp", None),
+ ByteField("r4LoHp", None),
+
+ BitField("r4LoLp", None, 5),
+ BitField("r4HiHp", None, 3),
+ ByteField("r4HiLp", None),
+ ByteField("r5LoHp", None),
+
+ BitField("r5LoLp", None, 5),
+ BitField("r5HiHp", None, 3),
+ ByteField("r5HiLp", None),
+ ByteField("r6LoHp", None),
+
+ BitField("r6LoLp", None, 5),
+ BitField("r6HiHp", None, 3),
+ ByteField("r6HiLp", None),
+ ByteField("r7LoHp", None),
+
+ BitField("r7LoLp", None, 5),
+ BitField("r7HiHp", None, 3),
+ ByteField("r7HiLp", None),
+ ByteField("r8LoHp", None),
+
+ BitField("r8LoLp", None, 5),
+ BitField("r8HiHp", None, 3),
+ ByteField("r8HiLp", None),
+ ByteField("r9LoHp", None),
+
+ BitField("r9LoLp", None, 5),
+ BitField("r9HiHp", None, 3),
+ ByteField("r9HiLp", None),
+ ByteField("r10LoHp", None),
+
+ BitField("r10LoLp", None, 5),
+ BitField("r10HiHp", None, 3),
+ ByteField("r10HiLp", None),
+ ByteField("r11LoHp", None),
+
+ BitField("r11LoLp", None, 5),
+ BitField("r11HiHp", None, 3),
+ ByteField("r11HiLp", None),
+ ByteField("r12LoHp", None),
+
+ BitField("r12LoLp", None, 5),
+ BitField("r12HiHp", None, 3),
+ ByteField("r12HiLp", None),
+ ByteField("r13LoHp", None),
+
+ BitField("r13LoLp", None, 5),
+ BitField("r13HiHp", None, 3),
+ ByteField("r13HiLp", None),
+ ByteField("r14LoHp", None),
+
+ BitField("r14LoLp", None, 5),
+ BitField("r14HiHp", None, 3),
+ ByteField("r14HiLp", None),
+ ByteField("r15LoHp", None),
+
+ BitField("r15LoLp", None, 5),
+ BitField("r15HiHp", None, 3),
+ ByteField("r15HiLp", None),
+ ByteField("r16LoHp", None),
+
+ BitField("r16LoLp", None, 5),
+ BitField("r16HiHp", None, 3),
+ ByteField("r16HiLp", None),
+ ByteField("r17LoHp", None),
+
+ BitField("r17LoLp", None, 5),
+ BitField("r17HiHp", None, 3),
+ ByteField("r17HiLp", None),
+ ByteField("r18LoHp", None),
+
+ BitField("r18LoLp", None, 5),
+ BitField("r18HiHp", None, 3),
+ ByteField("r18HiLp", None),
+ ByteField("r19LoHp", None),
+
+ BitField("r19LoLp", None, 5),
+ BitField("r19HiHp", None, 3),
+ ByteField("r19HiLp", None),
+ ByteField("r20LoHp", None),
+
+ BitField("r20LoLp", None, 5),
+ BitField("r20HiHp", None, 3),
+ ByteField("r20HiLp", None),
+ ByteField("r21LoHp", None),
+
+ BitField("r21LoLp", None, 5),
+ BitField("r21HiHp", None, 3),
+ ByteField("r21HiLp", None),
+ ByteField("r22LoHp", None),
+
+ BitField("r22LoLp", None, 5),
+ BitField("r22HiHp", None, 3),
+ ByteField("r22HiLp", None),
+ ByteField("r23LoHp", None),
+
+ BitField("r23LoLp", None, 5),
+ BitField("r23HiHp", None, 3),
+ ByteField("r23HiLp", None),
+ ByteField("r24LoHp", None),
+
+ BitField("r24LoLp", None, 5),
+ BitField("r24HiHp", None, 3),
+ ByteField("r24HiLp", None),
+ ByteField("r25LoHp", None),
+
+ BitField("r25LoLp", None, 5),
+ BitField("r25HiHp", None, 3),
+ ByteField("r25HiLp", None),
+ ByteField("r26LoHp", None),
+
+ BitField("r26LoLp", None, 5),
+ BitField("r26HiHp", None, 3),
+ ByteField("r26HiLp", None),
+ ByteField("r27LoHp", None),
+
+ BitField("r27LoLp", None, 5),
+ BitField("r27HiHp", None, 3),
+ ByteField("r27HiLp", None),
+ ByteField("r28LoHp", None),
+
+ BitField("r28LoLp", None, 5),
+ BitField("r28HiHp", None, 3),
+ ByteField("r28HiLp", None),
+ ByteField("r29LoHp", None),
+
+ BitField("r29LoLp", None, 5),
+ BitField("r29HiHp", None, 3),
+ ByteField("r29HiLp", None),
+ ByteField("r30LoHp", None),
+
+ BitField("r30LoLp", None, 5),
+ BitField("r30HiHp", None, 3),
+ ByteField("r30HiLp", None),
+ ByteField("r31LoHp", None),
+
+ BitField("r31LoLp", None, 5),
+ BitField("r31HiHp", None, 3),
+ ByteField("r31HiLp", None),
+ ByteField("r32LoHp", None),
+
+ BitField("r32LoLp", None, 5),
+ BitField("r32HiHp", None, 3),
+ ByteField("r32HiLp", None),
+ ByteField("r33LoHp", None),
+
+ BitField("r33LoLp", None, 5),
+ BitField("r33HiHp", None, 3),
+ ByteField("r33HiLp", None),
+ ByteField("r34LoHp", None),
+
+ BitField("r34LoLp", None, 5),
+ BitField("r34HiHp", None, 3),
+ ByteField("r34HiLp", None),
+ ByteField("r35LoHp", None),
+
+ BitField("r35LoLp", None, 5),
+ BitField("r35HiHp", None, 3),
+ ByteField("r35HiLp", None),
+ ByteField("r36LoHp", None),
+
+ BitField("r36LoLp", None, 5),
+ BitField("r36HiHp", None, 3),
+ ByteField("r36HiLp", None),
+ ByteField("r37LoHp", None),
+
+ BitField("r37LoLp", None, 5),
+ BitField("r37HiHp", None, 3),
+ ByteField("r37HiLp", None),
+ ByteField("r38LoHp", None),
+
+ BitField("r38LoLp", None, 5),
+ BitField("r38HiHp", None, 3),
+ ByteField("r38HiLp", None),
+ ByteField("r39LoHp", None),
+
+ BitField("r39LoLp", None, 5),
+ BitField("r39HiHp", None, 3),
+ ByteField("r39HiLp", None),
+ ByteField("r40LoHp", None),
+
+ BitField("r40LoLp", None, 5),
+ BitField("r40HiHp", None, 3),
+ ByteField("r40HiLp", None),
+ ByteField("r41LoHp", None),
+
+ BitField("r41LoLp", None, 5),
+ BitField("r41HiHp", None, 3),
+ ByteField("r41HiLp", None),
+ ByteField("r42LoHp", None),
+
+ BitField("r42LoLp", None, 5),
+ BitField("r42HiHp", None, 3),
+ ByteField("r42HiLp", None),
+ ByteField("r43LoHp", None),
+
+ BitField("r43LoLp", None, 5),
+ BitField("r43HiHp", None, 3),
+ ByteField("r43HiLp", None),
+ ByteField("r44LoHp", None),
+
+ BitField("r44LoLp", None, 5),
+ BitField("r44HiHp", None, 3),
+ ByteField("r44HiLp", None),
+ ByteField("r45LoHp", None),
+
+ BitField("r45LoLp", None, 5),
+ BitField("r45HiHp", None, 3),
+ ByteField("r45HiLp", None),
+ ByteField("r46LoHp", None),
+
+ BitField("r46LoLp", None, 5),
+ BitField("r46HiHp", None, 3),
+ ByteField("r46HiLp", None),
+ ByteField("r47LoHp", None),
+
+ BitField("r47LoLp", None, 5),
+ BitField("r47HiHp", None, 3),
+ ByteField("r47HiLp", None),
+ ByteField("r48LoHp", None),
+
+ BitField("r48LoLp", None, 5),
+ BitField("r48HiHp", None, 3),
+ ByteField("r48HiLp", None),
+ ByteField("r49LoHp", None),
+
+ BitField("r49LoLp", None, 5),
+ BitField("r49HiHp", None, 3),
+ ByteField("r49HiLp", None),
+ ByteField("r50LoHp", None),
+
+ BitField("r50LoLp", None, 5),
+ BitField("r50HiHp", None, 3),
+ ByteField("r50HiLp", None),
+ ByteField("r51LoHp", None),
+
+ BitField("r51LoLp", None, 5),
+ BitField("r51HiHp", None, 3),
+ ByteField("r51HiLp", None),
+ ByteField("r52LoHp", None),
+
+ BitField("r52LoLp", None, 5),
+ BitField("r52HiHp", None, 3),
+ ByteField("r52HiLp", None),
+ ByteField("r53LoHp", None),
+
+ BitField("r53LoLp", None, 5),
+ BitField("r53HiHp", None, 3),
+ ByteField("r53HiLp", None),
+ ByteField("r54LoHp", None),
+
+ BitField("r54LoLp", None, 5),
+ BitField("r54HiHp", None, 3),
+ ByteField("r54HiLp", None),
+ ByteField("r55LoHp", None),
+
+ BitField("r55LoLp", None, 5),
+ BitField("r55HiHp", None, 3),
+ ByteField("r55HiLp", None),
+ ByteField("r56LoHp", None),
+
+ BitField("r56LoLp", None, 5),
+ BitField("r56HiHp", None, 3),
+ ByteField("r56HiLp", None),
+ ByteField("r57LoHp", None),
+
+ BitField("r57LoLp", None, 5),
+ BitField("r57HiHp", None, 3),
+ ByteField("r57HiLp", None),
+ ByteField("r58LoHp", None),
+
+ BitField("r58LoLp", None, 5),
+ BitField("r58HiHp", None, 3),
+ ByteField("r58HiLp", None),
+ ByteField("r59LoHp", None),
+
+ BitField("r59LoLp", None, 5),
+ BitField("r59HiHp", None, 3),
+ ByteField("r59HiLp", None),
+ ByteField("r60LoHp", None),
+
+ BitField("r60LoLp", None, 5),
+ BitField("r60HiHp", None, 3),
+ ByteField("r60HiLp", None),
+ ByteField("r61LoHp", None),
+
+ BitField("r61LoLp", None, 5),
+ BitField("r61HiHp", None, 3),
+ ByteField("r61HiLp", None),
+ ByteField("r62LoHp", None),
+
+ BitField("r62LoLp", None, 5),
+ BitField("r62HiHp", None, 3),
+ ByteField("r62HiLp", None),
+ ByteField("r63LoHp", None),
+
+ BitField("r63LoLp", None, 5),
+ BitField("r63HiHp", None, 3),
+ ByteField("r63HiLp", None),
+ ByteField("r64LoHp", None),
+
+ BitField("r64LoLp", None, 5),
+ BitField("r64HiHp", None, 3),
+ ByteField("r64HiLp", None),
+ ByteField("r65LoHp", None),
+
+ BitField("r65LoLp", None, 5),
+ BitField("r65HiHp", None, 3),
+ ByteField("r65HiLp", None),
+ ByteField("r66LoHp", None),
+
+ BitField("r66LoLp", None, 5),
+ BitField("r66HiHp", None, 3),
+ ByteField("r66HiLp", None),
+ ByteField("r67LoHp", None),
+
+ BitField("r67LoLp", None, 5),
+ BitField("r67HiHp", None, 3),
+ ByteField("r67HiLp", None),
+ ByteField("r68LoHp", None),
+
+ BitField("r68LoLp", None, 5),
+ BitField("r68HiHp", None, 3),
+ ByteField("r68HiLp", None),
+ ByteField("r69LoHp", None),
+
+ BitField("r69LoLp", None, 5),
+ BitField("r69HiHp", None, 3),
+ ByteField("r69HiLp", None),
+ ByteField("r70LoHp", None),
+
+ BitField("r70LoLp", None, 5),
+ BitField("r70HiHp", None, 3),
+ ByteField("r70HiLp", None),
+ ByteField("r71LoHp", None),
+
+ BitField("r71LoLp", None, 5),
+ BitField("r71HiHp", None, 3),
+ ByteField("r71HiLp", None),
+ ByteField("r72LoHp", None),
+
+ BitField("r72LoLp", None, 5),
+ BitField("r72HiHp", None, 3),
+ ByteField("r72HiLp", None),
+ ByteField("r73LoHp", None),
+
+ BitField("r73LoLp", None, 5),
+ BitField("r73HiHp", None, 3),
+ ByteField("r73HiLp", None),
+ ByteField("r74LoHp", None),
+
+ BitField("r74LoLp", None, 5),
+ BitField("r74HiHp", None, 3),
+ ByteField("r74HiLp", None),
+ ByteField("r75LoHp", None),
+
+ BitField("r75LoLp", None, 5),
+ BitField("r75HiHp", None, 3),
+ ByteField("r75HiLp", None),
+ ByteField("r76LoHp", None),
+
+ BitField("r76LoLp", None, 5),
+ BitField("r76HiHp", None, 3),
+ ByteField("r76HiLp", None),
+ ByteField("r77LoHp", None),
+
+ BitField("r77LoLp", None, 5),
+ BitField("r77HiHp", None, 3),
+ ByteField("r77HiLp", None),
+ ByteField("r78LoHp", None),
+
+ BitField("r78LoLp", None, 5),
+ BitField("r78HiHp", None, 3),
+ ByteField("r78HiLp", None),
+ ByteField("r79LoHp", None),
+
+ BitField("r79LoLp", None, 5),
+ BitField("r79HiHp", None, 3),
+ ByteField("r79HiLp", None),
+ ByteField("r80LoHp", None),
+
+ BitField("r80LoLp", None, 5),
+ BitField("r80HiHp", None, 3),
+ ByteField("r80HiLp", None),
+ ByteField("r81LoHp", None),
+
+ BitField("r81LoLp", None, 5),
+ BitField("r81HiHp", None, 3),
+ ByteField("r81HiLp", None),
+ ByteField("r82LoHp", None),
+
+ BitField("r82LoLp", None, 5),
+ BitField("r82HiHp", None, 3),
+ ByteField("r82HiLp", None),
+ ByteField("r83LoHp", None),
+
+ BitField("r83LoLp", None, 5),
+ BitField("r83HiHp", None, 3),
+ ByteField("r83HiLp", None),
+ ByteField("r84LoHp", None),
+
+ BitField("r84LoLp", None, 5),
+ BitField("r84HiHp", None, 3),
+ ByteField("r84HiLp", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(5, 253, a, self.fields_desc, 1)
+ if self.lengthBR is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 3 to max for L3 message (251)
+class BaListPref(Packet):
+ """ BA List Pref Section 10.5.2.1c """
+ name = "BA List Pref"
+ fields_desc = [
+ XByteField("lengthBLP", None),
+
+ BitField("fixBit", 0x0, 1),
+ BitField("rangeLower", 0x0, 10),
+ BitField("fixBit2", 0x0, 1),
+ BitField("rangeUpper", 0x0, 10),
+ BitField("baFreq", 0x0, 10),
+ BitField("sparePad", 0x0, 8)
+ ]
+
+
+# len 17 || Have a look at the specs for the field format
+# Bit map 0 format
+# Range 1024 format
+# Range 512 format
+# Range 256 format
+# Range 128 format
+# Variable bit map format
+class CellChannelDescription(Packet):
+ """ Cell Channel Description Section 10.5.2.1b """
+ name = "Cell Channel Description "
+ fields_desc = [
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ ByteField("bit120", 0x0),
+ ByteField("bit112", 0x0),
+ ByteField("bit104", 0x0),
+ ByteField("bit96", 0x0),
+ ByteField("bit88", 0x0),
+ ByteField("bit80", 0x0),
+ ByteField("bit72", 0x0),
+ ByteField("bit64", 0x0),
+ ByteField("bit56", 0x0),
+ ByteField("bit48", 0x0),
+ ByteField("bit40", 0x0),
+ ByteField("bit32", 0x0),
+ ByteField("bit24", 0x0),
+ ByteField("bit16", 0x0),
+ ByteField("bit8", 0x0)
+ ]
+
+
+class CellDescription(Packet):
+ """ Cell Description Section 10.5.2.2 """
+ name = "Cell Description"
+ fields_desc = [
+ BitField("bcchHigh", 0x0, 2),
+ BitField("ncc", 0x0, 3),
+ BitField("bcc", 0x0, 3),
+ ByteField("bcchLow", 0x0)
+ ]
+
+
+class CellOptionsBCCH(Packet):
+ """ Cell Options (BCCH) Section 10.5.2.3 """
+ name = "Cell Options (BCCH)"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("pwrc", 0x0, 1),
+ BitField("dtx", 0x0, 2),
+ BitField("rLinkTout", 0x0, 4)
+ ]
+
+
+class CellOptionsSACCH(Packet):
+ """ Cell Options (SACCH) Section 10.5.2.3a """
+ name = "Cell Options (SACCH)"
+ fields_desc = [
+ BitField("dtx", 0x0, 1),
+ BitField("pwrc", 0x0, 1),
+ BitField("dtx", 0x0, 1),
+ BitField("rLinkTout", 0x0, 4)
+ ]
+
+
+class CellSelectionParameters(Packet):
+ """ Cell Selection Parameters Section 10.5.2.4 """
+ name = "Cell Selection Parameters"
+ fields_desc = [
+ BitField("cellReselect", 0x0, 3),
+ BitField("msTxPwrMax", 0x0, 5),
+ BitField("acs", None, 1),
+ BitField("neci", None, 1),
+ BitField("rxlenAccMin", None, 6)
+ ]
+
+
+class MacModeAndChannelCodingRequest(Packet):
+ """ MAC Mode and Channel Coding Requested Section 10.5.2.4a """
+ name = "MAC Mode and Channel Coding Requested"
+ fields_desc = [
+ BitField("macMode", 0x0, 2),
+ BitField("cs", 0x0, 2)
+ ]
+
+
+class ChannelDescription(Packet):
+ """ Channel Description Section 10.5.2.5 """
+ name = "Channel Description"
+ fields_desc = [
+
+ BitField("channelTyp", 0x0, 5),
+ BitField("tn", 0x0, 3),
+
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x1, 1),
+ BitField("maioHi", 0x0, 4),
+
+ BitField("maioLo", 0x0, 2),
+ BitField("hsn", 0x0, 6)
+ ]
+
+
+class ChannelDescription2(Packet):
+ """ Channel Description 2 Section 10.5.2.5a """
+ name = "Channel Description 2"
+ fields_desc = [
+ BitField("channelTyp", 0x0, 5),
+ BitField("tn", 0x0, 3),
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x0, 1),
+ # if h=1
+ # BitField("maioHi", 0x0, 4),
+ # BitField("maioLo", 0x0, 2),
+ # BitField("hsn", 0x0, 6)
+ BitField("spare", 0x0, 2),
+ BitField("arfcnHigh", 0x0, 2),
+ ByteField("arfcnLow", 0x0)
+ ]
+
+
+class ChannelMode(Packet):
+ """ Channel Mode Section 10.5.2.6 """
+ name = "Channel Mode"
+ fields_desc = [
+ ByteField("mode", 0x0)
+ ]
+
+
+class ChannelMode2(Packet):
+ """ Channel Mode 2 Section 10.5.2.7 """
+ name = "Channel Mode 2"
+ fields_desc = [
+ ByteField("mode", 0x0)
+ ]
+
+
+class ChannelNeeded(Packet):
+ """ Channel Needed Section 10.5.2.8 """
+ name = "Channel Needed"
+ fields_desc = [
+ BitField("channel2", 0x0, 2),
+ BitField("channel1", 0x0, 2),
+ ]
+
+
+class ChannelRequestDescription(Packet):
+ """Channel Request Description Section 10.5.2.8a """
+ name = "Channel Request Description"
+ fields_desc = [
+ BitField("mt", 0x0, 1),
+ ConditionalField(BitField("spare", 0x0, 39),
+ lambda pkt: pkt.mt == 0),
+ ConditionalField(BitField("spare", 0x0, 3),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("priority", 0x0, 2),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("rlcMode", 0x0, 1),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(BitField("llcFrame", 0x1, 1),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("reqBandMsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("reqBandLsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("rlcMsb", 0x0),
+ lambda pkt: pkt.mt == 1),
+ ConditionalField(ByteField("rlcLsb", 0x0),
+ lambda pkt: pkt.mt == 1)
+ ]
+
+
+class CipherModeSetting(Packet):
+ """Cipher Mode Setting Section 10.5.2.9 """
+ name = "Cipher Mode Setting"
+ fields_desc = [
+ BitField("algoId", 0x0, 3),
+ BitField("sc", 0x0, 1),
+ ]
+
+
+class CipherResponse(Packet):
+ """Cipher Response Section 10.5.2.10 """
+ name = "Cipher Response"
+ fields_desc = [
+ BitField("spare", 0x0, 3),
+ BitField("cr", 0x0, 1),
+ ]
+
+
+class ControlChannelDescription(Packet):
+ """Control Channel Description Section 10.5.2.11 """
+ name = "Control Channel Description"
+ fields_desc = [
+
+ BitField("spare", 0x0, 1),
+ BitField("att", 0x0, 1),
+ BitField("bsAgBlksRes", 0x0, 3),
+ BitField("ccchConf", 0x0, 3),
+
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("spare3", 0x0, 1),
+ BitField("spare4", 0x0, 1),
+ BitField("bsPaMfrms", 0x0, 3),
+
+ ByteField("t3212", 0x0)
+ ]
+
+
+class FrequencyChannelSequence(Packet):
+ """Frequency Channel Sequence Section 10.5.2.12"""
+ name = "Frequency Channel Sequence"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("lowestArfcn", 0x0, 7),
+ BitField("skipArfcn01", 0x0, 4),
+ BitField("skipArfcn02", 0x0, 4),
+ BitField("skipArfcn03", 0x0, 4),
+ BitField("skipArfcn04", 0x0, 4),
+ BitField("skipArfcn05", 0x0, 4),
+ BitField("skipArfcn06", 0x0, 4),
+ BitField("skipArfcn07", 0x0, 4),
+ BitField("skipArfcn08", 0x0, 4),
+ BitField("skipArfcn09", 0x0, 4),
+ BitField("skipArfcn10", 0x0, 4),
+ BitField("skipArfcn11", 0x0, 4),
+ BitField("skipArfcn12", 0x0, 4),
+ BitField("skipArfcn13", 0x0, 4),
+ BitField("skipArfcn14", 0x0, 4),
+ BitField("skipArfcn15", 0x0, 4),
+ BitField("skipArfcn16", 0x0, 4)
+ ]
+
+
+class FrequencyList(Packet):
+ """Frequency List Section 10.5.2.13"""
+ name = "Frequency List"
+ # Problem:
+ # There are several formats for the Frequency List information
+ # element, distinguished by the "format indicator" subfield.
+ # Some formats are frequency bit maps, the others use a special encoding
+ # scheme.
+ fields_desc = [
+ XByteField("lengthFL", None),
+
+ BitField("formatID", 0x0, 2),
+ BitField("spare", 0x0, 2),
+ BitField("arfcn124", 0x0, 1),
+ BitField("arfcn123", 0x0, 1),
+ BitField("arfcn122", 0x0, 1),
+ BitField("arfcn121", 0x0, 1),
+
+ ByteField("arfcn120", 0x0),
+ ByteField("arfcn112", 0x0),
+ ByteField("arfcn104", 0x0),
+ ByteField("arfcn96", 0x0),
+ ByteField("arfcn88", 0x0),
+ ByteField("arfcn80", 0x0),
+ ByteField("arfcn72", 0x0),
+ ByteField("arfcn64", 0x0),
+ ByteField("arfcn56", 0x0),
+ ByteField("arfcn48", 0x0),
+ ByteField("arfcn40", 0x0),
+ ByteField("arfcn32", 0x0),
+ ByteField("arfcn24", 0x0),
+ ByteField("arfcn16", 0x0),
+ ByteField("arfcn8", 0x0)
+ ]
+
+
+# len 4 to 13
+class GroupChannelDescription(Packet):
+ """Group Channel Description Section 10.5.2.14b"""
+ name = "Group Channel Description"
+ fields_desc = [
+ XByteField("lengthGCD", None),
+
+ BitField("channelType", 0x0, 5),
+ BitField("tn", 0x0, 3),
+
+ BitField("tsc", 0x0, 3),
+ BitField("h", 0x0, 1),
+ # if h == 0 the packet looks the following way:
+ ConditionalField(BitField("spare", 0x0, 2),
+ lambda pkt: pkt. h == 0x0),
+ ConditionalField(BitField("arfcnHi", 0x0, 2),
+ lambda pkt: pkt. h == 0x0),
+ ConditionalField(ByteField("arfcnLo", None),
+ lambda pkt: pkt. h == 0x0),
+ # if h == 1 the packet looks the following way:
+ ConditionalField(BitField("maioHi", 0x0, 4),
+ lambda pkt: pkt. h == 0x1),
+ ConditionalField(BitField("maioLo", None, 2),
+ lambda pkt: pkt. h == 0x1),
+ ConditionalField(BitField("hsn", None, 6),
+ lambda pkt: pkt. h == 0x1),
+ # finished with conditional fields
+ ByteField("maC6", None),
+ ByteField("maC7", None),
+ ByteField("maC8", None),
+ ByteField("maC9", None),
+ ByteField("maC10", None),
+ ByteField("maC11", None),
+ ByteField("maC12", None),
+ ByteField("maC13", None),
+ ByteField("maC14", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(4, 13, a, self.fields_desc, 1)
+ if self.lengthGCD is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class GprsResumption(Packet):
+ """GPRS Resumption Section 10.5.2.14c"""
+ name = "GPRS Resumption"
+ fields_desc = [
+ BitField("spare", 0x0, 3),
+ BitField("ack", 0x0, 1)
+ ]
+
+
+class HandoverReference(Packet):
+ """Handover Reference Section 10.5.2.15"""
+ name = "Handover Reference"
+ fields_desc = [
+ ByteField("handoverRef", 0x0)
+ ]
+
+
+class IraRestOctets(Packet):
+ """IAR Rest Octets Section 10.5.2.17"""
+ name = "IAR Rest Octets"
+ fields_desc = [
+ BitField("spare01", 0x0, 1),
+ BitField("spare02", 0x0, 1),
+ BitField("spare03", 0x1, 1),
+ BitField("spare04", 0x0, 1),
+ BitField("spare05", 0x1, 1),
+ BitField("spare06", 0x0, 1),
+ BitField("spare07", 0x1, 1),
+ BitField("spare08", 0x1, 1),
+ BitField("spare09", 0x0, 1),
+ BitField("spare10", 0x0, 1),
+ BitField("spare11", 0x1, 1),
+ BitField("spare12", 0x0, 1),
+ BitField("spare13", 0x1, 1),
+ BitField("spare14", 0x0, 1),
+ BitField("spare15", 0x1, 1),
+ BitField("spare16", 0x1, 1),
+ BitField("spare17", 0x0, 1),
+ BitField("spare18", 0x0, 1),
+ BitField("spare19", 0x1, 1),
+ BitField("spare20", 0x0, 1),
+ BitField("spare21", 0x1, 1),
+ BitField("spare22", 0x0, 1),
+ BitField("spare23", 0x1, 1),
+ BitField("spare24", 0x1, 1)
+ ]
+
+
+# len is 1 to 5 what do we do with the variable size? no lenght
+# field?! WTF
+class IaxRestOctets(Packet):
+ """IAX Rest Octets Section 10.5.2.18"""
+ name = "IAX Rest Octets"
+ fields_desc = [
+ BitField("spare01", 0x0, 1),
+ BitField("spare02", 0x0, 1),
+ BitField("spare03", 0x1, 1),
+ BitField("spare04", 0x0, 1),
+ BitField("spare05", 0x1, 1),
+ BitField("spare06", 0x0, 1),
+ BitField("spare07", 0x1, 1),
+ BitField("spare08", 0x1, 1),
+ ByteField("spareB1", None),
+ ByteField("spareB2", None),
+ ByteField("spareB3", None)
+ ]
+
+
+class L2PseudoLength(Packet):
+ """L2 Pseudo Length Section 10.5.2.19"""
+ name = "L2 Pseudo Length"
+ fields_desc = [
+ BitField("l2pLength", None, 6),
+ BitField("bit2", 0x0, 1),
+ BitField("bit1", 0x1, 1)
+ ]
+
+
+class MeasurementResults(Packet):
+ """Measurement Results Section 10.5.2.20"""
+ name = "Measurement Results"
+ fields_desc = [
+ BitField("baUsed", 0x0, 1),
+ BitField("dtxUsed", 0x0, 1),
+ BitField("rxLevFull", 0x0, 6),
+
+ BitField("spare", 0x0, 1),
+ BitField("measValid", 0x0, 1),
+ BitField("rxLevSub", 0x0, 6),
+
+ BitField("spare0", 0x0, 1),
+ BitField("rxqualFull", 0x0, 3),
+ BitField("rxqualSub", 0x0, 3),
+ BitField("noNcellHi", 0x0, 1),
+
+ BitField("noNcellLo", 0x0, 2),
+ BitField("rxlevC1", 0x0, 6),
+
+ BitField("bcchC1", 0x0, 5),
+ BitField("bsicC1Hi", 0x0, 3),
+
+ BitField("bsicC1Lo", 0x0, 3),
+ BitField("rxlevC2", 0x0, 5),
+
+ BitField("rxlevC2Lo", 0x0, 1),
+ BitField("bcchC2", 0x0, 5),
+ BitField("bsicC2Hi", 0x0, 2),
+
+ BitField("bscicC2Lo", 0x0, 4),
+ BitField("bscicC2Hi", 0x0, 4),
+
+ BitField("rxlevC3Lo", 0x0, 2),
+ BitField("bcchC3", 0x0, 5),
+ BitField("rxlevC3Hi", 0x0, 1),
+
+ BitField("bsicC3Lo", 0x0, 5),
+ BitField("bsicC3Hi", 0x0, 3),
+
+ BitField("rxlevC4Lo", 0x0, 3),
+ BitField("bcchC4", 0x0, 5),
+
+ BitField("bsicC4", 0x0, 6),
+ BitField("rxlevC5Hi", 0x0, 2),
+
+ BitField("rxlevC5Lo", 0x0, 4),
+ BitField("bcchC5Hi", 0x0, 4),
+
+ BitField("bcchC5Lo", 0x0, 1),
+ BitField("bsicC5", 0x0, 6),
+ BitField("rxlevC6", 0x0, 1),
+
+ BitField("rxlevC6Lo", 0x0, 5),
+ BitField("bcchC6Hi", 0x0, 3),
+
+ BitField("bcchC6Lo", 0x0, 3),
+ BitField("bsicC6", 0x0, 5)
+ ]
+
+
+class GprsMeasurementResults(Packet):
+ """GPRS Measurement Results Section 10.5.2.20a"""
+ name = "GPRS Measurement Results"
+ fields_desc = [
+ BitField("cValue", 0x0, 6),
+ BitField("rxqualHi", 0x0, 2),
+ BitField("rxqL", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("signVar", 0x0, 6)
+ ]
+
+
+# len 3 to 10
+class MobileAllocation(Packet):
+ """Mobile Allocation Section 10.5.2.21"""
+ name = "Mobile Allocation"
+ fields_desc = [
+ XByteField("lengthMA", None),
+ ByteField("maC64", 0x12),
+ ByteField("maC56", None), # optional fields start here
+ ByteField("maC48", None),
+ ByteField("maC40", None),
+ ByteField("maC32", None),
+ ByteField("maC24", None),
+ ByteField("maC16", None),
+ ByteField("maC8", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 9, a, self.fields_desc, 1)
+ if self.lengthMA is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MobileTimeDifference(Packet):
+ """Mobile Time Difference Section 10.5.2.21a"""
+ name = "Mobile Time Difference"
+ fields_desc = [
+ XByteField("lengthMTD", 0x5),
+ ByteField("valueHi", 0x0),
+ ByteField("valueCnt", 0x0),
+ BitField("valueLow", 0x0, 5),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1)
+ ]
+
+
+# min 4 octets max 8
+class MultiRateConfiguration(Packet):
+ """ MultiRate configuration Section 10.5.2.21aa"""
+ name = "MultiRate Configuration"
+ # This packet has a variable length and hence structure. This packet
+ # implements the longuest possible packet. If you biuild a shorter
+ # packet, for example having only 6 bytes, the last 4 bytes are named
+ # "Spare" in the specs. Here they are named "threshold2"
+ fields_desc = [
+ XByteField("lengthMRC", None),
+
+ BitField("mrVersion", 0x0, 3),
+ BitField("spare", 0x0, 1),
+ BitField("icmi", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("startMode", 0x0, 2),
+
+ ByteField("amrCodec", None),
+
+ BitField("spare", None, 2),
+ BitField("threshold1", None, 6),
+
+ BitField("hysteresis1", None, 4),
+ BitField("threshold2", None, 4),
+
+ BitField("threshold2cnt", None, 2),
+ BitField("hysteresis2", None, 4),
+ BitField("threshold3", None, 2),
+
+ BitField("threshold3cnt", None, 4),
+ BitField("hysteresis3", None, 4)
+ ]
+
+ def post_build(self, p, pay):
+ # we set the length
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 7, a, self.fields_desc, 1)
+ if self.lengthMRC is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 2 to 11
+class MultislotAllocation(Packet):
+ """Multislot Allocation Section 10.5.2.21b"""
+ name = "Multislot Allocation"
+ fields_desc = [
+ XByteField("lengthMSA", None),
+ BitField("ext0", 0x1, 1),
+ BitField("da", 0x0, 7),
+ ConditionalField(BitField("ext1", 0x1, 1), # optional
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("ua", 0x0, 7),
+ lambda pkt: pkt.ext0 == 0),
+ ByteField("chan1", None),
+ ByteField("chan2", None),
+ ByteField("chan3", None),
+ ByteField("chan4", None),
+ ByteField("chan5", None),
+ ByteField("chan6", None),
+ ByteField("chan7", None),
+ ByteField("chan8", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 11, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthMSA is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+class NcMode(Packet):
+ """NC mode Section 10.5.2.21c"""
+ name = "NC Mode"
+ fields_desc = [
+ BitField("spare", 0x0, 2),
+ BitField("ncMode", 0x0, 2)
+ ]
+
+
+class NeighbourCellsDescription(Packet):
+ """Neighbour Cells Description Section 10.5.2.22"""
+ name = "Neighbour Cells Description"
+ fields_desc = [
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("extInd", 0x0, 1),
+ BitField("baInd", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ BitField("120bits", 0x0, 120)
+ ]
+
+
+class NeighbourCellsDescription2(Packet):
+ """Neighbour Cells Description 2 Section 10.5.2.22a"""
+ name = "Neighbour Cells Description 2"
+ fields_desc = [
+ BitField("bit128", 0x0, 1),
+ BitField("multiband", 0x0, 2),
+ BitField("baInd", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+ BitField("120bits", 0x0, 120)
+ ]
+
+
+# len 4
+# strange packet, lots of valid formats
+
+# ideas for the dynamic packets:
+# 1] for user interaction: Create an interactive "builder" based on a
+# Q/A process (not very scapy like)
+# 2] for usage in scripts, create an alternative packet for every
+# possible packet layout
+#
+
+class DedicatedModeOrTBF(Packet):
+ """Dedicated mode or TBF Section 10.5.2.25b"""
+ name = "Dedicated Mode or TBF"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("tma", 0x0, 1),
+ BitField("downlink", 0x0, 1),
+ BitField("td", 0x0, 1)
+ ]
+
+
+class PageMode(Packet):
+ """Page Mode Section 10.5.2.26"""
+ name = "Page Mode"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("pm", 0x0, 2)
+ ]
+
+
+class NccPermitted(Packet):
+ """NCC Permitted Section 10.5.2.27"""
+ name = "NCC Permited"
+ fields_desc = [
+ ByteField("nccPerm", 0x0)
+ ]
+
+
+class PowerCommand(Packet):
+ """Power Command Section 10.5.2.28"""
+ name = "Power Command"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("spare2", 0x0, 1),
+ BitField("powerLvl", 0x0, 5)
+ ]
+
+
+class PowerCommandAndAccessType(Packet):
+ """Power Command and access type Section 10.5.2.28a"""
+ name = "Power Command and Access Type"
+ fields_desc = [
+ BitField("atc", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("powerLvl", 0x0, 5)
+ ]
+
+
+class RachControlParameters(Packet):
+ """RACH Control Parameters Section 10.5.2.29"""
+ name = "RACH Control Parameters"
+ fields_desc = [
+ BitField("maxRetrans", 0x0, 2),
+ BitField("txInteger", 0x0, 4),
+ BitField("cellBarrAccess", 0x0, 1),
+ BitField("re", 0x0, 1),
+ BitField("ACC15", 0x0, 1),
+ BitField("ACC14", 0x0, 1),
+ BitField("ACC13", 0x0, 1),
+ BitField("ACC12", 0x0, 1),
+ BitField("ACC11", 0x0, 1),
+ BitField("ACC10", 0x0, 1),
+ BitField("ACC09", 0x0, 1),
+ BitField("ACC08", 0x0, 1),
+ BitField("ACC07", 0x0, 1),
+ BitField("ACC06", 0x0, 1),
+ BitField("ACC05", 0x0, 1),
+ BitField("ACC04", 0x0, 1),
+ BitField("ACC03", 0x0, 1),
+ BitField("ACC02", 0x0, 1),
+ BitField("ACC01", 0x0, 1),
+ BitField("ACC00", 0x0, 1),
+ ]
+
+
+class RequestReference(Packet):
+ """Request Reference Section 10.5.2.30"""
+ name = "Request Reference"
+ fields_desc = [
+ ByteField("ra", 0x0),
+ BitField("t1", 0x0, 5),
+ BitField("t3Hi", 0x0, 3),
+ BitField("t3Lo", 0x0, 3),
+ BitField("t2", 0x0, 5)
+ ]
+
+
+class RrCause(Packet):
+ """RR Cause Section 10.5.2.31"""
+ name = "RR Cause"
+ fields_desc = [
+ ByteField("rrCause", 0x0)
+ ]
+
+
+class StartingTime(Packet):
+ """Starting Time Section 10.5.2.38"""
+ name = "Starting Time"
+ fields_desc = [
+ ByteField("ra", 0x0),
+ BitField("t1", 0x0, 5),
+ BitField("t3Hi", 0x0, 3),
+ BitField("t3Lo", 0x0, 3),
+ BitField("t2", 0x0, 5)
+ ]
+
+
+class SynchronizationIndication(Packet):
+ """Synchronization Indication Section 10.5.2.39"""
+ name = "Synchronization Indication"
+ fields_desc = [
+ BitField("nci", 0x0, 1),
+ BitField("rot", 0x0, 1),
+ BitField("si", 0x0, 2)
+ ]
+
+
+class TimingAdvance(Packet):
+ """Timing Advance Section 10.5.2.40"""
+ name = "Timing Advance"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1),
+ BitField("timingVal", 0x0, 6)
+ ]
+
+
+class TimeDifference(Packet):
+ """ Time Difference Section 10.5.2.41"""
+ name = "Time Difference"
+ fields_desc = [
+ XByteField("lengthTD", 0x3),
+ ByteField("timeValue", 0x0)
+ ]
+
+
+class Tlli(Packet):
+ """ TLLI Section Section 10.5.2.41a"""
+ name = "TLLI"
+ fields_desc = [
+ ByteField("value", 0x0),
+ ByteField("value1", 0x0),
+ ByteField("value2", 0x0),
+ ByteField("value3", 0x0)
+ ]
+
+
+class TmsiPTmsi(Packet):
+ """ TMSI/P-TMSI Section 10.5.2.42"""
+ name = "TMSI/P-TMSI"
+ fields_desc = [
+ ByteField("value", 0x0),
+ ByteField("value1", 0x0),
+ ByteField("value2", 0x0),
+ ByteField("value3", 0x0)
+ ]
+
+
+class VgcsTargetModeIdentication(Packet):
+ """ VGCS target Mode Indication 10.5.2.42a"""
+ name = "VGCS Target Mode Indication"
+ fields_desc = [
+ XByteField("lengthVTMI", 0x2),
+ BitField("targerMode", 0x0, 2),
+ BitField("cipherKeyNb", 0x0, 4),
+ BitField("spare", 0x0, 1),
+ BitField("spare1", 0x0, 1)
+ ]
+
+
+class WaitIndication(Packet):
+ """ Wait Indication Section 10.5.2.43"""
+ name = "Wait Indication"
+ fields_desc = [ # asciiart of specs strange
+ ByteField("timeoutVal", 0x0)
+ ]
+
+
+#class Si10RestOctets(Packet):
+# """SI10 rest octets 10.5.2.44"""
+# name = "SI10 rest octets"
+# fields_desc = [
+
+
+# len 17
+class ExtendedMeasurementResults(Packet):
+ """EXTENDED MEASUREMENT RESULTS Section 10.5.2.45"""
+ name = "Extended Measurement Results"
+ fields_desc = [
+
+ BitField("scUsed", None, 1),
+ BitField("dtxUsed", None, 1),
+ BitField("rxLevC0", None, 6),
+
+ BitField("rxLevC1", None, 6),
+ BitField("rxLevC2Hi", None, 2),
+
+ BitField("rxLevC2Lo", None, 4),
+ BitField("rxLevC3Hi", None, 4),
+
+ BitField("rxLevC3Lo", None, 3),
+ BitField("rxLevC4", None, 5),
+
+ BitField("rxLevC5", None, 6),
+ BitField("rxLevC6Hi", None, 2),
+
+ BitField("rxLevC6Lo", None, 4),
+ BitField("rxLevC7Hi", None, 4),
+
+ BitField("rxLevC7Lo", None, 2),
+ BitField("rxLevC8", None, 6),
+
+ BitField("rxLevC9", None, 6),
+ BitField("rxLevC10Hi", None, 2),
+
+ BitField("rxLevC10Lo", None, 4),
+ BitField("rxLevC11Hi", None, 4),
+
+ BitField("rxLevC13Lo", None, 2),
+ BitField("rxLevC12", None, 6),
+
+ BitField("rxLevC13", None, 6),
+ BitField("rxLevC14Hi", None, 2),
+
+ BitField("rxLevC14Lo", None, 4),
+ BitField("rxLevC15Hi", None, 4),
+
+ BitField("rxLevC15Lo", None, 2),
+ BitField("rxLevC16", None, 6),
+
+
+ BitField("rxLevC17", None, 6),
+ BitField("rxLevC18Hi", None, 2),
+
+ BitField("rxLevC18Lo", None, 4),
+ BitField("rxLevC19Hi", None, 4),
+
+ BitField("rxLevC19Lo", None, 2),
+ BitField("rxLevC20", None, 6)
+ ]
+
+
+# len 17
+class ExtendedMeasurementFrequencyList(Packet):
+ """Extended Measurement Frequency List Section 10.5.2.46"""
+ name = "Extended Measurement Frequency List"
+ fields_desc = [
+
+ BitField("bit128", 0x0, 1),
+ BitField("bit127", 0x0, 1),
+ BitField("spare", 0x0, 1),
+ BitField("seqCode", 0x0, 1),
+ BitField("bit124", 0x0, 1),
+ BitField("bit123", 0x0, 1),
+ BitField("bit122", 0x0, 1),
+ BitField("bit121", 0x0, 1),
+
+ BitField("bitsRest", 0x0, 128)
+ ]
+
+
+class SuspensionCause(Packet):
+ """Suspension Cause Section 10.5.2.47"""
+ name = "Suspension Cause"
+ fields_desc = [
+ ByteField("suspVal", 0x0)
+ ]
+
+
+class ApduID(Packet):
+ """APDU Flags Section 10.5.2.48"""
+ name = "Apdu Id"
+ fields_desc = [
+ BitField("id", None, 4)
+ ]
+
+
+class ApduFlags(Packet):
+ """APDU Flags Section 10.5.2.49"""
+ name = "Apdu Flags"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("cr", 0x0, 1),
+ BitField("firstSeg", 0x0, 1),
+ BitField("lastSeg", 0x0, 1)
+ ]
+
+
+# len 1 to max L3 (251) (done)
+class ApduData(Packet):
+ """APDU Data Section 10.5.2.50"""
+ name = "Apdu Data"
+ fields_desc = [
+ XByteField("lengthAD", None),
+ #optional
+ ByteField("apuInfo1", None),
+ ByteField("apuInfo2", None),
+ ByteField("apuInfo3", None),
+ ByteField("apuInfo4", None),
+ ByteField("apuInfo5", None),
+ ByteField("apuInfo6", None),
+ ByteField("apuInfo7", None),
+ ByteField("apuInfo8", None),
+ ByteField("apuInfo9", None),
+ ByteField("apuInfo10", None),
+ ByteField("apuInfo11", None),
+ ByteField("apuInfo12", None),
+ ByteField("apuInfo13", None),
+ ByteField("apuInfo14", None),
+ ByteField("apuInfo15", None),
+ ByteField("apuInfo16", None),
+ ByteField("apuInfo17", None),
+ ByteField("apuInfo18", None),
+ ByteField("apuInfo19", None),
+ ByteField("apuInfo20", None),
+ ByteField("apuInfo21", None),
+ ByteField("apuInfo22", None),
+ ByteField("apuInfo23", None),
+ ByteField("apuInfo24", None),
+ ByteField("apuInfo25", None),
+ ByteField("apuInfo26", None),
+ ByteField("apuInfo27", None),
+ ByteField("apuInfo28", None),
+ ByteField("apuInfo29", None),
+ ByteField("apuInfo30", None),
+ ByteField("apuInfo31", None),
+ ByteField("apuInfo32", None),
+ ByteField("apuInfo33", None),
+ ByteField("apuInfo34", None),
+ ByteField("apuInfo35", None),
+ ByteField("apuInfo36", None),
+ ByteField("apuInfo37", None),
+ ByteField("apuInfo38", None),
+ ByteField("apuInfo39", None),
+ ByteField("apuInfo40", None),
+ ByteField("apuInfo41", None),
+ ByteField("apuInfo42", None),
+ ByteField("apuInfo43", None),
+ ByteField("apuInfo44", None),
+ ByteField("apuInfo45", None),
+ ByteField("apuInfo46", None),
+ ByteField("apuInfo47", None),
+ ByteField("apuInfo48", None),
+ ByteField("apuInfo49", None),
+ ByteField("apuInfo50", None),
+ ByteField("apuInfo51", None),
+ ByteField("apuInfo52", None),
+ ByteField("apuInfo53", None),
+ ByteField("apuInfo54", None),
+ ByteField("apuInfo55", None),
+ ByteField("apuInfo56", None),
+ ByteField("apuInfo57", None),
+ ByteField("apuInfo58", None),
+ ByteField("apuInfo59", None),
+ ByteField("apuInfo60", None),
+ ByteField("apuInfo61", None),
+ ByteField("apuInfo62", None),
+ ByteField("apuInfo63", None),
+ ByteField("apuInfo64", None),
+ ByteField("apuInfo65", None),
+ ByteField("apuInfo66", None),
+ ByteField("apuInfo67", None),
+ ByteField("apuInfo68", None),
+ ByteField("apuInfo69", None),
+ ByteField("apuInfo70", None),
+ ByteField("apuInfo71", None),
+ ByteField("apuInfo72", None),
+ ByteField("apuInfo73", None),
+ ByteField("apuInfo74", None),
+ ByteField("apuInfo75", None),
+ ByteField("apuInfo76", None),
+ ByteField("apuInfo77", None),
+ ByteField("apuInfo78", None),
+ ByteField("apuInfo79", None),
+ ByteField("apuInfo80", None),
+ ByteField("apuInfo81", None),
+ ByteField("apuInfo82", None),
+ ByteField("apuInfo83", None),
+ ByteField("apuInfo84", None),
+ ByteField("apuInfo85", None),
+ ByteField("apuInfo86", None),
+ ByteField("apuInfo87", None),
+ ByteField("apuInfo88", None),
+ ByteField("apuInfo89", None),
+ ByteField("apuInfo90", None),
+ ByteField("apuInfo91", None),
+ ByteField("apuInfo92", None),
+ ByteField("apuInfo93", None),
+ ByteField("apuInfo94", None),
+ ByteField("apuInfo95", None),
+ ByteField("apuInfo96", None),
+ ByteField("apuInfo97", None),
+ ByteField("apuInfo98", None),
+ ByteField("apuInfo99", None),
+ ByteField("apuInfo100", None),
+ ByteField("apuInfo101", None),
+ ByteField("apuInfo102", None),
+ ByteField("apuInfo103", None),
+ ByteField("apuInfo104", None),
+ ByteField("apuInfo105", None),
+ ByteField("apuInfo106", None),
+ ByteField("apuInfo107", None),
+ ByteField("apuInfo108", None),
+ ByteField("apuInfo109", None),
+ ByteField("apuInfo110", None),
+ ByteField("apuInfo111", None),
+ ByteField("apuInfo112", None),
+ ByteField("apuInfo113", None),
+ ByteField("apuInfo114", None),
+ ByteField("apuInfo115", None),
+ ByteField("apuInfo116", None),
+ ByteField("apuInfo117", None),
+ ByteField("apuInfo118", None),
+ ByteField("apuInfo119", None),
+ ByteField("apuInfo120", None),
+ ByteField("apuInfo121", None),
+ ByteField("apuInfo122", None),
+ ByteField("apuInfo123", None),
+ ByteField("apuInfo124", None),
+ ByteField("apuInfo125", None),
+ ByteField("apuInfo126", None),
+ ByteField("apuInfo127", None),
+ ByteField("apuInfo128", None),
+ ByteField("apuInfo129", None),
+ ByteField("apuInfo130", None),
+ ByteField("apuInfo131", None),
+ ByteField("apuInfo132", None),
+ ByteField("apuInfo133", None),
+ ByteField("apuInfo134", None),
+ ByteField("apuInfo135", None),
+ ByteField("apuInfo136", None),
+ ByteField("apuInfo137", None),
+ ByteField("apuInfo138", None),
+ ByteField("apuInfo139", None),
+ ByteField("apuInfo140", None),
+ ByteField("apuInfo141", None),
+ ByteField("apuInfo142", None),
+ ByteField("apuInfo143", None),
+ ByteField("apuInfo144", None),
+ ByteField("apuInfo145", None),
+ ByteField("apuInfo146", None),
+ ByteField("apuInfo147", None),
+ ByteField("apuInfo148", None),
+ ByteField("apuInfo149", None),
+ ByteField("apuInfo150", None),
+ ByteField("apuInfo151", None),
+ ByteField("apuInfo152", None),
+ ByteField("apuInfo153", None),
+ ByteField("apuInfo154", None),
+ ByteField("apuInfo155", None),
+ ByteField("apuInfo156", None),
+ ByteField("apuInfo157", None),
+ ByteField("apuInfo158", None),
+ ByteField("apuInfo159", None),
+ ByteField("apuInfo160", None),
+ ByteField("apuInfo161", None),
+ ByteField("apuInfo162", None),
+ ByteField("apuInfo163", None),
+ ByteField("apuInfo164", None),
+ ByteField("apuInfo165", None),
+ ByteField("apuInfo166", None),
+ ByteField("apuInfo167", None),
+ ByteField("apuInfo168", None),
+ ByteField("apuInfo169", None),
+ ByteField("apuInfo170", None),
+ ByteField("apuInfo171", None),
+ ByteField("apuInfo172", None),
+ ByteField("apuInfo173", None),
+ ByteField("apuInfo174", None),
+ ByteField("apuInfo175", None),
+ ByteField("apuInfo176", None),
+ ByteField("apuInfo177", None),
+ ByteField("apuInfo178", None),
+ ByteField("apuInfo179", None),
+ ByteField("apuInfo180", None),
+ ByteField("apuInfo181", None),
+ ByteField("apuInfo182", None),
+ ByteField("apuInfo183", None),
+ ByteField("apuInfo184", None),
+ ByteField("apuInfo185", None),
+ ByteField("apuInfo186", None),
+ ByteField("apuInfo187", None),
+ ByteField("apuInfo188", None),
+ ByteField("apuInfo189", None),
+ ByteField("apuInfo190", None),
+ ByteField("apuInfo191", None),
+ ByteField("apuInfo192", None),
+ ByteField("apuInfo193", None),
+ ByteField("apuInfo194", None),
+ ByteField("apuInfo195", None),
+ ByteField("apuInfo196", None),
+ ByteField("apuInfo197", None),
+ ByteField("apuInfo198", None),
+ ByteField("apuInfo199", None),
+ ByteField("apuInfo200", None),
+ ByteField("apuInfo201", None),
+ ByteField("apuInfo202", None),
+ ByteField("apuInfo203", None),
+ ByteField("apuInfo204", None),
+ ByteField("apuInfo205", None),
+ ByteField("apuInfo206", None),
+ ByteField("apuInfo207", None),
+ ByteField("apuInfo208", None),
+ ByteField("apuInfo209", None),
+ ByteField("apuInfo210", None),
+ ByteField("apuInfo211", None),
+ ByteField("apuInfo212", None),
+ ByteField("apuInfo213", None),
+ ByteField("apuInfo214", None),
+ ByteField("apuInfo215", None),
+ ByteField("apuInfo216", None),
+ ByteField("apuInfo217", None),
+ ByteField("apuInfo218", None),
+ ByteField("apuInfo219", None),
+ ByteField("apuInfo220", None),
+ ByteField("apuInfo221", None),
+ ByteField("apuInfo222", None),
+ ByteField("apuInfo223", None),
+ ByteField("apuInfo224", None),
+ ByteField("apuInfo225", None),
+ ByteField("apuInfo226", None),
+ ByteField("apuInfo227", None),
+ ByteField("apuInfo228", None),
+ ByteField("apuInfo229", None),
+ ByteField("apuInfo230", None),
+ ByteField("apuInfo231", None),
+ ByteField("apuInfo232", None),
+ ByteField("apuInfo233", None),
+ ByteField("apuInfo234", None),
+ ByteField("apuInfo235", None),
+ ByteField("apuInfo236", None),
+ ByteField("apuInfo237", None),
+ ByteField("apuInfo238", None),
+ ByteField("apuInfo239", None),
+ ByteField("apuInfo240", None),
+ ByteField("apuInfo241", None),
+ ByteField("apuInfo242", None),
+ ByteField("apuInfo243", None),
+ ByteField("apuInfo244", None),
+ ByteField("apuInfo245", None),
+ ByteField("apuInfo246", None),
+ ByteField("apuInfo247", None),
+ ByteField("apuInfo248", None),
+ ByteField("apuInfo249", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 250, a, self.fields_desc, 1)
+ if self.lengthAD is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+#
+# 10.5.3 Mobility management information elements
+#
+
+
+# len 3 to L3 max (251) (done)
+class NetworkName(Packet):
+ """Network Name Section 10.5.3.5a"""
+ name = "Network Name"
+ fields_desc = [
+
+ XByteField("lengthNN", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("codingScheme", 0x0, 3),
+ BitField("addCi", 0x0, 1),
+ BitField("nbSpare", 0x0, 3),
+ # optional
+ ByteField("txtString1", None),
+ ByteField("txtString2", None),
+ ByteField("txtString3", None),
+ ByteField("txtString4", None),
+ ByteField("txtString5", None),
+ ByteField("txtString6", None),
+ ByteField("txtString7", None),
+ ByteField("txtString8", None),
+ ByteField("txtString9", None),
+ ByteField("txtString10", None),
+ ByteField("txtString11", None),
+ ByteField("txtString12", None),
+ ByteField("txtString13", None),
+ ByteField("txtString14", None),
+ ByteField("txtString15", None),
+ ByteField("txtString16", None),
+ ByteField("txtString17", None),
+ ByteField("txtString18", None),
+ ByteField("txtString19", None),
+ ByteField("txtString20", None),
+ ByteField("txtString21", None),
+ ByteField("txtString22", None),
+ ByteField("txtString23", None),
+ ByteField("txtString24", None),
+ ByteField("txtString25", None),
+ ByteField("txtString26", None),
+ ByteField("txtString27", None),
+ ByteField("txtString28", None),
+ ByteField("txtString29", None),
+ ByteField("txtString30", None),
+ ByteField("txtString31", None),
+ ByteField("txtString32", None),
+ ByteField("txtString33", None),
+ ByteField("txtString34", None),
+ ByteField("txtString35", None),
+ ByteField("txtString36", None),
+ ByteField("txtString37", None),
+ ByteField("txtString38", None),
+ ByteField("txtString39", None),
+ ByteField("txtString40", None),
+ ByteField("txtString41", None),
+ ByteField("txtString42", None),
+ ByteField("txtString43", None),
+ ByteField("txtString44", None),
+ ByteField("txtString45", None),
+ ByteField("txtString46", None),
+ ByteField("txtString47", None),
+ ByteField("txtString48", None),
+ ByteField("txtString49", None),
+ ByteField("txtString50", None),
+ ByteField("txtString51", None),
+ ByteField("txtString52", None),
+ ByteField("txtString53", None),
+ ByteField("txtString54", None),
+ ByteField("txtString55", None),
+ ByteField("txtString56", None),
+ ByteField("txtString57", None),
+ ByteField("txtString58", None),
+ ByteField("txtString59", None),
+ ByteField("txtString60", None),
+ ByteField("txtString61", None),
+ ByteField("txtString62", None),
+ ByteField("txtString63", None),
+ ByteField("txtString64", None),
+ ByteField("txtString65", None),
+ ByteField("txtString66", None),
+ ByteField("txtString67", None),
+ ByteField("txtString68", None),
+ ByteField("txtString69", None),
+ ByteField("txtString70", None),
+ ByteField("txtString71", None),
+ ByteField("txtString72", None),
+ ByteField("txtString73", None),
+ ByteField("txtString74", None),
+ ByteField("txtString75", None),
+ ByteField("txtString76", None),
+ ByteField("txtString77", None),
+ ByteField("txtString78", None),
+ ByteField("txtString79", None),
+ ByteField("txtString80", None),
+ ByteField("txtString81", None),
+ ByteField("txtString82", None),
+ ByteField("txtString83", None),
+ ByteField("txtString84", None),
+ ByteField("txtString85", None),
+ ByteField("txtString86", None),
+ ByteField("txtString87", None),
+ ByteField("txtString88", None),
+ ByteField("txtString89", None),
+ ByteField("txtString90", None),
+ ByteField("txtString91", None),
+ ByteField("txtString92", None),
+ ByteField("txtString93", None),
+ ByteField("txtString94", None),
+ ByteField("txtString95", None),
+ ByteField("txtString96", None),
+ ByteField("txtString97", None),
+ ByteField("txtString98", None),
+ ByteField("txtString99", None),
+ ByteField("txtString100", None),
+ ByteField("txtString101", None),
+ ByteField("txtString102", None),
+ ByteField("txtString103", None),
+ ByteField("txtString104", None),
+ ByteField("txtString105", None),
+ ByteField("txtString106", None),
+ ByteField("txtString107", None),
+ ByteField("txtString108", None),
+ ByteField("txtString109", None),
+ ByteField("txtString110", None),
+ ByteField("txtString111", None),
+ ByteField("txtString112", None),
+ ByteField("txtString113", None),
+ ByteField("txtString114", None),
+ ByteField("txtString115", None),
+ ByteField("txtString116", None),
+ ByteField("txtString117", None),
+ ByteField("txtString118", None),
+ ByteField("txtString119", None),
+ ByteField("txtString120", None),
+ ByteField("txtString121", None),
+ ByteField("txtString122", None),
+ ByteField("txtString123", None),
+ ByteField("txtString124", None),
+ ByteField("txtString125", None),
+ ByteField("txtString126", None),
+ ByteField("txtString127", None),
+ ByteField("txtString128", None),
+ ByteField("txtString129", None),
+ ByteField("txtString130", None),
+ ByteField("txtString131", None),
+ ByteField("txtString132", None),
+ ByteField("txtString133", None),
+ ByteField("txtString134", None),
+ ByteField("txtString135", None),
+ ByteField("txtString136", None),
+ ByteField("txtString137", None),
+ ByteField("txtString138", None),
+ ByteField("txtString139", None),
+ ByteField("txtString140", None),
+ ByteField("txtString141", None),
+ ByteField("txtString142", None),
+ ByteField("txtString143", None),
+ ByteField("txtString144", None),
+ ByteField("txtString145", None),
+ ByteField("txtString146", None),
+ ByteField("txtString147", None),
+ ByteField("txtString148", None),
+ ByteField("txtString149", None),
+ ByteField("txtString150", None),
+ ByteField("txtString151", None),
+ ByteField("txtString152", None),
+ ByteField("txtString153", None),
+ ByteField("txtString154", None),
+ ByteField("txtString155", None),
+ ByteField("txtString156", None),
+ ByteField("txtString157", None),
+ ByteField("txtString158", None),
+ ByteField("txtString159", None),
+ ByteField("txtString160", None),
+ ByteField("txtString161", None),
+ ByteField("txtString162", None),
+ ByteField("txtString163", None),
+ ByteField("txtString164", None),
+ ByteField("txtString165", None),
+ ByteField("txtString166", None),
+ ByteField("txtString167", None),
+ ByteField("txtString168", None),
+ ByteField("txtString169", None),
+ ByteField("txtString170", None),
+ ByteField("txtString171", None),
+ ByteField("txtString172", None),
+ ByteField("txtString173", None),
+ ByteField("txtString174", None),
+ ByteField("txtString175", None),
+ ByteField("txtString176", None),
+ ByteField("txtString177", None),
+ ByteField("txtString178", None),
+ ByteField("txtString179", None),
+ ByteField("txtString180", None),
+ ByteField("txtString181", None),
+ ByteField("txtString182", None),
+ ByteField("txtString183", None),
+ ByteField("txtString184", None),
+ ByteField("txtString185", None),
+ ByteField("txtString186", None),
+ ByteField("txtString187", None),
+ ByteField("txtString188", None),
+ ByteField("txtString189", None),
+ ByteField("txtString190", None),
+ ByteField("txtString191", None),
+ ByteField("txtString192", None),
+ ByteField("txtString193", None),
+ ByteField("txtString194", None),
+ ByteField("txtString195", None),
+ ByteField("txtString196", None),
+ ByteField("txtString197", None),
+ ByteField("txtString198", None),
+ ByteField("txtString199", None),
+ ByteField("txtString200", None),
+ ByteField("txtString201", None),
+ ByteField("txtString202", None),
+ ByteField("txtString203", None),
+ ByteField("txtString204", None),
+ ByteField("txtString205", None),
+ ByteField("txtString206", None),
+ ByteField("txtString207", None),
+ ByteField("txtString208", None),
+ ByteField("txtString209", None),
+ ByteField("txtString210", None),
+ ByteField("txtString211", None),
+ ByteField("txtString212", None),
+ ByteField("txtString213", None),
+ ByteField("txtString214", None),
+ ByteField("txtString215", None),
+ ByteField("txtString216", None),
+ ByteField("txtString217", None),
+ ByteField("txtString218", None),
+ ByteField("txtString219", None),
+ ByteField("txtString220", None),
+ ByteField("txtString221", None),
+ ByteField("txtString222", None),
+ ByteField("txtString223", None),
+ ByteField("txtString224", None),
+ ByteField("txtString225", None),
+ ByteField("txtString226", None),
+ ByteField("txtString227", None),
+ ByteField("txtString228", None),
+ ByteField("txtString229", None),
+ ByteField("txtString230", None),
+ ByteField("txtString231", None),
+ ByteField("txtString232", None),
+ ByteField("txtString233", None),
+ ByteField("txtString234", None),
+ ByteField("txtString235", None),
+ ByteField("txtString236", None),
+ ByteField("txtString237", None),
+ ByteField("txtString238", None),
+ ByteField("txtString239", None),
+ ByteField("txtString240", None),
+ ByteField("txtString241", None),
+ ByteField("txtString242", None),
+ ByteField("txtString243", None),
+ ByteField("txtString244", None),
+ ByteField("txtString245", None),
+ ByteField("txtString246", None),
+ ByteField("txtString247", None),
+ ByteField("txtString248", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 250, a, self.fields_desc, 1)
+ if self.lengthNN is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class TimeZone(Packet):
+ """Time Zone Section 10.5.3.8"""
+ name = "Time Zone"
+ fields_desc = [
+ ByteField("timeZone", 0x0),
+ ]
+
+
+class TimeZoneAndTime(Packet):
+ """Time Zone and Time Section 10.5.3.9"""
+ name = "Time Zone and Time"
+ fields_desc = [
+ ByteField("year", 0x0),
+ ByteField("month", 0x0),
+ ByteField("day", 0x0),
+ ByteField("hour", 0x0),
+ ByteField("minute", 0x0),
+ ByteField("second", 0x0),
+ ByteField("timeZone", 0x0)
+ ]
+
+
+class CtsPermission(Packet):
+ """CTS permission Section 10.5.3.10"""
+ name = "Cts Permission"
+ fields_desc = [
+ ]
+
+
+class LsaIdentifier(Packet):
+ """LSA Identifier Section 10.5.3.11"""
+ name = "Lsa Identifier"
+ fields_desc = [
+ ByteField("lsaID", 0x0),
+ ByteField("lsaID1", 0x0),
+ ByteField("lsaID2", 0x0)
+ ]
+
+
+#
+# 10.5.4 Call control information elements
+#
+
+#10.5.4.1 Extensions of codesets
+# This is only text and no packet
+
+class LockingShiftProcedure(Packet):
+ """Locking shift procedure Section 10.5.4.2"""
+ name = "Locking Shift Procedure"
+ fields_desc = [
+ BitField("lockShift", 0x0, 1),
+ BitField("codesetId", 0x0, 3)
+ ]
+
+
+class NonLockingShiftProcedure(Packet):
+ """Non-locking shift procedure Section 10.5.4.3"""
+ name = "Non-locking Shift Procedure"
+ fields_desc = [
+ BitField("nonLockShift", 0x1, 1),
+ BitField("codesetId", 0x0, 3)
+ ]
+
+
+class AuxiliaryStates(Packet):
+ """Auxiliary states Section 10.5.4.4"""
+ name = "Auxiliary States"
+ fields_desc = [
+ XByteField("lengthAS", 0x3),
+ BitField("ext", 0x1, 1),
+ BitField("spare", 0x0, 3),
+ BitField("holdState", 0x0, 2),
+ BitField("mptyState", 0x0, 2)
+ ]
+
+
+# len 3 to 15
+class BearerCapability(Packet):
+ """Bearer capability Section 10.5.4.5"""
+ name = "Bearer Capability"
+ fields_desc = [
+
+ XByteField("lengthBC", None),
+
+ BitField("ext0", 0x1, 1),
+ BitField("radioChReq", 0x1, 2),
+ BitField("codingStd", 0x0, 1),
+ BitField("transMode", 0x0, 1),
+ BitField("infoTransCa", 0x0, 3),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("coding", None, 1),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("spare", None, 2),
+ lambda pkt: pkt.ext0 == 0),
+ ConditionalField(BitField("speechVers", 0x0, 4),
+ lambda pkt: pkt.ext0 == 0),
+
+ ConditionalField(BitField("ext2", 0x1, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("compress", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("structure", None, 2),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("dupMode", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("config", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("nirr", None, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("establi", 0x0, 1),
+ lambda pkt: pkt.ext1 == 0),
+
+ BitField("ext3", None, 1),
+ BitField("accessId", None, 2),
+ BitField("rateAda", None, 2),
+ BitField("signaling", None, 3),
+
+ ConditionalField(BitField("ext4", None, 1),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("otherITC", None, 2),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("otherRate", None, 2),
+ lambda pkt: pkt.ext3 == 0),
+ ConditionalField(BitField("spare1", 0x0, 3),
+ lambda pkt: pkt.ext3 == 0),
+
+ ConditionalField(BitField("ext5", 0x1, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("hdr", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("multiFr", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("mode", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("lli", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("assig", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("inbNeg", None, 1),
+ lambda pkt: pkt.ext4 == 0),
+ ConditionalField(BitField("spare2", 0x0, 1),
+ lambda pkt: pkt.ext4 == 0),
+
+ BitField("ext6", None, 1),
+ BitField("layer1Id", None, 2),
+ BitField("userInf", None, 4),
+ BitField("sync", None, 1),
+
+ ConditionalField(BitField("ext7", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("stopBit", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("negoc", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("nbDataBit", None, 1),
+ lambda pkt: pkt.ext6 == 0),
+ ConditionalField(BitField("userRate", None, 4),
+ lambda pkt: pkt.ext6 == 0),
+
+ ConditionalField(BitField("ext8", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("interRate", None, 2),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("nicTX", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("nicRX", None, 1),
+ lambda pkt: pkt.ext7 == 0),
+ ConditionalField(BitField("parity", None, 3),
+ lambda pkt: pkt.ext7 == 0),
+
+ ConditionalField(BitField("ext9", None, 1),
+ lambda pkt: pkt.ext8 == 0),
+ ConditionalField(BitField("connEle", None, 2),
+ lambda pkt: pkt.ext8 == 0),
+ ConditionalField(BitField("modemType", None, 5),
+ lambda pkt: pkt.ext8 == 0),
+
+ ConditionalField(BitField("ext10", None, 1),
+ lambda pkt: pkt.ext9 == 0),
+ ConditionalField(BitField("otherModemType", None, 2),
+ lambda pkt: pkt.ext9 == 0),
+ ConditionalField(BitField("netUserRate", None, 5),
+ lambda pkt: pkt.ext9 == 0),
+
+ ConditionalField(BitField("ext11", None, 1),
+ lambda pkt: pkt.ext10 == 0),
+ ConditionalField(BitField("chanCoding", None, 4),
+ lambda pkt: pkt.ext10 == 0),
+ ConditionalField(BitField("maxTrafficChan", None, 3),
+ lambda pkt: pkt.ext10 == 0),
+
+ ConditionalField(BitField("ext12", None, 1),
+ lambda pkt: pkt.ext11 == 0),
+ ConditionalField(BitField("uimi", None, 3),
+ lambda pkt: pkt.ext11 == 0),
+ ConditionalField(BitField("airInterfaceUserRate", None, 4),
+ lambda pkt: pkt.ext11 == 0),
+
+ ConditionalField(BitField("ext13", 0x1, 1),
+ lambda pkt: pkt.ext12 == 0),
+ ConditionalField(BitField("layer2Ch", None, 2),
+ lambda pkt: pkt.ext12 == 0),
+ ConditionalField(BitField("userInfoL2", 0x0, 5),
+ lambda pkt: pkt.ext12 == 0)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 15, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthBC is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+class CallControlCapabilities(Packet):
+ """Call Control Capabilities Section 10.5.4.5a"""
+ name = "Call Control Capabilities"
+ fields_desc = [
+ XByteField("lengthCCC", 0x3),
+ BitField("spare", 0x0, 6),
+ BitField("pcp", 0x0, 1),
+ BitField("dtmf", 0x0, 1)
+ ]
+
+
+class CallState(Packet):
+ """Call State Section 10.5.4.6"""
+ name = "Call State"
+ fields_desc = [
+ BitField("codingStd", 0x0, 2),
+ BitField("stateValue", 0x0, 6)
+ ]
+
+
+# len 3 to 43
+class CalledPartyBcdNumber(Packet):
+ """Called party BCD number Section 10.5.4.7"""
+ name = "Called Party BCD Number"
+ fields_desc = [
+ XByteField("lengthCPBN", None),
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("nbPlanId", 0x0, 4),
+ # optional
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+
+ BitField("nbDigit22", None, 4),
+ BitField("nbDigit21", None, 4),
+ BitField("nbDigit24", None, 4),
+ BitField("nbDigit23", None, 4),
+
+ BitField("nbDigit26", None, 4),
+ BitField("nbDigit25", None, 4),
+ BitField("nbDigit28", None, 4),
+ BitField("nbDigit27", None, 4),
+
+ BitField("nbDigit30", None, 4),
+ BitField("nbDigit29", None, 4),
+ BitField("nbDigit32", None, 4),
+ BitField("nbDigit31", None, 4),
+
+ BitField("nbDigit34", None, 4),
+ BitField("nbDigit33", None, 4),
+ BitField("nbDigit36", None, 4),
+ BitField("nbDigit35", None, 4),
+
+ BitField("nbDigit38", None, 4),
+ BitField("nbDigit37", None, 4),
+ BitField("nbDigit40", None, 4),
+ BitField("nbDigit39", None, 4),
+# ^^^^^^ 20 first optional bytes ^^^^^^^^^^^^^^^
+ BitField("nbDigit42", None, 4),
+ BitField("nbDigit41", None, 4),
+ BitField("nbDigit44", None, 4),
+ BitField("nbDigit43", None, 4),
+
+ BitField("nbDigit46", None, 4),
+ BitField("nbDigit45", None, 4),
+ BitField("nbDigit48", None, 4),
+ BitField("nbDigit47", None, 4),
+
+ BitField("nbDigit50", None, 4),
+ BitField("nbDigit49", None, 4),
+ BitField("nbDigit52", None, 4),
+ BitField("nbDigit51", None, 4),
+
+ BitField("nbDigit54", None, 4),
+ BitField("nbDigit53", None, 4),
+ BitField("nbDigit56", None, 4),
+ BitField("nbDigit55", None, 4),
+
+ BitField("nbDigit58", None, 4),
+ BitField("nbDigit57", None, 4),
+ BitField("nbDigit60", None, 4),
+ BitField("nbDigit59", None, 4),
+
+ BitField("nbDigit62", None, 4),
+ BitField("nbDigit61", None, 4),
+ BitField("nbDigit64", None, 4),
+ BitField("nbDigit63", None, 4),
+
+ BitField("nbDigit66", None, 4),
+ BitField("nbDigit65", None, 4),
+ BitField("nbDigit68", None, 4),
+ BitField("nbDigit67", None, 4),
+
+ BitField("nbDigit70", None, 4),
+ BitField("nbDigit69", None, 4),
+ BitField("nbDigit72", None, 4),
+ BitField("nbDigit71", None, 4),
+
+ BitField("nbDigit74", None, 4),
+ BitField("nbDigit73", None, 4),
+ BitField("nbDigit76", None, 4),
+ BitField("nbDigit75", None, 4),
+
+ BitField("nbDigit78", None, 4),
+ BitField("nbDigit77", None, 4),
+ BitField("nbDigit80", None, 4),
+ BitField("nbDigit79", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 42, a, self.fields_desc, 1)
+ if self.lengthCPBN is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 2 to 23
+class CalledPartySubaddress(Packet):
+ """Called party subaddress Section 10.5.4.8"""
+ name = "Called Party Subaddress"
+ fields_desc = [
+ XByteField("lengthCPS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("subAddr", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 23, a, self.fields_desc, 1)
+ if self.lengthCPS is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 3 to 14
+class CallingPartyBcdNumber(Packet):
+ """Called party subaddress Section 10.5.4.9"""
+ name = "Called Party Subaddress"
+ fields_desc = [
+ XByteField("lengthCPBN", None),
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("nbPlanId", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", None, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", None, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", 0x0, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 13, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthCPBN is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+# len 2 to 23
+class CallingPartySubaddress(Packet):
+ """Calling party subaddress Section 10.5.4.10"""
+ name = "Calling Party Subaddress"
+ fields_desc = [
+ XByteField("lengthCPS", None),
+ # optional
+ BitField("ext1", None, 1),
+ BitField("typeAddr", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 22, a, self.fields_desc, 1)
+ if self.lengthCPS is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 4 to 32
+class Cause(Packet):
+ """Cause Section 10.5.4.11"""
+ name = "Cause"
+ fields_desc = [
+
+ XByteField("lengthC", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("codingStd", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("location", 0x0, 4),
+
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("recommendation", 0x1, 7),
+ lambda pkt: pkt.ext == 0),
+ # optional
+ BitField("ext2", None, 1),
+ BitField("causeValue", None, 7),
+
+ ByteField("diagnositc0", None),
+ ByteField("diagnositc1", None),
+ ByteField("diagnositc2", None),
+ ByteField("diagnositc3", None),
+ ByteField("diagnositc4", None),
+ ByteField("diagnositc5", None),
+ ByteField("diagnositc6", None),
+ ByteField("diagnositc7", None),
+ ByteField("diagnositc8", None),
+ ByteField("diagnositc9", None),
+ ByteField("diagnositc10", None),
+ ByteField("diagnositc11", None),
+ ByteField("diagnositc12", None),
+ ByteField("diagnositc13", None),
+ ByteField("diagnositc14", None),
+ ByteField("diagnositc15", None),
+ ByteField("diagnositc16", None),
+ ByteField("diagnositc17", None),
+ ByteField("diagnositc18", None),
+ ByteField("diagnositc19", None),
+ ByteField("diagnositc20", None),
+ ByteField("diagnositc21", None),
+ ByteField("diagnositc22", None),
+ ByteField("diagnositc23", None),
+ ByteField("diagnositc24", None),
+ ByteField("diagnositc25", None),
+ ByteField("diagnositc26", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(3, 31, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthC is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+class ClirSuppression(Packet):
+ """CLIR suppression Section 10.5.4.11a"""
+ name = "Clir Suppression"
+ fields_desc = [
+ ]
+
+
+class ClirInvocation(Packet):
+ """CLIR invocation Section 10.5.4.11b"""
+ name = "Clir Invocation"
+ fields_desc = [
+ ]
+
+
+class CongestionLevel(Packet):
+ """Congestion level Section 10.5.4.12"""
+ name = "Congestion Level"
+ fields_desc = [
+ BitField("notDef", 0x0, 4) # not defined by the std
+ ]
+
+
+# len 3 to 14
+class ConnectedNumber(Packet):
+ """Connected number Section 10.5.4.13"""
+ name = "Connected Number"
+ fields_desc = [
+
+ XByteField("lengthCN", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("typePlanId", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", None, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", None, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", None, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 13, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthCN is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+# len 2 to 23
+class ConnectedSubaddress(Packet):
+ """Connected subaddress Section 10.5.4.14"""
+ name = "Connected Subaddress"
+ fields_desc = [
+
+ XByteField("lengthCS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("typeOfSub", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ a = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 22, a, self.fields_desc, 1)
+ if self.lengthCS is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# len 2 to L3 (251) (done)
+class Facility(Packet):
+ """Facility Section 10.5.4.15"""
+ name = "Facility"
+ fields_desc = [
+ XByteField("lengthF", None),
+ # optional
+ ByteField("facilityInfo1", None),
+ ByteField("facilityInfo2", None),
+ ByteField("facilityInfo3", None),
+ ByteField("facilityInfo4", None),
+ ByteField("facilityInfo5", None),
+ ByteField("facilityInfo6", None),
+ ByteField("facilityInfo7", None),
+ ByteField("facilityInfo8", None),
+ ByteField("facilityInfo9", None),
+ ByteField("facilityInfo10", None),
+ ByteField("facilityInfo11", None),
+ ByteField("facilityInfo12", None),
+ ByteField("facilityInfo13", None),
+ ByteField("facilityInfo14", None),
+ ByteField("facilityInfo15", None),
+ ByteField("facilityInfo16", None),
+ ByteField("facilityInfo17", None),
+ ByteField("facilityInfo18", None),
+ ByteField("facilityInfo19", None),
+ ByteField("facilityInfo20", None),
+ ByteField("facilityInfo21", None),
+ ByteField("facilityInfo22", None),
+ ByteField("facilityInfo23", None),
+ ByteField("facilityInfo24", None),
+ ByteField("facilityInfo25", None),
+ ByteField("facilityInfo26", None),
+ ByteField("facilityInfo27", None),
+ ByteField("facilityInfo28", None),
+ ByteField("facilityInfo29", None),
+ ByteField("facilityInfo30", None),
+ ByteField("facilityInfo31", None),
+ ByteField("facilityInfo32", None),
+ ByteField("facilityInfo33", None),
+ ByteField("facilityInfo34", None),
+ ByteField("facilityInfo35", None),
+ ByteField("facilityInfo36", None),
+ ByteField("facilityInfo37", None),
+ ByteField("facilityInfo38", None),
+ ByteField("facilityInfo39", None),
+ ByteField("facilityInfo40", None),
+ ByteField("facilityInfo41", None),
+ ByteField("facilityInfo42", None),
+ ByteField("facilityInfo43", None),
+ ByteField("facilityInfo44", None),
+ ByteField("facilityInfo45", None),
+ ByteField("facilityInfo46", None),
+ ByteField("facilityInfo47", None),
+ ByteField("facilityInfo48", None),
+ ByteField("facilityInfo49", None),
+ ByteField("facilityInfo50", None),
+ ByteField("facilityInfo51", None),
+ ByteField("facilityInfo52", None),
+ ByteField("facilityInfo53", None),
+ ByteField("facilityInfo54", None),
+ ByteField("facilityInfo55", None),
+ ByteField("facilityInfo56", None),
+ ByteField("facilityInfo57", None),
+ ByteField("facilityInfo58", None),
+ ByteField("facilityInfo59", None),
+ ByteField("facilityInfo60", None),
+ ByteField("facilityInfo61", None),
+ ByteField("facilityInfo62", None),
+ ByteField("facilityInfo63", None),
+ ByteField("facilityInfo64", None),
+ ByteField("facilityInfo65", None),
+ ByteField("facilityInfo66", None),
+ ByteField("facilityInfo67", None),
+ ByteField("facilityInfo68", None),
+ ByteField("facilityInfo69", None),
+ ByteField("facilityInfo70", None),
+ ByteField("facilityInfo71", None),
+ ByteField("facilityInfo72", None),
+ ByteField("facilityInfo73", None),
+ ByteField("facilityInfo74", None),
+ ByteField("facilityInfo75", None),
+ ByteField("facilityInfo76", None),
+ ByteField("facilityInfo77", None),
+ ByteField("facilityInfo78", None),
+ ByteField("facilityInfo79", None),
+ ByteField("facilityInfo80", None),
+ ByteField("facilityInfo81", None),
+ ByteField("facilityInfo82", None),
+ ByteField("facilityInfo83", None),
+ ByteField("facilityInfo84", None),
+ ByteField("facilityInfo85", None),
+ ByteField("facilityInfo86", None),
+ ByteField("facilityInfo87", None),
+ ByteField("facilityInfo88", None),
+ ByteField("facilityInfo89", None),
+ ByteField("facilityInfo90", None),
+ ByteField("facilityInfo91", None),
+ ByteField("facilityInfo92", None),
+ ByteField("facilityInfo93", None),
+ ByteField("facilityInfo94", None),
+ ByteField("facilityInfo95", None),
+ ByteField("facilityInfo96", None),
+ ByteField("facilityInfo97", None),
+ ByteField("facilityInfo98", None),
+ ByteField("facilityInfo99", None),
+ ByteField("facilityInfo100", None),
+ ByteField("facilityInfo101", None),
+ ByteField("facilityInfo102", None),
+ ByteField("facilityInfo103", None),
+ ByteField("facilityInfo104", None),
+ ByteField("facilityInfo105", None),
+ ByteField("facilityInfo106", None),
+ ByteField("facilityInfo107", None),
+ ByteField("facilityInfo108", None),
+ ByteField("facilityInfo109", None),
+ ByteField("facilityInfo110", None),
+ ByteField("facilityInfo111", None),
+ ByteField("facilityInfo112", None),
+ ByteField("facilityInfo113", None),
+ ByteField("facilityInfo114", None),
+ ByteField("facilityInfo115", None),
+ ByteField("facilityInfo116", None),
+ ByteField("facilityInfo117", None),
+ ByteField("facilityInfo118", None),
+ ByteField("facilityInfo119", None),
+ ByteField("facilityInfo120", None),
+ ByteField("facilityInfo121", None),
+ ByteField("facilityInfo122", None),
+ ByteField("facilityInfo123", None),
+ ByteField("facilityInfo124", None),
+ ByteField("facilityInfo125", None),
+ ByteField("facilityInfo126", None),
+ ByteField("facilityInfo127", None),
+ ByteField("facilityInfo128", None),
+ ByteField("facilityInfo129", None),
+ ByteField("facilityInfo130", None),
+ ByteField("facilityInfo131", None),
+ ByteField("facilityInfo132", None),
+ ByteField("facilityInfo133", None),
+ ByteField("facilityInfo134", None),
+ ByteField("facilityInfo135", None),
+ ByteField("facilityInfo136", None),
+ ByteField("facilityInfo137", None),
+ ByteField("facilityInfo138", None),
+ ByteField("facilityInfo139", None),
+ ByteField("facilityInfo140", None),
+ ByteField("facilityInfo141", None),
+ ByteField("facilityInfo142", None),
+ ByteField("facilityInfo143", None),
+ ByteField("facilityInfo144", None),
+ ByteField("facilityInfo145", None),
+ ByteField("facilityInfo146", None),
+ ByteField("facilityInfo147", None),
+ ByteField("facilityInfo148", None),
+ ByteField("facilityInfo149", None),
+ ByteField("facilityInfo150", None),
+ ByteField("facilityInfo151", None),
+ ByteField("facilityInfo152", None),
+ ByteField("facilityInfo153", None),
+ ByteField("facilityInfo154", None),
+ ByteField("facilityInfo155", None),
+ ByteField("facilityInfo156", None),
+ ByteField("facilityInfo157", None),
+ ByteField("facilityInfo158", None),
+ ByteField("facilityInfo159", None),
+ ByteField("facilityInfo160", None),
+ ByteField("facilityInfo161", None),
+ ByteField("facilityInfo162", None),
+ ByteField("facilityInfo163", None),
+ ByteField("facilityInfo164", None),
+ ByteField("facilityInfo165", None),
+ ByteField("facilityInfo166", None),
+ ByteField("facilityInfo167", None),
+ ByteField("facilityInfo168", None),
+ ByteField("facilityInfo169", None),
+ ByteField("facilityInfo170", None),
+ ByteField("facilityInfo171", None),
+ ByteField("facilityInfo172", None),
+ ByteField("facilityInfo173", None),
+ ByteField("facilityInfo174", None),
+ ByteField("facilityInfo175", None),
+ ByteField("facilityInfo176", None),
+ ByteField("facilityInfo177", None),
+ ByteField("facilityInfo178", None),
+ ByteField("facilityInfo179", None),
+ ByteField("facilityInfo180", None),
+ ByteField("facilityInfo181", None),
+ ByteField("facilityInfo182", None),
+ ByteField("facilityInfo183", None),
+ ByteField("facilityInfo184", None),
+ ByteField("facilityInfo185", None),
+ ByteField("facilityInfo186", None),
+ ByteField("facilityInfo187", None),
+ ByteField("facilityInfo188", None),
+ ByteField("facilityInfo189", None),
+ ByteField("facilityInfo190", None),
+ ByteField("facilityInfo191", None),
+ ByteField("facilityInfo192", None),
+ ByteField("facilityInfo193", None),
+ ByteField("facilityInfo194", None),
+ ByteField("facilityInfo195", None),
+ ByteField("facilityInfo196", None),
+ ByteField("facilityInfo197", None),
+ ByteField("facilityInfo198", None),
+ ByteField("facilityInfo199", None),
+ ByteField("facilityInfo200", None),
+ ByteField("facilityInfo201", None),
+ ByteField("facilityInfo202", None),
+ ByteField("facilityInfo203", None),
+ ByteField("facilityInfo204", None),
+ ByteField("facilityInfo205", None),
+ ByteField("facilityInfo206", None),
+ ByteField("facilityInfo207", None),
+ ByteField("facilityInfo208", None),
+ ByteField("facilityInfo209", None),
+ ByteField("facilityInfo210", None),
+ ByteField("facilityInfo211", None),
+ ByteField("facilityInfo212", None),
+ ByteField("facilityInfo213", None),
+ ByteField("facilityInfo214", None),
+ ByteField("facilityInfo215", None),
+ ByteField("facilityInfo216", None),
+ ByteField("facilityInfo217", None),
+ ByteField("facilityInfo218", None),
+ ByteField("facilityInfo219", None),
+ ByteField("facilityInfo220", None),
+ ByteField("facilityInfo221", None),
+ ByteField("facilityInfo222", None),
+ ByteField("facilityInfo223", None),
+ ByteField("facilityInfo224", None),
+ ByteField("facilityInfo225", None),
+ ByteField("facilityInfo226", None),
+ ByteField("facilityInfo227", None),
+ ByteField("facilityInfo228", None),
+ ByteField("facilityInfo229", None),
+ ByteField("facilityInfo230", None),
+ ByteField("facilityInfo231", None),
+ ByteField("facilityInfo232", None),
+ ByteField("facilityInfo233", None),
+ ByteField("facilityInfo234", None),
+ ByteField("facilityInfo235", None),
+ ByteField("facilityInfo236", None),
+ ByteField("facilityInfo237", None),
+ ByteField("facilityInfo238", None),
+ ByteField("facilityInfo239", None),
+ ByteField("facilityInfo240", None),
+ ByteField("facilityInfo241", None),
+ ByteField("facilityInfo242", None),
+ ByteField("facilityInfo243", None),
+ ByteField("facilityInfo244", None),
+ ByteField("facilityInfo245", None),
+ ByteField("facilityInfo246", None),
+ ByteField("facilityInfo247", None),
+ ByteField("facilityInfo248", None),
+ ByteField("facilityInfo249", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(7, 250, a, self.fields_desc, 1)
+ if self.lengthF is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+#len 2 to 5
+class HighLayerCompatibility(Packet):
+ """High layer compatibility Section 10.5.4.16"""
+ name = "High Layer Compatibility"
+ fields_desc = [
+
+ XByteField("lengthHLC", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("codingStd", None, 2),
+ BitField("interpret", None, 3),
+ BitField("presMeth", None, 2),
+
+ BitField("ext1", None, 1),
+ BitField("highLayerId", None, 7),
+
+ ConditionalField(BitField("ext2", 0x1, 1),
+ lambda pkt: pkt.ext1 == 0),
+ ConditionalField(BitField("exHiLayerId", 0x0, 7),
+ lambda pkt: pkt.ext1 == 0),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 4, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthHLC is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+#
+# 10.5.4.16.1 Static conditions for the high layer
+# compatibility IE contents
+#
+
+
+class KeypadFacility(Packet):
+ """Keypad facility Section 10.5.4.17"""
+ name = "Keypad Facility"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("keyPadInfo", 0x0, 7)
+ ]
+
+
+# len 2 to 15
+class LowLayerCompatibility(Packet):
+ """Low layer compatibility Section 10.5.4.18"""
+ name = "Low Layer Compatibility"
+ fields_desc = [
+
+ XByteField("lengthLLC", None),
+ # optional
+ ByteField("rest0", None),
+ ByteField("rest1", None),
+ ByteField("rest2", None),
+ ByteField("rest3", None),
+ ByteField("rest4", None),
+ ByteField("rest5", None),
+ ByteField("rest6", None),
+ ByteField("rest7", None),
+ ByteField("rest8", None),
+ ByteField("rest9", None),
+ ByteField("rest10", None),
+ ByteField("rest11", None),
+ ByteField("rest12", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 14, a, self.fields_desc, 1)
+ if self.lengthLLC is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class MoreData(Packet):
+ """More data Section 10.5.4.19"""
+ name = "More Data"
+ fields_desc = [
+ ]
+
+
+class NotificationIndicator(Packet):
+ """Notification indicator Section 10.5.4.20"""
+ name = "Notification Indicator"
+ fields_desc = [
+ BitField("ext1", 0x1, 1),
+ BitField("notifDesc", 0x0, 7)
+ ]
+
+
+class ProgressIndicator(Packet):
+ """Progress indicator Section 10.5.4.21"""
+ name = "Progress Indicator"
+ fields_desc = [
+ XByteField("lengthPI", 0x2),
+ BitField("ext", 0x1, 1),
+ BitField("codingStd", 0x0, 2),
+ BitField("spare", 0x0, 1),
+ BitField("location", 0x0, 4),
+ BitField("ext1", 0x1, 1),
+ BitField("progressDesc", 0x0, 7)
+ ]
+
+
+class RecallType(Packet):
+ """Recall type $(CCBS)$ Section 10.5.4.21a"""
+ name = "Recall Type $(CCBS)$"
+ fields_desc = [
+ BitField("spare", 0x0, 5),
+ BitField("recallType", 0x0, 3)
+ ]
+
+
+# len 3 to 19
+class RedirectingPartyBcdNumber(Packet):
+ """Redirecting party BCD number Section 10.5.4.21b"""
+ name = "Redirecting Party BCD Number"
+ fields_desc = [
+
+ XByteField("lengthRPBN", None),
+
+ BitField("ext", 0x1, 1),
+ BitField("typeNb", 0x0, 3),
+ BitField("numberingPlan", 0x0, 4),
+ # optional
+ ConditionalField(BitField("ext1", 0x1, 1),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("presId", 0x0, 2),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("spare", 0x0, 3),
+ lambda pkt: pkt.ext == 0),
+ ConditionalField(BitField("screenId", 0x0, 2),
+ lambda pkt: pkt.ext == 0),
+
+ BitField("nbDigit2", None, 4),
+ BitField("nbDigit1", None, 4),
+
+ BitField("nbDigit4", None, 4),
+ BitField("nbDigit3", None, 4),
+
+ BitField("nbDigit6", None, 4),
+ BitField("nbDigit5", None, 4),
+
+ BitField("nbDigit8", None, 4),
+ BitField("nbDigit7", None, 4),
+
+ BitField("nbDigit10", None, 4),
+ BitField("nbDigit9", None, 4),
+
+ BitField("nbDigit12", None, 4),
+ BitField("nbDigit11", None, 4),
+
+ BitField("nbDigit14", None, 4),
+ BitField("nbDigit13", None, 4),
+
+ BitField("nbDigit16", None, 4),
+ BitField("nbDigit15", None, 4),
+
+ BitField("nbDigit18", None, 4),
+ BitField("nbDigit17", None, 4),
+
+ BitField("nbDigit20", None, 4),
+ BitField("nbDigit19", None, 4),
+
+ BitField("nbDigit22", None, 4),
+ BitField("nbDigit21", None, 4),
+
+ BitField("nbDigit24", None, 4),
+ BitField("nbDigit23", None, 4),
+
+ BitField("nbDigit26", None, 4),
+ BitField("nbDigit25", None, 4),
+
+ BitField("nbDigit28", None, 4),
+ BitField("nbDigit27", None, 4),
+
+ BitField("nbDigit30", None, 4),
+ BitField("nbDigit29", None, 4),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 18, a, self.fields_desc, 1)
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ if self.lengthRPBN is None:
+ p = struct.pack(">B", len(p)-1) + p[1:]
+ return p + pay
+
+
+# length 2 to 23
+class RedirectingPartySubaddress(Packet):
+ """Redirecting party subaddress Section 10.5.4.21c"""
+ name = "Redirecting Party BCD Number"
+ fields_desc = [
+
+ XByteField("lengthRPS", None),
+ # optional
+ BitField("ext", None, 1),
+ BitField("typeSub", None, 3),
+ BitField("oddEven", None, 1),
+ BitField("spare", None, 3),
+
+ ByteField("subInfo0", None),
+ ByteField("subInfo1", None),
+ ByteField("subInfo2", None),
+ ByteField("subInfo3", None),
+ ByteField("subInfo4", None),
+ ByteField("subInfo5", None),
+ ByteField("subInfo6", None),
+ ByteField("subInfo7", None),
+ ByteField("subInfo8", None),
+ ByteField("subInfo9", None),
+ ByteField("subInfo10", None),
+ ByteField("subInfo11", None),
+ ByteField("subInfo12", None),
+ ByteField("subInfo13", None),
+ ByteField("subInfo14", None),
+ ByteField("subInfo15", None),
+ ByteField("subInfo16", None),
+ ByteField("subInfo17", None),
+ ByteField("subInfo18", None),
+ ByteField("subInfo19", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 22, a, self.fields_desc, 1)
+ if self.lengthRPS is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class RepeatIndicator(Packet):
+ """Repeat indicator Section 10.5.4.22"""
+ name = "Repeat Indicator"
+ fields_desc = [
+ BitField("repeatIndic", 0x0, 4)
+ ]
+
+
+# no upper length min 2(max for L3) (251)
+class SetupContainer(Packet):
+ """SETUP Container $(CCBS)$ Section 10.5.4.22b"""
+ name = "Setup Container $(CCBS)$"
+ fields_desc = [
+ XByteField("lengthSC", None),
+ # optional
+ ByteField("mess1", None),
+ ByteField("mess2", None),
+ ByteField("mess3", None),
+ ByteField("mess4", None),
+ ByteField("mess5", None),
+ ByteField("mess6", None),
+ ByteField("mess7", None),
+ ByteField("mess8", None),
+ ByteField("mess9", None),
+ ByteField("mess10", None),
+ ByteField("mess11", None),
+ ByteField("mess12", None),
+ ByteField("mess13", None),
+ ByteField("mess14", None),
+ ByteField("mess15", None),
+ ByteField("mess16", None),
+ ByteField("mess17", None),
+ ByteField("mess18", None),
+ ByteField("mess19", None),
+ ByteField("mess20", None),
+ ByteField("mess21", None),
+ ByteField("mess22", None),
+ ByteField("mess23", None),
+ ByteField("mess24", None),
+ ByteField("mess25", None),
+ ByteField("mess26", None),
+ ByteField("mess27", None),
+ ByteField("mess28", None),
+ ByteField("mess29", None),
+ ByteField("mess30", None),
+ ByteField("mess31", None),
+ ByteField("mess32", None),
+ ByteField("mess33", None),
+ ByteField("mess34", None),
+ ByteField("mess35", None),
+ ByteField("mess36", None),
+ ByteField("mess37", None),
+ ByteField("mess38", None),
+ ByteField("mess39", None),
+ ByteField("mess40", None),
+ ByteField("mess41", None),
+ ByteField("mess42", None),
+ ByteField("mess43", None),
+ ByteField("mess44", None),
+ ByteField("mess45", None),
+ ByteField("mess46", None),
+ ByteField("mess47", None),
+ ByteField("mess48", None),
+ ByteField("mess49", None),
+ ByteField("mess50", None),
+ ByteField("mess51", None),
+ ByteField("mess52", None),
+ ByteField("mess53", None),
+ ByteField("mess54", None),
+ ByteField("mess55", None),
+ ByteField("mess56", None),
+ ByteField("mess57", None),
+ ByteField("mess58", None),
+ ByteField("mess59", None),
+ ByteField("mess60", None),
+ ByteField("mess61", None),
+ ByteField("mess62", None),
+ ByteField("mess63", None),
+ ByteField("mess64", None),
+ ByteField("mess65", None),
+ ByteField("mess66", None),
+ ByteField("mess67", None),
+ ByteField("mess68", None),
+ ByteField("mess69", None),
+ ByteField("mess70", None),
+ ByteField("mess71", None),
+ ByteField("mess72", None),
+ ByteField("mess73", None),
+ ByteField("mess74", None),
+ ByteField("mess75", None),
+ ByteField("mess76", None),
+ ByteField("mess77", None),
+ ByteField("mess78", None),
+ ByteField("mess79", None),
+ ByteField("mess80", None),
+ ByteField("mess81", None),
+ ByteField("mess82", None),
+ ByteField("mess83", None),
+ ByteField("mess84", None),
+ ByteField("mess85", None),
+ ByteField("mess86", None),
+ ByteField("mess87", None),
+ ByteField("mess88", None),
+ ByteField("mess89", None),
+ ByteField("mess90", None),
+ ByteField("mess91", None),
+ ByteField("mess92", None),
+ ByteField("mess93", None),
+ ByteField("mess94", None),
+ ByteField("mess95", None),
+ ByteField("mess96", None),
+ ByteField("mess97", None),
+ ByteField("mess98", None),
+ ByteField("mess99", None),
+ ByteField("mess100", None),
+ ByteField("mess101", None),
+ ByteField("mess102", None),
+ ByteField("mess103", None),
+ ByteField("mess104", None),
+ ByteField("mess105", None),
+ ByteField("mess106", None),
+ ByteField("mess107", None),
+ ByteField("mess108", None),
+ ByteField("mess109", None),
+ ByteField("mess110", None),
+ ByteField("mess111", None),
+ ByteField("mess112", None),
+ ByteField("mess113", None),
+ ByteField("mess114", None),
+ ByteField("mess115", None),
+ ByteField("mess116", None),
+ ByteField("mess117", None),
+ ByteField("mess118", None),
+ ByteField("mess119", None),
+ ByteField("mess120", None),
+ ByteField("mess121", None),
+ ByteField("mess122", None),
+ ByteField("mess123", None),
+ ByteField("mess124", None),
+ ByteField("mess125", None),
+ ByteField("mess126", None),
+ ByteField("mess127", None),
+ ByteField("mess128", None),
+ ByteField("mess129", None),
+ ByteField("mess130", None),
+ ByteField("mess131", None),
+ ByteField("mess132", None),
+ ByteField("mess133", None),
+ ByteField("mess134", None),
+ ByteField("mess135", None),
+ ByteField("mess136", None),
+ ByteField("mess137", None),
+ ByteField("mess138", None),
+ ByteField("mess139", None),
+ ByteField("mess140", None),
+ ByteField("mess141", None),
+ ByteField("mess142", None),
+ ByteField("mess143", None),
+ ByteField("mess144", None),
+ ByteField("mess145", None),
+ ByteField("mess146", None),
+ ByteField("mess147", None),
+ ByteField("mess148", None),
+ ByteField("mess149", None),
+ ByteField("mess150", None),
+ ByteField("mess151", None),
+ ByteField("mess152", None),
+ ByteField("mess153", None),
+ ByteField("mess154", None),
+ ByteField("mess155", None),
+ ByteField("mess156", None),
+ ByteField("mess157", None),
+ ByteField("mess158", None),
+ ByteField("mess159", None),
+ ByteField("mess160", None),
+ ByteField("mess161", None),
+ ByteField("mess162", None),
+ ByteField("mess163", None),
+ ByteField("mess164", None),
+ ByteField("mess165", None),
+ ByteField("mess166", None),
+ ByteField("mess167", None),
+ ByteField("mess168", None),
+ ByteField("mess169", None),
+ ByteField("mess170", None),
+ ByteField("mess171", None),
+ ByteField("mess172", None),
+ ByteField("mess173", None),
+ ByteField("mess174", None),
+ ByteField("mess175", None),
+ ByteField("mess176", None),
+ ByteField("mess177", None),
+ ByteField("mess178", None),
+ ByteField("mess179", None),
+ ByteField("mess180", None),
+ ByteField("mess181", None),
+ ByteField("mess182", None),
+ ByteField("mess183", None),
+ ByteField("mess184", None),
+ ByteField("mess185", None),
+ ByteField("mess186", None),
+ ByteField("mess187", None),
+ ByteField("mess188", None),
+ ByteField("mess189", None),
+ ByteField("mess190", None),
+ ByteField("mess191", None),
+ ByteField("mess192", None),
+ ByteField("mess193", None),
+ ByteField("mess194", None),
+ ByteField("mess195", None),
+ ByteField("mess196", None),
+ ByteField("mess197", None),
+ ByteField("mess198", None),
+ ByteField("mess199", None),
+ ByteField("mess200", None),
+ ByteField("mess201", None),
+ ByteField("mess202", None),
+ ByteField("mess203", None),
+ ByteField("mess204", None),
+ ByteField("mess205", None),
+ ByteField("mess206", None),
+ ByteField("mess207", None),
+ ByteField("mess208", None),
+ ByteField("mess209", None),
+ ByteField("mess210", None),
+ ByteField("mess211", None),
+ ByteField("mess212", None),
+ ByteField("mess213", None),
+ ByteField("mess214", None),
+ ByteField("mess215", None),
+ ByteField("mess216", None),
+ ByteField("mess217", None),
+ ByteField("mess218", None),
+ ByteField("mess219", None),
+ ByteField("mess220", None),
+ ByteField("mess221", None),
+ ByteField("mess222", None),
+ ByteField("mess223", None),
+ ByteField("mess224", None),
+ ByteField("mess225", None),
+ ByteField("mess226", None),
+ ByteField("mess227", None),
+ ByteField("mess228", None),
+ ByteField("mess229", None),
+ ByteField("mess230", None),
+ ByteField("mess231", None),
+ ByteField("mess232", None),
+ ByteField("mess233", None),
+ ByteField("mess234", None),
+ ByteField("mess235", None),
+ ByteField("mess236", None),
+ ByteField("mess237", None),
+ ByteField("mess238", None),
+ ByteField("mess239", None),
+ ByteField("mess240", None),
+ ByteField("mess241", None),
+ ByteField("mess242", None),
+ ByteField("mess243", None),
+ ByteField("mess244", None),
+ ByteField("mess245", None),
+ ByteField("mess246", None),
+ ByteField("mess247", None),
+ ByteField("mess248", None),
+ ByteField("mess249", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 250, a, self.fields_desc, 1)
+ if self.lengthSC is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class Signal(Packet):
+ """Signal Section 10.5.4.23"""
+ name = "Signal"
+ fields_desc = [
+ ByteField("sigValue", 0x0)
+ ]
+
+
+# length 2 to max for L3 message (251)
+class SsVersionIndicator(Packet):
+ """SS Version Indicator Section 10.5.4.24"""
+ name = "SS Version Indicator"
+ fields_desc = [
+ XByteField("lengthSVI", None),
+ # optional
+ ByteField("info1", None),
+ ByteField("info2", None),
+ ByteField("info3", None),
+ ByteField("info4", None),
+ ByteField("info5", None),
+ ByteField("info6", None),
+ ByteField("info7", None),
+ ByteField("info8", None),
+ ByteField("info9", None),
+ ByteField("info10", None),
+ ByteField("info11", None),
+ ByteField("info12", None),
+ ByteField("info13", None),
+ ByteField("info14", None),
+ ByteField("info15", None),
+ ByteField("info16", None),
+ ByteField("info17", None),
+ ByteField("info18", None),
+ ByteField("info19", None),
+ ByteField("info20", None),
+ ByteField("info21", None),
+ ByteField("info22", None),
+ ByteField("info23", None),
+ ByteField("info24", None),
+ ByteField("info25", None),
+ ByteField("info26", None),
+ ByteField("info27", None),
+ ByteField("info28", None),
+ ByteField("info29", None),
+ ByteField("info30", None),
+ ByteField("info31", None),
+ ByteField("info32", None),
+ ByteField("info33", None),
+ ByteField("info34", None),
+ ByteField("info35", None),
+ ByteField("info36", None),
+ ByteField("info37", None),
+ ByteField("info38", None),
+ ByteField("info39", None),
+ ByteField("info40", None),
+ ByteField("info41", None),
+ ByteField("info42", None),
+ ByteField("info43", None),
+ ByteField("info44", None),
+ ByteField("info45", None),
+ ByteField("info46", None),
+ ByteField("info47", None),
+ ByteField("info48", None),
+ ByteField("info49", None),
+ ByteField("info50", None),
+ ByteField("info51", None),
+ ByteField("info52", None),
+ ByteField("info53", None),
+ ByteField("info54", None),
+ ByteField("info55", None),
+ ByteField("info56", None),
+ ByteField("info57", None),
+ ByteField("info58", None),
+ ByteField("info59", None),
+ ByteField("info60", None),
+ ByteField("info61", None),
+ ByteField("info62", None),
+ ByteField("info63", None),
+ ByteField("info64", None),
+ ByteField("info65", None),
+ ByteField("info66", None),
+ ByteField("info67", None),
+ ByteField("info68", None),
+ ByteField("info69", None),
+ ByteField("info70", None),
+ ByteField("info71", None),
+ ByteField("info72", None),
+ ByteField("info73", None),
+ ByteField("info74", None),
+ ByteField("info75", None),
+ ByteField("info76", None),
+ ByteField("info77", None),
+ ByteField("info78", None),
+ ByteField("info79", None),
+ ByteField("info80", None),
+ ByteField("info81", None),
+ ByteField("info82", None),
+ ByteField("info83", None),
+ ByteField("info84", None),
+ ByteField("info85", None),
+ ByteField("info86", None),
+ ByteField("info87", None),
+ ByteField("info88", None),
+ ByteField("info89", None),
+ ByteField("info90", None),
+ ByteField("info91", None),
+ ByteField("info92", None),
+ ByteField("info93", None),
+ ByteField("info94", None),
+ ByteField("info95", None),
+ ByteField("info96", None),
+ ByteField("info97", None),
+ ByteField("info98", None),
+ ByteField("info99", None),
+ ByteField("info100", None),
+ ByteField("info101", None),
+ ByteField("info102", None),
+ ByteField("info103", None),
+ ByteField("info104", None),
+ ByteField("info105", None),
+ ByteField("info106", None),
+ ByteField("info107", None),
+ ByteField("info108", None),
+ ByteField("info109", None),
+ ByteField("info110", None),
+ ByteField("info111", None),
+ ByteField("info112", None),
+ ByteField("info113", None),
+ ByteField("info114", None),
+ ByteField("info115", None),
+ ByteField("info116", None),
+ ByteField("info117", None),
+ ByteField("info118", None),
+ ByteField("info119", None),
+ ByteField("info120", None),
+ ByteField("info121", None),
+ ByteField("info122", None),
+ ByteField("info123", None),
+ ByteField("info124", None),
+ ByteField("info125", None),
+ ByteField("info126", None),
+ ByteField("info127", None),
+ ByteField("info128", None),
+ ByteField("info129", None),
+ ByteField("info130", None),
+ ByteField("info131", None),
+ ByteField("info132", None),
+ ByteField("info133", None),
+ ByteField("info134", None),
+ ByteField("info135", None),
+ ByteField("info136", None),
+ ByteField("info137", None),
+ ByteField("info138", None),
+ ByteField("info139", None),
+ ByteField("info140", None),
+ ByteField("info141", None),
+ ByteField("info142", None),
+ ByteField("info143", None),
+ ByteField("info144", None),
+ ByteField("info145", None),
+ ByteField("info146", None),
+ ByteField("info147", None),
+ ByteField("info148", None),
+ ByteField("info149", None),
+ ByteField("info150", None),
+ ByteField("info151", None),
+ ByteField("info152", None),
+ ByteField("info153", None),
+ ByteField("info154", None),
+ ByteField("info155", None),
+ ByteField("info156", None),
+ ByteField("info157", None),
+ ByteField("info158", None),
+ ByteField("info159", None),
+ ByteField("info160", None),
+ ByteField("info161", None),
+ ByteField("info162", None),
+ ByteField("info163", None),
+ ByteField("info164", None),
+ ByteField("info165", None),
+ ByteField("info166", None),
+ ByteField("info167", None),
+ ByteField("info168", None),
+ ByteField("info169", None),
+ ByteField("info170", None),
+ ByteField("info171", None),
+ ByteField("info172", None),
+ ByteField("info173", None),
+ ByteField("info174", None),
+ ByteField("info175", None),
+ ByteField("info176", None),
+ ByteField("info177", None),
+ ByteField("info178", None),
+ ByteField("info179", None),
+ ByteField("info180", None),
+ ByteField("info181", None),
+ ByteField("info182", None),
+ ByteField("info183", None),
+ ByteField("info184", None),
+ ByteField("info185", None),
+ ByteField("info186", None),
+ ByteField("info187", None),
+ ByteField("info188", None),
+ ByteField("info189", None),
+ ByteField("info190", None),
+ ByteField("info191", None),
+ ByteField("info192", None),
+ ByteField("info193", None),
+ ByteField("info194", None),
+ ByteField("info195", None),
+ ByteField("info196", None),
+ ByteField("info197", None),
+ ByteField("info198", None),
+ ByteField("info199", None),
+ ByteField("info200", None),
+ ByteField("info201", None),
+ ByteField("info202", None),
+ ByteField("info203", None),
+ ByteField("info204", None),
+ ByteField("info205", None),
+ ByteField("info206", None),
+ ByteField("info207", None),
+ ByteField("info208", None),
+ ByteField("info209", None),
+ ByteField("info210", None),
+ ByteField("info211", None),
+ ByteField("info212", None),
+ ByteField("info213", None),
+ ByteField("info214", None),
+ ByteField("info215", None),
+ ByteField("info216", None),
+ ByteField("info217", None),
+ ByteField("info218", None),
+ ByteField("info219", None),
+ ByteField("info220", None),
+ ByteField("info221", None),
+ ByteField("info222", None),
+ ByteField("info223", None),
+ ByteField("info224", None),
+ ByteField("info225", None),
+ ByteField("info226", None),
+ ByteField("info227", None),
+ ByteField("info228", None),
+ ByteField("info229", None),
+ ByteField("info230", None),
+ ByteField("info231", None),
+ ByteField("info232", None),
+ ByteField("info233", None),
+ ByteField("info234", None),
+ ByteField("info235", None),
+ ByteField("info236", None),
+ ByteField("info237", None),
+ ByteField("info238", None),
+ ByteField("info239", None),
+ ByteField("info240", None),
+ ByteField("info241", None),
+ ByteField("info242", None),
+ ByteField("info243", None),
+ ByteField("info244", None),
+ ByteField("info245", None),
+ ByteField("info246", None),
+ ByteField("info247", None),
+ ByteField("info248", None),
+ ByteField("info249", None),
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(1, 250, a, self.fields_desc, 1)
+ if self.lengthSVI is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+# length 3 to 35 or 131
+class UserUser(Packet):
+ """User-user Section 10.5.4.25"""
+ name = "User-User"
+ fields_desc = [
+
+ XByteField("lengthUU", None), # dynamic length of field depending
+ # of the type of message
+ # let user decide which length he
+ # wants to take
+ # => more fuzzing options
+ ByteField("userUserPD", 0x0),
+ # optional
+ ByteField("userUserInfo1", None),
+ ByteField("userUserInfo2", None),
+ ByteField("userUserInfo3", None),
+ ByteField("userUserInfo4", None),
+ ByteField("userUserInfo5", None),
+ ByteField("userUserInfo6", None),
+ ByteField("userUserInfo7", None),
+ ByteField("userUserInfo8", None),
+ ByteField("userUserInfo9", None),
+ ByteField("userUserInfo10", None),
+ ByteField("userUserInfo11", None),
+ ByteField("userUserInfo12", None),
+ ByteField("userUserInfo13", None),
+ ByteField("userUserInfo14", None),
+ ByteField("userUserInfo15", None),
+ ByteField("userUserInfo16", None),
+ ByteField("userUserInfo17", None),
+ ByteField("userUserInfo18", None),
+ ByteField("userUserInfo19", None),
+ ByteField("userUserInfo20", None),
+ ByteField("userUserInfo21", None),
+ ByteField("userUserInfo22", None),
+ ByteField("userUserInfo23", None),
+ ByteField("userUserInfo24", None),
+ ByteField("userUserInfo25", None),
+ ByteField("userUserInfo26", None),
+ ByteField("userUserInfo27", None),
+ ByteField("userUserInfo28", None),
+ ByteField("userUserInfo29", None),
+ ByteField("userUserInfo30", None),
+ ByteField("userUserInfo31", None),
+ ByteField("userUserInfo32", None),
+ # long packet
+ ByteField("userUserInfo33", None),
+ ByteField("userUserInfo34", None),
+ ByteField("userUserInfo35", None),
+ ByteField("userUserInfo36", None),
+ ByteField("userUserInfo37", None),
+ ByteField("userUserInfo38", None),
+ ByteField("userUserInfo39", None),
+ ByteField("userUserInfo40", None),
+ ByteField("userUserInfo41", None),
+ ByteField("userUserInfo42", None),
+ ByteField("userUserInfo43", None),
+ ByteField("userUserInfo44", None),
+ ByteField("userUserInfo45", None),
+ ByteField("userUserInfo46", None),
+ ByteField("userUserInfo47", None),
+ ByteField("userUserInfo48", None),
+ ByteField("userUserInfo49", None),
+ ByteField("userUserInfo50", None),
+ ByteField("userUserInfo51", None),
+ ByteField("userUserInfo52", None),
+ ByteField("userUserInfo53", None),
+ ByteField("userUserInfo54", None),
+ ByteField("userUserInfo55", None),
+ ByteField("userUserInfo56", None),
+ ByteField("userUserInfo57", None),
+ ByteField("userUserInfo58", None),
+ ByteField("userUserInfo59", None),
+ ByteField("userUserInfo60", None),
+ ByteField("userUserInfo61", None),
+ ByteField("userUserInfo62", None),
+ ByteField("userUserInfo63", None),
+ ByteField("userUserInfo64", None),
+ ByteField("userUserInfo65", None),
+ ByteField("userUserInfo66", None),
+ ByteField("userUserInfo67", None),
+ ByteField("userUserInfo68", None),
+ ByteField("userUserInfo69", None),
+ ByteField("userUserInfo70", None),
+ ByteField("userUserInfo71", None),
+ ByteField("userUserInfo72", None),
+ ByteField("userUserInfo73", None),
+ ByteField("userUserInfo74", None),
+ ByteField("userUserInfo75", None),
+ ByteField("userUserInfo76", None),
+ ByteField("userUserInfo77", None),
+ ByteField("userUserInfo78", None),
+ ByteField("userUserInfo79", None),
+ ByteField("userUserInfo80", None),
+ ByteField("userUserInfo81", None),
+ ByteField("userUserInfo82", None),
+ ByteField("userUserInfo83", None),
+ ByteField("userUserInfo84", None),
+ ByteField("userUserInfo85", None),
+ ByteField("userUserInfo86", None),
+ ByteField("userUserInfo87", None),
+ ByteField("userUserInfo88", None),
+ ByteField("userUserInfo89", None),
+ ByteField("userUserInfo90", None),
+ ByteField("userUserInfo91", None),
+ ByteField("userUserInfo92", None),
+ ByteField("userUserInfo93", None),
+ ByteField("userUserInfo94", None),
+ ByteField("userUserInfo95", None),
+ ByteField("userUserInfo96", None),
+ ByteField("userUserInfo97", None),
+ ByteField("userUserInfo98", None),
+ ByteField("userUserInfo99", None),
+ ByteField("userUserInfo100", None),
+ ByteField("userUserInfo101", None),
+ ByteField("userUserInfo102", None),
+ ByteField("userUserInfo103", None),
+ ByteField("userUserInfo104", None),
+ ByteField("userUserInfo105", None),
+ ByteField("userUserInfo106", None),
+ ByteField("userUserInfo107", None),
+ ByteField("userUserInfo108", None),
+ ByteField("userUserInfo109", None),
+ ByteField("userUserInfo110", None),
+ ByteField("userUserInfo111", None),
+ ByteField("userUserInfo112", None),
+ ByteField("userUserInfo113", None),
+ ByteField("userUserInfo114", None),
+ ByteField("userUserInfo115", None),
+ ByteField("userUserInfo116", None),
+ ByteField("userUserInfo117", None),
+ ByteField("userUserInfo118", None),
+ ByteField("userUserInfo119", None),
+ ByteField("userUserInfo120", None),
+ ByteField("userUserInfo121", None),
+ ByteField("userUserInfo122", None),
+ ByteField("userUserInfo123", None),
+ ByteField("userUserInfo124", None),
+ ByteField("userUserInfo125", None),
+ ByteField("userUserInfo126", None),
+ ByteField("userUserInfo127", None),
+ ByteField("userUserInfo128", None),
+ ByteField("userUserInfo129", None),
+ ByteField("userUserInfo130", None),
+ ByteField("userUserInfo131", None)
+ ]
+
+ def post_build(self, p, pay):
+ aList = []
+ i = 0
+ for i in range(0, len(self.fields_desc)):
+ aList.append(self.fields_desc[i].name)
+ a = []
+ for i in aList:
+ a.append(getattr(self, i))
+ res = adapt(2, 133, a, self.fields_desc, 1)
+ if self.lengthUU is None:
+ p = struct.pack(">B", res[1]) + p[1:]
+ if res[0] is not 0:
+ p = p[:-res[0]]
+ return p + pay
+
+
+class AlertingPattern(Packet):
+ """Alerting Pattern 10.5.4.26"""
+ name = "Alerting Pattern"
+ fields_desc = [
+ XByteField("lengthAP", 0x3),
+ BitField("spare", 0x0, 4),
+ BitField("alertingValue", 0x0, 4)
+ ]
+
+
+class AllowedActions(Packet):
+ """Allowed actions $(CCBS)$ Section 10.5.4.26"""
+ name = "Allowed Actions $(CCBS)$"
+ fields_desc = [
+ XByteField("lengthAP", 0x3),
+ BitField("CCBS", 0x0, 1),
+ BitField("spare", 0x0, 7)
+ ]
+
+
+#
+# 10.5.5 GPRS mobility management information elements
+#
+
+
+class AttachType(Packet):
+ """Attach type Section 10.5.5.2"""
+ name = "Attach Type"
+ fields_desc = [
+ BitField("spare", 0x0, 1),
+ BitField("type", 0x1, 3)
+ ]
+
+
+if __name__ == "__main__":
+ interact(mydict=globals(), mybanner="Scapy GSM-UM (Air) Addon")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gtp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gtp.py
new file mode 100644
index 00000000..008a0200
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/gtp.py
@@ -0,0 +1,546 @@
+#! /usr/bin/env python
+
+## Copyright (C) 2014 Guillaume Valadon <guillaume.valadon@ssi.gouv.fr>
+## 2014 Alexis Sultan <alexis.sultan@sfr.com>
+## 2012 ffranz <ffranz@iniqua.com>
+##
+## This program is published under a GPLv2 license
+
+# scapy.contrib.description = GTP
+# scapy.contrib.status = loads
+
+import time
+import logging
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP, UDP
+
+# GTP Data types
+
+GTPmessageType = { 1: "echo_request",
+ 2: "echo_response",
+ 16: "create_pdp_context_req",
+ 17: "create_pdp_context_res",
+ 20: "delete_pdp_context_req",
+ 21: "delete_pdp_context_res",
+ 26: "error_indication",
+ 27: "pdu_notification_req",
+ 255: "gtp_u_header" }
+
+IEType = { 1: "Cause",
+ 2: "IMSI",
+ 3: "RAI",
+ 4: "TLLI",
+ 5: "P_TMSI",
+ 14: "Recovery",
+ 15: "SelectionMode",
+ 16: "TEIDI",
+ 17: "TEICP",
+ 19: "TeardownInd",
+ 20: "NSAPI",
+ 26: "ChargingChrt",
+ 27: "TraceReference",
+ 28: "TraceType",
+ 128: "EndUserAddress",
+ 131: "AccessPointName",
+ 132: "ProtocolConfigurationOptions",
+ 133: "GSNAddress",
+ 134: "MSInternationalNumber",
+ 135: "QoS",
+ 148: "CommonFlags",
+ 151: "RatType",
+ 152: "UserLocationInformation",
+ 153: "MSTimeZone",
+ 154: "IMEI" }
+
+CauseValues = { 0: "Request IMSI",
+ 1: "Request IMEI",
+ 2: "Request IMSI and IMEI",
+ 3: "No identity needed",
+ 4: "MS Refuses",
+ 5: "MS is not GPRS Responding",
+ 128: "Request accepted",
+ 129: "New PDP type due to network preference",
+ 130: "New PDP type due to single address bearer only",
+ 192: "Non-existent",
+ 193: "Invalid message format",
+ 194: "IMSI not known",
+ 195: "MS is GPRS Detached",
+ 196: "MS is not GPRS Responding",
+ 197: "MS Refuses",
+ 198: "Version not supported",
+ 199: "No resources available",
+ 200: "Service not supported",
+ 201: "Mandatory IE incorrect",
+ 202: "Mandatory IE missing",
+ 203: "Optional IE incorrect",
+ 204: "System failure",
+ 205: "Roaming restriction",
+ 206: "P-TMSI Signature mismatch",
+ 207: "GPRS connection suspended",
+ 208: "Authentication failure",
+ 209: "User authentication failed",
+ 210: "Context not found",
+ 211: "All dynamic PDP addresses are occupied",
+ 212: "No memory is available",
+ 213: "Reallocation failure",
+ 214: "Unknown mandatory extension header",
+ 215: "Semantic error in the TFT operation",
+ 216: "Syntactic error in TFT operation",
+ 217: "Semantic errors in packet filter(s)",
+ 218: "Syntactic errors in packet filter(s)",
+ 219: "Missing or unknown APN",
+ 220: "Unknown PDP address or PDP type",
+ 221: "PDP context without TFT already activated",
+ 222: "APN access denied : no subscription",
+ 223: "APN Restriction type incompatibility with currently active PDP Contexts",
+ 224: "MS MBMS Capabilities Insufficient",
+ 225: "Invalid Correlation : ID",
+ 226: "MBMS Bearer Context Superseded",
+ 227: "Bearer Control Mode violation",
+ 228: "Collision with network initiated request" }
+
+Selection_Mode = { 11111100: "MS or APN",
+ 11111101: "MS",
+ 11111110: "NET",
+ 11111111: "FutureUse" }
+
+TeardownInd_value = { 254: "False",
+ 255: "True" }
+
+class TBCDByteField(StrFixedLenField):
+
+ def i2h(self, pkt, val):
+ ret = []
+ for i in range(len(val)):
+ byte = ord(val[i])
+ left = byte >> 4
+ right = byte & 0xF
+ if left == 0xF:
+ ret += [ "%d" % right ]
+ else:
+ ret += [ "%d" % right, "%d" % left ]
+ return "".join(ret)
+
+ def i2repr(self, pkt, x):
+ return repr(self.i2h(pkt,x))
+
+ def i2m(self, pkt, val):
+ ret_string = ""
+ for i in range(0, len(val), 2):
+ tmp = val[i:i+2]
+ if len(tmp) == 2:
+ ret_string += chr(int(tmp[1] + tmp[0], 16))
+ else:
+ ret_string += chr(int("F" + tmp[0], 16))
+ return ret_string
+
+class GTPHeader(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Header"
+ fields_desc=[ BitField("version", 1, 3),
+ BitField("PT", 1, 1),
+ BitField("reserved", 0, 1),
+ BitField("E", 0, 1),
+ BitField("S", 1, 1),
+ BitField("PN", 0, 1),
+ ByteEnumField("gtp_type", None, GTPmessageType),
+ ShortField("length", None),
+ IntField("teid", 0) ]
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.length is None:
+ l = len(p)-8
+ p = p[:2] + struct.pack("!H", l)+ p[4:]
+ return p
+
+ def hashret(self):
+ return struct.pack("B", self.version) + self.payload.hashret()
+
+ def answers(self, other):
+ return (isinstance(other, GTPHeader) and
+ self.version == other.version and
+ self.payload.answers(other.payload))
+
+class GTPEchoRequest(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Echo Request"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),]
+
+ def hashret(self):
+ return struct.pack("H", self.seq)
+
+class IE_Cause(Packet):
+ name = "Cause"
+ fields_desc = [ ByteEnumField("ietype", 1, IEType),
+ BitField("Response", None, 1),
+ BitField("Rejection", None, 1),
+ BitEnumField("CauseValue", None, 6, CauseValues) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_IMSI(Packet):
+ name = "IMSI - Subscriber identity of the MS"
+ fields_desc = [ ByteEnumField("ietype", 2, IEType),
+ TBCDByteField("imsi", str(RandNum(0, 999999999999999)), 8) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_Routing(Packet):
+ name = "Routing Area Identity"
+ fields_desc = [ ByteEnumField("ietype", 3, IEType),
+ TBCDByteField("MCC", "", 2),
+ # MNC: if the third digit of MCC is 0xf, then the length of MNC is 1 byte
+ TBCDByteField("MNC", "", 1),
+ ShortField("LAC", None),
+ ByteField("RAC", None) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_Recovery(Packet):
+ name = "Recovery"
+ fields_desc = [ ByteEnumField("ietype", 14, IEType),
+ ByteField("res-counter", 24) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_SelectionMode(Packet):
+ # Indicates the origin of the APN in the message
+ name = "Selection Mode"
+ fields_desc = [ ByteEnumField("ietype", 15, IEType),
+ BitEnumField("SelectionMode", "MS or APN", 8, Selection_Mode) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_TEIDI(Packet):
+ name = "Tunnel Endpoint Identifier Data"
+ fields_desc = [ ByteEnumField("ietype", 16, IEType),
+ XIntField("TEIDI", RandInt()) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_TEICP(Packet):
+ name = "Tunnel Endpoint Identifier Control Plane"
+ fields_desc = [ ByteEnumField("ietype", 17, IEType),
+ XIntField("TEICI", RandInt())]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_Teardown(Packet):
+ name = "Teardown Indicator"
+ fields_desc = [ ByteEnumField("ietype", 19, IEType),
+ ByteEnumField("indicator", "True", TeardownInd_value) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_NSAPI(Packet):
+ # Identifies a PDP context in a mobility management context specified by TEICP
+ name = "NSAPI"
+ fields_desc = [ ByteEnumField("ietype", 20, IEType),
+ XBitField("sparebits", 0x0000, 4),
+ XBitField("NSAPI", RandNum(0, 15), 4) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_ChargingCharacteristics(Packet):
+ # Way of informing both the SGSN and GGSN of the rules for
+ name = "Charging Characteristics"
+ fields_desc = [ ByteEnumField("ietype", 26, IEType),
+ # producing charging information based on operator configured triggers.
+ # 0000 .... .... .... : spare
+ # .... 1... .... .... : normal charging
+ # .... .0.. .... .... : prepaid charging
+ # .... ..0. .... .... : flat rate charging
+ # .... ...0 .... .... : hot billing charging
+ # .... .... 0000 0000 : reserved
+ XBitField("Ch_ChSpare", None, 4),
+ XBitField("normal_charging", None, 1),
+ XBitField("prepaid_charging", None, 1),
+ XBitField("flat_rate_charging", None, 1),
+ XBitField("hot_billing_charging", None, 1),
+ XBitField("Ch_ChReserved", 0, 8) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_TraceReference(Packet):
+ # Identifies a record or a collection of records for a particular trace.
+ name = "Trace Reference"
+ fields_desc = [ ByteEnumField("ietype", 27, IEType),
+ XBitField("Trace_reference", None, 16) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_TraceType(Packet):
+ # Indicates the type of the trace
+ name = "Trace Type"
+ fields_desc = [ ByteEnumField("ietype", 28, IEType),
+ XBitField("Trace_type", None, 16) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_EndUserAddress(Packet):
+ # Supply protocol specific information of the external packet
+ name = "End User Addresss"
+ fields_desc = [ ByteEnumField("ietype", 128, IEType),
+ # data network accessed by the GGPRS subscribers.
+ # - Request
+ # 1 Type (1byte)
+ # 2-3 Length (2bytes) - value 2
+ # 4 Spare + PDP Type Organization
+ # 5 PDP Type Number
+ # - Response
+ # 6-n PDP Address
+ BitField("EndUserAddressLength", 2, 16),
+ BitField("EndUserAddress", 1111, 4),
+ BitField("PDPTypeOrganization", 1, 4),
+ XByteField("PDPTypeNumber", None) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class APNStrLenField(StrLenField):
+ # Inspired by DNSStrField
+ def m2i(self, pkt, s):
+ ret_s = ""
+ tmp_s = s
+ while tmp_s:
+ tmp_len = struct.unpack("!B", tmp_s[0])[0] + 1
+ if tmp_len > len(tmp_s):
+ warning("APN prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s)))
+ ret_s += tmp_s[1:tmp_len]
+ tmp_s = tmp_s[tmp_len:]
+ if len(tmp_s) :
+ ret_s += "."
+ s = ret_s
+ return s
+ def i2m(self, pkt, s):
+ s = "".join(map(lambda x: chr(len(x))+x, s.split(".")))
+ return s
+
+
+class IE_AccessPointName(Packet):
+ # Sent by SGSN or by GGSN as defined in 3GPP TS 23.060
+ name = "Access Point Name"
+ fields_desc = [ ByteEnumField("ietype", 131, IEType),
+ ShortField("length", None),
+ APNStrLenField("APN", "nternet", length_from=lambda x: x.length) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+ def post_build(self, p, pay):
+ if self.length is None:
+ l = len(p)-3
+ p = p[:2] + struct.pack("!B", l)+ p[3:]
+ return p
+
+class IE_ProtocolConfigurationOptions(Packet):
+ name = "Protocol Configuration Options"
+ fields_desc = [ ByteEnumField("ietype", 132, IEType),
+ ShortField("length", 4),
+ StrLenField("Protocol Configuration", "", length_from=lambda x: x.length) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_GSNAddress(Packet):
+ name = "GSN Address"
+ fields_desc = [ ByteEnumField("ietype", 133, IEType),
+ ShortField("length", 4),
+ IPField("address", RandIP()) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_MSInternationalNumber(Packet):
+ name = "MS International Number"
+ fields_desc = [ ByteEnumField("ietype", 134, IEType),
+ ShortField("length", None),
+ FlagsField("flags", 0x91, 8, ["Extension","","","International Number","","","","ISDN numbering"]),
+ TBCDByteField("digits", "33607080910", length_from=lambda x: x.length-1) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_UserLocationInformation(Packet):
+ name = "User Location Information"
+ fields_desc = [ ByteEnumField("ietype", 152, IEType),
+ ShortField("length", None),
+ ByteField("type", 1),
+ # Only type 1 is currently supported
+ TBCDByteField("MCC", "", 2),
+ # MNC: if the third digit of MCC is 0xf, then the length of MNC is 1 byte
+ TBCDByteField("MNC", "", 1),
+ ShortField("LAC", None),
+ ShortField("SAC", None) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_IMEI(Packet):
+ name = "IMEI"
+ fields_desc = [ ByteEnumField("ietype", 154, IEType),
+ ShortField("length", None),
+ TBCDByteField("IMEI", "", length_from=lambda x: x.length) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class IE_NotImplementedTLV(Packet):
+ name = "IE not implemented"
+ fields_desc = [ ByteEnumField("ietype", 0, IEType),
+ ShortField("length", None),
+ StrLenField("data", "", length_from=lambda x: x.length) ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+ietypecls = { 1: IE_Cause, 2: IE_IMSI, 3: IE_Routing, 14: IE_Recovery, 15: IE_SelectionMode, 16: IE_TEIDI,
+ 17: IE_TEICP, 19: IE_Teardown, 20: IE_NSAPI, 26: IE_ChargingCharacteristics,
+ 27: IE_TraceReference, 28: IE_TraceType,
+ 128: IE_EndUserAddress, 131: IE_AccessPointName, 132: IE_ProtocolConfigurationOptions,
+ 133: IE_GSNAddress, 134: IE_MSInternationalNumber, 152: IE_UserLocationInformation, 154: IE_IMEI }
+
+def IE_Dispatcher(s):
+ """Choose the correct Information Element class."""
+
+ if len(s) < 1:
+ return Raw(s)
+
+ # Get the IE type
+ ietype = ord(s[0])
+ cls = ietypecls.get(ietype, Raw)
+
+ # if ietype greater than 128 are TLVs
+ if cls == Raw and ietype & 128 == 128:
+ cls = IE_NotImplementedTLV
+
+ return cls(s)
+
+class GTPEchoResponse(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Echo Response"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),
+ PacketListField("IE_list", [], IE_Dispatcher) ]
+
+ def hashret(self):
+ return struct.pack("H", self.seq)
+
+ def answers(self, other):
+ return self.seq == other.seq
+
+
+class GTPCreatePDPContextRequest(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Create PDP Context Request"
+ fields_desc = [ ShortField("seq", RandShort()),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),
+ PacketListField("IE_list", [ IE_TEIDI(), IE_NSAPI(), IE_GSNAddress(),
+ IE_GSNAddress(),
+ IE_NotImplementedTLV(ietype=135, length=15,data=RandString(15)) ],
+ IE_Dispatcher) ]
+ def hashret(self):
+ return struct.pack("H", self.seq)
+
+class GTPCreatePDPContextResponse(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Create PDP Context Response"
+ fields_desc = [ ShortField("seq", RandShort()),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),
+ PacketListField("IE_list", [], IE_Dispatcher) ]
+
+ def hashret(self):
+ return struct.pack("H", self.seq)
+
+ def answers(self, other):
+ return self.seq == other.seq
+
+class GTPErrorIndication(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Error Indication"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex",0),
+ PacketListField("IE_list", [], IE_Dispatcher) ]
+
+class GTPDeletePDPContextRequest(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Delete PDP Context Request"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),
+ PacketListField("IE_list", [], IE_Dispatcher) ]
+
+class GTPDeletePDPContextResponse(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP Delete PDP Context Response"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex",0),
+ PacketListField("IE_list", [], IE_Dispatcher) ]
+
+class GTPPDUNotificationRequest(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP PDU Notification Request"
+ fields_desc = [ XBitField("seq", 0, 16),
+ ByteField("npdu", 0),
+ ByteField("next_ex", 0),
+ PacketListField("IE_list", [ IE_IMSI(),
+ IE_TEICP(TEICI=RandInt()),
+ IE_EndUserAddress(PDPTypeNumber=0x21),
+ IE_AccessPointName(),
+ IE_GSNAddress(address="127.0.0.1"),
+ ], IE_Dispatcher) ]
+
+class GTP_U_Header(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP-U Header"
+ # GTP-U protocol is used to transmit T-PDUs between GSN pairs (or between an SGSN and an RNC in UMTS),
+ # encapsulated in G-PDUs. A G-PDU is a packet including a GTP-U header and a T-PDU. The Path Protocol
+ # defines the path and the GTP-U header defines the tunnel. Several tunnels may be multiplexed on a single path.
+ fields_desc = [ BitField("version", 1,3),
+ BitField("PT", 1, 1),
+ BitField("Reserved", 0, 1),
+ BitField("E", 0,1),
+ BitField("S", 0, 1),
+ BitField("PN", 0, 1),
+ ByteEnumField("gtp_type", None, GTPmessageType),
+ BitField("length", None, 16),
+ XBitField("TEID", 0, 32),
+ ConditionalField(XBitField("seq", 0, 16), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1),
+ ConditionalField(ByteField("npdu", 0), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1),
+ ConditionalField(ByteField("next_ex", 0), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1),
+ ]
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.length is None:
+ l = len(p)-8
+ p = p[:2] + struct.pack("!H", l)+ p[4:]
+ return p
+
+class GTPmorethan1500(Packet):
+ # 3GPP TS 29.060 V9.1.0 (2009-12)
+ name = "GTP More than 1500"
+ fields_desc = [ ByteEnumField("IE_Cause", "Cause", IEType),
+ BitField("IE", 1, 12000),]
+
+# Bind GTP-C
+bind_layers(UDP, GTPHeader, dport = 2123)
+bind_layers(UDP, GTPHeader, sport = 2123)
+bind_layers(GTPHeader, GTPEchoRequest, gtp_type = 1)
+bind_layers(GTPHeader, GTPEchoResponse, gtp_type = 2)
+bind_layers(GTPHeader, GTPCreatePDPContextRequest, gtp_type = 16)
+bind_layers(GTPHeader, GTPCreatePDPContextResponse, gtp_type = 17)
+bind_layers(GTPHeader, GTPDeletePDPContextRequest, gtp_type = 20)
+bind_layers(GTPHeader, GTPDeletePDPContextResponse, gtp_type = 21)
+bind_layers(GTPHeader, GTPPDUNotificationRequest, gtp_type = 27)
+
+# Bind GTP-U
+bind_layers(UDP, GTP_U_Header, dport = 2152)
+bind_layers(UDP, GTP_U_Header, sport = 2152)
+bind_layers(GTP_U_Header, IP, gtp_type = 255)
+
+if __name__ == "__main__":
+ from scapy.all import *
+ interact(mydict=globals(), mybanner="GTPv1 add-on")
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmp.py
new file mode 100644
index 00000000..b3505810
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmp.py
@@ -0,0 +1,171 @@
+#! /usr/bin/env python
+
+# scapy.contrib.description = IGMP/IGMPv2
+# scapy.contrib.status = loads
+
+
+# TODO: scapy 2 has function getmacbyip, maybe it can replace igmpize
+# at least from the MAC layer
+
+from scapy.all import *
+
+#--------------------------------------------------------------------------
+def isValidMCAddr(ip):
+ """convert dotted quad string to long and check the first octet"""
+ FirstOct=atol(ip)>>24 & 0xFF
+ return (FirstOct >= 224) and (FirstOct <= 239)
+
+#--------------------------------------------------------------------------
+
+class IGMP(Packet):
+ """IGMP Message Class for v1 and v2.
+
+This class is derived from class Packet. You need to "igmpize"
+the IP and Ethernet layers before a full packet is sent.
+a=Ether(src="00:01:02:03:04:05")
+b=IP(src="1.2.3.4")
+c=IGMP(type=0x12, gaddr="224.2.3.4")
+c.igmpize(b, a)
+print("Joining IP " + c.gaddr + " MAC " + a.dst)
+sendp(a/b/c, iface="en0")
+
+ Parameters:
+ type IGMP type field, 0x11, 0x12, 0x16 or 0x17
+ mrtime Maximum Response time (zero for v1)
+ gaddr Multicast Group Address 224.x.x.x/4
+
+See RFC2236, Section 2. Introduction for definitions of proper
+IGMPv2 message format http://www.faqs.org/rfcs/rfc2236.html
+
+ """
+ name = "IGMP"
+
+ igmptypes = { 0x11 : "Group Membership Query",
+ 0x12 : "Version 1 - Membership Report",
+ 0x16 : "Version 2 - Membership Report",
+ 0x17 : "Leave Group"}
+
+ fields_desc = [ ByteEnumField("type", 0x11, igmptypes),
+ ByteField("mrtime",20),
+ XShortField("chksum", None),
+ IPField("gaddr", "0.0.0.0")]
+
+#--------------------------------------------------------------------------
+ def post_build(self, p, pay):
+ """Called implicitly before a packet is sent to compute and place IGMP checksum.
+
+ Parameters:
+ self The instantiation of an IGMP class
+ p The IGMP message in hex in network byte order
+ pay Additional payload for the IGMP message
+ """
+ p += pay
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
+ return p
+
+#--------------------------------------------------------------------------
+ def mysummary(self):
+ """Display a summary of the IGMP object."""
+
+ if isinstance(self.underlayer, IP):
+ return self.underlayer.sprintf("IGMP: %IP.src% > %IP.dst% %IGMP.type% %IGMP.gaddr%")
+ else:
+ return self.sprintf("IGMP %IGMP.type% %IGMP.gaddr%")
+
+#--------------------------------------------------------------------------
+ def igmpize(self, ip=None, ether=None):
+ """Called to explicitely fixup associated IP and Ethernet headers
+
+ Parameters:
+ self The instantiation of an IGMP class.
+ ip The instantiation of the associated IP class.
+ ether The instantiation of the associated Ethernet.
+
+ Returns:
+ True The tuple ether/ip/self passed all check and represents
+ a proper IGMP packet.
+ False One of more validation checks failed and no fields
+ were adjusted.
+
+ The function will examine the IGMP message to assure proper format.
+ Corrections will be attempted if possible. The IP header is then properly
+ adjusted to ensure correct formatting and assignment. The Ethernet header
+ is then adjusted to the proper IGMP packet format.
+ """
+
+# The rules are:
+# 1. the Max Response time is meaningful only in Membership Queries and should be zero
+# otherwise (RFC 2236, section 2.2)
+
+ if (self.type != 0x11): #rule 1
+ self.mrtime = 0
+
+ if (self.adjust_ip(ip) == True):
+ if (self.adjust_ether(ip, ether) == True): return True
+ return False
+
+#--------------------------------------------------------------------------
+ def adjust_ether (self, ip=None, ether=None):
+ """Called to explicitely fixup an associated Ethernet header
+
+ The function adjusts the ethernet header destination MAC address based on
+ the destination IP address.
+ """
+# The rules are:
+# 1. send to the group mac address address corresponding to the IP.dst
+ if ip != None and ip.haslayer(IP) and ether != None and ether.haslayer(Ether):
+ iplong = atol(ip.dst)
+ ether.dst = "01:00:5e:%02x:%02x:%02x" % ( (iplong>>16)&0x7F, (iplong>>8)&0xFF, (iplong)&0xFF )
+ # print "igmpize ip " + ip.dst + " as mac " + ether.dst
+ return True
+ else:
+ return False
+
+#--------------------------------------------------------------------------
+ def adjust_ip (self, ip=None):
+ """Called to explicitely fixup an associated IP header
+
+ The function adjusts the IP header based on conformance rules
+ and the group address encoded in the IGMP message.
+ The rules are:
+ 1. Send General Group Query to 224.0.0.1 (all systems)
+ 2. Send Leave Group to 224.0.0.2 (all routers)
+ 3a.Otherwise send the packet to the group address
+ 3b.Send reports/joins to the group address
+ 4. ttl = 1 (RFC 2236, section 2)
+ 5. send the packet with the router alert IP option (RFC 2236, section 2)
+ """
+ if ip != None and ip.haslayer(IP):
+ if (self.type == 0x11):
+ if (self.gaddr == "0.0.0.0"):
+ ip.dst = "224.0.0.1" # IP rule 1
+ retCode = True
+ elif isValidMCAddr(self.gaddr):
+ ip.dst = self.gaddr # IP rule 3a
+ retCode = True
+ else:
+ print("Warning: Using invalid Group Address")
+ retCode = False
+ elif ((self.type == 0x17) and isValidMCAddr(self.gaddr)):
+ ip.dst = "224.0.0.2" # IP rule 2
+ retCode = True
+ elif ((self.type == 0x12) or (self.type == 0x16)) and (isValidMCAddr(self.gaddr)):
+ ip.dst = self.gaddr # IP rule 3b
+ retCode = True
+ else:
+ print("Warning: Using invalid IGMP Type")
+ retCode = False
+ else:
+ print("Warning: No IGMP Group Address set")
+ retCode = False
+ if retCode == True:
+ ip.ttl=1 # IP Rule 4
+ ip.options=[IPOption_Router_Alert()] # IP rule 5
+ return retCode
+
+
+bind_layers( IP, IGMP, frag=0, proto=2)
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmpv3.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmpv3.py
new file mode 100644
index 00000000..8322c7a3
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/igmpv3.py
@@ -0,0 +1,270 @@
+#! /usr/bin/env python
+
+# http://trac.secdev.org/scapy/ticket/31
+
+# scapy.contrib.description = IGMPv3
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+
+""" Based on the following references
+ http://www.iana.org/assignments/igmp-type-numbers
+ http://www.rfc-editor.org/rfc/pdfrfc/rfc3376.txt.pdf
+
+"""
+
+# TODO: Merge IGMPv3 packet Bindlayers correct for
+# membership source/Group records
+# ConditionalField parameters for IGMPv3 commented out
+#
+# See RFC3376, Section 4. Message Formats for definitions of proper IGMPv3 message format
+# http://www.faqs.org/rfcs/rfc3376.html
+#
+# See RFC4286, For definitions of proper messages for Multicast Router Discovery.
+# http://www.faqs.org/rfcs/rfc4286.html
+#
+
+#import sys, socket, struct, time
+from scapy.all import *
+print("IGMPv3 is still under development - Nov 2010")
+
+
+class IGMPv3gr(Packet):
+ """IGMP Group Record for IGMPv3 Membership Report
+
+ This class is derived from class Packet and should be concatenated to an
+ instantiation of class IGMPv3. Within the IGMPv3 instantiation, the numgrp
+ element will need to be manipulated to indicate the proper number of
+ group records.
+ """
+ name = "IGMPv3gr"
+ igmpv3grtypes = { 1 : "Mode Is Include",
+ 2 : "Mode Is Exclude",
+ 3 : "Change To Include Mode",
+ 4 : "Change To Exclude Mode",
+ 5 : "Allow New Sources",
+ 6 : "Block Old Sources"}
+
+ fields_desc = [ ByteEnumField("rtype", 1, igmpv3grtypes),
+ ByteField("auxdlen",0),
+ FieldLenField("numsrc", None, "srcaddrs"),
+ IPField("maddr", "0.0.0.0"),
+ FieldListField("srcaddrs", None, IPField("sa", "0.0.0.0"), "numsrc") ]
+ #show_indent=0
+#--------------------------------------------------------------------------
+ def post_build(self, p, pay):
+ """Called implicitly before a packet is sent.
+ """
+ p += pay
+ if self.auxdlen != 0:
+ print("NOTICE: A properly formatted and complaint V3 Group Record should have an Auxiliary Data length of zero (0).")
+ print(" Subsequent Group Records are lost!")
+ return p
+#--------------------------------------------------------------------------
+ def mysummary(self):
+ """Display a summary of the IGMPv3 group record."""
+ return self.sprintf("IGMPv3 Group Record %IGMPv3gr.type% %IGMPv3gr.maddr%")
+
+
+class IGMPv3(Packet):
+ """IGMP Message Class for v3.
+
+ This class is derived from class Packet.
+ The fields defined below are a
+ direct interpretation of the v3 Membership Query Message.
+ Fields 'type' through 'qqic' are directly assignable.
+ For 'numsrc', do not assign a value.
+ Instead add to the 'srcaddrs' list to auto-set 'numsrc'. To
+ assign values to 'srcaddrs', use the following methods:
+ c = IGMPv3()
+ c.srcaddrs = ['1.2.3.4', '5.6.7.8']
+ c.srcaddrs += ['192.168.10.24']
+ At this point, 'c.numsrc' is three (3)
+
+ 'chksum' is automagically calculated before the packet is sent.
+
+ 'mrcode' is also the Advertisement Interval field
+
+ """
+ name = "IGMPv3"
+ igmpv3types = { 0x11 : "Membership Query",
+ 0x22 : "Version 3 Membership Report",
+ 0x30 : "Multicast Router Advertisement",
+ 0x31 : "Multicast Router Solicitation",
+ 0x32 : "Multicast Router Termination"}
+
+ fields_desc = [ ByteEnumField("type", 0x11, igmpv3types),
+ ByteField("mrcode",0),
+ XShortField("chksum", None),
+ IPField("gaddr", "0.0.0.0")
+ ]
+ # use float_encode()
+
+ # if type = 0x11 (Membership Query), the next field is group address
+ # ConditionalField(IPField("gaddr", "0.0.0.0"), "type", lambda x:x==0x11),
+ # else if type = 0x22 (Membership Report), the next fields are
+ # reserved and number of group records
+ #ConditionalField(ShortField("rsvd2", 0), "type", lambda x:x==0x22),
+ #ConditionalField(ShortField("numgrp", 0), "type", lambda x:x==0x22),
+# FieldLenField("numgrp", None, "grprecs")]
+ # else if type = 0x30 (Multicast Router Advertisement), the next fields are
+ # query interval and robustness
+ #ConditionalField(ShortField("qryIntvl", 0), "type", lambda x:x==0x30),
+ #ConditionalField(ShortField("robust", 0), "type", lambda x:x==0x30),
+# The following are only present for membership queries
+ # ConditionalField(BitField("resv", 0, 4), "type", lambda x:x==0x11),
+ # ConditionalField(BitField("s", 0, 1), "type", lambda x:x==0x11),
+ # ConditionalField(BitField("qrv", 0, 3), "type", lambda x:x==0x11),
+ # ConditionalField(ByteField("qqic",0), "type", lambda x:x==0x11),
+ # ConditionalField(FieldLenField("numsrc", None, "srcaddrs"), "type", lambda x:x==0x11),
+ # ConditionalField(FieldListField("srcaddrs", None, IPField("sa", "0.0.0.0"), "numsrc"), "type", lambda x:x==0x11),
+
+#--------------------------------------------------------------------------
+ def float_encode(self, value):
+ """Convert the integer value to its IGMPv3 encoded time value if needed.
+
+ If value < 128, return the value specified. If >= 128, encode as a floating
+ point value. Value can be 0 - 31744.
+ """
+ if value < 128:
+ code = value
+ elif value > 31743:
+ code = 255
+ else:
+ exp=0
+ value>>=3
+ while(value>31):
+ exp+=1
+ value>>=1
+ exp<<=4
+ code = 0x80 | exp | (value & 0x0F)
+ return code
+
+#--------------------------------------------------------------------------
+ def post_build(self, p, pay):
+ """Called implicitly before a packet is sent to compute and place IGMPv3 checksum.
+
+ Parameters:
+ self The instantiation of an IGMPv3 class
+ p The IGMPv3 message in hex in network byte order
+ pay Additional payload for the IGMPv3 message
+ """
+ p += pay
+ if self.type in [0, 0x31, 0x32, 0x22]: # for these, field is reserved (0)
+ p = p[:1]+chr(0)+p[2:]
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
+ return p
+
+#--------------------------------------------------------------------------
+ def mysummary(self):
+ """Display a summary of the IGMPv3 object."""
+
+ if isinstance(self.underlayer, IP):
+ return self.underlayer.sprintf("IGMPv3: %IP.src% > %IP.dst% %IGMPv3.type% %IGMPv3.gaddr%")
+ else:
+ return self.sprintf("IGMPv3 %IGMPv3.type% %IGMPv3.gaddr%")
+
+#--------------------------------------------------------------------------
+ def igmpize(self, ip=None, ether=None):
+ """Called to explicitely fixup associated IP and Ethernet headers
+
+ Parameters:
+ self The instantiation of an IGMP class.
+ ip The instantiation of the associated IP class.
+ ether The instantiation of the associated Ethernet.
+
+ Returns:
+ True The tuple ether/ip/self passed all check and represents
+ a proper IGMP packet.
+ False One of more validation checks failed and no fields
+ were adjusted.
+
+ The function will examine the IGMP message to assure proper format.
+ Corrections will be attempted if possible. The IP header is then properly
+ adjusted to ensure correct formatting and assignment. The Ethernet header
+ is then adjusted to the proper IGMP packet format.
+ """
+
+# The rules are:
+# 1. ttl = 1 (RFC 2236, section 2)
+# igmp_binds = [ (IP, IGMP, { "proto": 2 , "ttl": 1 }),
+# 2. tos = 0xC0 (RFC 3376, section 4)
+# (IP, IGMPv3, { "proto": 2 , "ttl": 1, "tos":0xc0 }),
+# (IGMPv3, IGMPv3gr, { }) ]
+# The rules are:
+# 1. the Max Response time is meaningful only in Membership Queries and should be zero
+# otherwise (RFC 2236, section 2.2)
+
+ if (self.type != 0x11): #rule 1
+ self.mrtime = 0
+
+ if (self.adjust_ip(ip) == True):
+ if (self.adjust_ether(ip, ether) == True): return True
+ return False
+
+#--------------------------------------------------------------------------
+ def adjust_ether (self, ip=None, ether=None):
+ """Called to explicitely fixup an associated Ethernet header
+
+ The function adjusts the ethernet header destination MAC address based on
+ the destination IP address.
+ """
+# The rules are:
+# 1. send to the group mac address address corresponding to the IP.dst
+ if ip != None and ip.haslayer(IP) and ether != None and ether.haslayer(Ether):
+ iplong = atol(ip.dst)
+ ether.dst = "01:00:5e:%02x:%02x:%02x" % ( (iplong>>16)&0x7F, (iplong>>8)&0xFF, (iplong)&0xFF )
+ # print "igmpize ip " + ip.dst + " as mac " + ether.dst
+ return True
+ else:
+ return False
+
+#--------------------------------------------------------------------------
+ def adjust_ip (self, ip=None):
+ """Called to explicitely fixup an associated IP header
+
+ The function adjusts the IP header based on conformance rules
+ and the group address encoded in the IGMP message.
+ The rules are:
+ 1. Send General Group Query to 224.0.0.1 (all systems)
+ 2. Send Leave Group to 224.0.0.2 (all routers)
+ 3a.Otherwise send the packet to the group address
+ 3b.Send reports/joins to the group address
+ 4. ttl = 1 (RFC 2236, section 2)
+ 5. send the packet with the router alert IP option (RFC 2236, section 2)
+ """
+ if ip != None and ip.haslayer(IP):
+ if (self.type == 0x11):
+ if (self.gaddr == "0.0.0.0"):
+ ip.dst = "224.0.0.1" # IP rule 1
+ retCode = True
+ elif isValidMCAddr(self.gaddr):
+ ip.dst = self.gaddr # IP rule 3a
+ retCode = True
+ else:
+ print("Warning: Using invalid Group Address")
+ retCode = False
+ elif ((self.type == 0x17) and isValidMCAddr(self.gaddr)):
+ ip.dst = "224.0.0.2" # IP rule 2
+ retCode = True
+ elif ((self.type == 0x12) or (self.type == 0x16)) and (isValidMCAddr(self.gaddr)):
+ ip.dst = self.gaddr # IP rule 3b
+ retCode = True
+ else:
+ print("Warning: Using invalid IGMP Type")
+ retCode = False
+ else:
+ print("Warning: No IGMP Group Address set")
+ retCode = False
+ if retCode == True:
+ ip.ttl=1 # IP Rule 4
+ ip.options=[IPOption_Router_Alert()] # IP rule 5
+ return retCode
+
+
+bind_layers( IP, IGMPv3, frag=0, proto=2, ttl=1, tos=0xc0)
+bind_layers( IGMPv3, IGMPv3gr, frag=0, proto=2)
+bind_layers( IGMPv3gr, IGMPv3gr, frag=0, proto=2)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ikev2.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ikev2.py
new file mode 100644
index 00000000..fd38b80c
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ikev2.py
@@ -0,0 +1,362 @@
+#!/usr/bin/env python
+
+# http://trac.secdev.org/scapy/ticket/353
+
+# scapy.contrib.description = IKEv2
+# scapy.contrib.status = loads
+
+from scapy.all import *
+import logging
+
+
+## Modified from the original ISAKMP code by Yaron Sheffer <yaronf.ietf@gmail.com>, June 2010.
+
+import struct
+from scapy.packet import *
+from scapy.fields import *
+from scapy.ansmachine import *
+from scapy.layers.inet import IP,UDP
+from scapy.sendrecv import sr
+
+# see http://www.iana.org/assignments/ikev2-parameters for details
+IKEv2AttributeTypes= { "Encryption": (1, { "DES-IV64" : 1,
+ "DES" : 2,
+ "3DES" : 3,
+ "RC5" : 4,
+ "IDEA" : 5,
+ "CAST" : 6,
+ "Blowfish" : 7,
+ "3IDEA" : 8,
+ "DES-IV32" : 9,
+ "AES-CBC" : 12,
+ "AES-CTR" : 13,
+ "AES-CCM-8" : 14,
+ "AES-CCM-12" : 15,
+ "AES-CCM-16" : 16,
+ "AES-GCM-8ICV" : 18,
+ "AES-GCM-12ICV" : 19,
+ "AES-GCM-16ICV" : 20,
+ "Camellia-CBC" : 23,
+ "Camellia-CTR" : 24,
+ "Camellia-CCM-8ICV" : 25,
+ "Camellia-CCM-12ICV" : 26,
+ "Camellia-CCM-16ICV" : 27,
+ }, 0),
+ "PRF": (2, {"PRF_HMAC_MD5":1,
+ "PRF_HMAC_SHA1":2,
+ "PRF_HMAC_TIGER":3,
+ "PRF_AES128_XCBC":4,
+ "PRF_HMAC_SHA2_256":5,
+ "PRF_HMAC_SHA2_384":6,
+ "PRF_HMAC_SHA2_512":7,
+ "PRF_AES128_CMAC":8,
+ }, 0),
+ "Integrity": (3, { "HMAC-MD5-96": 1,
+ "HMAC-SHA1-96": 2,
+ "DES-MAC": 3,
+ "KPDK-MD5": 4,
+ "AES-XCBC-96": 5,
+ "HMAC-MD5-128": 6,
+ "HMAC-SHA1-160": 7,
+ "AES-CMAC-96": 8,
+ "AES-128-GMAC": 9,
+ "AES-192-GMAC": 10,
+ "AES-256-GMAC": 11,
+ "SHA2-256-128": 12,
+ "SHA2-384-192": 13,
+ "SHA2-512-256": 14,
+ }, 0),
+ "GroupDesc": (4, { "768MODPgr" : 1,
+ "1024MODPgr" : 2,
+ "1536MODPgr" : 5,
+ "2048MODPgr" : 14,
+ "3072MODPgr" : 15,
+ "4096MODPgr" : 16,
+ "6144MODPgr" : 17,
+ "8192MODPgr" : 18,
+ "256randECPgr" : 19,
+ "384randECPgr" : 20,
+ "521randECPgr" : 21,
+ "1024MODP160POSgr" : 22,
+ "2048MODP224POSgr" : 23,
+ "2048MODP256POSgr" : 24,
+ "192randECPgr" : 25,
+ "224randECPgr" : 26,
+ }, 0),
+ "Extended Sequence Number": (5, {"No ESN": 0,
+ "ESN": 1, }, 0),
+ }
+
+# the name 'IKEv2TransformTypes' is actually a misnomer (since the table
+# holds info for all IKEv2 Attribute types, not just transforms, but we'll
+# keep it for backwards compatibility... for now at least
+IKEv2TransformTypes = IKEv2AttributeTypes
+
+IKEv2TransformNum = {}
+for n in IKEv2TransformTypes:
+ val = IKEv2TransformTypes[n]
+ tmp = {}
+ for e in val[1]:
+ tmp[val[1][e]] = e
+ IKEv2TransformNum[val[0]] = (n,tmp, val[2])
+
+IKEv2Transforms = {}
+for n in IKEv2TransformTypes:
+ IKEv2Transforms[IKEv2TransformTypes[n][0]]=n
+
+del(n)
+del(e)
+del(tmp)
+del(val)
+
+# Note: Transform and Proposal can only be used inside the SA payload
+IKEv2_payload_type = ["None", "", "Proposal", "Transform"]
+
+IKEv2_payload_type.extend([""] * 29)
+IKEv2_payload_type.extend(["SA","KE","IDi","IDr", "CERT","CERTREQ","AUTH","Nonce","Notify","Delete",
+ "VendorID","TSi","TSr","Encrypted","CP","EAP"])
+
+IKEv2_exchange_type = [""] * 34
+IKEv2_exchange_type.extend(["IKE_SA_INIT","IKE_AUTH","CREATE_CHILD_SA",
+ "INFORMATIONAL", "IKE_SESSION_RESUME"])
+
+
+class IKEv2_class(Packet):
+ def guess_payload_class(self, payload):
+ np = self.next_payload
+ logging.debug("For IKEv2_class np=%d" % np)
+ if np == 0:
+ return conf.raw_layer
+ elif np < len(IKEv2_payload_type):
+ pt = IKEv2_payload_type[np]
+ logging.debug(globals().get("IKEv2_payload_%s" % pt, IKEv2_payload))
+ return globals().get("IKEv2_payload_%s" % pt, IKEv2_payload)
+ else:
+ return IKEv2_payload
+
+
+class IKEv2(IKEv2_class): # rfc4306
+ name = "IKEv2"
+ fields_desc = [
+ StrFixedLenField("init_SPI","",8),
+ StrFixedLenField("resp_SPI","",8),
+ ByteEnumField("next_payload",0,IKEv2_payload_type),
+ XByteField("version",0x20), # IKEv2, right?
+ ByteEnumField("exch_type",0,IKEv2_exchange_type),
+ FlagsField("flags",0, 8, ["res0","res1","res2","Initiator","Version","Response","res6","res7"]),
+ IntField("id",0),
+ IntField("length",None)
+ ]
+
+ def guess_payload_class(self, payload):
+ if self.flags & 1:
+ return conf.raw_layer
+ return IKEv2_class.guess_payload_class(self, payload)
+
+ def answers(self, other):
+ if isinstance(other, IKEv2):
+ if other.init_SPI == self.init_SPI:
+ return 1
+ return 0
+ def post_build(self, p, pay):
+ p += pay
+ if self.length is None:
+ p = p[:24]+struct.pack("!I",len(p))+p[28:]
+ return p
+
+
+class IKEv2_Key_Length_Attribute(IntField):
+ # We only support the fixed-length Key Length attribute (the only one currently defined)
+ name="key length"
+ def __init__(self, name):
+ IntField.__init__(self, name, "0x800E0000")
+
+ def i2h(self, pkt, x):
+ return IntField.i2h(self, pkt, x & 0xFFFF)
+
+ def h2i(self, pkt, x):
+ return IntField.h2i(self, pkt, struct.pack("!I", 0x800E0000 | int(x, 0)))
+
+
+class IKEv2_Transform_ID(ShortField):
+ def i2h(self, pkt, x):
+ if pkt == None:
+ return None
+ else:
+ map = IKEv2TransformNum[pkt.transform_type][1]
+ return map[x]
+
+ def h2i(self, pkt, x):
+ if pkt == None:
+ return None
+ else:
+ map = IKEv2TransformNum[pkt.transform_type][1]
+ for k in keys(map):
+ if map[k] == x:
+ return k
+ return None
+
+class IKEv2_payload_Transform(IKEv2_class):
+ name = "IKE Transform"
+ fields_desc = [
+ ByteEnumField("next_payload",None,{0:"last", 3:"Transform"}),
+ ByteField("res",0),
+ ShortField("length",8),
+ ByteEnumField("transform_type",None,IKEv2Transforms),
+ ByteField("res2",0),
+ IKEv2_Transform_ID("transform_id", 0),
+ ConditionalField(IKEv2_Key_Length_Attribute("key_length"), lambda pkt: pkt.length > 8),
+ ]
+
+class IKEv2_payload_Proposal(IKEv2_class):
+ name = "IKEv2 Proposal"
+ fields_desc = [
+ ByteEnumField("next_payload",None,{0:"last", 2:"Proposal"}),
+ ByteField("res",0),
+ FieldLenField("length",None,"trans","H", adjust=lambda pkt,x:x+8),
+ ByteField("proposal",1),
+ ByteEnumField("proto",1,{1:"IKEv2"}),
+ FieldLenField("SPIsize",None,"SPI","B"),
+ ByteField("trans_nb",None),
+ StrLenField("SPI","",length_from=lambda x:x.SPIsize),
+ PacketLenField("trans",conf.raw_layer(),IKEv2_payload_Transform,length_from=lambda x:x.length-8),
+ ]
+
+
+class IKEv2_payload(IKEv2_class):
+ name = "IKEv2 Payload"
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ FlagsField("flags",0, 8, ["critical","res1","res2","res3","res4","res5","res6","res7"]),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+
+class IKEv2_payload_VendorID(IKEv2_class):
+ name = "IKEv2 Vendor ID"
+ overload_fields = { IKEv2: { "next_payload":43 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"vendorID","H", adjust=lambda pkt,x:x+4),
+ StrLenField("vendorID","",length_from=lambda x:x.length-4),
+ ]
+
+class IKEv2_payload_Delete(IKEv2_class):
+ name = "IKEv2 Vendor ID"
+ overload_fields = { IKEv2: { "next_payload":42 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"vendorID","H", adjust=lambda pkt,x:x+4),
+ StrLenField("vendorID","",length_from=lambda x:x.length-4),
+ ]
+
+class IKEv2_payload_SA(IKEv2_class):
+ name = "IKEv2 SA"
+ overload_fields = { IKEv2: { "next_payload":33 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"prop","H", adjust=lambda pkt,x:x+4),
+ PacketLenField("prop",conf.raw_layer(),IKEv2_payload_Proposal,length_from=lambda x:x.length-4),
+ ]
+
+class IKEv2_payload_Nonce(IKEv2_class):
+ name = "IKEv2 Nonce"
+ overload_fields = { IKEv2: { "next_payload":40 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+class IKEv2_payload_Notify(IKEv2_class):
+ name = "IKEv2 Notify"
+ overload_fields = { IKEv2: { "next_payload":41 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+class IKEv2_payload_KE(IKEv2_class):
+ name = "IKEv2 Key Exchange"
+ overload_fields = { IKEv2: { "next_payload":34 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+6),
+ ShortEnumField("group", 0, IKEv2TransformTypes['GroupDesc'][1]),
+ StrLenField("load","",length_from=lambda x:x.length-6),
+ ]
+
+class IKEv2_payload_IDi(IKEv2_class):
+ name = "IKEv2 Identification - Initiator"
+ overload_fields = { IKEv2: { "next_payload":35 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+8),
+ ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
+ ByteEnumField("ProtoID",0,{0:"Unused"}),
+ ShortEnumField("Port",0,{0:"Unused"}),
+# IPField("IdentData","127.0.0.1"),
+ StrLenField("load","",length_from=lambda x:x.length-8),
+ ]
+
+class IKEv2_payload_IDr(IKEv2_class):
+ name = "IKEv2 Identification - Responder"
+ overload_fields = { IKEv2: { "next_payload":36 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+8),
+ ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
+ ByteEnumField("ProtoID",0,{0:"Unused"}),
+ ShortEnumField("Port",0,{0:"Unused"}),
+# IPField("IdentData","127.0.0.1"),
+ StrLenField("load","",length_from=lambda x:x.length-8),
+ ]
+
+
+
+class IKEv2_payload_Encrypted(IKEv2_class):
+ name = "IKEv2 Encrypted and Authenticated"
+ overload_fields = { IKEv2: { "next_payload":46 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,IKEv2_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+
+
+IKEv2_payload_type_overload = {}
+for i in range(len(IKEv2_payload_type)):
+ name = "IKEv2_payload_%s" % IKEv2_payload_type[i]
+ if name in globals():
+ IKEv2_payload_type_overload[globals()[name]] = {"next_payload":i}
+
+del(i)
+del(name)
+IKEv2_class.overload_fields = IKEv2_payload_type_overload.copy()
+
+split_layers(UDP, ISAKMP, sport=500)
+split_layers(UDP, ISAKMP, dport=500)
+
+bind_layers( UDP, IKEv2, dport=500, sport=500) # TODO: distinguish IKEv1/IKEv2
+bind_layers( UDP, IKEv2, dport=4500, sport=4500)
+
+def ikev2scan(ip):
+ return sr(IP(dst=ip)/UDP()/IKEv2(init_SPI=RandString(8),
+ exch_type=34)/IKEv2_payload_SA(prop=IKEv2_payload_Proposal()))
+
+# conf.debug_dissector = 1
+
+if __name__ == "__main__":
+ interact(mydict=globals(), mybanner="IKEv2 alpha-level protocol implementation")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ldp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ldp.py
new file mode 100644
index 00000000..bc2464ab
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ldp.py
@@ -0,0 +1,475 @@
+# scapy.contrib.description = Label Distribution Protocol (LDP)
+# scapy.contrib.status = loads
+
+# http://git.savannah.gnu.org/cgit/ldpscapy.git/snapshot/ldpscapy-5285b81d6e628043df2a83301b292f24a95f0ba1.tar.gz
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Copyright (C) 2010 Florian Duraffourg
+
+import struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.ansmachine import *
+from scapy.layers.inet import UDP
+from scapy.layers.inet import TCP
+from scapy.base_classes import Net
+
+
+# Guess payload
+def guess_payload(p):
+ LDPTypes = {
+ 0x0001: LDPNotification,
+ 0x0100: LDPHello,
+ 0x0200: LDPInit,
+ 0x0201: LDPKeepAlive,
+ 0x0300: LDPAddress,
+ 0x0301: LDPAddressWM,
+ 0x0400: LDPLabelMM,
+ 0x0401: LDPLabelReqM,
+ 0x0404: LDPLabelARM,
+ 0x0402: LDPLabelWM,
+ 0x0403: LDPLabelRelM,
+ }
+ type = struct.unpack("!H",p[0:2])[0]
+ type = type & 0x7fff
+ if type == 0x0001 and struct.unpack("!H",p[2:4])[0] > 20:
+ return LDP
+ if type in LDPTypes:
+ return LDPTypes[type]
+ else:
+ return conf.raw_layer
+
+## Fields ##
+
+# 3.4.1. FEC TLV
+
+class FecTLVField(StrField):
+ islist=1
+ def m2i(self, pkt, x):
+ nbr = struct.unpack("!H",x[2:4])[0]
+ used = 0
+ x=x[4:]
+ list=[]
+ while x:
+ #if x[0] == 1:
+ # list.append('Wildcard')
+ #else:
+ #mask=ord(x[8*i+3])
+ #add=inet_ntoa(x[8*i+4:8*i+8])
+ mask=ord(x[3])
+ nbroctets = mask / 8
+ if mask % 8:
+ nbroctets += 1
+ add=inet_ntoa(x[4:4+nbroctets]+"\x00"*(4-nbroctets))
+ list.append( (add, mask) )
+ used += 4 + nbroctets
+ x=x[4+nbroctets:]
+ return list
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = "\x01\x00"
+ l = 0
+ fec = ""
+ for o in x:
+ fec += "\x02\x00\x01"
+ # mask length
+ fec += struct.pack("!B",o[1])
+ # Prefix
+ fec += inet_aton(o[0])
+ l += 8
+ s += struct.pack("!H",l)
+ s += fec
+ return s
+ def size(self, s):
+ """Get the size of this field"""
+ l = 4 + struct.unpack("!H",s[2:4])[0]
+ return l
+ def getfield(self, pkt, s):
+ l = self.size(s)
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+# 3.4.2.1. Generic Label TLV
+
+class LabelTLVField(StrField):
+ def m2i(self, pkt, x):
+ return struct.unpack("!I",x[4:8])[0]
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = "\x02\x00\x00\x04"
+ s += struct.pack("!I",x)
+ return s
+ def size(self, s):
+ """Get the size of this field"""
+ l = 4 + struct.unpack("!H",s[2:4])[0]
+ return l
+ def getfield(self, pkt, s):
+ l = self.size(s)
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+# 3.4.3. Address List TLV
+
+class AddressTLVField(StrField):
+ islist=1
+ def m2i(self, pkt, x):
+ nbr = struct.unpack("!H",x[2:4])[0] - 2
+ nbr /= 4
+ x=x[6:]
+ list=[]
+ for i in range(0,nbr):
+ add = x[4*i:4*i+4]
+ list.append(inet_ntoa(add))
+ return list
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ l=2+len(x)*4
+ s = "\x01\x01"+struct.pack("!H",l)+"\x00\x01"
+ for o in x:
+ s += inet_aton(o)
+ return s
+ def size(self, s):
+ """Get the size of this field"""
+ l = 4 + struct.unpack("!H",s[2:4])[0]
+ return l
+ def getfield(self, pkt, s):
+ l = self.size(s)
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+# 3.4.6. Status TLV
+
+class StatusTLVField(StrField):
+ islist=1
+ def m2i(self, pkt, x):
+ l = []
+ statuscode = struct.unpack("!I",x[4:8])[0]
+ l.append( (statuscode & 2**31) >> 31)
+ l.append( (statuscode & 2**30) >> 30)
+ l.append( statuscode & 0x3FFFFFFF )
+ l.append( struct.unpack("!I", x[8:12])[0] )
+ l.append( struct.unpack("!H", x[12:14])[0] )
+ return l
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = "\x03\x00" + struct.pack("!H",10)
+ statuscode = 0
+ if x[0] != 0:
+ statuscode += 2**31
+ if x[1] != 0:
+ statuscode += 2**30
+ statuscode += x[2]
+ s += struct.pack("!I",statuscode)
+ if len(x) > 3:
+ s += struct.pack("!I",x[3])
+ else:
+ s += "\x00\x00\x00\x00"
+ if len(x) > 4:
+ s += struct.pack("!H",x[4])
+ else:
+ s += "\x00\x00"
+ return s
+ def getfield(self, pkt, s):
+ l = 14
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+# 3.5.2 Common Hello Parameters TLV
+class CommonHelloTLVField(StrField):
+ islist = 1
+ def m2i(self, pkt, x):
+ list = []
+ v = struct.unpack("!H",x[4:6])[0]
+ list.append(v)
+ flags = struct.unpack("B",x[6])[0]
+ v = ( flags & 0x80 ) >> 7
+ list.append(v)
+ v = ( flags & 0x40 ) >> 7
+ list.append(v)
+ return list
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = "\x04\x00\x00\x04"
+ s += struct.pack("!H",x[0])
+ byte = 0
+ if x[1] == 1:
+ byte += 0x80
+ if x[2] == 1:
+ byte += 0x40
+ s += struct.pack("!B",byte)
+ s += "\x00"
+ return s
+ def getfield(self, pkt, s):
+ l = 8
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+# 3.5.3 Common Session Parameters TLV
+class CommonSessionTLVField(StrField):
+ islist = 1
+ def m2i(self, pkt, x):
+ l = []
+ l.append(struct.unpack("!H",x[6:8])[0])
+ octet = struct.unpack("B",x[8:9])[0]
+ l.append( (octet & 2**7 ) >> 7 )
+ l.append( (octet & 2**6 ) >> 6 )
+ l.append( struct.unpack("B",x[9:10])[0] )
+ l.append( struct.unpack("!H",x[10:12])[0] )
+ l.append( inet_ntoa(x[12:16]) )
+ l.append( struct.unpack("!H",x[16:18])[0] )
+ return l
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = "\x05\x00\x00\x0E\x00\x01"
+ s += struct.pack("!H",x[0])
+ octet = 0
+ if x[1] != 0:
+ octet += 2**7
+ if x[2] != 0:
+ octet += 2**6
+ s += struct.pack("!B",octet)
+ s += struct.pack("!B",x[3])
+ s += struct.pack("!H",x[4])
+ s += inet_aton(x[5])
+ s += struct.pack("!H",x[6])
+ return s
+ def getfield(self, pkt, s):
+ l = 18
+ return s[l:],self.m2i(pkt, s[:l])
+
+
+
+## Messages ##
+
+# 3.5.1. Notification Message
+class LDPNotification(Packet):
+ name = "LDPNotification"
+ fields_desc = [ BitField("u",0,1),
+ BitField("type", 0x0001, 15),
+ ShortField("len", None),
+ IntField("id", 0) ,
+ StatusTLVField("status",(0,0,0,0,0)) ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.2. Hello Message
+class LDPHello(Packet):
+ name = "LDPHello"
+ fields_desc = [ BitField("u",0,1),
+ BitField("type", 0x0100, 15),
+ ShortField("len", None),
+ IntField("id", 0) ,
+ CommonHelloTLVField("params",[180,0,0]) ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.3. Initialization Message
+class LDPInit(Packet):
+ name = "LDPInit"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0200, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ CommonSessionTLVField("params",None)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.4. KeepAlive Message
+class LDPKeepAlive(Packet):
+ name = "LDPKeepAlive"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0201, 15),
+ ShortField("len", None),
+ IntField("id", 0)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.5. Address Message
+
+class LDPAddress(Packet):
+ name = "LDPAddress"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0300, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ AddressTLVField("address",None) ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.6. Address Withdraw Message
+
+class LDPAddressWM(Packet):
+ name = "LDPAddressWM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0301, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ AddressTLVField("address",None) ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.7. Label Mapping Message
+
+class LDPLabelMM(Packet):
+ name = "LDPLabelMM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0400, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ FecTLVField("fec",None),
+ LabelTLVField("label",0)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+# 3.5.8. Label Request Message
+
+class LDPLabelReqM(Packet):
+ name = "LDPLabelReqM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0401, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ FecTLVField("fec",None)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.9. Label Abort Request Message
+
+class LDPLabelARM(Packet):
+ name = "LDPLabelARM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0404, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ FecTLVField("fec",None),
+ IntField("labelRMid",0)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.10. Label Withdraw Message
+
+class LDPLabelWM(Packet):
+ name = "LDPLabelWM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0402, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ FecTLVField("fec",None),
+ LabelTLVField("label",0)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.5.11. Label Release Message
+
+class LDPLabelRelM(Packet):
+ name = "LDPLabelRelM"
+ fields_desc = [ BitField("u",0,1),
+ XBitField("type", 0x0403, 15),
+ ShortField("len", None),
+ IntField("id", 0),
+ FecTLVField("fec",None),
+ LabelTLVField("label",0)]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p) - 4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+
+# 3.1. LDP PDUs
+class LDP(Packet):
+ name = "LDP"
+ fields_desc = [ ShortField("version",1),
+ ShortField("len", None),
+ IPField("id","127.0.0.1"),
+ ShortField("space",0) ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p)+len(pay)-4
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ return p+pay
+ def guess_payload_class(self, p):
+ return guess_payload(p)
+
+bind_layers( TCP, LDP, sport=646, dport=646 )
+bind_layers( UDP, LDP, sport=646, dport=646 )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/mpls.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/mpls.py
new file mode 100644
index 00000000..037278c5
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/mpls.py
@@ -0,0 +1,17 @@
+# http://trac.secdev.org/scapy/ticket/31
+
+# scapy.contrib.description = MPLS
+# scapy.contrib.status = loads
+
+from scapy.packet import Packet,bind_layers
+from scapy.fields import BitField,ByteField
+from scapy.layers.l2 import Ether
+
+class MPLS(Packet):
+ name = "MPLS"
+ fields_desc = [ BitField("label", 3, 20),
+ BitField("cos", 0, 3),
+ BitField("s", 1, 1),
+ ByteField("ttl", 0) ]
+
+bind_layers(Ether, MPLS, type=0x8847)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ospf.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ospf.py
new file mode 100644
index 00000000..a6422bd8
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ospf.py
@@ -0,0 +1,833 @@
+#!/usr/bin/env python
+
+# scapy.contrib.description = OSPF
+# scapy.contrib.status = loads
+
+"""
+OSPF extension for Scapy <http://www.secdev.org/scapy>
+
+This module provides Scapy layers for the Open Shortest Path First
+routing protocol as defined in RFC 2328 and RFC 5340.
+
+Copyright (c) 2008 Dirk Loss : mail dirk-loss de
+Copyright (c) 2010 Jochen Bartl : jochen.bartl gmail com
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+"""
+
+
+from scapy.all import *
+
+EXT_VERSION = "v0.9.2"
+
+
+class OSPFOptionsField(FlagsField):
+
+ def __init__(self, name="options", default=0, size=8,
+ names=["MT", "E", "MC", "NP", "L", "DC", "O", "DN"]):
+ FlagsField.__init__(self, name, default, size, names)
+
+
+_OSPF_types = {1: "Hello",
+ 2: "DBDesc",
+ 3: "LSReq",
+ 4: "LSUpd",
+ 5: "LSAck"}
+
+
+class OSPF_Hdr(Packet):
+ name = "OSPF Header"
+ fields_desc = [
+ ByteField("version", 2),
+ ByteEnumField("type", 1, _OSPF_types),
+ ShortField("len", None),
+ IPField("src", "1.1.1.1"),
+ IPField("area", "0.0.0.0"), # default: backbone
+ XShortField("chksum", None),
+ ShortEnumField("authtype", 0, {0:"Null", 1:"Simple", 2:"Crypto"}),
+ # Null or Simple Authentication
+ ConditionalField(XLongField("authdata", 0), lambda pkt:pkt.authtype != 2),
+ # Crypto Authentication
+ ConditionalField(XShortField("reserved", 0), lambda pkt:pkt.authtype == 2),
+ ConditionalField(ByteField("keyid", 1), lambda pkt:pkt.authtype == 2),
+ ConditionalField(ByteField("authdatalen", 0), lambda pkt:pkt.authtype == 2),
+ ConditionalField(XIntField("seq", 0), lambda pkt:pkt.authtype == 2),
+ # TODO: Support authdata (which is appended to the packets as if it were padding)
+ ]
+
+ def post_build(self, p, pay):
+ # TODO: Remove LLS data from pay
+ # LLS data blocks may be attached to OSPF Hello and DD packets
+ # The length of the LLS block shall not be included into the length of OSPF packet
+ # See <http://tools.ietf.org/html/rfc5613>
+ p += pay
+ l = self.len
+ if l is None:
+ l = len(p)
+ p = p[:2] + struct.pack("!H", l) + p[4:]
+ if self.chksum is None:
+ if self.authtype == 2:
+ ck = 0 # Crypto, see RFC 2328, D.4.3
+ else:
+ # Checksum is calculated without authentication data
+ # Algorithm is the same as in IP()
+ ck = checksum(p[:16] + p[24:])
+ p = p[:12] + chr(ck >> 8) + chr(ck & 0xff) + p[14:]
+ # TODO: Handle Crypto: Add message digest (RFC 2328, D.4.3)
+ return p
+
+ def hashret(self):
+ return struct.pack("H", self.area) + self.payload.hashret()
+
+ def answers(self, other):
+ if (isinstance(other, OSPF_Hdr) and
+ self.area == other.area and
+ self.type == 5): # Only acknowledgements answer other packets
+ return self.payload.answers(other.payload)
+ return 0
+
+
+class OSPF_Hello(Packet):
+ name = "OSPF Hello"
+ fields_desc = [IPField("mask", "255.255.255.0"),
+ ShortField("hellointerval", 10),
+ OSPFOptionsField(),
+ ByteField("prio", 1),
+ IntField("deadinterval", 40),
+ IPField("router", "0.0.0.0"),
+ IPField("backup", "0.0.0.0"),
+ FieldListField("neighbors", [], IPField("", "0.0.0.0"), length_from=lambda pkt: (pkt.underlayer.len - 44))]
+
+ def guess_payload_class(self, payload):
+ # check presence of LLS data block flag
+ if self.options & 0x10 == 0x10:
+ return OSPF_LLS_Hdr
+ else:
+ return Packet.guess_payload_class(self, payload)
+
+
+class LLS_Generic_TLV(Packet):
+ name = "LLS Generic"
+ fields_desc = [ShortField("type", 1),
+ FieldLenField("len", None, length_of=lambda x: x.val),
+ StrLenField("val", "", length_from=lambda x: x.len)]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+
+class LLS_ExtendedOptionsField(FlagsField):
+
+ def __init__(self, name="options", default=0, size=32,
+ names=["LR", "RS"]):
+ FlagsField.__init__(self, name, default, size, names)
+
+
+class LLS_Extended_Options(LLS_Generic_TLV):
+ name = "LLS Extended Options and Flags"
+ fields_desc = [ShortField("type", 1),
+ ShortField("len", 4),
+ LLS_ExtendedOptionsField()]
+
+
+class LLS_Crypto_Auth(LLS_Generic_TLV):
+ name = "LLS Cryptographic Authentication"
+ fields_desc = [ShortField("type", 2),
+ FieldLenField("len", 20, fmt="B", length_of=lambda x: x.authdata),
+ XIntField("sequence", "\x00\x00\x00\x00"),
+ StrLenField("authdata", "\x00" * 16, length_from=lambda x: x.len)]
+
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+
+ if l is None:
+ # length = len(sequence) + len(authdata) + len(payload)
+ l = len(p[3:])
+ p = p[:2] + struct.pack("!H", l) + p[3:]
+
+ return p
+
+_OSPF_LLSclasses = {1: "LLS_Extended_Options",
+ 2: "LLS_Crypto_Auth"}
+
+
+def _LLSGuessPayloadClass(p, **kargs):
+ """ Guess the correct LLS class for a given payload """
+
+ cls = conf.raw_layer
+ if len(p) >= 4:
+ typ = struct.unpack("!H", p[0:2])[0]
+ clsname = _OSPF_LLSclasses.get(typ, "LLS_Generic_TLV")
+ cls = globals()[clsname]
+ return cls(p, **kargs)
+
+
+class OSPF_LLS_Hdr(Packet):
+ name = "OSPF Link-local signaling"
+ fields_desc = [XShortField("chksum", None),
+ # FIXME Length should be displayed in 32-bit words
+ ShortField("len", None),
+ PacketListField("llstlv", [], _LLSGuessPayloadClass)]
+
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+ if l is None:
+ # Length in 32-bit words
+ l = len(p) / 4
+ p = p[:2] + struct.pack("!H", l) + p[4:]
+ if self.chksum is None:
+ c = checksum(p)
+ p = chr((c >> 8) & 0xff) + chr(c & 0xff) + p[2:]
+ return p
+
+_OSPF_LStypes = {1: "router",
+ 2: "network",
+ 3: "summaryIP",
+ 4: "summaryASBR",
+ 5: "external",
+ 7: "NSSAexternal"}
+
+_OSPF_LSclasses = {1: "OSPF_Router_LSA",
+ 2: "OSPF_Network_LSA",
+ 3: "OSPF_SummaryIP_LSA",
+ 4: "OSPF_SummaryASBR_LSA",
+ 5: "OSPF_External_LSA",
+ 7: "OSPF_NSSA_External_LSA"}
+
+
+def ospf_lsa_checksum(lsa):
+ """ Fletcher checksum for OSPF LSAs, returned as a 2 byte string.
+
+ Give the whole LSA packet as argument.
+ For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.
+ """
+ # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
+
+ CHKSUM_OFFSET = 16
+
+ if len(lsa) < CHKSUM_OFFSET:
+ raise Exception("LSA Packet too short (%s bytes)" % len(lsa))
+
+ c0 = c1 = 0
+ # Calculation is done with checksum set to zero
+ lsa = lsa[:CHKSUM_OFFSET] + "\x00\x00" + lsa[CHKSUM_OFFSET + 2:]
+ for char in lsa[2:]: # leave out age
+ c0 += ord(char)
+ c1 += c0
+
+ c0 %= 255
+ c1 %= 255
+
+ x = ((len(lsa) - CHKSUM_OFFSET - 1) * c0 - c1) % 255
+
+ if (x <= 0):
+ x += 255
+
+ y = 510 - c0 - x
+
+ if (y > 255):
+ y -= 255
+ #checksum = (x << 8) + y
+
+ return chr(x) + chr(y)
+
+
+class OSPF_LSA_Hdr(Packet):
+ name = "OSPF LSA Header"
+ fields_desc = [ShortField("age", 1),
+ OSPFOptionsField(),
+ ByteEnumField("type", 1, _OSPF_LStypes),
+ IPField("id", "192.168.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", 0),
+ ShortField("len", 36)]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+_OSPF_Router_LSA_types = {1: "p2p",
+ 2: "transit",
+ 3: "stub",
+ 4: "virtual"}
+
+
+class OSPF_Link(Packet):
+ name = "OSPF Link"
+ fields_desc = [IPField("id", "192.168.0.0"),
+ IPField("data", "255.255.255.0"),
+ ByteEnumField("type", 3, _OSPF_Router_LSA_types),
+ ByteField("toscount", 0),
+ ShortField("metric", 10),
+ # TODO: define correct conditions
+ ConditionalField(ByteField("tos", 0), lambda pkt: False),
+ ConditionalField(ByteField("reserved", 0), lambda pkt: False),
+ ConditionalField(ShortField("tosmetric", 0), lambda pkt: False)]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+def _LSAGuessPayloadClass(p, **kargs):
+ """ Guess the correct LSA class for a given payload """
+ # This is heavily based on scapy-cdp.py by Nicolas Bareil and Arnaud Ebalard
+ # XXX: This only works if all payload
+ cls = conf.raw_layer
+ if len(p) >= 4:
+ typ = struct.unpack("!B", p[3])[0]
+ clsname = _OSPF_LSclasses.get(typ, "Raw")
+ cls = globals()[clsname]
+ return cls(p, **kargs)
+
+
+class OSPF_BaseLSA(Packet):
+ """ An abstract base class for Link State Advertisements """
+
+ def post_build(self, p, pay):
+ length = self.len
+ if length is None:
+ length = len(p)
+ p = p[:18] + struct.pack("!H", length) + p[20:]
+ if self.chksum is None:
+ chksum = ospf_lsa_checksum(p)
+ p = p[:16] + chksum + p[18:]
+ return p # p+pay?
+
+ def extract_padding(self, s):
+ length = self.len
+ return "", s
+
+
+class OSPF_Router_LSA(OSPF_BaseLSA):
+ name = "OSPF Router LSA"
+ fields_desc = [ShortField("age", 1),
+ OSPFOptionsField(),
+ ByteField("type", 1),
+ IPField("id", "1.1.1.1"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ FlagsField("flags", 0, 8, ["B", "E", "V", "W", "Nt"]),
+ ByteField("reserved", 0),
+ FieldLenField("linkcount", None, count_of="linklist"),
+ PacketListField("linklist", [], OSPF_Link,
+ count_from=lambda pkt: pkt.linkcount,
+ length_from=lambda pkt: pkt.linkcount * 12)]
+
+
+class OSPF_Network_LSA(OSPF_BaseLSA):
+ name = "OSPF Network LSA"
+ fields_desc = [ShortField("age", 1),
+ OSPFOptionsField(),
+ ByteField("type", 2),
+ IPField("id", "192.168.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ IPField("mask", "255.255.255.0"),
+ FieldListField("routerlist", [], IPField("", "1.1.1.1"),
+ length_from=lambda pkt: pkt.len - 24)]
+
+
+class OSPF_SummaryIP_LSA(OSPF_BaseLSA):
+ name = "OSPF Summary LSA (IP Network)"
+ fields_desc = [ShortField("age", 1),
+ OSPFOptionsField(),
+ ByteField("type", 3),
+ IPField("id", "192.168.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ IPField("mask", "255.255.255.0"),
+ ByteField("reserved", 0),
+ X3BytesField("metric", 10),
+ # TODO: Define correct conditions
+ ConditionalField(ByteField("tos", 0), lambda pkt:False),
+ ConditionalField(X3BytesField("tosmetric", 0), lambda pkt:False)]
+
+
+class OSPF_SummaryASBR_LSA(OSPF_SummaryIP_LSA):
+ name = "OSPF Summary LSA (AS Boundary Router)"
+ type = 4
+ id = "2.2.2.2"
+ mask = "0.0.0.0"
+ metric = 20
+
+
+class OSPF_External_LSA(OSPF_BaseLSA):
+ name = "OSPF External LSA (ASBR)"
+ fields_desc = [ShortField("age", 1),
+ OSPFOptionsField(),
+ ByteField("type", 5),
+ IPField("id", "192.168.0.0"),
+ IPField("adrouter", "2.2.2.2"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ IPField("mask", "255.255.255.0"),
+ FlagsField("ebit", 0, 1, ["E"]),
+ BitField("reserved", 0, 7),
+ X3BytesField("metric", 20),
+ IPField("fwdaddr", "0.0.0.0"),
+ XIntField("tag", 0),
+ # TODO: Define correct conditions
+ ConditionalField(ByteField("tos", 0), lambda pkt:False),
+ ConditionalField(X3BytesField("tosmetric", 0), lambda pkt:False)]
+
+
+class OSPF_NSSA_External_LSA(OSPF_External_LSA):
+ name = "OSPF NSSA External LSA"
+ type = 7
+
+
+class OSPF_DBDesc(Packet):
+ name = "OSPF Database Description"
+ fields_desc = [ShortField("mtu", 1500),
+ OSPFOptionsField(),
+ FlagsField("dbdescr", 0, 8, ["MS", "M", "I", "R", "4", "3", "2", "1"]),
+ IntField("ddseq", 1),
+ PacketListField("lsaheaders", None, OSPF_LSA_Hdr,
+ count_from = lambda pkt: None,
+ length_from = lambda pkt: pkt.underlayer.len - 24 - 8)]
+
+ def guess_payload_class(self, payload):
+ # check presence of LLS data block flag
+ if self.options & 0x10 == 0x10:
+ return OSPF_LLS_Hdr
+ else:
+ return Packet.guess_payload_class(self, payload)
+
+
+class OSPF_LSReq_Item(Packet):
+ name = "OSPF Link State Request (item)"
+ fields_desc = [IntEnumField("type", 1, _OSPF_LStypes),
+ IPField("id", "1.1.1.1"),
+ IPField("adrouter", "1.1.1.1")]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+class OSPF_LSReq(Packet):
+ name = "OSPF Link State Request (container)"
+ fields_desc = [PacketListField("requests", None, OSPF_LSReq_Item,
+ count_from = lambda pkt:None,
+ length_from = lambda pkt:pkt.underlayer.len - 24)]
+
+
+class OSPF_LSUpd(Packet):
+ name = "OSPF Link State Update"
+ fields_desc = [FieldLenField("lsacount", None, fmt="!I", count_of="lsalist"),
+ PacketListField("lsalist", [], _LSAGuessPayloadClass,
+ count_from = lambda pkt: pkt.lsacount,
+ length_from = lambda pkt: pkt.underlayer.len - 24)]
+
+
+class OSPF_LSAck(Packet):
+ name = "OSPF Link State Acknowledgement"
+ fields_desc = [PacketListField("lsaheaders", None, OSPF_LSA_Hdr,
+ count_from = lambda pkt: None,
+ length_from = lambda pkt: pkt.underlayer.len - 24)]
+
+ def answers(self, other):
+ if isinstance(other, OSPF_LSUpd):
+ for reqLSA in other.lsalist:
+ for ackLSA in self.lsaheaders:
+ if (reqLSA.type == ackLSA.type and
+ reqLSA.seq == ackLSA.seq):
+ return 1
+ return 0
+
+
+#------------------------------------------------------------------------------
+# OSPFv3
+#------------------------------------------------------------------------------
+# TODO: Add length_from / adjust functionality to IP6Field and remove this class
+class OspfIP6Field(StrField, IP6Field):
+ """
+ Special IP6Field for prefix fields in OSPFv3 LSAs
+ """
+
+ def __init__(self, name, default, length=None, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+ if length is not None:
+ self.length_from = lambda pkt, length = length: length
+
+ def any2i(self, pkt, x):
+ return IP6Field.any2i(self, pkt, x)
+
+ def i2repr(self, pkt, x):
+ return IP6Field.i2repr(self, pkt, x)
+
+ def h2i(self, pkt, x):
+ return IP6Field.h2i(self, pkt, x)
+
+ def i2m(self, pkt, x):
+ x = inet_pton(socket.AF_INET6, x)
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return x[:l]
+
+ def m2i(self, pkt, x):
+ l = self.length_from(pkt)
+
+ prefixlen = self.prefixlen_to_bytelen(l)
+ if l > 128:
+ warning("OspfIP6Field: Prefix length is > 128. Dissection of this packet will fail")
+ else:
+ pad = "\x00" * (16 - prefixlen)
+ x += pad
+
+ return inet_ntop(socket.AF_INET6, x)
+
+ def prefixlen_to_bytelen(self, l):
+ if l <= 32:
+ return 4
+ elif l <= 64:
+ return 8
+ elif l <= 96:
+ return 12
+ else:
+ return 16
+
+ def i2len(self, pkt, x):
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return l
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ l = self.prefixlen_to_bytelen(l)
+
+ return s[l:], self.m2i(pkt, s[:l])
+
+
+class OSPFv3_Hdr(Packet):
+ name = "OSPFv3 Header"
+ fields_desc = [ByteField("version", 3),
+ ByteEnumField("type", 1, _OSPF_types),
+ ShortField("len", None),
+ IPField("src", "1.1.1.1"),
+ IPField("area", "0.0.0.0"),
+ XShortField("chksum", None),
+ ByteField("instance", 0),
+ ByteField("reserved", 0)]
+
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+
+ if l is None:
+ l = len(p)
+ p = p[:2] + struct.pack("!H", l) + p[4:]
+
+ if self.chksum is None:
+ chksum = in6_chksum(89, self.underlayer, p)
+ p = p[:12] + chr(chksum >> 8) + chr(chksum & 0xff) + p[14:]
+
+ return p
+
+
+class OSPFv3OptionsField(FlagsField):
+
+ def __init__(self, name="options", default=0, size=24,
+ names=["V6", "E", "MC", "N", "R", "DC", "AF", "L", "I", "F"]):
+ FlagsField.__init__(self, name, default, size, names)
+
+
+class OSPFv3_Hello(Packet):
+ name = "OSPFv3 Hello"
+ fields_desc = [IntField("intid", 0),
+ ByteField("prio", 1),
+ OSPFv3OptionsField(),
+ ShortField("hellointerval", 10),
+ ShortField("deadinterval", 40),
+ IPField("router", "0.0.0.0"),
+ IPField("backup", "0.0.0.0"),
+ FieldListField("neighbors", [], IPField("", "0.0.0.0"),
+ length_from=lambda pkt: (pkt.underlayer.len - 36))]
+
+
+_OSPFv3_LStypes = {0x2001: "router",
+ 0x2002: "network",
+ 0x2003: "interAreaPrefix",
+ 0x2004: "interAreaRouter",
+ 0x4005: "asExternal",
+ 0x2007: "type7",
+ 0x0008: "link",
+ 0x2009: "intraAreaPrefix"}
+
+_OSPFv3_LSclasses = {0x2001: "OSPFv3_Router_LSA",
+ 0x2002: "OSPFv3_Network_LSA",
+ 0x2003: "OSPFv3_Inter_Area_Prefix_LSA",
+ 0x2004: "OSPFv3_Inter_Area_Router_LSA",
+ 0x4005: "OSPFv3_AS_External_LSA",
+ 0x2007: "OSPFv3_Type_7_LSA",
+ 0x0008: "OSPFv3_Link_LSA",
+ 0x2009: "OSPFv3_Intra_Area_Prefix_LSA"}
+
+
+class OSPFv3_LSA_Hdr(Packet):
+ name = "OSPFv3 LSA Header"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2001, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", 0),
+ ShortField("len", 36)]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+def _OSPFv3_LSAGuessPayloadClass(p, **kargs):
+ """ Guess the correct OSPFv3 LSA class for a given payload """
+
+ cls = conf.raw_layer
+
+ if len(p) >= 6:
+ typ = struct.unpack("!H", p[2:4])[0]
+ clsname = _OSPFv3_LSclasses.get(typ, "Raw")
+ cls = globals()[clsname]
+
+ return cls(p, **kargs)
+
+
+_OSPFv3_Router_LSA_types = {1: "p2p",
+ 2: "transit",
+ 3: "reserved",
+ 4: "virtual"}
+
+
+class OSPFv3_Link(Packet):
+ name = "OSPFv3 Link"
+ fields_desc = [ByteEnumField("type", 1, _OSPFv3_Router_LSA_types),
+ ByteField("reserved", 0),
+ ShortField("metric", 10),
+ IntField("intid", 0),
+ IntField("neighintid", 0),
+ IPField("neighbor", "2.2.2.2")]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+class OSPFv3_Router_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Router LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2001, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ FlagsField("flags", 0, 8, ["B", "E", "V", "W"]),
+ OSPFv3OptionsField(),
+ PacketListField("linklist", [], OSPFv3_Link,
+ length_from=lambda pkt:pkt.len - 24)]
+
+
+class OSPFv3_Network_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Network LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2002, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ ByteField("reserved", 0),
+ OSPFv3OptionsField(),
+ FieldListField("routerlist", [], IPField("", "0.0.0.1"),
+ length_from=lambda pkt: pkt.len - 24)]
+
+
+class OSPFv3PrefixOptionsField(FlagsField):
+
+ def __init__(self, name="prefixoptions", default=0, size=8,
+ names=["NU", "LA", "MC", "P"]):
+ FlagsField.__init__(self, name, default, size, names)
+
+
+class OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Inter Area Prefix LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2003, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ ByteField("reserved", 0),
+ X3BytesField("metric", 10),
+ ByteField("prefixlen", 64),
+ OSPFv3PrefixOptionsField(),
+ ShortField("reserved2", 0),
+ OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)]
+
+
+class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Inter Area Router LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2004, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ ByteField("reserved", 0),
+ X3BytesField("metric", 1),
+ IPField("router", "2.2.2.2")]
+
+
+class OSPFv3_AS_External_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 AS External LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x4005, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ FlagsField("flags", 0, 8, ["T", "F", "E"]),
+ X3BytesField("metric", 20),
+ ByteField("prefixlen", 64),
+ OSPFv3PrefixOptionsField(),
+ ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
+ OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen),
+ ConditionalField(IP6Field("fwaddr", "::"), lambda pkt: pkt.flags & 0x02 == 0x02),
+ ConditionalField(IntField("tag", 0), lambda pkt: pkt.flags & 0x01 == 0x01),
+ ConditionalField(IPField("reflsid", 0), lambda pkt: pkt.reflstype != 0)]
+
+
+class OSPFv3_Type_7_LSA(OSPFv3_AS_External_LSA):
+ name = "OSPFv3 Type 7 LSA"
+ type = 0x2007
+
+
+class OSPFv3_Prefix_Item(Packet):
+ name = "OSPFv3 Link Prefix Item"
+ fields_desc = [ByteField("prefixlen", 64),
+ OSPFv3PrefixOptionsField(),
+ ShortField("metric", 10),
+ OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+class OSPFv3_Link_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Link LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x0008, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ ByteField("prio", 1),
+ OSPFv3OptionsField(),
+ IP6Field("lladdr", "fe80::"),
+ IntField("prefixes", 0),
+ PacketListField("prefixlist", None, OSPFv3_Prefix_Item,
+ count_from = lambda pkt: pkt.prefixes)]
+
+
+class OSPFv3_Intra_Area_Prefix_LSA(OSPF_BaseLSA):
+ name = "OSPFv3 Intra Area Prefix LSA"
+ fields_desc = [ShortField("age", 1),
+ ShortEnumField("type", 0x2009, _OSPFv3_LStypes),
+ IPField("id", "0.0.0.0"),
+ IPField("adrouter", "1.1.1.1"),
+ XIntField("seq", 0x80000001),
+ XShortField("chksum", None),
+ ShortField("len", None),
+ ShortField("prefixes", 0),
+ ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
+ IPField("reflsid", "0.0.0.0"),
+ IPField("refadrouter", "0.0.0.0"),
+ PacketListField("prefixlist", None, OSPFv3_Prefix_Item,
+ count_from = lambda pkt: pkt.prefixes)]
+
+
+class OSPFv3_DBDesc(Packet):
+ name = "OSPFv3 Database Description"
+ fields_desc = [ByteField("reserved", 0),
+ OSPFv3OptionsField(),
+ ShortField("mtu", 1500),
+ ByteField("reserved2", 0),
+ FlagsField("dbdescr", 0, 8, ["MS", "M", "I", "R"]),
+ IntField("ddseq", 1),
+ PacketListField("lsaheaders", None, OSPFv3_LSA_Hdr,
+ count_from = lambda pkt:None,
+ length_from = lambda pkt:pkt.underlayer.len - 28)]
+
+
+class OSPFv3_LSReq_Item(Packet):
+ name = "OSPFv3 Link State Request (item)"
+ fields_desc = [ShortField("reserved", 0),
+ ShortEnumField("type", 0x2001, _OSPFv3_LStypes),
+ IPField("id", "1.1.1.1"),
+ IPField("adrouter", "1.1.1.1")]
+
+ def extract_padding(self, s):
+ return "", s
+
+
+class OSPFv3_LSReq(Packet):
+ name = "OSPFv3 Link State Request (container)"
+ fields_desc = [PacketListField("requests", None, OSPFv3_LSReq_Item,
+ count_from = lambda pkt:None,
+ length_from = lambda pkt:pkt.underlayer.len - 16)]
+
+
+class OSPFv3_LSUpd(Packet):
+ name = "OSPFv3 Link State Update"
+ fields_desc = [FieldLenField("lsacount", None, fmt="!I", count_of="lsalist"),
+ PacketListField("lsalist", [], _OSPFv3_LSAGuessPayloadClass,
+ count_from = lambda pkt:pkt.lsacount,
+ length_from = lambda pkt:pkt.underlayer.len - 16)]
+
+
+class OSPFv3_LSAck(Packet):
+ name = "OSPFv3 Link State Acknowledgement"
+ fields_desc = [PacketListField("lsaheaders", None, OSPFv3_LSA_Hdr,
+ count_from = lambda pkt:None,
+ length_from = lambda pkt:pkt.underlayer.len - 16)]
+
+
+bind_layers(IP, OSPF_Hdr, proto=89)
+bind_layers(OSPF_Hdr, OSPF_Hello, type=1)
+bind_layers(OSPF_Hdr, OSPF_DBDesc, type=2)
+bind_layers(OSPF_Hdr, OSPF_LSReq, type=3)
+bind_layers(OSPF_Hdr, OSPF_LSUpd, type=4)
+bind_layers(OSPF_Hdr, OSPF_LSAck, type=5)
+
+bind_layers(IPv6, OSPFv3_Hdr, nh=89)
+bind_layers(OSPFv3_Hdr, OSPFv3_Hello, type=1)
+bind_layers(OSPFv3_Hdr, OSPFv3_DBDesc, type=2)
+bind_layers(OSPFv3_Hdr, OSPFv3_LSReq, type=3)
+bind_layers(OSPFv3_Hdr, OSPFv3_LSUpd, type=4)
+bind_layers(OSPFv3_Hdr, OSPFv3_LSAck, type=5)
+
+
+if __name__ == "__main__":
+ interact(mydict=globals(), mybanner="OSPF extension %s" % EXT_VERSION)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi.py
new file mode 100644
index 00000000..f4364096
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi.py
@@ -0,0 +1,86 @@
+## This file is (hopefully) part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## <jellch@harris.com>
+## This program is published under a GPLv2 license
+
+# scapy.contrib.description = PPI
+# scapy.contrib.status = loads
+
+
+"""
+PPI (Per-Packet Information).
+"""
+import logging,struct
+from scapy.config import conf
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import Ether
+from scapy.layers.dot11 import Dot11
+
+# Dictionary to map the TLV type to the class name of a sub-packet
+_ppi_types = {}
+def addPPIType(id, value):
+ _ppi_types[id] = value
+def getPPIType(id, default="default"):
+ return _ppi_types.get(id, _ppi_types.get(default, None))
+
+
+# Default PPI Field Header
+class PPIGenericFldHdr(Packet):
+ name = "PPI Field Header"
+ fields_desc = [ LEShortField('pfh_type', 0),
+ FieldLenField('pfh_length', None, length_of="value", fmt='<H', adjust=lambda p,x:x+4),
+ StrLenField("value", "", length_from=lambda p:p.pfh_length) ]
+
+ def extract_padding(self, p):
+ return "",p
+
+def _PPIGuessPayloadClass(p, **kargs):
+ """ This function tells the PacketListField how it should extract the
+ TLVs from the payload. We pass cls only the length string
+ pfh_len says it needs. If a payload is returned, that means
+ part of the sting was unused. This converts to a Raw layer, and
+ the remainder of p is added as Raw's payload. If there is no
+ payload, the remainder of p is added as out's payload.
+ """
+ if len(p) >= 4:
+ t,pfh_len = struct.unpack("<HH", p[:4])
+ # Find out if the value t is in the dict _ppi_types.
+ # If not, return the default TLV class
+ cls = getPPIType(t, "default")
+ pfh_len += 4
+ out = cls(p[:pfh_len], **kargs)
+ if (out.payload):
+ out.payload = conf.raw_layer(out.payload.load)
+ if (len(p) > pfh_len):
+ out.payload.payload = conf.padding_layer(p[pfh_len:])
+ elif (len(p) > pfh_len):
+ out.payload = conf.padding_layer(p[pfh_len:])
+
+ else:
+ out = conf.raw_layer(p, **kargs)
+ return out
+
+
+
+
+class PPI(Packet):
+ name = "PPI Packet Header"
+ fields_desc = [ ByteField('pph_version', 0),
+ ByteField('pph_flags', 0),
+ FieldLenField('pph_len', None, length_of="PPIFieldHeaders", fmt="<H", adjust=lambda p,x:x+8 ),
+ LEIntField('dlt', None),
+ PacketListField("PPIFieldHeaders", [], _PPIGuessPayloadClass, length_from=lambda p:p.pph_len-8,) ]
+ def guess_payload_class(self,payload):
+ return conf.l2types.get(self.dlt, Packet.guess_payload_class(self, payload))
+
+#Register PPI
+addPPIType("default", PPIGenericFldHdr)
+
+conf.l2types.register(192, PPI)
+conf.l2types.register_num2layer(192, PPI)
+
+bind_layers(PPI, Dot11, dlt=conf.l2types.get(Dot11))
+bind_layers(Dot11, PPI)
+bind_layers(PPI, Ether, dlt=conf.l2types.get(Ether))
+bind_layers(Dot11, Ether)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_cace.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_cace.py
new file mode 100644
index 00000000..ba2c4abf
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_cace.py
@@ -0,0 +1,87 @@
+## This file is (hopefully) part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## <jellch@harris.com>
+## This program is published under a GPLv2 license
+
+# scapy.contrib.description = PPI CACE
+# scapy.contrib.status = loads
+
+"""
+CACE PPI types
+"""
+import logging,struct
+from scapy.config import conf
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import Ether
+from scapy.layers.dot11 import Dot11
+from scapy.contrib.ppi import *
+
+PPI_DOT11COMMON = 2
+PPI_DOT11NMAC = 3
+PPI_DOT11NMACPHY = 4
+PPI_SPECTRUMMAP = 5
+PPI_PROCESSINFO = 6
+PPI_CAPTUREINFO = 7
+PPI_AGGREGATION = 8
+PPI_DOT3 = 9
+
+# PPI 802.11 Common Field Header Fields
+class dBmByteField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "b")
+ def i2repr(self, pkt, val):
+ if (val != None):
+ val = "%4d dBm" % val
+ return val
+
+class PPITSFTField(LELongField):
+ def i2h(self, pkt, val):
+ flags = 0
+ if (pkt):
+ flags = pkt.getfieldval("Pkt_Flags")
+ if not flags:
+ flags = 0
+ if (flags & 0x02):
+ scale = 1e-3
+ else:
+ scale = 1e-6
+ tout = scale * float(val)
+ return tout
+ def h2i(self, pkt, val):
+ scale = 1e6
+ if pkt:
+ flags = pkt.getfieldval("Pkt_Flags")
+ if flags:
+ if (flags & 0x02):
+ scale = 1e3
+ tout = int((scale * val) + 0.5)
+ return tout
+
+_PPIDot11CommonChFlags = ['','','','','Turbo','CCK','OFDM','2GHz','5GHz',
+ 'PassiveOnly','Dynamic CCK-OFDM','GSFK']
+
+_PPIDot11CommonPktFlags = ['FCS','TSFT_ms','FCS_Invalid','PHY_Error']
+
+# PPI 802.11 Common Field Header
+class Dot11Common(Packet):
+ name = "PPI 802.11-Common"
+ fields_desc = [ LEShortField('pfh_type',PPI_DOT11COMMON),
+ LEShortField('pfh_length', 20),
+ PPITSFTField('TSF_Timer', 0),
+ FlagsField('Pkt_Flags',0, -16, _PPIDot11CommonPktFlags),
+ LEShortField('Rate',0),
+ LEShortField('Ch_Freq',0),
+ FlagsField('Ch_Flags', 0, -16, _PPIDot11CommonChFlags),
+ ByteField('FHSS_Hop',0),
+ ByteField('FHSS_Pat',0),
+ dBmByteField('Antsignal',-128),
+ dBmByteField('Antnoise',-128)]
+
+ def extract_padding(self, p):
+ return "",p
+#Hopefully other CACE defined types will be added here.
+
+#Add the dot11common layer to the PPI array
+addPPIType(PPI_DOT11COMMON, Dot11Common)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_geotag.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_geotag.py
new file mode 100644
index 00000000..19371512
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ppi_geotag.py
@@ -0,0 +1,464 @@
+## This file is (hopefully) part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## <jellch@harris.com>
+## This program is published under a GPLv2 license
+
+# scapy.contrib.description = PPI GEOLOCATION
+# scapy.contrib.status = loads
+
+
+"""
+PPI-GEOLOCATION tags
+"""
+import struct
+from scapy.packet import *
+from scapy.fields import *
+from scapy.contrib.ppi import PPIGenericFldHdr,addPPIType
+
+CURR_GEOTAG_VER = 2 #Major revision of specification
+
+PPI_GPS = 30002
+PPI_VECTOR = 30003
+PPI_SENSOR = 30004
+PPI_ANTENNA = 30005
+#The FixedX_Y Fields are used to store fixed point numbers in a variety of fields in the GEOLOCATION-TAGS specification
+class Fixed3_6Field(LEIntField):
+ def i2h(self, pkt, x):
+ if x is not None:
+ if (x < 0):
+ warning("Fixed3_6: Internal value too negative: %d" % x)
+ x = 0
+ elif (x > 999999999):
+ warning("Fixed3_6: Internal value too positive: %d" % x)
+ x = 999999999
+ x = x * 1e-6
+ return x
+ def h2i(self, pkt, x):
+ if x is not None:
+ if (x <= -0.5e-6):
+ warning("Fixed3_6: Input value too negative: %.7f" % x)
+ x = 0
+ elif (x >= 999.9999995):
+ warning("Fixed3_6: Input value too positive: %.7f" % x)
+ x = 999.999999
+ x = int(round(x * 1e6))
+ return x
+ def i2m(self, pkt, x):
+ """Convert internal value to machine value"""
+ if x is None:
+ #Try to return zero if undefined
+ x = self.h2i(pkt, 0)
+ return x
+
+ def i2repr(self,pkt,x):
+ if x is None:
+ y=0
+ else:
+ y=self.i2h(pkt,x)
+ return "%3.6f"%(y)
+class Fixed3_7Field(LEIntField):
+ def i2h(self, pkt, x):
+ if x is not None:
+ if (x < 0):
+ warning("Fixed3_7: Internal value too negative: %d" % x)
+ x = 0
+ elif (x > 3600000000):
+ warning("Fixed3_7: Internal value too positive: %d" % x)
+ x = 3600000000
+ x = (x - 1800000000) * 1e-7
+ return x
+ def h2i(self, pkt, x):
+ if x is not None:
+ if (x <= -180.00000005):
+ warning("Fixed3_7: Input value too negative: %.8f" % x)
+ x = -180.0
+ elif (x >= 180.00000005):
+ warning("Fixed3_7: Input value too positive: %.8f" % x)
+ x = 180.0
+ x = int(round((x + 180.0) * 1e7))
+ return x
+ def i2m(self, pkt, x):
+ """Convert internal value to machine value"""
+ if x is None:
+ #Try to return zero if undefined
+ x = self.h2i(pkt, 0)
+ return x
+ def i2repr(self,pkt,x):
+ if x is None:
+ y=0
+ else:
+ y=self.i2h(pkt,x)
+ return "%3.7f"%(y)
+
+class Fixed6_4Field(LEIntField):
+ def i2h(self, pkt, x):
+ if x is not None:
+ if (x < 0):
+ warning("Fixed6_4: Internal value too negative: %d" % x)
+ x = 0
+ elif (x > 3600000000):
+ warning("Fixed6_4: Internal value too positive: %d" % x)
+ x = 3600000000
+ x = (x - 1800000000) * 1e-4
+ return x
+ def h2i(self, pkt, x):
+ if x is not None:
+ if (x <= -180000.00005):
+ warning("Fixed6_4: Input value too negative: %.5f" % x)
+ x = -180000.0
+ elif (x >= 180000.00005):
+ warning("Fixed6_4: Input value too positive: %.5f" % x)
+ x = 180000.0
+ x = int(round((x + 180000.0) * 1e4))
+ return x
+ def i2m(self, pkt, x):
+ """Convert internal value to machine value"""
+ if x is None:
+ #Try to return zero if undefined
+ x = self.h2i(pkt, 0)
+ return x
+ def i2repr(self,pkt,x):
+ if x is None:
+ y=0
+ else:
+ y=self.i2h(pkt,x)
+ return "%6.4f"%(y)
+#The GPS timestamps fractional time counter is stored in a 32-bit unsigned ns counter.
+#The ept field is as well,
+class NSCounter_Field(LEIntField):
+ def i2h(self, pkt, x): #converts nano-seconds to seconds for output
+ if x is not None:
+ if (x < 0):
+ warning("NSCounter_Field: Internal value too negative: %d" % x)
+ x = 0
+ elif (x >= 2**32):
+ warning("NSCounter_Field: Internal value too positive: %d" % x)
+ x = 2**32-1
+ x = (x / 1e9)
+ return x
+ def h2i(self, pkt, x): #converts input in seconds into nano-seconds for storage
+ if x is not None:
+ if (x < 0):
+ warning("NSCounter_Field: Input value too negative: %.10f" % x)
+ x = 0
+ elif (x >= (2**32) / 1e9):
+ warning("NSCounter_Field: Input value too positive: %.10f" % x)
+ x = (2**32-1) / 1e9
+ x = int(round((x * 1e9)))
+ return x
+ def i2repr(self,pkt,x):
+ if x is None:
+ y=0
+ else:
+ y=self.i2h(pkt,x)
+ return "%1.9f"%(y)
+
+class UTCTimeField(IntField):
+ def __init__(self, name, default, epoch=time.gmtime(0), strf="%a, %d %b %Y %H:%M:%S +0000"):
+ IntField.__init__(self, name, default)
+ self.epoch = epoch
+ self.delta = time.mktime(epoch) - time.mktime(time.gmtime(0))
+ self.strf = strf
+ def i2repr(self, pkt, x):
+ if x is None:
+ x = 0
+ x = int(x) + self.delta
+ t = time.strftime(self.strf, time.gmtime(x))
+ return "%s (%d)" % (t, x)
+
+class LETimeField(UTCTimeField,LEIntField):
+ def __init__(self, name, default, epoch=time.gmtime(0), strf="%a, %d %b %Y %H:%M:%S +0000"):
+ LEIntField.__init__(self, name, default)
+ self.epoch = epoch
+ self.delta = time.mktime(epoch) - time.mktime(time.gmtime(0))
+ self.strf = strf
+
+class SignedByteField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "b")
+ def randval(self):
+ return RandSByte()
+
+class XLEShortField(LEShortField,XShortField):
+ def i2repr(self, pkt, x):
+ return XShortField.i2repr(self, pkt, x)
+
+class XLEIntField(LEIntField,XIntField):
+ def i2repr(self, pkt, x):
+ return XIntField.i2repr(self, pkt, x)
+
+class GPSTime_Field(LETimeField):
+ def __init__(self, name, default):
+ return LETimeField.__init__(self, name, default, strf="%a, %d %b %Y %H:%M:%S UTC")
+
+class VectorFlags_Field(XLEIntField):
+ """Represents te VectorFlags field. Handles the RelativeTo:sub-field"""
+ _fwdstr = "DefinesForward"
+ _resmask = 0xfffffff8
+ _relmask = 0x6
+ _relnames = ["RelativeToForward", "RelativeToEarth", "RelativeToCurrent", "RelativeToReserved"]
+ _relvals = [0x00, 0x02, 0x04, 0x06]
+ def i2repr(self, pkt, x):
+ if x is None:
+ return str(x)
+ r = []
+ if (x & 0x1):
+ r.append(self._fwdstr)
+ i = (x & self._relmask) >> 1
+ r.append(self._relnames[i])
+ i = x & self._resmask
+ if (i):
+ r.append("ReservedBits:%08X" % i)
+ sout = "+".join(r)
+ return sout
+ def any2i(self, pkt, x):
+ if type(x) is str:
+ r = x.split("+")
+ y = 0
+ for value in r:
+ if (value == self._fwdstr):
+ y |= 0x1
+ elif (value in self._relnames):
+ i = self._relnames.index(value)
+ y &= (~self._relmask)
+ y |= self._relvals[i]
+ else:
+ #logging.warning("Unknown VectorFlags Argument: %s" % value)
+ pass
+ else:
+ y = x
+ #print "any2i: %s --> %s" % (str(x), str(y))
+ return y
+
+class HCSIFlagsField(FlagsField):
+ """ A FlagsField where each bit/flag turns a conditional field on or off.
+ If the value is None when building a packet, i2m() will check the value of
+ every field in self.names. If the field's value is not None, the corresponding
+ flag will be set. """
+ def i2m(self, pkt, val):
+ if val is None:
+ val = 0
+ if (pkt):
+ for i in range(len(self.names)):
+ name = self.names[i][0]
+ value = pkt.getfieldval(name)
+ if value is not None:
+ val |= 1 << i
+ return val
+
+class HCSINullField(StrFixedLenField):
+ def __init__(self, name, default):
+ return StrFixedLenField.__init__(self, name, default, length=0)
+
+class HCSIDescField(StrFixedLenField):
+ def __init__(self, name, default):
+ return StrFixedLenField.__init__(self, name, default, length=32)
+
+class HCSIAppField(StrFixedLenField):
+ def __init__(self, name, default):
+ return StrFixedLenField.__init__(self, name, default, length=60)
+
+def _FlagsList(myfields):
+ flags = []
+ for i in range(32):
+ flags.append("Reserved%02d" % i)
+ for i in myfields.keys():
+ flags[i] = myfields[i]
+ return flags
+
+# Define all geolocation-tag flags lists
+_hcsi_gps_flags = _FlagsList({0:"No Fix Available", 1:"GPS", 2:"Differential GPS",
+ 3:"Pulse Per Second", 4:"Real Time Kinematic",
+ 5:"Float Real Time Kinematic", 6:"Estimated (Dead Reckoning)",
+ 7:"Manual Input", 8:"Simulation"})
+
+#_hcsi_vector_flags = _FlagsList({0:"ForwardFrame", 1:"RotationsAbsoluteXYZ", 5:"OffsetFromGPS_XYZ"})
+#This has been replaced with the VectorFlags_Field class, in order to handle the RelativeTo:subfield
+
+_hcsi_vector_char_flags = _FlagsList({0:"Antenna", 1:"Direction of Travel",
+ 2:"Front of Vehicle", 3:"Angle of Arrival", 4:"Transmitter Position",
+ 8:"GPS Derived", 9:"INS Derived", 10:"Compass Derived",
+ 11:"Acclerometer Derived", 12:"Human Derived"})
+
+_hcsi_antenna_flags = _FlagsList({ 1:"Horizontal Polarization", 2:"Vertical Polarization",
+ 3:"Circular Polarization Left", 4:"Circular Polarization Right",
+ 16:"Electronically Steerable", 17:"Mechanically Steerable"})
+
+""" HCSI PPI Fields are similar to RadioTap. A mask field called "present" specifies if each field
+is present. All other fields are conditional. When dissecting a packet, each field is present if
+"present" has the corresponding bit set. When building a packet, if "present" is None, the mask is
+set to include every field that does not have a value of None. Otherwise, if the mask field is
+not None, only the fields specified by "present" will be added to the packet.
+
+To build each Packet type, build a list of the fields normally, excluding the present bitmask field.
+The code will then construct conditional versions of each field and add the present field.
+See GPS_Fields as an example. """
+
+# Conditional test for all HCSI Fields
+def _HCSITest(pkt, ibit, name):
+ if pkt.present is None:
+ return (pkt.getfieldval(name) is not None)
+ return pkt.present & ibit
+
+# Wrap optional fields in ConditionalField, add HCSIFlagsField
+def _HCSIBuildFields(fields):
+ names = [f.name for f in fields]
+ cond_fields = [ HCSIFlagsField('present', None, -len(names), names)]
+ for i in range(len(names)):
+ ibit = 1 << i
+ seval = "lambda pkt:_HCSITest(pkt,%s,'%s')" % (ibit, names[i])
+ test = eval(seval)
+ cond_fields.append(ConditionalField(fields[i], test))
+ return cond_fields
+
+class HCSIPacket(Packet):
+ name = "PPI HCSI"
+ fields_desc = [ LEShortField('pfh_type', None),
+ LEShortField('pfh_length', None),
+ ByteField('geotag_ver', CURR_GEOTAG_VER),
+ ByteField('geotag_pad', 0),
+ LEShortField('geotag_len', None)]
+ def post_build(self, p, pay):
+ if self.pfh_length is None:
+ l = len(p) - 4
+ sl = struct.pack('<H',l)
+ p = p[:2] + sl + p[4:]
+ if self.geotag_len is None:
+ l_g = len(p) - 4
+ sl_g = struct.pack('<H',l_g)
+ p = p[:6] + sl_g + p[8:]
+ p += pay
+ return p
+ def extract_padding(self, p):
+ return "",p
+
+#GPS Fields
+GPS_Fields = [FlagsField("GPSFlags", None, -32, _hcsi_gps_flags),
+ Fixed3_7Field("Latitude", None),
+ Fixed3_7Field("Longitude", None), Fixed6_4Field("Altitude", None),
+ Fixed6_4Field("Altitude_g", None), GPSTime_Field("GPSTime", None),
+ NSCounter_Field("FractionalTime", None), Fixed3_6Field("eph", None),
+ Fixed3_6Field("epv", None), NSCounter_Field("ept", None),
+ HCSINullField("Reserved10", None), HCSINullField("Reserved11", None),
+ HCSINullField("Reserved12", None), HCSINullField("Reserved13", None),
+ HCSINullField("Reserved14", None), HCSINullField("Reserved15", None),
+ HCSINullField("Reserved16", None), HCSINullField("Reserved17", None),
+ HCSINullField("Reserved18", None), HCSINullField("Reserved19", None),
+ HCSINullField("Reserved20", None), HCSINullField("Reserved21", None),
+ HCSINullField("Reserved22", None), HCSINullField("Reserved23", None),
+ HCSINullField("Reserved24", None), HCSINullField("Reserved25", None),
+ HCSINullField("Reserved26", None), HCSINullField("Reserved27", None),
+ HCSIDescField("DescString", None), XLEIntField("AppId", None),
+ HCSIAppField("AppData", None), HCSINullField("Extended", None)]
+
+class GPS(HCSIPacket):
+ name = "PPI GPS"
+ fields_desc = [ LEShortField('pfh_type', PPI_GPS), #pfh_type
+ LEShortField('pfh_length', None), #pfh_len
+ ByteField('geotag_ver', CURR_GEOTAG_VER), #base_geotag_header.ver
+ ByteField('geotag_pad', 0), #base_geotag_header.pad
+ LEShortField('geotag_len', None)] + _HCSIBuildFields(GPS_Fields)
+
+
+#Vector Fields
+VEC_Fields = [VectorFlags_Field("VectorFlags", None),
+ FlagsField("VectorChars", None, -32, _hcsi_vector_char_flags),
+ Fixed3_6Field("Pitch", None), Fixed3_6Field("Roll", None),
+ Fixed3_6Field("Heading", None), Fixed6_4Field("Off_X", None),
+ Fixed6_4Field("Off_Y", None), Fixed6_4Field("Off_Z", None),
+ HCSINullField("Reserved08", None), HCSINullField("Reserved09", None),
+ HCSINullField("Reserved10", None), HCSINullField("Reserved11", None),
+ HCSINullField("Reserved12", None), HCSINullField("Reserved13", None),
+ HCSINullField("Reserved14", None), HCSINullField("Reserved15", None),
+ Fixed3_6Field("Err_Rot", None), Fixed6_4Field("Err_Off", None),
+ HCSINullField("Reserved18", None), HCSINullField("Reserved19", None),
+ HCSINullField("Reserved20", None), HCSINullField("Reserved21", None),
+ HCSINullField("Reserved22", None), HCSINullField("Reserved23", None),
+ HCSINullField("Reserved24", None), HCSINullField("Reserved25", None),
+ HCSINullField("Reserved26", None), HCSINullField("Reserved27", None),
+ HCSIDescField("DescString", None), XLEIntField("AppId", None),
+ HCSIAppField("AppData", None), HCSINullField("Extended", None)]
+
+class Vector(HCSIPacket):
+ name = "PPI Vector"
+ fields_desc = [ LEShortField('pfh_type', PPI_VECTOR), #pfh_type
+ LEShortField('pfh_length', None), #pfh_len
+ ByteField('geotag_ver', CURR_GEOTAG_VER), #base_geotag_header.ver
+ ByteField('geotag_pad', 0), #base_geotag_header.pad
+ LEShortField('geotag_len', None)] + _HCSIBuildFields(VEC_Fields)
+
+#Sensor Fields
+# http://www.iana.org/assignments/icmp-parameters
+sensor_types= { 1 : "Velocity",
+ 2 : "Acceleration",
+ 3 : "Jerk",
+ 100 : "Rotation",
+ 101 : "Magnetic",
+ 1000: "Temperature",
+ 1001: "Barometer",
+ 1002: "Humidity",
+ 2000: "TDOA_Clock",
+ 2001: "Phase"
+ }
+SENS_Fields = [ LEShortEnumField('SensorType', None, sensor_types),
+ SignedByteField('ScaleFactor', None),
+ Fixed6_4Field('Val_X', None),
+ Fixed6_4Field('Val_Y', None),
+ Fixed6_4Field('Val_Z', None),
+ Fixed6_4Field('Val_T', None),
+ Fixed6_4Field('Val_E', None),
+ HCSINullField("Reserved07", None), HCSINullField("Reserved08", None),
+ HCSINullField("Reserved09", None), HCSINullField("Reserved10", None),
+ HCSINullField("Reserved11", None), HCSINullField("Reserved12", None),
+ HCSINullField("Reserved13", None), HCSINullField("Reserved14", None),
+ HCSINullField("Reserved15", None), HCSINullField("Reserved16", None),
+ HCSINullField("Reserved17", None), HCSINullField("Reserved18", None),
+ HCSINullField("Reserved19", None), HCSINullField("Reserved20", None),
+ HCSINullField("Reserved21", None), HCSINullField("Reserved22", None),
+ HCSINullField("Reserved23", None), HCSINullField("Reserved24", None),
+ HCSINullField("Reserved25", None), HCSINullField("Reserved26", None),
+ HCSINullField("Reserved27", None),
+ HCSIDescField("DescString", None), XLEIntField("AppId", None),
+ HCSIAppField("AppData", None), HCSINullField("Extended", None)]
+
+
+
+class Sensor(HCSIPacket):
+ name = "PPI Sensor"
+ fields_desc = [ LEShortField('pfh_type', PPI_SENSOR), #pfh_type
+ LEShortField('pfh_length', None), #pfh_len
+ ByteField('geotag_ver', CURR_GEOTAG_VER ), #base_geotag_header.ver
+ ByteField('geotag_pad', 0), #base_geotag_header.pad
+ LEShortField('geotag_len', None)] + _HCSIBuildFields(SENS_Fields)
+
+# HCSIAntenna Fields
+ANT_Fields = [FlagsField("AntennaFlags", None, -32, _hcsi_antenna_flags),
+ ByteField("Gain", None),
+ Fixed3_6Field("HorizBw", None), Fixed3_6Field("VertBw", None),
+ Fixed3_6Field("PrecisionGain",None), XLEShortField("BeamID", None),
+ HCSINullField("Reserved06", None), HCSINullField("Reserved07", None),
+ HCSINullField("Reserved08", None), HCSINullField("Reserved09", None),
+ HCSINullField("Reserved10", None), HCSINullField("Reserved11", None),
+ HCSINullField("Reserved12", None), HCSINullField("Reserved13", None),
+ HCSINullField("Reserved14", None), HCSINullField("Reserved15", None),
+ HCSINullField("Reserved16", None), HCSINullField("Reserved17", None),
+ HCSINullField("Reserved18", None), HCSINullField("Reserved19", None),
+ HCSINullField("Reserved20", None), HCSINullField("Reserved21", None),
+ HCSINullField("Reserved22", None), HCSINullField("Reserved23", None),
+ HCSINullField("Reserved24", None), HCSINullField("Reserved25", None),
+ HCSIDescField("SerialNumber", None), HCSIDescField("ModelName", None),
+ HCSIDescField("DescString", None), XLEIntField("AppId", None),
+ HCSIAppField("AppData", None), HCSINullField("Extended", None)]
+
+class Antenna(HCSIPacket):
+ name = "PPI Antenna"
+ fields_desc = [ LEShortField('pfh_type', PPI_ANTENNA), #pfh_type
+ LEShortField('pfh_length', None), #pfh_len
+ ByteField('geotag_ver', CURR_GEOTAG_VER), #base_geotag_header.ver
+ ByteField('geotag_pad', 0), #base_geotag_header.pad
+ LEShortField('geotag_len', None)] + _HCSIBuildFields(ANT_Fields)
+
+addPPIType(PPI_GPS, GPS)
+addPPIType(PPI_VECTOR, Vector)
+addPPIType(PPI_SENSOR, Sensor)
+addPPIType(PPI_ANTENNA,Antenna)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ripng.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ripng.py
new file mode 100644
index 00000000..47e17bc4
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ripng.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+# http://trac.secdev.org/scapy/ticket/301
+
+# scapy.contrib.description = RIPng
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+from scapy.layers.inet6 import *
+
+class RIPng(Packet):
+ name = "RIPng header"
+ fields_desc = [
+ ByteEnumField("cmd", 1, {1 : "req", 2 : "resp"}),
+ ByteField("ver", 1),
+ ShortField("null", 0),
+ ]
+
+class RIPngEntry(Packet):
+ name = "RIPng entry"
+ fields_desc = [
+ ConditionalField(IP6Field("prefix", "::"),
+ lambda pkt: pkt.metric != 255),
+ ConditionalField(IP6Field("nexthop", "::"),
+ lambda pkt: pkt.metric == 255),
+ ShortField("routetag", 0),
+ ByteField("prefixlen", 0),
+ ByteEnumField("metric", 1, {16 : "Unreach",
+ 255 : "next-hop entry"})
+ ]
+
+bind_layers(UDP, RIPng, sport=521, dport=521)
+bind_layers(RIPng, RIPngEntry)
+bind_layers(RIPngEntry, RIPngEntry)
+
+if __name__ == "__main__":
+ from scapy.main import interact
+ interact(mydict=globals(), mybanner="RIPng")
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/rsvp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/rsvp.py
new file mode 100644
index 00000000..c9d4ebee
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/rsvp.py
@@ -0,0 +1,188 @@
+## RSVP layer
+
+# http://trac.secdev.org/scapy/ticket/197
+
+# scapy.contrib.description = RSVP
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP
+
+rsvpmsgtypes = { 0x01 : "Path",
+ 0x02 : "Reservation request",
+ 0x03 : "Path error",
+ 0x04 : "Reservation request error",
+ 0x05 : "Path teardown",
+ 0x06 : "Reservation teardown",
+ 0x07 : "Reservation request acknowledgment"
+}
+
+class RSVP(Packet):
+ name = "RSVP"
+ fields_desc = [ BitField("Version",1,4),
+ BitField("Flags",1,4),
+ ByteEnumField("Class",0x01, rsvpmsgtypes),
+ XShortField("chksum", None),
+ ByteField("TTL",1),
+ XByteField("dataofs", 0),
+ ShortField("Length",None)]
+ def post_build(self, p, pay):
+ p += pay
+ if self.Length is None:
+ l = len(p)
+ p = p[:6]+chr((l>>8)&0xff)+chr(l&0xff)+p[8:]
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
+ return p
+
+rsvptypes = { 0x01 : "Session",
+ 0x03 : "HOP",
+ 0x04 : "INTEGRITY",
+ 0x05 : "TIME_VALUES",
+ 0x06 : "ERROR_SPEC",
+ 0x07 : "SCOPE",
+ 0x08 : "STYLE",
+ 0x09 : "FLOWSPEC",
+ 0x0A : "FILTER_SPEC",
+ 0x0B : "SENDER_TEMPLATE",
+ 0x0C : "SENDER_TSPEC",
+ 0x0D : "ADSPEC",
+ 0x0E : "POLICY_DATA",
+ 0x0F : "RESV_CONFIRM",
+ 0x10 : "RSVP_LABEL",
+ 0x11 : "HOP_COUNT",
+ 0x12 : "STRICT_SOURCE_ROUTE",
+ 0x13 : "LABEL_REQUEST",
+ 0x14 : "EXPLICIT_ROUTE",
+ 0x15 : "ROUTE_RECORD",
+ 0x16 : "HELLO",
+ 0x17 : "MESSAGE_ID",
+ 0x18 : "MESSAGE_ID_ACK",
+ 0x19 : "MESSAGE_ID_LIST",
+ 0x1E : "DIAGNOSTIC",
+ 0x1F : "ROUTE",
+ 0x20 : "DIAG_RESPONSE",
+ 0x21 : "DIAG_SELECT",
+ 0x22 : "RECOVERY_LABEL",
+ 0x23 : "UPSTREAM_LABEL",
+ 0x24 : "LABEL_SET",
+ 0x25 : "PROTECTION",
+ 0x26 : "PRIMARY PATH ROUTE",
+ 0x2A : "DSBM IP ADDRESS",
+ 0x2B : "SBM_PRIORITY",
+ 0x2C : "DSBM TIMER INTERVALS",
+ 0x2D : "SBM_INFO",
+ 0x32 : "S2L_SUB_LSP",
+ 0x3F : "DETOUR",
+ 0x40 : "CHALLENGE",
+ 0x41 : "DIFF-SERV",
+ 0x42 : "CLASSTYPE",
+ 0x43 : "LSP_REQUIRED_ATTRIBUTES",
+ 0x80 : "NODE_CHAR",
+ 0x81 : "SUGGESTED_LABEL",
+ 0x82 : "ACCEPTABLE_LABEL_SET",
+ 0x83 : "RESTART_CA",
+ 0x84 : "SESSION-OF-INTEREST",
+ 0x85 : "LINK_CAPABILITY",
+ 0x86 : "Capability Object",
+ 0xA1 : "RSVP_HOP_L2",
+ 0xA2 : "LAN_NHOP_L2",
+ 0xA3 : "LAN_NHOP_L3",
+ 0xA4 : "LAN_LOOPBACK",
+ 0xA5 : "TCLASS",
+ 0xC0 : "TUNNEL",
+ 0xC1 : "LSP_TUNNEL_INTERFACE_ID",
+ 0xC2 : "USER_ERROR_SPEC",
+ 0xC3 : "NOTIFY_REQUEST",
+ 0xC4 : "ADMIN-STATUS",
+ 0xC5 : "LSP_ATTRIBUTES",
+ 0xC6 : "ALARM_SPEC",
+ 0xC7 : "ASSOCIATION",
+ 0xC8 : "SECONDARY_EXPLICIT_ROUTE",
+ 0xC9 : "SECONDARY_RECORD_ROUTE",
+ 0xCD : "FAST_REROUTE",
+ 0xCF : "SESSION_ATTRIBUTE",
+ 0xE1 : "DCLASS",
+ 0xE2 : "PACKETCABLE EXTENSIONS",
+ 0xE3 : "ATM_SERVICECLASS",
+ 0xE4 : "CALL_OPS (ASON)",
+ 0xE5 : "GENERALIZED_UNI",
+ 0xE6 : "CALL_ID",
+ 0xE7 : "3GPP2_Object",
+ 0xE8 : "EXCLUDE_ROUTE"
+}
+
+class RSVP_Object(Packet):
+ name = "RSVP_Object"
+ fields_desc = [ ShortField("Length",4),
+ ByteEnumField("Class",0x01, rsvptypes),
+ ByteField("C-Type",1)]
+ def guess_payload_class(self, payload):
+ if self.Class == 0x03:
+ return RSVP_HOP
+ elif self.Class == 0x05:
+ return RSVP_Time
+ elif self.Class == 0x0c:
+ return RSVP_SenderTSPEC
+ elif self.Class == 0x13:
+ return RSVP_LabelReq
+ elif self.Class == 0xCF:
+ return RSVP_SessionAttrb
+ else:
+ return RSVP_Data
+
+
+
+class RSVP_Data(Packet):
+ name = "Data"
+ fields_desc = [StrLenField("Data","",length_from= lambda pkt:pkt.underlayer.Length - 4)]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+class RSVP_HOP(Packet):
+ name = "HOP"
+ fields_desc = [ IPField("neighbor","0.0.0.0"),
+ BitField("inface",1,32)]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+class RSVP_Time(Packet):
+ name = "Time Val"
+ fields_desc = [ BitField("refresh",1,32)]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+class RSVP_SenderTSPEC(Packet):
+ name = "Sender_TSPEC"
+ fields_desc = [ ByteField("Msg_Format",0),
+ ByteField("reserve",0),
+ ShortField("Data_Length",4),
+ ByteField("Srv_hdr",1),
+ ByteField("reserve2",0),
+ ShortField("Srv_Length",4),
+ StrLenField("Tokens","",length_from= lambda pkt:pkt.underlayer.Length - 12) ]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+class RSVP_LabelReq(Packet):
+ name = "Lable Req"
+ fields_desc = [ ShortField("reserve",1),
+ ShortField("L3PID",1)]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+class RSVP_SessionAttrb(Packet):
+ name = "Session_Attribute"
+ fields_desc = [ ByteField("Setup_priority",1),
+ ByteField("Hold_priority",1),
+ ByteField("flags",1),
+ ByteField("Name_length",1),
+ StrLenField("Name","",length_from= lambda pkt:pkt.underlayer.Length - 8),
+ ]
+ def default_payload_class(self, payload):
+ return RSVP_Object
+
+bind_layers( IP, RSVP, { "proto" : 46} )
+bind_layers( RSVP, RSVP_Object, {})
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/skinny.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/skinny.py
new file mode 100644
index 00000000..47935c9e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/skinny.py
@@ -0,0 +1,499 @@
+#! /usr/bin/env python
+
+# scapy.contrib.description = Skinny Call Control Protocol (SCCP)
+# scapy.contrib.status = loads
+
+
+#############################################################################
+## ##
+## scapy-skinny.py --- Skinny Call Control Protocol (SCCP) extension ##
+## ##
+## Copyright (C) 2006 Nicolas Bareil <nicolas.bareil@ eads.net> ##
+## EADS/CRC security team ##
+## ##
+## This program is free software; you can redistribute it and/or modify it ##
+## under the terms of the GNU General Public License version 2 as ##
+## published by the Free Software Foundation; version 2. ##
+## ##
+## This program is distributed in the hope that it will be useful, but ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of ##
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
+## General Public License for more details. ##
+## ##
+#############################################################################
+
+from scapy.all import *
+import builtins
+
+#####################################################################
+# Helpers and constants
+#####################################################################
+
+skinny_messages_cls = {
+# Station -> Callmanager
+ 0x0000: "SkinnyMessageKeepAlive",
+ 0x0001: "SkinnyMessageRegister",
+ 0x0002: "SkinnyMessageIpPort",
+ 0x0003: "SkinnyMessageKeypadButton",
+ 0x0004: "SkinnyMessageEnblocCall",
+ 0x0005: "SkinnyMessageStimulus",
+ 0x0006: "SkinnyMessageOffHook",
+ 0x0007: "SkinnyMessageOnHook",
+ 0x0008: "SkinnyMessageHookFlash",
+ 0x0009: "SkinnyMessageForwardStatReq",
+ 0x000A: "SkinnyMessageSpeedDialStatReq",
+ 0x000B: "SkinnyMessageLineStatReq",
+ 0x000C: "SkinnyMessageConfigStatReq",
+ 0x000D: "SkinnyMessageTimeDateReq",
+ 0x000E: "SkinnyMessageButtonTemplateReq",
+ 0x000F: "SkinnyMessageVersionReq",
+ 0x0010: "SkinnyMessageCapabilitiesRes",
+ 0x0011: "SkinnyMessageMediaPortList",
+ 0x0012: "SkinnyMessageServerReq",
+ 0x0020: "SkinnyMessageAlarm",
+ 0x0021: "SkinnyMessageMulticastMediaReceptionAck",
+ 0x0022: "SkinnyMessageOpenReceiveChannelAck",
+ 0x0023: "SkinnyMessageConnectionStatisticsRes",
+ 0x0024: "SkinnyMessageOffHookWithCgpn",
+ 0x0025: "SkinnyMessageSoftKeySetReq",
+ 0x0026: "SkinnyMessageSoftKeyEvent",
+ 0x0027: "SkinnyMessageUnregister",
+ 0x0028: "SkinnyMessageSoftKeyTemplateReq",
+ 0x0029: "SkinnyMessageRegisterTokenReq",
+ 0x002A: "SkinnyMessageMediaTransmissionFailure",
+ 0x002B: "SkinnyMessageHeadsetStatus",
+ 0x002C: "SkinnyMessageMediaResourceNotification",
+ 0x002D: "SkinnyMessageRegisterAvailableLines",
+ 0x002E: "SkinnyMessageDeviceToUserData",
+ 0x002F: "SkinnyMessageDeviceToUserDataResponse",
+ 0x0030: "SkinnyMessageUpdateCapabilities",
+ 0x0031: "SkinnyMessageOpenMultiMediaReceiveChannelAck",
+ 0x0032: "SkinnyMessageClearConference",
+ 0x0033: "SkinnyMessageServiceURLStatReq",
+ 0x0034: "SkinnyMessageFeatureStatReq",
+ 0x0035: "SkinnyMessageCreateConferenceRes",
+ 0x0036: "SkinnyMessageDeleteConferenceRes",
+ 0x0037: "SkinnyMessageModifyConferenceRes",
+ 0x0038: "SkinnyMessageAddParticipantRes",
+ 0x0039: "SkinnyMessageAuditConferenceRes",
+ 0x0040: "SkinnyMessageAuditParticipantRes",
+ 0x0041: "SkinnyMessageDeviceToUserDataVersion1",
+# Callmanager -> Station */
+ 0x0081: "SkinnyMessageRegisterAck",
+ 0x0082: "SkinnyMessageStartTone",
+ 0x0083: "SkinnyMessageStopTone",
+ 0x0085: "SkinnyMessageSetRinger",
+ 0x0086: "SkinnyMessageSetLamp",
+ 0x0087: "SkinnyMessageSetHkFDetect",
+ 0x0088: "SkinnyMessageSpeakerMode",
+ 0x0089: "SkinnyMessageSetMicroMode",
+ 0x008A: "SkinnyMessageStartMediaTransmission",
+ 0x008B: "SkinnyMessageStopMediaTransmission",
+ 0x008C: "SkinnyMessageStartMediaReception",
+ 0x008D: "SkinnyMessageStopMediaReception",
+ 0x008F: "SkinnyMessageCallInfo",
+ 0x0090: "SkinnyMessageForwardStat",
+ 0x0091: "SkinnyMessageSpeedDialStat",
+ 0x0092: "SkinnyMessageLineStat",
+ 0x0093: "SkinnyMessageConfigStat",
+ 0x0094: "SkinnyMessageTimeDate",
+ 0x0095: "SkinnyMessageStartSessionTransmission",
+ 0x0096: "SkinnyMessageStopSessionTransmission",
+ 0x0097: "SkinnyMessageButtonTemplate",
+ 0x0098: "SkinnyMessageVersion",
+ 0x0099: "SkinnyMessageDisplayText",
+ 0x009A: "SkinnyMessageClearDisplay",
+ 0x009B: "SkinnyMessageCapabilitiesReq",
+ 0x009C: "SkinnyMessageEnunciatorCommand",
+ 0x009D: "SkinnyMessageRegisterReject",
+ 0x009E: "SkinnyMessageServerRes",
+ 0x009F: "SkinnyMessageReset",
+ 0x0100: "SkinnyMessageKeepAliveAck",
+ 0x0101: "SkinnyMessageStartMulticastMediaReception",
+ 0x0102: "SkinnyMessageStartMulticastMediaTransmission",
+ 0x0103: "SkinnyMessageStopMulticastMediaReception",
+ 0x0104: "SkinnyMessageStopMulticastMediaTransmission",
+ 0x0105: "SkinnyMessageOpenReceiveChannel",
+ 0x0106: "SkinnyMessageCloseReceiveChannel",
+ 0x0107: "SkinnyMessageConnectionStatisticsReq",
+ 0x0108: "SkinnyMessageSoftKeyTemplateRes",
+ 0x0109: "SkinnyMessageSoftKeySetRes",
+ 0x0110: "SkinnyMessageSoftKeyEvent",
+ 0x0111: "SkinnyMessageCallState",
+ 0x0112: "SkinnyMessagePromptStatus",
+ 0x0113: "SkinnyMessageClearPromptStatus",
+ 0x0114: "SkinnyMessageDisplayNotify",
+ 0x0115: "SkinnyMessageClearNotify",
+ 0x0116: "SkinnyMessageCallPlane",
+ 0x0117: "SkinnyMessageCallPlane",
+ 0x0118: "SkinnyMessageUnregisterAck",
+ 0x0119: "SkinnyMessageBackSpaceReq",
+ 0x011A: "SkinnyMessageRegisterTokenAck",
+ 0x011B: "SkinnyMessageRegisterTokenReject",
+ 0x0042: "SkinnyMessageDeviceToUserDataResponseVersion1",
+ 0x011C: "SkinnyMessageStartMediaFailureDetection",
+ 0x011D: "SkinnyMessageDialedNumber",
+ 0x011E: "SkinnyMessageUserToDeviceData",
+ 0x011F: "SkinnyMessageFeatureStat",
+ 0x0120: "SkinnyMessageDisplayPriNotify",
+ 0x0121: "SkinnyMessageClearPriNotify",
+ 0x0122: "SkinnyMessageStartAnnouncement",
+ 0x0123: "SkinnyMessageStopAnnouncement",
+ 0x0124: "SkinnyMessageAnnouncementFinish",
+ 0x0127: "SkinnyMessageNotifyDtmfTone",
+ 0x0128: "SkinnyMessageSendDtmfTone",
+ 0x0129: "SkinnyMessageSubscribeDtmfPayloadReq",
+ 0x012A: "SkinnyMessageSubscribeDtmfPayloadRes",
+ 0x012B: "SkinnyMessageSubscribeDtmfPayloadErr",
+ 0x012C: "SkinnyMessageUnSubscribeDtmfPayloadReq",
+ 0x012D: "SkinnyMessageUnSubscribeDtmfPayloadRes",
+ 0x012E: "SkinnyMessageUnSubscribeDtmfPayloadErr",
+ 0x012F: "SkinnyMessageServiceURLStat",
+ 0x0130: "SkinnyMessageCallSelectStat",
+ 0x0131: "SkinnyMessageOpenMultiMediaChannel",
+ 0x0132: "SkinnyMessageStartMultiMediaTransmission",
+ 0x0133: "SkinnyMessageStopMultiMediaTransmission",
+ 0x0134: "SkinnyMessageMiscellaneousCommand",
+ 0x0135: "SkinnyMessageFlowControlCommand",
+ 0x0136: "SkinnyMessageCloseMultiMediaReceiveChannel",
+ 0x0137: "SkinnyMessageCreateConferenceReq",
+ 0x0138: "SkinnyMessageDeleteConferenceReq",
+ 0x0139: "SkinnyMessageModifyConferenceReq",
+ 0x013A: "SkinnyMessageAddParticipantReq",
+ 0x013B: "SkinnyMessageDropParticipantReq",
+ 0x013C: "SkinnyMessageAuditConferenceReq",
+ 0x013D: "SkinnyMessageAuditParticipantReq",
+ 0x013F: "SkinnyMessageUserToDeviceDataVersion1",
+ }
+
+skinny_callstates = {
+ 0x1: "Off Hook",
+ 0x2: "On Hook",
+ 0x3: "Ring out",
+ 0xc: "Proceeding",
+}
+
+
+skinny_ring_type = {
+ 0x1: "Ring off"
+}
+
+skinny_speaker_modes = {
+ 0x1: "Speaker on",
+ 0x2: "Speaker off"
+}
+
+skinny_lamp_mode = {
+ 0x1: "Off (?)",
+ 0x2: "On",
+}
+
+skinny_stimulus = {
+ 0x9: "Line"
+}
+
+
+############
+## Fields ##
+############
+
+class SkinnyDateTimeField(StrFixedLenField):
+ def __init__(self, name, default):
+ StrFixedLenField.__init__(self, name, default, 32)
+
+ def m2i(self, pkt, s):
+ year,month,dow,day,hour,min,sec,milisecond=struct.unpack('<8I', s)
+ return (year, month, day, hour, min, sec)
+
+ def i2m(self, pkt, val):
+ if type(val) is str:
+ val = self.h2i(pkt, val)
+ l= val[:2] + (0,) + val[2:7] + (0,)
+ return struct.pack('<8I', *l)
+
+ def i2h(self, pkt, x):
+ if type(x) is str:
+ return x
+ else:
+ return time.ctime(time.mktime(x+(0,0,0)))
+
+ def i2repr(self, pkt, x):
+ return self.i2h(pkt, x)
+
+ def h2i(self, pkt, s):
+ t = ()
+ if type(s) is str:
+ t = time.strptime(s)
+ t = t[:2] + t[2:-3]
+ else:
+ if not s:
+ y,m,d,h,min,sec,rest,rest,rest = time.gmtime(time.time())
+ t = (y,m,d,h,min,sec)
+ else:
+ t=s
+ return t
+
+
+###########################
+## Packet abstract class ##
+###########################
+
+class SkinnyMessageGeneric(Packet):
+ name='Generic message'
+
+class SkinnyMessageKeepAlive(Packet):
+ name='keep alive'
+
+class SkinnyMessageKeepAliveAck(Packet):
+ name='keep alive ack'
+
+class SkinnyMessageOffHook(Packet):
+ name = 'Off Hook'
+ fields_desc = [ LEIntField("unknown1", 0),
+ LEIntField("unknown2", 0),]
+
+class SkinnyMessageOnHook(SkinnyMessageOffHook):
+ name = 'On Hook'
+
+class SkinnyMessageCallState(Packet):
+ name='Skinny Call state message'
+ fields_desc = [ LEIntEnumField("state", 1, skinny_callstates),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0),
+ LEIntField("unknown1", 4),
+ LEIntField("unknown2", 0),
+ LEIntField("unknown3", 0) ]
+
+class SkinnyMessageSoftKeyEvent(Packet):
+ name='Soft Key Event'
+ fields_desc = [ LEIntField("key", 0),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+class SkinnyMessageSetRinger(Packet):
+ name='Ring message'
+ fields_desc = [ LEIntEnumField("ring", 0x1, skinny_ring_type),
+ LEIntField("unknown1", 0),
+ LEIntField("unknown2", 0),
+ LEIntField("unknown3", 0) ]
+
+_skinny_tones = {
+ 0x21: 'Inside dial tone',
+ 0x22: 'xxx',
+ 0x23: 'xxx',
+ 0x24: 'Alerting tone',
+ 0x25: 'Reorder Tone'
+ }
+
+class SkinnyMessageStartTone(Packet):
+ name='Start tone'
+ fields_desc = [ LEIntEnumField("tone", 0x21, _skinny_tones),
+ LEIntField("unknown1", 0),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+class SkinnyMessageStopTone(SkinnyMessageGeneric):
+ name='stop tone'
+ fields_desc = [ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+
+class SkinnyMessageSpeakerMode(Packet):
+ name='Speaker mdoe'
+ fields_desc = [ LEIntEnumField("ring", 0x1, skinny_speaker_modes) ]
+
+class SkinnyMessageSetLamp(Packet):
+ name='Lamp message (light of the phone)'
+ fields_desc = [ LEIntEnumField("stimulus", 0x5, skinny_stimulus),
+ LEIntField("instance", 1),
+ LEIntEnumField("mode", 2, skinny_lamp_mode) ]
+
+class SkinnyMessageSoftKeyEvent(Packet):
+ name=' Call state message'
+ fields_desc = [ LEIntField("instance", 1),
+ LEIntField("callid", 0),
+ LEIntField("set", 0),
+ LEIntField("map", 0xffff)]
+
+class SkinnyMessagePromptStatus(Packet):
+ name='Prompt status'
+ fields_desc = [ LEIntField("timeout", 0),
+ StrFixedLenField("text", "\0"*32, 32),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+class SkinnyMessageCallPlane(Packet):
+ name='Activate/Desactivate Call Plane Message'
+ fields_desc = [ LEIntField("instance", 1)]
+
+class SkinnyMessageTimeDate(Packet):
+ name='Setting date and time'
+ fields_desc = [ SkinnyDateTimeField("settime", None),
+ LEIntField("timestamp", 0) ]
+
+class SkinnyMessageClearPromptStatus(Packet):
+ name='clear prompt status'
+ fields_desc = [ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+class SkinnyMessageKeypadButton(Packet):
+ name='keypad button'
+ fields_desc = [ LEIntField("key", 0),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+class SkinnyMessageDialedNumber(Packet):
+ name='dialed number'
+ fields_desc = [ StrFixedLenField("number", "1337", 24),
+ LEIntField("instance", 1),
+ LEIntField("callid", 0)]
+
+_skinny_message_callinfo_restrictions = ['CallerName'
+ , 'CallerNumber'
+ , 'CalledName'
+ , 'CalledNumber'
+ , 'OriginalCalledName'
+ , 'OriginalCalledNumber'
+ , 'LastRedirectName'
+ , 'LastRedirectNumber'] + ['Bit%d' % i for i in range(8,15)]
+class SkinnyMessageCallInfo(Packet):
+ name='call information'
+ fields_desc = [ StrFixedLenField("callername", "Jean Valjean", 40),
+ StrFixedLenField("callernum", "1337", 24),
+ StrFixedLenField("calledname", "Causette", 40),
+ StrFixedLenField("callednum", "1034", 24),
+ LEIntField("lineinstance", 1),
+ LEIntField("callid", 0),
+ StrFixedLenField("originalcalledname", "Causette", 40),
+ StrFixedLenField("originalcallednum", "1034", 24),
+ StrFixedLenField("lastredirectingname", "Causette", 40),
+ StrFixedLenField("lastredirectingnum", "1034", 24),
+ LEIntField("originalredirectreason", 0),
+ LEIntField("lastredirectreason", 0),
+ StrFixedLenField('voicemailboxG', '\0'*24, 24),
+ StrFixedLenField('voicemailboxD', '\0'*24, 24),
+ StrFixedLenField('originalvoicemailboxD', '\0'*24, 24),
+ StrFixedLenField('lastvoicemailboxD', '\0'*24, 24),
+ LEIntField('security', 0),
+ FlagsField('restriction', 0, 16, _skinny_message_callinfo_restrictions),
+ LEIntField('unknown', 0)]
+
+
+class SkinnyRateField(LEIntField):
+ def i2repr(self, pkt, x):
+ if x is None:
+ x=0
+ return '%d ms/pkt' % x
+
+_skinny_codecs = {
+ 0x0: 'xxx',
+ 0x1: 'xxx',
+ 0x2: 'xxx',
+ 0x3: 'xxx',
+ 0x4: 'G711 ulaw 64k'
+ }
+
+_skinny_echo = {
+ 0x0: 'echo cancelation off',
+ 0x1: 'echo cancelation on'
+ }
+
+class SkinnyMessageOpenReceiveChannel(Packet):
+ name='open receive channel'
+ fields_desc = [LEIntField('conference', 0),
+ LEIntField('passthru', 0),
+ SkinnyRateField('rate', 20),
+ LEIntEnumField('codec', 4, _skinny_codecs),
+ LEIntEnumField('echo', 0, _skinny_echo),
+ LEIntField('unknown1', 0),
+ LEIntField('callid', 0)]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+_skinny_receive_channel_status = {
+ 0x0: 'ok',
+ 0x1: 'ko'
+ }
+
+class SkinnyMessageOpenReceiveChannelAck(Packet):
+ name='open receive channel'
+ fields_desc = [LEIntEnumField('status', 0, _skinny_receive_channel_status),
+ IPField('remote', '0.0.0.0'),
+ LEIntField('port', RandShort()),
+ LEIntField('passthru', 0),
+ LEIntField('callid', 0)]
+
+_skinny_silence = {
+ 0x0: 'silence suppression off',
+ 0x1: 'silence suppression on',
+ }
+
+class SkinnyFramePerPacketField(LEIntField):
+ def i2repr(self, pkt, x):
+ if x is None:
+ x=0
+ return '%d frames/pkt' % x
+
+class SkinnyMessageStartMediaTransmission(Packet):
+ name='start multimedia transmission'
+ fields_desc = [LEIntField('conference', 0),
+ LEIntField('passthru', 0),
+ IPField('remote', '0.0.0.0'),
+ LEIntField('port', RandShort()),
+ SkinnyRateField('rate', 20),
+ LEIntEnumField('codec', 4, _skinny_codecs),
+ LEIntField('precedence', 200),
+ LEIntEnumField('silence', 0, _skinny_silence),
+ SkinnyFramePerPacketField('maxframes', 0),
+ LEIntField('unknown1', 0),
+ LEIntField('callid', 0)]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+class SkinnyMessageCloseReceiveChannel(Packet):
+ name='close receive channel'
+ fields_desc = [LEIntField('conference', 0),
+ LEIntField('passthru', 0),
+ IPField('remote', '0.0.0.0'),
+ LEIntField('port', RandShort()),
+ SkinnyRateField('rate', 20),
+ LEIntEnumField('codec', 4, _skinny_codecs),
+ LEIntField('precedence', 200),
+ LEIntEnumField('silence', 0, _skinny_silence),
+ LEIntField('callid', 0)]
+
+class SkinnyMessageStopMultiMediaTransmission(Packet):
+ name='stop multimedia transmission'
+ fields_desc = [LEIntField('conference', 0),
+ LEIntField('passthru', 0),
+ LEIntField('callid', 0)]
+
+class Skinny(Packet):
+ name="Skinny"
+ fields_desc = [ LEIntField("len", None),
+ LEIntField("res",0),
+ LEIntEnumField("msg",0, skinny_messages) ]
+
+ def post_build(self, pkt, p):
+ if self.len is None:
+ l=len(p)+len(pkt)-8 # on compte pas les headers len et reserved
+ pkt=struct.pack('@I', l)+pkt[4:]
+ return pkt+p
+
+# An helper
+def get_cls(name, fallback_cls):
+ return globals().get(name, fallback_cls)
+ #return builtins.__dict__.get(name, fallback_cls)
+
+for msgid,strcls in skinny_messages_cls.items():
+ cls=get_cls(strcls, SkinnyMessageGeneric)
+ bind_layers(Skinny, cls, {"msg": msgid})
+
+bind_layers(TCP, Skinny, { "dport": 2000 } )
+bind_layers(TCP, Skinny, { "sport": 2000 } )
+
+if __name__ == "__main__":
+ interact(mydict=globals(),mybanner="Welcome to Skinny add-on")
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ubberlogger.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ubberlogger.py
new file mode 100644
index 00000000..1c01db2f
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/ubberlogger.py
@@ -0,0 +1,101 @@
+# Author: Sylvain SARMEJEANNE
+# http://trac.secdev.org/scapy/ticket/1
+
+# scapy.contrib.description = Ubberlogger dissectors
+# scapy.contrib.status = untested
+
+from scapy.packet import *
+from scapy.fields import *
+
+# Syscalls known by Uberlogger
+uberlogger_sys_calls = {0:"READ_ID",
+ 1:"OPEN_ID",
+ 2:"WRITE_ID",
+ 3:"CHMOD_ID",
+ 4:"CHOWN_ID",
+ 5:"SETUID_ID",
+ 6:"CHROOT_ID",
+ 7:"CREATE_MODULE_ID",
+ 8:"INIT_MODULE_ID",
+ 9:"DELETE_MODULE_ID",
+ 10:"CAPSET_ID",
+ 11:"CAPGET_ID",
+ 12:"FORK_ID",
+ 13:"EXECVE_ID"}
+
+# First part of the header
+class Uberlogger_honeypot_caract(Packet):
+ name = "Uberlogger honeypot_caract"
+ fields_desc = [ByteField("honeypot_id", 0),
+ ByteField("reserved", 0),
+ ByteField("os_type_and_version", 0)]
+
+# Second part of the header
+class Uberlogger_uber_h(Packet):
+ name = "Uberlogger uber_h"
+ fields_desc = [ByteEnumField("syscall_type", 0, uberlogger_sys_calls),
+ IntField("time_sec", 0),
+ IntField("time_usec", 0),
+ IntField("pid", 0),
+ IntField("uid", 0),
+ IntField("euid", 0),
+ IntField("cap_effective", 0),
+ IntField("cap_inheritable", 0),
+ IntField("cap_permitted", 0),
+ IntField("res", 0),
+ IntField("length", 0)]
+
+# The 9 following classes are options depending on the syscall type
+class Uberlogger_capget_data(Packet):
+ name = "Uberlogger capget_data"
+ fields_desc = [IntField("target_pid", 0)]
+
+class Uberlogger_capset_data(Packet):
+ name = "Uberlogger capset_data"
+ fields_desc = [IntField("target_pid", 0),
+ IntField("effective_cap", 0),
+ IntField("permitted_cap", 0),
+ IntField("inheritable_cap", 0)]
+
+class Uberlogger_chmod_data(Packet):
+ name = "Uberlogger chmod_data"
+ fields_desc = [ShortField("mode", 0)]
+
+class Uberlogger_chown_data(Packet):
+ name = "Uberlogger chown_data"
+ fields_desc = [IntField("uid", 0),
+ IntField("gid", 0)]
+
+class Uberlogger_open_data(Packet):
+ name = "Uberlogger open_data"
+ fields_desc = [IntField("flags", 0),
+ IntField("mode", 0)]
+
+class Uberlogger_read_data(Packet):
+ name = "Uberlogger read_data"
+ fields_desc = [IntField("fd", 0),
+ IntField("count", 0)]
+
+class Uberlogger_setuid_data(Packet):
+ name = "Uberlogger setuid_data"
+ fields_desc = [IntField("uid", 0)]
+
+class Uberlogger_create_module_data(Packet):
+ name = "Uberlogger create_module_data"
+ fields_desc = [IntField("size", 0)]
+
+class Uberlogger_execve_data(Packet):
+ name = "Uberlogger execve_data"
+ fields_desc = [IntField("nbarg", 0)]
+
+# Layer bounds for Uberlogger
+bind_layers(Uberlogger_honeypot_caract,Uberlogger_uber_h)
+bind_layers(Uberlogger_uber_h,Uberlogger_capget_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_capset_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_chmod_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_chown_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_open_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_read_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_setuid_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_create_module_data)
+bind_layers(Uberlogger_uber_h,Uberlogger_execve_data)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vqp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vqp.py
new file mode 100644
index 00000000..9328cea4
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vqp.py
@@ -0,0 +1,58 @@
+
+# http://trac.secdev.org/scapy/ticket/147
+
+# scapy.contrib.description = VLAN Query Protocol
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+
+class VQP(Packet):
+ name = "VQP"
+ fields_desc = [
+ ByteField("const", 1),
+ ByteEnumField("type", 1, {
+ 1:"requestPort", 2:"responseVLAN",
+ 3:"requestReconfirm", 4:"responseReconfirm"
+ }),
+ ByteEnumField("errorcodeaction", 0, {
+ 0:"none",3:"accessDenied",
+ 4:"shutdownPort", 5:"wrongDomain"
+ }),
+ ByteEnumField("unknown", 2, {
+ 2:"inGoodResponse", 6:"inRequests"
+ }),
+ IntField("seq",0),
+ ]
+
+class VQPEntry(Packet):
+ name = "VQPEntry"
+ fields_desc = [
+ IntEnumField("datatype", 0, {
+ 3073:"clientIPAddress", 3074:"portName",
+ 3075:"VLANName", 3076:"Domain", 3077:"ethernetPacket",
+ 3078:"ReqMACAddress", 3079:"unknown",
+ 3080:"ResMACAddress"
+ }),
+ FieldLenField("len", None),
+ ConditionalField(IPField("datatom", "0.0.0.0"),
+ lambda p:p.datatype==3073),
+ ConditionalField(MACField("data", "00:00:00:00:00:00"),
+ lambda p:p.datatype==3078),
+ ConditionalField(MACField("data", "00:00:00:00:00:00"),
+ lambda p:p.datatype==3080),
+ ConditionalField(StrLenField("data", None,
+ length_from=lambda p:p.len),
+ lambda p:p.datatype not in [3073, 3078, 3080]),
+ ]
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p.data)
+ p = p[:2]+struct.pack("!H",l)+p[4:]
+ return p
+
+bind_layers(UDP, VQP, sport=1589)
+bind_layers(UDP, VQP, dport=1589)
+bind_layers(VQP, VQPEntry, )
+bind_layers(VQPEntry, VQPEntry, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vtp.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vtp.py
new file mode 100644
index 00000000..af5c2823
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/vtp.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+# scapy.contrib.description = VLAN Trunking Protocol (VTP)
+# scapy.contrib.status = loads
+
+"""
+ VTP Scapy Extension
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ :version: 2009-02-15
+ :copyright: 2009 by Jochen Bartl
+ :e-mail: lobo@c3a.de / jochen.bartl@gmail.com
+ :license: GPL v2
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ :TODO
+
+ - Join messages
+ - RE MD5 hash calculation
+ - Have a closer look at 8 byte padding in summary adv.
+ "debug sw-vlan vtp packets" sais the TLV length is invalid,
+ when I change the values
+ '\x00\x00\x00\x01\x06\x01\x00\x02'
+ * \x00\x00 ?
+ * \x00\x01 tlvtype?
+ * \x06 length?
+ * \x00\x02 value?
+ - h2i function for VTPTimeStampField
+
+ :References:
+
+ - Understanding VLAN Trunk Protocol (VTP)
+ http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml
+"""
+
+from scapy.all import *
+
+_VTP_VLAN_TYPE = {
+ 1 : 'Ethernet',
+ 2 : 'FDDI',
+ 3 : 'TrCRF',
+ 4 : 'FDDI-net',
+ 5 : 'TrBRF'
+ }
+
+_VTP_VLANINFO_TLV_TYPE = {
+ 0x01 : 'Source-Routing Ring Number',
+ 0x02 : 'Source-Routing Bridge Number',
+ 0x03 : 'Spanning-Tree Protocol Type',
+ 0x04 : 'Parent VLAN',
+ 0x05 : 'Translationally Bridged VLANs',
+ 0x06 : 'Pruning',
+ 0x07 : 'Bridge Type',
+ 0x08 : 'Max ARE Hop Count',
+ 0x09 : 'Max STE Hop Count',
+ 0x0A : 'Backup CRF Mode'
+ }
+
+
+class VTPVlanInfoTlv(Packet):
+ name = "VTP VLAN Info TLV"
+ fields_desc = [
+ ByteEnumField("type", 0, _VTP_VLANINFO_TLV_TYPE),
+ ByteField("length", 0),
+ StrLenField("value", None, length_from=lambda pkt : pkt.length + 1)
+ ]
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+class VTPVlanInfo(Packet):
+ name = "VTP VLAN Info"
+ fields_desc = [
+ ByteField("len", None), # FIXME: compute length
+ ByteEnumField("status", 0, {0 : "active", 1 : "suspended"}),
+ ByteEnumField("type", 1, _VTP_VLAN_TYPE),
+ FieldLenField("vlannamelen", None, "vlanname", "B"),
+ ShortField("vlanid", 1),
+ ShortField("mtu", 1500),
+ XIntField("dot10index", None),
+ StrLenField("vlanname", "default", length_from=lambda pkt:4 * ((pkt.vlannamelen + 3) / 4)),
+ ConditionalField(PacketListField("tlvlist", [], VTPVlanInfoTlv,
+ length_from=lambda pkt:pkt.len - 12 - (4 * ((pkt.vlannamelen + 3) / 4))),
+ lambda pkt:pkt.type not in [1, 2])
+ ]
+
+ def post_build(self, p, pay):
+ vlannamelen = 4 * ((len(self.vlanname) + 3) / 4)
+
+ if self.len == None:
+ l = vlannamelen + 12
+ p = chr(l & 0xff) + p[1:]
+
+ # Pad vlan name with zeros if vlannamelen > len(vlanname)
+ l = vlannamelen - len(self.vlanname)
+ if l != 0:
+ p += "\x00" * l
+
+ p += pay
+
+ return p
+
+ def guess_payload_class(self, p):
+ return conf.padding_layer
+
+_VTP_Types = {
+ 1 : 'Summary Advertisement',
+ 2 : 'Subset Advertisements',
+ 3 : 'Advertisement Request',
+ 4 : 'Join'
+ }
+
+class VTPTimeStampField(StrFixedLenField):
+ def __init__(self, name, default):
+ StrFixedLenField.__init__(self, name, default, 12)
+
+ def i2repr(self, pkt, x):
+ return "%s-%s-%s %s:%s:%s" % (x[:2], x[2:4], x[4:6], x[6:8], x[8:10], x[10:12])
+
+class VTP(Packet):
+ name = "VTP"
+ fields_desc = [
+ ByteField("ver", 2),
+ ByteEnumField("code", 1, _VTP_Types),
+ ConditionalField(ByteField("followers", 1),
+ lambda pkt:pkt.code == 1),
+ ConditionalField(ByteField("seq", 1),
+ lambda pkt:pkt.code == 2),
+ ConditionalField(ByteField("reserved", 0),
+ lambda pkt:pkt.code == 3),
+ ByteField("domnamelen", None),
+ StrFixedLenField("domname", "manbearpig", 32),
+ ConditionalField(SignedIntField("rev", 0),
+ lambda pkt:pkt.code == 1 or
+ pkt.code == 2),
+ # updater identity
+ ConditionalField(IPField("uid", "192.168.0.1"),
+ lambda pkt:pkt.code == 1),
+ ConditionalField(VTPTimeStampField("timestamp", '930301000000'),
+ lambda pkt:pkt.code == 1),
+ ConditionalField(StrFixedLenField("md5", "\x00" * 16, 16),
+ lambda pkt:pkt.code == 1),
+ ConditionalField(
+ PacketListField("vlaninfo", [], VTPVlanInfo),
+ lambda pkt: pkt.code == 2),
+ ConditionalField(ShortField("startvalue", 0),
+ lambda pkt:pkt.code == 3)
+ ]
+
+ def post_build(self, p, pay):
+ if self.domnamelen == None:
+ domnamelen = len(self.domname.strip("\x00"))
+ p = p[:3] + chr(domnamelen & 0xff) + p[4:]
+
+ p += pay
+
+ return p
+
+bind_layers(SNAP, VTP, code=0x2003)
+
+if __name__ == '__main__':
+ interact(mydict=globals(), mybanner="VTP")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/contrib/wpa_eapol.py b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/wpa_eapol.py
new file mode 100644
index 00000000..084eedd8
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/contrib/wpa_eapol.py
@@ -0,0 +1,35 @@
+
+# http://trac.secdev.org/scapy/ticket/104
+
+# scapy.contrib.description = WPA EAPOL dissector
+# scapy.contrib.status = loads
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import *
+
+class WPA_key(Packet):
+ name = "WPA_key"
+ fields_desc = [ ByteField("descriptor_type", 1),
+ ShortField("key_info",0),
+ LenField("len", None, "H"),
+ StrFixedLenField("replay_counter", "", 8),
+ StrFixedLenField("nonce", "", 32),
+ StrFixedLenField("key_iv", "", 16),
+ StrFixedLenField("wpa_key_rsc", "", 8),
+ StrFixedLenField("wpa_key_id", "", 8),
+ StrFixedLenField("wpa_key_mic", "", 16),
+ LenField("wpa_key_length", None, "H"),
+ StrLenField("wpa_key", "", length_from=lambda pkt:pkt.wpa_key_length) ]
+ def extract_padding(self, s):
+ l = self.len
+ return s[:l],s[l:]
+ def hashret(self):
+ return chr(self.type)+self.payload.hashret()
+ def answers(self, other):
+ if isinstance(other,WPA_key):
+ return 1
+ return 0
+
+
+bind_layers( EAPOL, WPA_key, type=3)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/crypto/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/crypto/__init__.py
new file mode 100644
index 00000000..b441863e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/crypto/__init__.py
@@ -0,0 +1,17 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Arnaud Ebalard <arno@natisbad.org>
+## This program is published under a GPLv2 license
+
+"""
+Tools for handling with digital certificates.
+"""
+
+try:
+ import Crypto
+except ImportError:
+ import logging
+ log_loading = logging.getLogger("scapy.loading")
+ log_loading.info("Can't import python Crypto lib. Disabled certificate manipulation tools")
+else:
+ from scapy.crypto.cert import *
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/crypto/cert.py b/scripts/external_libs/scapy-python3-0.18/scapy/crypto/cert.py
new file mode 100644
index 00000000..c4291059
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/crypto/cert.py
@@ -0,0 +1,2486 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Arnaud Ebalard <arno@natisbad.org>
+## This program is published under a GPLv2 license
+
+"""
+Cryptographic certificates.
+"""
+
+import os, sys, math, socket, struct, hmac, string, time, random, tempfile
+from subprocess import Popen, PIPE
+from scapy.utils import strxor
+try:
+ HAS_HASHLIB=True
+ import hashlib
+except:
+ HAS_HASHLIB=False
+
+from Crypto.PublicKey import *
+from Crypto.Cipher import *
+from Crypto.Hash import *
+from Crypto.Util import number
+
+# Maximum allowed size in bytes for a certificate file, to avoid
+# loading huge file when importing a cert
+MAX_KEY_SIZE=50*1024
+MAX_CERT_SIZE=50*1024
+MAX_CRL_SIZE=10*1024*1024 # some are that big
+
+#####################################################################
+# Some helpers
+#####################################################################
+
+def popen3(cmd):
+ p = Popen(cmd, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE,
+ close_fds=True)
+ return p.stdout, p.stdin, p.stderr
+
+def warning(m):
+ print("WARNING: %s" % m)
+
+def randstring(l):
+ """
+ Returns a random string of length l (l >= 0)
+ """
+ tmp = map(lambda x: struct.pack("B", random.randrange(0, 256, 1)), [""]*l)
+ return "".join(tmp)
+
+def zerofree_randstring(l):
+ """
+ Returns a random string of length l (l >= 0) without zero in it.
+ """
+ tmp = map(lambda x: struct.pack("B", random.randrange(1, 256, 1)), [""]*l)
+ return "".join(tmp)
+
+def strand(s1, s2):
+ """
+ Returns the binary AND of the 2 provided strings s1 and s2. s1 and s2
+ must be of same length.
+ """
+ return "".join(map(lambda x,y:chr(ord(x)&ord(y)), s1, s2))
+
+# OS2IP function defined in RFC 3447 for octet string to integer conversion
+def pkcs_os2ip(x):
+ """
+ Accepts a byte string as input parameter and return the associated long
+ value:
+
+ Input : x octet string to be converted
+
+ Output: x corresponding nonnegative integer
+
+ Reverse function is pkcs_i2osp()
+ """
+ return number.bytes_to_long(x)
+
+# IP2OS function defined in RFC 3447 for octet string to integer conversion
+def pkcs_i2osp(x,xLen):
+ """
+ Converts a long (the first parameter) to the associated byte string
+ representation of length l (second parameter). Basically, the length
+ parameters allow the function to perform the associated padding.
+
+ Input : x nonnegative integer to be converted
+ xLen intended length of the resulting octet string
+
+ Output: x corresponding nonnegative integer
+
+ Reverse function is pkcs_os2ip().
+ """
+ z = number.long_to_bytes(x)
+ padlen = max(0, xLen-len(z))
+ return '\x00'*padlen + z
+
+# for every hash function a tuple is provided, giving access to
+# - hash output length in byte
+# - associated hash function that take data to be hashed as parameter
+# XXX I do not provide update() at the moment.
+# - DER encoding of the leading bits of digestInfo (the hash value
+# will be concatenated to create the complete digestInfo).
+#
+# Notes:
+# - MD4 asn.1 value should be verified. Also, as stated in
+# PKCS#1 v2.1, MD4 should not be used.
+# - hashlib is available from http://code.krypto.org/python/hashlib/
+# - 'tls' one is the concatenation of both md5 and sha1 hashes used
+# by SSL/TLS when signing/verifying things
+_hashFuncParams = {
+ "md2" : (16,
+ lambda x: MD2.new(x).digest(),
+ '\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10'),
+ "md4" : (16,
+ lambda x: MD4.new(x).digest(),
+ '\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04\x05\x00\x04\x10'), # is that right ?
+ "md5" : (16,
+ lambda x: MD5.new(x).digest(),
+ '\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10'),
+ "sha1" : (20,
+ lambda x: SHA.new(x).digest(),
+ '\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14'),
+ "tls" : (36,
+ lambda x: MD5.new(x).digest() + SHA.new(x).digest(),
+ '') }
+
+if HAS_HASHLIB:
+ _hashFuncParams["sha224"] = (28,
+ lambda x: hashlib.sha224(x).digest(),
+ '\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c')
+ _hashFuncParams["sha256"] = (32,
+ lambda x: hashlib.sha256(x).digest(),
+ '\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20')
+ _hashFuncParams["sha384"] = (48,
+ lambda x: hashlib.sha384(x).digest(),
+ '\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30')
+ _hashFuncParams["sha512"] = (64,
+ lambda x: hashlib.sha512(x).digest(),
+ '\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40')
+else:
+ warning("hashlib support is not available. Consider installing it")
+ warning("if you need sha224, sha256, sha384 and sha512 algs.")
+
+def pkcs_mgf1(mgfSeed, maskLen, h):
+ """
+ Implements generic MGF1 Mask Generation function as described in
+ Appendix B.2.1 of RFC 3447. The hash function is passed by name.
+ valid values are 'md2', 'md4', 'md5', 'sha1', 'tls, 'sha256',
+ 'sha384' and 'sha512'. Returns None on error.
+
+ Input:
+ mgfSeed: seed from which mask is generated, an octet string
+ maskLen: intended length in octets of the mask, at most 2^32 * hLen
+ hLen (see below)
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). hLen denotes the length in octets of
+ the hash function output.
+
+ Output:
+ an octet string of length maskLen
+ """
+
+ # steps are those of Appendix B.2.1
+ if not h in _hashFuncParams:
+ warning("pkcs_mgf1: invalid hash (%s) provided")
+ return None
+ hLen = _hashFuncParams[h][0]
+ hFunc = _hashFuncParams[h][1]
+ if maskLen > 2**32 * hLen: # 1)
+ warning("pkcs_mgf1: maskLen > 2**32 * hLen")
+ return None
+ T = "" # 2)
+ maxCounter = math.ceil(float(maskLen) / float(hLen)) # 3)
+ counter = 0
+ while counter < maxCounter:
+ C = pkcs_i2osp(counter, 4)
+ T += hFunc(mgfSeed + C)
+ counter += 1
+ return T[:maskLen]
+
+
+def pkcs_emsa_pss_encode(M, emBits, h, mgf, sLen):
+ """
+ Implements EMSA-PSS-ENCODE() function described in Sect. 9.1.1 of RFC 3447
+
+ Input:
+ M : message to be encoded, an octet string
+ emBits: maximal bit length of the integer resulting of pkcs_os2ip(EM),
+ where EM is the encoded message, output of the function.
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). hLen denotes the length in octets of
+ the hash function output.
+ mgf : the mask generation function f : seed, maskLen -> mask
+ sLen : intended length in octets of the salt
+
+ Output:
+ encoded message, an octet string of length emLen = ceil(emBits/8)
+
+ On error, None is returned.
+ """
+
+ # 1) is not done
+ hLen = _hashFuncParams[h][0] # 2)
+ hFunc = _hashFuncParams[h][1]
+ mHash = hFunc(M)
+ emLen = int(math.ceil(emBits/8.))
+ if emLen < hLen + sLen + 2: # 3)
+ warning("encoding error (emLen < hLen + sLen + 2)")
+ return None
+ salt = randstring(sLen) # 4)
+ MPrime = '\x00'*8 + mHash + salt # 5)
+ H = hFunc(MPrime) # 6)
+ PS = '\x00'*(emLen - sLen - hLen - 2) # 7)
+ DB = PS + '\x01' + salt # 8)
+ dbMask = mgf(H, emLen - hLen - 1) # 9)
+ maskedDB = strxor(DB, dbMask) # 10)
+ l = (8*emLen - emBits)/8 # 11)
+ rem = 8*emLen - emBits - 8*l # additionnal bits
+ andMask = l*'\x00'
+ if rem:
+ j = chr(reduce(lambda x,y: x+y, map(lambda x: 1<<x, range(8-rem))))
+ andMask += j
+ l += 1
+ maskedDB = strand(maskedDB[:l], andMask) + maskedDB[l:]
+ EM = maskedDB + H + '\xbc' # 12)
+ return EM # 13)
+
+
+def pkcs_emsa_pss_verify(M, EM, emBits, h, mgf, sLen):
+ """
+ Implements EMSA-PSS-VERIFY() function described in Sect. 9.1.2 of RFC 3447
+
+ Input:
+ M : message to be encoded, an octet string
+ EM : encoded message, an octet string of length emLen = ceil(emBits/8)
+ emBits: maximal bit length of the integer resulting of pkcs_os2ip(EM)
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). hLen denotes the length in octets of
+ the hash function output.
+ mgf : the mask generation function f : seed, maskLen -> mask
+ sLen : intended length in octets of the salt
+
+ Output:
+ True if the verification is ok, False otherwise.
+ """
+
+ # 1) is not done
+ hLen = _hashFuncParams[h][0] # 2)
+ hFunc = _hashFuncParams[h][1]
+ mHash = hFunc(M)
+ emLen = int(math.ceil(emBits/8.)) # 3)
+ if emLen < hLen + sLen + 2:
+ return False
+ if EM[-1] != '\xbc': # 4)
+ return False
+ l = emLen - hLen - 1 # 5)
+ maskedDB = EM[:l]
+ H = EM[l:l+hLen]
+ l = (8*emLen - emBits)/8 # 6)
+ rem = 8*emLen - emBits - 8*l # additionnal bits
+ andMask = l*'\xff'
+ if rem:
+ val = reduce(lambda x,y: x+y, map(lambda x: 1<<x, range(8-rem)))
+ j = chr(~val & 0xff)
+ andMask += j
+ l += 1
+ if strand(maskedDB[:l], andMask) != '\x00'*l:
+ return False
+ dbMask = mgf(H, emLen - hLen - 1) # 7)
+ DB = strxor(maskedDB, dbMask) # 8)
+ l = (8*emLen - emBits)/8 # 9)
+ rem = 8*emLen - emBits - 8*l # additionnal bits
+ andMask = l*'\x00'
+ if rem:
+ j = chr(reduce(lambda x,y: x+y, map(lambda x: 1<<x, range(8-rem))))
+ andMask += j
+ l += 1
+ DB = strand(DB[:l], andMask) + DB[l:]
+ l = emLen - hLen - sLen - 1 # 10)
+ if DB[:l] != '\x00'*(l-1) + '\x01':
+ return False
+ salt = DB[-sLen:] # 11)
+ MPrime = '\x00'*8 + mHash + salt # 12)
+ HPrime = hFunc(MPrime) # 13)
+ return H == HPrime # 14)
+
+
+def pkcs_emsa_pkcs1_v1_5_encode(M, emLen, h): # section 9.2 of RFC 3447
+ """
+ Implements EMSA-PKCS1-V1_5-ENCODE() function described in Sect.
+ 9.2 of RFC 3447.
+
+ Input:
+ M : message to be encode, an octet string
+ emLen: intended length in octets of the encoded message, at least
+ tLen + 11, where tLen is the octet length of the DER encoding
+ T of a certain value computed during the encoding operation.
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). hLen denotes the length in octets of
+ the hash function output.
+
+ Output:
+ encoded message, an octet string of length emLen
+
+ On error, None is returned.
+ """
+ hLen = _hashFuncParams[h][0] # 1)
+ hFunc = _hashFuncParams[h][1]
+ H = hFunc(M)
+ hLeadingDigestInfo = _hashFuncParams[h][2] # 2)
+ T = hLeadingDigestInfo + H
+ tLen = len(T)
+ if emLen < tLen + 11: # 3)
+ warning("pkcs_emsa_pkcs1_v1_5_encode: intended encoded message length too short")
+ return None
+ PS = '\xff'*(emLen - tLen - 3) # 4)
+ EM = '\x00' + '\x01' + PS + '\x00' + T # 5)
+ return EM # 6)
+
+
+# XXX should add other pgf1 instance in a better fashion.
+
+def create_ca_file(anchor_list, filename):
+ """
+ Concatenate all the certificates (PEM format for the export) in
+ 'anchor_list' and write the result to file 'filename'. On success
+ 'filename' is returned, None otherwise.
+
+ If you are used to OpenSSL tools, this function builds a CAfile
+ that can be used for certificate and CRL check.
+
+ Also see create_temporary_ca_file().
+ """
+ try:
+ f = open(filename, "w")
+ for a in anchor_list:
+ s = a.output(fmt="PEM")
+ f.write(s)
+ f.close()
+ except:
+ return None
+ return filename
+
+def create_temporary_ca_file(anchor_list):
+ """
+ Concatenate all the certificates (PEM format for the export) in
+ 'anchor_list' and write the result to file to a temporary file
+ using mkstemp() from tempfile module. On success 'filename' is
+ returned, None otherwise.
+
+ If you are used to OpenSSL tools, this function builds a CAfile
+ that can be used for certificate and CRL check.
+
+ Also see create_temporary_ca_file().
+ """
+ try:
+ f, fname = tempfile.mkstemp()
+ for a in anchor_list:
+ s = a.output(fmt="PEM")
+ l = os.write(f, s)
+ os.close(f)
+ except:
+ return None
+ return fname
+
+def create_temporary_ca_path(anchor_list, folder):
+ """
+ Create a CA path folder as defined in OpenSSL terminology, by
+ storing all certificates in 'anchor_list' list in PEM format
+ under provided 'folder' and then creating the associated links
+ using the hash as usually done by c_rehash.
+
+ Note that you can also include CRL in 'anchor_list'. In that
+ case, they will also be stored under 'folder' and associated
+ links will be created.
+
+ In folder, the files are created with names of the form
+ 0...ZZ.pem. If you provide an empty list, folder will be created
+ if it does not already exist, but that's all.
+
+ The number of certificates written to folder is returned on
+ success, None on error.
+ """
+ # We should probably avoid writing duplicate anchors and also
+ # check if they are all certs.
+ try:
+ if not os.path.isdir(folder):
+ os.makedirs(folder)
+ except:
+ return None
+
+ l = len(anchor_list)
+ if l == 0:
+ return None
+ fmtstr = "%%0%sd.pem" % math.ceil(math.log(l, 10))
+ i = 0
+ try:
+ for a in anchor_list:
+ fname = os.path.join(folder, fmtstr % i)
+ f = open(fname, "w")
+ s = a.output(fmt="PEM")
+ f.write(s)
+ f.close()
+ i += 1
+ except:
+ return None
+
+ r,w,e=popen3(["c_rehash", folder])
+ r.close(); w.close(); e.close()
+
+ return l
+
+
+#####################################################################
+# Public Key Cryptography related stuff
+#####################################################################
+
+class OSSLHelper:
+ def _apply_ossl_cmd(self, osslcmd, rawdata):
+ r,w,e=popen3(osslcmd)
+ w.write(rawdata)
+ w.close()
+ res = r.read()
+ r.close()
+ e.close()
+ return res
+
+class _EncryptAndVerify:
+ ### Below are encryption methods
+
+ def _rsaep(self, m):
+ """
+ Internal method providing raw RSA encryption, i.e. simple modular
+ exponentiation of the given message representative 'm', a long
+ between 0 and n-1.
+
+ This is the encryption primitive RSAEP described in PKCS#1 v2.1,
+ i.e. RFC 3447 Sect. 5.1.1.
+
+ Input:
+ m: message representative, a long between 0 and n-1, where
+ n is the key modulus.
+
+ Output:
+ ciphertext representative, a long between 0 and n-1
+
+ Not intended to be used directly. Please, see encrypt() method.
+ """
+
+ n = self.modulus
+ if type(m) is int:
+ m = long(m)
+ if type(m) is not long or m > n-1:
+ warning("Key._rsaep() expects a long between 0 and n-1")
+ return None
+
+ return self.key.encrypt(m, "")[0]
+
+
+ def _rsaes_pkcs1_v1_5_encrypt(self, M):
+ """
+ Implements RSAES-PKCS1-V1_5-ENCRYPT() function described in section
+ 7.2.1 of RFC 3447.
+
+ Input:
+ M: message to be encrypted, an octet string of length mLen, where
+ mLen <= k - 11 (k denotes the length in octets of the key modulus)
+
+ Output:
+ ciphertext, an octet string of length k
+
+ On error, None is returned.
+ """
+
+ # 1) Length checking
+ mLen = len(M)
+ k = self.modulusLen / 8
+ if mLen > k - 11:
+ warning("Key._rsaes_pkcs1_v1_5_encrypt(): message too "
+ "long (%d > %d - 11)" % (mLen, k))
+ return None
+
+ # 2) EME-PKCS1-v1_5 encoding
+ PS = zerofree_randstring(k - mLen - 3) # 2.a)
+ EM = '\x00' + '\x02' + PS + '\x00' + M # 2.b)
+
+ # 3) RSA encryption
+ m = pkcs_os2ip(EM) # 3.a)
+ c = self._rsaep(m) # 3.b)
+ C = pkcs_i2osp(c, k) # 3.c)
+
+ return C # 4)
+
+
+ def _rsaes_oaep_encrypt(self, M, h=None, mgf=None, L=None):
+ """
+ Internal method providing RSAES-OAEP-ENCRYPT as defined in Sect.
+ 7.1.1 of RFC 3447. Not intended to be used directly. Please, see
+ encrypt() method for type "OAEP".
+
+
+ Input:
+ M : message to be encrypted, an octet string of length mLen
+ where mLen <= k - 2*hLen - 2 (k denotes the length in octets
+ of the RSA modulus and hLen the length in octets of the hash
+ function output)
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). hLen denotes the length in octets of
+ the hash function output. 'sha1' is used by default if not
+ provided.
+ mgf: the mask generation function f : seed, maskLen -> mask
+ L : optional label to be associated with the message; the default
+ value for L, if not provided is the empty string
+
+ Output:
+ ciphertext, an octet string of length k
+
+ On error, None is returned.
+ """
+ # The steps below are the one described in Sect. 7.1.1 of RFC 3447.
+ # 1) Length Checking
+ # 1.a) is not done
+ mLen = len(M)
+ if h is None:
+ h = "sha1"
+ if not h in _hashFuncParams:
+ warning("Key._rsaes_oaep_encrypt(): unknown hash function %s.", h)
+ return None
+ hLen = _hashFuncParams[h][0]
+ hFun = _hashFuncParams[h][1]
+ k = self.modulusLen / 8
+ if mLen > k - 2*hLen - 2: # 1.b)
+ warning("Key._rsaes_oaep_encrypt(): message too long.")
+ return None
+
+ # 2) EME-OAEP encoding
+ if L is None: # 2.a)
+ L = ""
+ lHash = hFun(L)
+ PS = '\x00'*(k - mLen - 2*hLen - 2) # 2.b)
+ DB = lHash + PS + '\x01' + M # 2.c)
+ seed = randstring(hLen) # 2.d)
+ if mgf is None: # 2.e)
+ mgf = lambda x,y: pkcs_mgf1(x,y,h)
+ dbMask = mgf(seed, k - hLen - 1)
+ maskedDB = strxor(DB, dbMask) # 2.f)
+ seedMask = mgf(maskedDB, hLen) # 2.g)
+ maskedSeed = strxor(seed, seedMask) # 2.h)
+ EM = '\x00' + maskedSeed + maskedDB # 2.i)
+
+ # 3) RSA Encryption
+ m = pkcs_os2ip(EM) # 3.a)
+ c = self._rsaep(m) # 3.b)
+ C = pkcs_i2osp(c, k) # 3.c)
+
+ return C # 4)
+
+
+ def encrypt(self, m, t=None, h=None, mgf=None, L=None):
+ """
+ Encrypt message 'm' using 't' encryption scheme where 't' can be:
+
+ - None: the message 'm' is directly applied the RSAEP encryption
+ primitive, as described in PKCS#1 v2.1, i.e. RFC 3447
+ Sect 5.1.1. Simply put, the message undergo a modular
+ exponentiation using the public key. Additionnal method
+ parameters are just ignored.
+
+ - 'pkcs': the message 'm' is applied RSAES-PKCS1-V1_5-ENCRYPT encryption
+ scheme as described in section 7.2.1 of RFC 3447. In that
+ context, other parameters ('h', 'mgf', 'l') are not used.
+
+ - 'oaep': the message 'm' is applied the RSAES-OAEP-ENCRYPT encryption
+ scheme, as described in PKCS#1 v2.1, i.e. RFC 3447 Sect
+ 7.1.1. In that context,
+
+ o 'h' parameter provides the name of the hash method to use.
+ Possible values are "md2", "md4", "md5", "sha1", "tls",
+ "sha224", "sha256", "sha384" and "sha512". if none is provided,
+ sha1 is used.
+
+ o 'mgf' is the mask generation function. By default, mgf
+ is derived from the provided hash function using the
+ generic MGF1 (see pkcs_mgf1() for details).
+
+ o 'L' is the optional label to be associated with the
+ message. If not provided, the default value is used, i.e
+ the empty string. No check is done on the input limitation
+ of the hash function regarding the size of 'L' (for
+ instance, 2^61 - 1 for SHA-1). You have been warned.
+ """
+
+ if t is None: # Raw encryption
+ m = pkcs_os2ip(m)
+ c = self._rsaep(m)
+ return pkcs_i2osp(c, self.modulusLen/8)
+
+ elif t == "pkcs":
+ return self._rsaes_pkcs1_v1_5_encrypt(m)
+
+ elif t == "oaep":
+ return self._rsaes_oaep_encrypt(m, h, mgf, L)
+
+ else:
+ warning("Key.encrypt(): Unknown encryption type (%s) provided" % t)
+ return None
+
+ ### Below are verification related methods
+
+ def _rsavp1(self, s):
+ """
+ Internal method providing raw RSA verification, i.e. simple modular
+ exponentiation of the given signature representative 'c', an integer
+ between 0 and n-1.
+
+ This is the signature verification primitive RSAVP1 described in
+ PKCS#1 v2.1, i.e. RFC 3447 Sect. 5.2.2.
+
+ Input:
+ s: signature representative, an integer between 0 and n-1,
+ where n is the key modulus.
+
+ Output:
+ message representative, an integer between 0 and n-1
+
+ Not intended to be used directly. Please, see verify() method.
+ """
+ return self._rsaep(s)
+
+ def _rsassa_pss_verify(self, M, S, h=None, mgf=None, sLen=None):
+ """
+ Implements RSASSA-PSS-VERIFY() function described in Sect 8.1.2
+ of RFC 3447
+
+ Input:
+ M: message whose signature is to be verified
+ S: signature to be verified, an octet string of length k, where k
+ is the length in octets of the RSA modulus n.
+
+ Output:
+ True is the signature is valid. False otherwise.
+ """
+
+ # Set default parameters if not provided
+ if h is None: # By default, sha1
+ h = "sha1"
+ if not h in _hashFuncParams:
+ warning("Key._rsassa_pss_verify(): unknown hash function "
+ "provided (%s)" % h)
+ return False
+ if mgf is None: # use mgf1 with underlying hash function
+ mgf = lambda x,y: pkcs_mgf1(x, y, h)
+ if sLen is None: # use Hash output length (A.2.3 of RFC 3447)
+ hLen = _hashFuncParams[h][0]
+ sLen = hLen
+
+ # 1) Length checking
+ modBits = self.modulusLen
+ k = modBits / 8
+ if len(S) != k:
+ return False
+
+ # 2) RSA verification
+ s = pkcs_os2ip(S) # 2.a)
+ m = self._rsavp1(s) # 2.b)
+ emLen = math.ceil((modBits - 1) / 8.) # 2.c)
+ EM = pkcs_i2osp(m, emLen)
+
+ # 3) EMSA-PSS verification
+ Result = pkcs_emsa_pss_verify(M, EM, modBits - 1, h, mgf, sLen)
+
+ return Result # 4)
+
+
+ def _rsassa_pkcs1_v1_5_verify(self, M, S, h):
+ """
+ Implements RSASSA-PKCS1-v1_5-VERIFY() function as described in
+ Sect. 8.2.2 of RFC 3447.
+
+ Input:
+ M: message whose signature is to be verified, an octet string
+ S: signature to be verified, an octet string of length k, where
+ k is the length in octets of the RSA modulus n
+ h: hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384').
+
+ Output:
+ True if the signature is valid. False otherwise.
+ """
+
+ # 1) Length checking
+ k = self.modulusLen / 8
+ if len(S) != k:
+ warning("invalid signature (len(S) != k)")
+ return False
+
+ # 2) RSA verification
+ s = pkcs_os2ip(S) # 2.a)
+ m = self._rsavp1(s) # 2.b)
+ EM = pkcs_i2osp(m, k) # 2.c)
+
+ # 3) EMSA-PKCS1-v1_5 encoding
+ EMPrime = pkcs_emsa_pkcs1_v1_5_encode(M, k, h)
+ if EMPrime is None:
+ warning("Key._rsassa_pkcs1_v1_5_verify(): unable to encode.")
+ return False
+
+ # 4) Comparison
+ return EM == EMPrime
+
+
+ def verify(self, M, S, t=None, h=None, mgf=None, sLen=None):
+ """
+ Verify alleged signature 'S' is indeed the signature of message 'M' using
+ 't' signature scheme where 't' can be:
+
+ - None: the alleged signature 'S' is directly applied the RSAVP1 signature
+ primitive, as described in PKCS#1 v2.1, i.e. RFC 3447 Sect
+ 5.2.1. Simply put, the provided signature is applied a moular
+ exponentiation using the public key. Then, a comparison of the
+ result is done against 'M'. On match, True is returned.
+ Additionnal method parameters are just ignored.
+
+ - 'pkcs': the alleged signature 'S' and message 'M' are applied
+ RSASSA-PKCS1-v1_5-VERIFY signature verification scheme as
+ described in Sect. 8.2.2 of RFC 3447. In that context,
+ the hash function name is passed using 'h'. Possible values are
+ "md2", "md4", "md5", "sha1", "tls", "sha224", "sha256", "sha384"
+ and "sha512". If none is provided, sha1 is used. Other additionnal
+ parameters are ignored.
+
+ - 'pss': the alleged signature 'S' and message 'M' are applied
+ RSASSA-PSS-VERIFY signature scheme as described in Sect. 8.1.2.
+ of RFC 3447. In that context,
+
+ o 'h' parameter provides the name of the hash method to use.
+ Possible values are "md2", "md4", "md5", "sha1", "tls", "sha224",
+ "sha256", "sha384" and "sha512". if none is provided, sha1
+ is used.
+
+ o 'mgf' is the mask generation function. By default, mgf
+ is derived from the provided hash function using the
+ generic MGF1 (see pkcs_mgf1() for details).
+
+ o 'sLen' is the length in octet of the salt. You can overload the
+ default value (the octet length of the hash value for provided
+ algorithm) by providing another one with that parameter.
+ """
+ if t is None: # RSAVP1
+ S = pkcs_os2ip(S)
+ n = self.modulus
+ if S > n-1:
+ warning("Signature to be verified is too long for key modulus")
+ return False
+ m = self._rsavp1(S)
+ if m is None:
+ return False
+ l = int(math.ceil(math.log(m, 2) / 8.)) # Hack
+ m = pkcs_i2osp(m, l)
+ return M == m
+
+ elif t == "pkcs": # RSASSA-PKCS1-v1_5-VERIFY
+ if h is None:
+ h = "sha1"
+ return self._rsassa_pkcs1_v1_5_verify(M, S, h)
+
+ elif t == "pss": # RSASSA-PSS-VERIFY
+ return self._rsassa_pss_verify(M, S, h, mgf, sLen)
+
+ else:
+ warning("Key.verify(): Unknown signature type (%s) provided" % t)
+ return None
+
+class _DecryptAndSignMethods(OSSLHelper):
+ ### Below are decryption related methods. Encryption ones are inherited
+ ### from PubKey
+
+ def _rsadp(self, c):
+ """
+ Internal method providing raw RSA decryption, i.e. simple modular
+ exponentiation of the given ciphertext representative 'c', a long
+ between 0 and n-1.
+
+ This is the decryption primitive RSADP described in PKCS#1 v2.1,
+ i.e. RFC 3447 Sect. 5.1.2.
+
+ Input:
+ c: ciphertest representative, a long between 0 and n-1, where
+ n is the key modulus.
+
+ Output:
+ ciphertext representative, a long between 0 and n-1
+
+ Not intended to be used directly. Please, see encrypt() method.
+ """
+
+ n = self.modulus
+ if type(c) is int:
+ c = long(c)
+ if type(c) is not long or c > n-1:
+ warning("Key._rsaep() expects a long between 0 and n-1")
+ return None
+
+ return self.key.decrypt(c)
+
+
+ def _rsaes_pkcs1_v1_5_decrypt(self, C):
+ """
+ Implements RSAES-PKCS1-V1_5-DECRYPT() function described in section
+ 7.2.2 of RFC 3447.
+
+ Input:
+ C: ciphertext to be decrypted, an octet string of length k, where
+ k is the length in octets of the RSA modulus n.
+
+ Output:
+ an octet string of length k at most k - 11
+
+ on error, None is returned.
+ """
+
+ # 1) Length checking
+ cLen = len(C)
+ k = self.modulusLen / 8
+ if cLen != k or k < 11:
+ warning("Key._rsaes_pkcs1_v1_5_decrypt() decryption error "
+ "(cLen != k or k < 11)")
+ return None
+
+ # 2) RSA decryption
+ c = pkcs_os2ip(C) # 2.a)
+ m = self._rsadp(c) # 2.b)
+ EM = pkcs_i2osp(m, k) # 2.c)
+
+ # 3) EME-PKCS1-v1_5 decoding
+
+ # I am aware of the note at the end of 7.2.2 regarding error
+ # conditions reporting but the one provided below are for _local_
+ # debugging purposes. --arno
+
+ if EM[0] != '\x00':
+ warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
+ "(first byte is not 0x00)")
+ return None
+
+ if EM[1] != '\x02':
+ warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
+ "(second byte is not 0x02)")
+ return None
+
+ tmp = EM[2:].split('\x00', 1)
+ if len(tmp) != 2:
+ warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
+ "(no 0x00 to separate PS from M)")
+ return None
+
+ PS, M = tmp
+ if len(PS) < 8:
+ warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
+ "(PS is less than 8 byte long)")
+ return None
+
+ return M # 4)
+
+
+ def _rsaes_oaep_decrypt(self, C, h=None, mgf=None, L=None):
+ """
+ Internal method providing RSAES-OAEP-DECRYPT as defined in Sect.
+ 7.1.2 of RFC 3447. Not intended to be used directly. Please, see
+ encrypt() method for type "OAEP".
+
+
+ Input:
+ C : ciphertext to be decrypted, an octet string of length k, where
+ k = 2*hLen + 2 (k denotes the length in octets of the RSA modulus
+ and hLen the length in octets of the hash function output)
+ h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+ 'sha256', 'sha384'). 'sha1' is used if none is provided.
+ mgf: the mask generation function f : seed, maskLen -> mask
+ L : optional label whose association with the message is to be
+ verified; the default value for L, if not provided is the empty
+ string.
+
+ Output:
+ message, an octet string of length k mLen, where mLen <= k - 2*hLen - 2
+
+ On error, None is returned.
+ """
+ # The steps below are the one described in Sect. 7.1.2 of RFC 3447.
+
+ # 1) Length Checking
+ # 1.a) is not done
+ if h is None:
+ h = "sha1"
+ if not h in _hashFuncParams:
+ warning("Key._rsaes_oaep_decrypt(): unknown hash function %s.", h)
+ return None
+ hLen = _hashFuncParams[h][0]
+ hFun = _hashFuncParams[h][1]
+ k = self.modulusLen / 8
+ cLen = len(C)
+ if cLen != k: # 1.b)
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(cLen != k)")
+ return None
+ if k < 2*hLen + 2:
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(k < 2*hLen + 2)")
+ return None
+
+ # 2) RSA decryption
+ c = pkcs_os2ip(C) # 2.a)
+ m = self._rsadp(c) # 2.b)
+ EM = pkcs_i2osp(m, k) # 2.c)
+
+ # 3) EME-OAEP decoding
+ if L is None: # 3.a)
+ L = ""
+ lHash = hFun(L)
+ Y = EM[:1] # 3.b)
+ if Y != '\x00':
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(Y is not zero)")
+ return None
+ maskedSeed = EM[1:1+hLen]
+ maskedDB = EM[1+hLen:]
+ if mgf is None:
+ mgf = lambda x,y: pkcs_mgf1(x, y, h)
+ seedMask = mgf(maskedDB, hLen) # 3.c)
+ seed = strxor(maskedSeed, seedMask) # 3.d)
+ dbMask = mgf(seed, k - hLen - 1) # 3.e)
+ DB = strxor(maskedDB, dbMask) # 3.f)
+
+ # I am aware of the note at the end of 7.1.2 regarding error
+ # conditions reporting but the one provided below are for _local_
+ # debugging purposes. --arno
+
+ lHashPrime = DB[:hLen] # 3.g)
+ tmp = DB[hLen:].split('\x01', 1)
+ if len(tmp) != 2:
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(0x01 separator not found)")
+ return None
+ PS, M = tmp
+ if PS != '\x00'*len(PS):
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(invalid padding string)")
+ return None
+ if lHash != lHashPrime:
+ warning("Key._rsaes_oaep_decrypt(): decryption error. "
+ "(invalid hash)")
+ return None
+ return M # 4)
+
+
+ def decrypt(self, C, t=None, h=None, mgf=None, L=None):
+ """
+ Decrypt ciphertext 'C' using 't' decryption scheme where 't' can be:
+
+ - None: the ciphertext 'C' is directly applied the RSADP decryption
+ primitive, as described in PKCS#1 v2.1, i.e. RFC 3447
+ Sect 5.1.2. Simply, put the message undergo a modular
+ exponentiation using the private key. Additionnal method
+ parameters are just ignored.
+
+ - 'pkcs': the ciphertext 'C' is applied RSAES-PKCS1-V1_5-DECRYPT
+ decryption scheme as described in section 7.2.2 of RFC 3447.
+ In that context, other parameters ('h', 'mgf', 'l') are not
+ used.
+
+ - 'oaep': the ciphertext 'C' is applied the RSAES-OAEP-DECRYPT decryption
+ scheme, as described in PKCS#1 v2.1, i.e. RFC 3447 Sect
+ 7.1.2. In that context,
+
+ o 'h' parameter provides the name of the hash method to use.
+ Possible values are "md2", "md4", "md5", "sha1", "tls",
+ "sha224", "sha256", "sha384" and "sha512". if none is provided,
+ sha1 is used by default.
+
+ o 'mgf' is the mask generation function. By default, mgf
+ is derived from the provided hash function using the
+ generic MGF1 (see pkcs_mgf1() for details).
+
+ o 'L' is the optional label to be associated with the
+ message. If not provided, the default value is used, i.e
+ the empty string. No check is done on the input limitation
+ of the hash function regarding the size of 'L' (for
+ instance, 2^61 - 1 for SHA-1). You have been warned.
+ """
+ if t is None:
+ C = pkcs_os2ip(C)
+ c = self._rsadp(C)
+ l = int(math.ceil(math.log(c, 2) / 8.)) # Hack
+ return pkcs_i2osp(c, l)
+
+ elif t == "pkcs":
+ return self._rsaes_pkcs1_v1_5_decrypt(C)
+
+ elif t == "oaep":
+ return self._rsaes_oaep_decrypt(C, h, mgf, L)
+
+ else:
+ warning("Key.decrypt(): Unknown decryption type (%s) provided" % t)
+ return None
+
+ ### Below are signature related methods. Verification ones are inherited from
+ ### PubKey
+
+ def _rsasp1(self, m):
+ """
+ Internal method providing raw RSA signature, i.e. simple modular
+ exponentiation of the given message representative 'm', an integer
+ between 0 and n-1.
+
+ This is the signature primitive RSASP1 described in PKCS#1 v2.1,
+ i.e. RFC 3447 Sect. 5.2.1.
+
+ Input:
+ m: message representative, an integer between 0 and n-1, where
+ n is the key modulus.
+
+ Output:
+ signature representative, an integer between 0 and n-1
+
+ Not intended to be used directly. Please, see sign() method.
+ """
+ return self._rsadp(m)
+
+
+ def _rsassa_pss_sign(self, M, h=None, mgf=None, sLen=None):
+ """
+ Implements RSASSA-PSS-SIGN() function described in Sect. 8.1.1 of
+ RFC 3447.
+
+ Input:
+ M: message to be signed, an octet string
+
+ Output:
+ signature, an octet string of length k, where k is the length in
+ octets of the RSA modulus n.
+
+ On error, None is returned.
+ """
+
+ # Set default parameters if not provided
+ if h is None: # By default, sha1
+ h = "sha1"
+ if not h in _hashFuncParams:
+ warning("Key._rsassa_pss_sign(): unknown hash function "
+ "provided (%s)" % h)
+ return None
+ if mgf is None: # use mgf1 with underlying hash function
+ mgf = lambda x,y: pkcs_mgf1(x, y, h)
+ if sLen is None: # use Hash output length (A.2.3 of RFC 3447)
+ hLen = _hashFuncParams[h][0]
+ sLen = hLen
+
+ # 1) EMSA-PSS encoding
+ modBits = self.modulusLen
+ k = modBits / 8
+ EM = pkcs_emsa_pss_encode(M, modBits - 1, h, mgf, sLen)
+ if EM is None:
+ warning("Key._rsassa_pss_sign(): unable to encode")
+ return None
+
+ # 2) RSA signature
+ m = pkcs_os2ip(EM) # 2.a)
+ s = self._rsasp1(m) # 2.b)
+ S = pkcs_i2osp(s, k) # 2.c)
+
+ return S # 3)
+
+
+ def _rsassa_pkcs1_v1_5_sign(self, M, h):
+ """
+ Implements RSASSA-PKCS1-v1_5-SIGN() function as described in
+ Sect. 8.2.1 of RFC 3447.
+
+ Input:
+ M: message to be signed, an octet string
+ h: hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls'
+ 'sha256', 'sha384').
+
+ Output:
+ the signature, an octet string.
+ """
+
+ # 1) EMSA-PKCS1-v1_5 encoding
+ k = self.modulusLen / 8
+ EM = pkcs_emsa_pkcs1_v1_5_encode(M, k, h)
+ if EM is None:
+ warning("Key._rsassa_pkcs1_v1_5_sign(): unable to encode")
+ return None
+
+ # 2) RSA signature
+ m = pkcs_os2ip(EM) # 2.a)
+ s = self._rsasp1(m) # 2.b)
+ S = pkcs_i2osp(s, k) # 2.c)
+
+ return S # 3)
+
+
+ def sign(self, M, t=None, h=None, mgf=None, sLen=None):
+ """
+ Sign message 'M' using 't' signature scheme where 't' can be:
+
+ - None: the message 'M' is directly applied the RSASP1 signature
+ primitive, as described in PKCS#1 v2.1, i.e. RFC 3447 Sect
+ 5.2.1. Simply put, the message undergo a modular exponentiation
+ using the private key. Additionnal method parameters are just
+ ignored.
+
+ - 'pkcs': the message 'M' is applied RSASSA-PKCS1-v1_5-SIGN signature
+ scheme as described in Sect. 8.2.1 of RFC 3447. In that context,
+ the hash function name is passed using 'h'. Possible values are
+ "md2", "md4", "md5", "sha1", "tls", "sha224", "sha256", "sha384"
+ and "sha512". If none is provided, sha1 is used. Other additionnal
+ parameters are ignored.
+
+ - 'pss' : the message 'M' is applied RSASSA-PSS-SIGN signature scheme as
+ described in Sect. 8.1.1. of RFC 3447. In that context,
+
+ o 'h' parameter provides the name of the hash method to use.
+ Possible values are "md2", "md4", "md5", "sha1", "tls", "sha224",
+ "sha256", "sha384" and "sha512". if none is provided, sha1
+ is used.
+
+ o 'mgf' is the mask generation function. By default, mgf
+ is derived from the provided hash function using the
+ generic MGF1 (see pkcs_mgf1() for details).
+
+ o 'sLen' is the length in octet of the salt. You can overload the
+ default value (the octet length of the hash value for provided
+ algorithm) by providing another one with that parameter.
+ """
+
+ if t is None: # RSASP1
+ M = pkcs_os2ip(M)
+ n = self.modulus
+ if M > n-1:
+ warning("Message to be signed is too long for key modulus")
+ return None
+ s = self._rsasp1(M)
+ if s is None:
+ return None
+ return pkcs_i2osp(s, self.modulusLen/8)
+
+ elif t == "pkcs": # RSASSA-PKCS1-v1_5-SIGN
+ if h is None:
+ h = "sha1"
+ return self._rsassa_pkcs1_v1_5_sign(M, h)
+
+ elif t == "pss": # RSASSA-PSS-SIGN
+ return self._rsassa_pss_sign(M, h, mgf, sLen)
+
+ else:
+ warning("Key.sign(): Unknown signature type (%s) provided" % t)
+ return None
+
+
+def openssl_parse_RSA(fmt="PEM"):
+ return popen3(['openssl', 'rsa', '-text', '-pubin', '-inform', fmt, '-noout'])
+def openssl_convert_RSA(infmt="PEM", outfmt="DER"):
+ return ['openssl', 'rsa', '-pubin', '-inform', infmt, '-outform', outfmt]
+
+class PubKey(OSSLHelper, _EncryptAndVerify):
+ # Below are the fields we recognize in the -text output of openssl
+ # and from which we extract information. We expect them in that
+ # order. Number of spaces does matter.
+ possible_fields = [ "Modulus (",
+ "Exponent:" ]
+ possible_fields_count = len(possible_fields)
+
+ def __init__(self, keypath):
+ error_msg = "Unable to import key."
+
+ # XXX Temporary hack to use PubKey inside Cert
+ if type(keypath) is tuple:
+ e, m, mLen = keypath
+ self.modulus = m
+ self.modulusLen = mLen
+ self.pubExp = e
+ return
+
+ fields_dict = {}
+ for k in self.possible_fields:
+ fields_dict[k] = None
+
+ self.keypath = None
+ rawkey = None
+
+ if (not '\x00' in keypath) and os.path.isfile(keypath): # file
+ self.keypath = keypath
+ key_size = os.path.getsize(keypath)
+ if key_size > MAX_KEY_SIZE:
+ raise Exception(error_msg)
+ try:
+ f = open(keypath)
+ rawkey = f.read()
+ f.close()
+ except:
+ raise Exception(error_msg)
+ else:
+ rawkey = keypath
+
+ if rawkey is None:
+ raise Exception(error_msg)
+
+ self.rawkey = rawkey
+
+ key_header = "-----BEGIN PUBLIC KEY-----"
+ key_footer = "-----END PUBLIC KEY-----"
+ l = rawkey.split(key_header, 1)
+ if len(l) == 2: # looks like PEM
+ tmp = l[1]
+ l = tmp.split(key_footer, 1)
+ if len(l) == 2:
+ tmp = l[0]
+ rawkey = "%s%s%s\n" % (key_header, tmp, key_footer)
+ else:
+ raise Exception(error_msg)
+ r,w,e = openssl_parse_RSA("PEM")
+ w.write(rawkey)
+ w.close()
+ textkey = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res == '':
+ self.format = "PEM"
+ self.pemkey = rawkey
+ self.textkey = textkey
+ cmd = openssl_convert_RSA_cmd("PEM", "DER")
+ self.derkey = self._apply_ossl_cmd(cmd, rawkey)
+ else:
+ raise Exception(error_msg)
+ else: # not PEM, try DER
+ r,w,e = openssl_parse_RSA("DER")
+ w.write(rawkey)
+ w.close()
+ textkey = r.read()
+ r.close()
+ res = e.read()
+ if res == '':
+ self.format = "DER"
+ self.derkey = rawkey
+ self.textkey = textkey
+ cmd = openssl_convert_RSA_cmd("DER", "PEM")
+ self.pemkey = self._apply_ossl_cmd(cmd, rawkey)
+ cmd = openssl_convert_RSA_cmd("DER", "DER")
+ self.derkey = self._apply_ossl_cmd(cmd, rawkey)
+ else:
+ try: # Perhaps it is a cert
+ c = Cert(keypath)
+ except:
+ raise Exception(error_msg)
+ # TODO:
+ # Reconstruct a key (der and pem) and provide:
+ # self.format
+ # self.derkey
+ # self.pemkey
+ # self.textkey
+ # self.keypath
+
+ self.osslcmdbase = ['openssl', 'rsa', '-pubin', '-inform', self.format]
+
+ self.keypath = keypath
+
+ # Parse the -text output of openssl to make things available
+ l = self.textkey.split('\n', 1)
+ if len(l) != 2:
+ raise Exception(error_msg)
+ cur, tmp = l
+ i = 0
+ k = self.possible_fields[i] # Modulus (
+ cur = cur[len(k):] + '\n'
+ while k:
+ l = tmp.split('\n', 1)
+ if len(l) != 2: # Over
+ fields_dict[k] = cur
+ break
+ l, tmp = l
+
+ newkey = 0
+ # skip fields we have already seen, this is the purpose of 'i'
+ for j in range(i, self.possible_fields_count):
+ f = self.possible_fields[j]
+ if l.startswith(f):
+ fields_dict[k] = cur
+ cur = l[len(f):] + '\n'
+ k = f
+ newkey = 1
+ i = j+1
+ break
+ if newkey == 1:
+ continue
+ cur += l + '\n'
+
+ # modulus and modulus length
+ v = fields_dict["Modulus ("]
+ self.modulusLen = None
+ if v:
+ v, rem = v.split(' bit):', 1)
+ self.modulusLen = int(v)
+ rem = rem.replace('\n','').replace(' ','').replace(':','')
+ self.modulus = long(rem, 16)
+ if self.modulus is None:
+ raise Exception(error_msg)
+
+ # public exponent
+ v = fields_dict["Exponent:"]
+ self.pubExp = None
+ if v:
+ self.pubExp = long(v.split('(', 1)[0])
+ if self.pubExp is None:
+ raise Exception(error_msg)
+
+ self.key = RSA.construct((self.modulus, self.pubExp, ))
+
+ def __str__(self):
+ return self.derkey
+
+
+class Key(_DecryptAndSignMethods, _EncryptAndVerify):
+ # Below are the fields we recognize in the -text output of openssl
+ # and from which we extract information. We expect them in that
+ # order. Number of spaces does matter.
+ possible_fields = [ "Private-Key: (",
+ "modulus:",
+ "publicExponent:",
+ "privateExponent:",
+ "prime1:",
+ "prime2:",
+ "exponent1:",
+ "exponent2:",
+ "coefficient:" ]
+ possible_fields_count = len(possible_fields)
+
+ def __init__(self, keypath):
+ error_msg = "Unable to import key."
+
+ fields_dict = {}
+ for k in self.possible_fields:
+ fields_dict[k] = None
+
+ self.keypath = None
+ rawkey = None
+
+ if (not '\x00' in keypath) and os.path.isfile(keypath):
+ self.keypath = keypath
+ key_size = os.path.getsize(keypath)
+ if key_size > MAX_KEY_SIZE:
+ raise Exception(error_msg)
+ try:
+ f = open(keypath)
+ rawkey = f.read()
+ f.close()
+ except:
+ raise Exception(error_msg)
+ else:
+ rawkey = keypath
+
+ if rawkey is None:
+ raise Exception(error_msg)
+
+ self.rawkey = rawkey
+
+ # Let's try to get file format : PEM or DER.
+ fmtstr = 'openssl rsa -text -inform %s -noout'
+ convertstr = 'openssl rsa -inform %s -outform %s'
+ key_header = "-----BEGIN RSA PRIVATE KEY-----"
+ key_footer = "-----END RSA PRIVATE KEY-----"
+ l = rawkey.split(key_header, 1)
+ if len(l) == 2: # looks like PEM
+ tmp = l[1]
+ l = tmp.split(key_footer, 1)
+ if len(l) == 2:
+ tmp = l[0]
+ rawkey = "%s%s%s\n" % (key_header, tmp, key_footer)
+ else:
+ raise Exception(error_msg)
+ r,w,e = popen3((fmtstr % "PEM").split(" "))
+ w.write(rawkey)
+ w.close()
+ textkey = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res == '':
+ self.format = "PEM"
+ self.pemkey = rawkey
+ self.textkey = textkey
+ cmd = (convertstr % ("PEM", "DER")).split(" ")
+ self.derkey = self._apply_ossl_cmd(cmd, rawkey)
+ else:
+ raise Exception(error_msg)
+ else: # not PEM, try DER
+ r,w,e = popen3((fmtstr % "DER").split(" "))
+ w.write(rawkey)
+ w.close()
+ textkey = r.read()
+ r.close()
+ res = e.read()
+ if res == '':
+ self.format = "DER"
+ self.derkey = rawkey
+ self.textkey = textkey
+ cmd = (convertstr % ("DER", "PEM")).split(" ")
+ self.pemkey = self._apply_ossl_cmd(cmd, rawkey)
+ cmd = (convertstr % ("DER", "DER")).split(" ")
+ self.derkey = self._apply_ossl_cmd(cmd, rawkey)
+ else:
+ raise Exception(error_msg)
+
+ self.osslcmdbase = ['openssl', 'rsa', '-inform', self.format]
+
+ r,w,e = popen3(["openssl", "asn1parse", "-inform", "DER"])
+ w.write(self.derkey)
+ w.close()
+ self.asn1parsekey = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res != '':
+ raise Exception(error_msg)
+
+ self.keypath = keypath
+
+ # Parse the -text output of openssl to make things available
+ l = self.textkey.split('\n', 1)
+ if len(l) != 2:
+ raise Exception(error_msg)
+ cur, tmp = l
+ i = 0
+ k = self.possible_fields[i] # Private-Key: (
+ cur = cur[len(k):] + '\n'
+ while k:
+ l = tmp.split('\n', 1)
+ if len(l) != 2: # Over
+ fields_dict[k] = cur
+ break
+ l, tmp = l
+
+ newkey = 0
+ # skip fields we have already seen, this is the purpose of 'i'
+ for j in range(i, self.possible_fields_count):
+ f = self.possible_fields[j]
+ if l.startswith(f):
+ fields_dict[k] = cur
+ cur = l[len(f):] + '\n'
+ k = f
+ newkey = 1
+ i = j+1
+ break
+ if newkey == 1:
+ continue
+ cur += l + '\n'
+
+ # modulus length
+ v = fields_dict["Private-Key: ("]
+ self.modulusLen = None
+ if v:
+ self.modulusLen = int(v.split(' bit', 1)[0])
+ if self.modulusLen is None:
+ raise Exception(error_msg)
+
+ # public exponent
+ v = fields_dict["publicExponent:"]
+ self.pubExp = None
+ if v:
+ self.pubExp = long(v.split('(', 1)[0])
+ if self.pubExp is None:
+ raise Exception(error_msg)
+
+ tmp = {}
+ for k in ["modulus:", "privateExponent:", "prime1:", "prime2:",
+ "exponent1:", "exponent2:", "coefficient:"]:
+ v = fields_dict[k]
+ if v:
+ s = v.replace('\n', '').replace(' ', '').replace(':', '')
+ tmp[k] = long(s, 16)
+ else:
+ raise Exception(error_msg)
+
+ self.modulus = tmp["modulus:"]
+ self.privExp = tmp["privateExponent:"]
+ self.prime1 = tmp["prime1:"]
+ self.prime2 = tmp["prime2:"]
+ self.exponent1 = tmp["exponent1:"]
+ self.exponent2 = tmp["exponent2:"]
+ self.coefficient = tmp["coefficient:"]
+
+ self.key = RSA.construct((self.modulus, self.pubExp, self.privExp))
+
+ def __str__(self):
+ return self.derkey
+
+
+# We inherit from PubKey to get access to all encryption and verification
+# methods. To have that working, we simply need Cert to provide
+# modulusLen and key attribute.
+# XXX Yes, it is a hack.
+class Cert(OSSLHelper, _EncryptAndVerify):
+ # Below are the fields we recognize in the -text output of openssl
+ # and from which we extract information. We expect them in that
+ # order. Number of spaces does matter.
+ possible_fields = [ " Version:",
+ " Serial Number:",
+ " Signature Algorithm:",
+ " Issuer:",
+ " Not Before:",
+ " Not After :",
+ " Subject:",
+ " Public Key Algorithm:",
+ " Modulus (",
+ " Exponent:",
+ " X509v3 Subject Key Identifier:",
+ " X509v3 Authority Key Identifier:",
+ " keyid:",
+ " DirName:",
+ " serial:",
+ " X509v3 Basic Constraints:",
+ " X509v3 Key Usage:",
+ " X509v3 Extended Key Usage:",
+ " X509v3 CRL Distribution Points:",
+ " Authority Information Access:",
+ " Signature Algorithm:" ]
+ possible_fields_count = len(possible_fields)
+
+ def __init__(self, certpath):
+ error_msg = "Unable to import certificate."
+
+ fields_dict = {}
+ for k in self.possible_fields:
+ fields_dict[k] = None
+
+ self.certpath = None
+ rawcert = None
+
+ if (not '\x00' in certpath) and os.path.isfile(certpath): # file
+ self.certpath = certpath
+ cert_size = os.path.getsize(certpath)
+ if cert_size > MAX_CERT_SIZE:
+ raise Exception(error_msg)
+ try:
+ f = open(certpath)
+ rawcert = f.read()
+ f.close()
+ except:
+ raise Exception(error_msg)
+ else:
+ rawcert = certpath
+
+ if rawcert is None:
+ raise Exception(error_msg)
+
+ self.rawcert = rawcert
+
+ # Let's try to get file format : PEM or DER.
+ fmtstr = 'openssl x509 -text -inform %s -noout'
+ convertstr = 'openssl x509 -inform %s -outform %s'
+ cert_header = "-----BEGIN CERTIFICATE-----"
+ cert_footer = "-----END CERTIFICATE-----"
+ l = rawcert.split(cert_header, 1)
+ if len(l) == 2: # looks like PEM
+ tmp = l[1]
+ l = tmp.split(cert_footer, 1)
+ if len(l) == 2:
+ tmp = l[0]
+ rawcert = "%s%s%s\n" % (cert_header, tmp, cert_footer)
+ else:
+ raise Exception(error_msg)
+ r,w,e = popen3((fmtstr % "PEM").split(" "))
+ w.write(rawcert)
+ w.close()
+ textcert = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res == '':
+ self.format = "PEM"
+ self.pemcert = rawcert
+ self.textcert = textcert
+ cmd = (convertstr % ("PEM", "DER")).split(" ")
+ self.dercert = self._apply_ossl_cmd(cmd, rawcert)
+ else:
+ raise Exception(error_msg)
+ else: # not PEM, try DER
+ r,w,e = popen3((fmtstr % "DER").split(" "))
+ w.write(rawcert)
+ w.close()
+ textcert = r.read()
+ r.close()
+ res = e.read()
+ if res == '':
+ self.format = "DER"
+ self.dercert = rawcert
+ self.textcert = textcert
+ cmd = (convertstr % ("DER", "PEM")).split(" ")
+ self.pemcert = self._apply_ossl_cmd(cmd, rawcert)
+ cmd = (convertstr % ("DER", "DER")).split(" ")
+ self.dercert = self._apply_ossl_cmd(cmd, rawcert)
+ else:
+ raise Exception(error_msg)
+
+ self.osslcmdbase = ['openssl', 'x509', '-inform', self.format]
+
+ r,w,e = popen3('openssl asn1parse -inform DER'.split(' '))
+ w.write(self.dercert)
+ w.close()
+ self.asn1parsecert = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res != '':
+ raise Exception(error_msg)
+
+ # Grab _raw_ X509v3 Authority Key Identifier, if any.
+ tmp = self.asn1parsecert.split(":X509v3 Authority Key Identifier", 1)
+ self.authorityKeyID = None
+ if len(tmp) == 2:
+ tmp = tmp[1]
+ tmp = tmp.split("[HEX DUMP]:", 1)[1]
+ self.authorityKeyID=tmp.split('\n',1)[0]
+
+ # Grab _raw_ X509v3 Subject Key Identifier, if any.
+ tmp = self.asn1parsecert.split(":X509v3 Subject Key Identifier", 1)
+ self.subjectKeyID = None
+ if len(tmp) == 2:
+ tmp = tmp[1]
+ tmp = tmp.split("[HEX DUMP]:", 1)[1]
+ self.subjectKeyID=tmp.split('\n',1)[0]
+
+ # Get tbsCertificate using the worst hack. output of asn1parse
+ # looks like that:
+ #
+ # 0:d=0 hl=4 l=1298 cons: SEQUENCE
+ # 4:d=1 hl=4 l=1018 cons: SEQUENCE
+ # ...
+ #
+ l1,l2 = self.asn1parsecert.split('\n', 2)[:2]
+ hl1 = int(l1.split("hl=",1)[1].split("l=",1)[0])
+ rem = l2.split("hl=",1)[1]
+ hl2, rem = rem.split("l=",1)
+ hl2 = int(hl2)
+ l = int(rem.split("cons",1)[0])
+ self.tbsCertificate = self.dercert[hl1:hl1+hl2+l]
+
+ # Parse the -text output of openssl to make things available
+ tmp = self.textcert.split('\n', 2)[2]
+ l = tmp.split('\n', 1)
+ if len(l) != 2:
+ raise Exception(error_msg)
+ cur, tmp = l
+ i = 0
+ k = self.possible_fields[i] # Version:
+ cur = cur[len(k):] + '\n'
+ while k:
+ l = tmp.split('\n', 1)
+ if len(l) != 2: # Over
+ fields_dict[k] = cur
+ break
+ l, tmp = l
+
+ newkey = 0
+ # skip fields we have already seen, this is the purpose of 'i'
+ for j in range(i, self.possible_fields_count):
+ f = self.possible_fields[j]
+ if l.startswith(f):
+ fields_dict[k] = cur
+ cur = l[len(f):] + '\n'
+ k = f
+ newkey = 1
+ i = j+1
+ break
+ if newkey == 1:
+ continue
+ cur += l + '\n'
+
+ # version
+ v = fields_dict[" Version:"]
+ self.version = None
+ if v:
+ self.version = int(v[1:2])
+ if self.version is None:
+ raise Exception(error_msg)
+
+ # serial number
+ v = fields_dict[" Serial Number:"]
+ self.serial = None
+ if v:
+ v = v.replace('\n', '').strip()
+ if "0x" in v:
+ v = v.split("0x", 1)[1].split(')', 1)[0]
+ v = v.replace(':', '').upper()
+ if len(v) % 2:
+ v = '0' + v
+ self.serial = v
+ if self.serial is None:
+ raise Exception(error_msg)
+
+ # Signature Algorithm
+ v = fields_dict[" Signature Algorithm:"]
+ self.sigAlg = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.sigAlg = v
+ if self.sigAlg is None:
+ raise Exception(error_msg)
+
+ # issuer
+ v = fields_dict[" Issuer:"]
+ self.issuer = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.issuer = v
+ if self.issuer is None:
+ raise Exception(error_msg)
+
+ # not before
+ v = fields_dict[" Not Before:"]
+ self.notBefore_str = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.notBefore_str = v
+ if self.notBefore_str is None:
+ raise Exception(error_msg)
+ try:
+ self.notBefore = time.strptime(self.notBefore_str,
+ "%b %d %H:%M:%S %Y %Z")
+ except:
+ self.notBefore = time.strptime(self.notBefore_str,
+ "%b %d %H:%M:%S %Y")
+ self.notBefore_str_simple = time.strftime("%x", self.notBefore)
+
+ # not after
+ v = fields_dict[" Not After :"]
+ self.notAfter_str = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.notAfter_str = v
+ if self.notAfter_str is None:
+ raise Exception(error_msg)
+ try:
+ self.notAfter = time.strptime(self.notAfter_str,
+ "%b %d %H:%M:%S %Y %Z")
+ except:
+ self.notAfter = time.strptime(self.notAfter_str,
+ "%b %d %H:%M:%S %Y")
+ self.notAfter_str_simple = time.strftime("%x", self.notAfter)
+
+ # subject
+ v = fields_dict[" Subject:"]
+ self.subject = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.subject = v
+ if self.subject is None:
+ raise Exception(error_msg)
+
+ # Public Key Algorithm
+ v = fields_dict[" Public Key Algorithm:"]
+ self.pubKeyAlg = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.pubKeyAlg = v
+ if self.pubKeyAlg is None:
+ raise Exception(error_msg)
+
+ # Modulus
+ v = fields_dict[" Modulus ("]
+ self.modulus = None
+ if v:
+ v,t = v.split(' bit):',1)
+ self.modulusLen = int(v)
+ t = t.replace(' ', '').replace('\n', ''). replace(':', '')
+ self.modulus_hexdump = t
+ self.modulus = long(t, 16)
+ if self.modulus is None:
+ raise Exception(error_msg)
+
+ # Exponent
+ v = fields_dict[" Exponent:"]
+ self.exponent = None
+ if v:
+ v = v.split('(',1)[0]
+ self.exponent = long(v)
+ if self.exponent is None:
+ raise Exception(error_msg)
+
+ # Public Key instance
+ self.key = RSA.construct((self.modulus, self.exponent, ))
+
+ # Subject Key Identifier
+
+ # Authority Key Identifier: keyid, dirname and serial
+ self.authorityKeyID_keyid = None
+ self.authorityKeyID_dirname = None
+ self.authorityKeyID_serial = None
+ if self.authorityKeyID: # (hex version already done using asn1parse)
+ v = fields_dict[" keyid:"]
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip().replace(':', '')
+ self.authorityKeyID_keyid = v
+ v = fields_dict[" DirName:"]
+ if v:
+ v = v.split('\n',1)[0]
+ self.authorityKeyID_dirname = v
+ v = fields_dict[" serial:"]
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip().replace(':', '')
+ self.authorityKeyID_serial = v
+
+ # Basic constraints
+ self.basicConstraintsCritical = False
+ self.basicConstraints=None
+ v = fields_dict[" X509v3 Basic Constraints:"]
+ if v:
+ self.basicConstraints = {}
+ v,t = v.split('\n',2)[:2]
+ if "critical" in v:
+ self.basicConstraintsCritical = True
+ if "CA:" in t:
+ self.basicConstraints["CA"] = t.split('CA:')[1][:4] == "TRUE"
+ if "pathlen:" in t:
+ self.basicConstraints["pathlen"] = int(t.split('pathlen:')[1])
+
+ # X509v3 Key Usage
+ self.keyUsage = []
+ v = fields_dict[" X509v3 Key Usage:"]
+ if v:
+ # man 5 x509v3_config
+ ku_mapping = {"Digital Signature": "digitalSignature",
+ "Non Repudiation": "nonRepudiation",
+ "Key Encipherment": "keyEncipherment",
+ "Data Encipherment": "dataEncipherment",
+ "Key Agreement": "keyAgreement",
+ "Certificate Sign": "keyCertSign",
+ "CRL Sign": "cRLSign",
+ "Encipher Only": "encipherOnly",
+ "Decipher Only": "decipherOnly"}
+ v = v.split('\n',2)[1]
+ l = map(lambda x: x.strip(), v.split(','))
+ while l:
+ c = l.pop()
+ if c in ku_mapping:
+ self.keyUsage.append(ku_mapping[c])
+ else:
+ self.keyUsage.append(c) # Add it anyway
+ print("Found unknown X509v3 Key Usage: '%s'" % c)
+ print("Report it to arno (at) natisbad.org for addition")
+
+ # X509v3 Extended Key Usage
+ self.extKeyUsage = []
+ v = fields_dict[" X509v3 Extended Key Usage:"]
+ if v:
+ # man 5 x509v3_config:
+ eku_mapping = {"TLS Web Server Authentication": "serverAuth",
+ "TLS Web Client Authentication": "clientAuth",
+ "Code Signing": "codeSigning",
+ "E-mail Protection": "emailProtection",
+ "Time Stamping": "timeStamping",
+ "Microsoft Individual Code Signing": "msCodeInd",
+ "Microsoft Commercial Code Signing": "msCodeCom",
+ "Microsoft Trust List Signing": "msCTLSign",
+ "Microsoft Encrypted File System": "msEFS",
+ "Microsoft Server Gated Crypto": "msSGC",
+ "Netscape Server Gated Crypto": "nsSGC",
+ "IPSec End System": "iPsecEndSystem",
+ "IPSec Tunnel": "iPsecTunnel",
+ "IPSec User": "iPsecUser"}
+ v = v.split('\n',2)[1]
+ l = map(lambda x: x.strip(), v.split(','))
+ while l:
+ c = l.pop()
+ if c in eku_mapping:
+ self.extKeyUsage.append(eku_mapping[c])
+ else:
+ self.extKeyUsage.append(c) # Add it anyway
+ print("Found unknown X509v3 Extended Key Usage: '%s'" % c)
+ print("Report it to arno (at) natisbad.org for addition")
+
+ # CRL Distribution points
+ self.cRLDistributionPoints = []
+ v = fields_dict[" X509v3 CRL Distribution Points:"]
+ if v:
+ v = v.split("\n\n", 1)[0]
+ v = v.split("URI:")[1:]
+ self.CRLDistributionPoints = map(lambda x: x.strip(), v)
+
+ # Authority Information Access: list of tuples ("method", "location")
+ self.authorityInfoAccess = []
+ v = fields_dict[" Authority Information Access:"]
+ if v:
+ v = v.split("\n\n", 1)[0]
+ v = v.split("\n")[1:]
+ for e in v:
+ method, location = map(lambda x: x.strip(), e.split(" - ", 1))
+ self.authorityInfoAccess.append((method, location))
+
+ # signature field
+ v = fields_dict[" Signature Algorithm:" ]
+ self.sig = None
+ if v:
+ v = v.split('\n',1)[1]
+ v = v.replace(' ', '').replace('\n', '')
+ self.sig = "".join(map(lambda x: chr(int(x, 16)), v.split(':')))
+ self.sigLen = len(self.sig)
+ if self.sig is None:
+ raise Exception(error_msg)
+
+ def isIssuerCert(self, other):
+ """
+ True if 'other' issued 'self', i.e.:
+ - self.issuer == other.subject
+ - self is signed by other
+ """
+ # XXX should be done on raw values, instead of their textual repr
+ if self.issuer != other.subject:
+ return False
+
+ # Sanity check regarding modulus length and the
+ # signature length
+ keyLen = (other.modulusLen + 7)/8
+ if keyLen != self.sigLen:
+ return False
+
+ unenc = other.encrypt(self.sig) # public key encryption, i.e. decrypt
+
+ # XXX Check block type (00 or 01 and type of padding)
+ unenc = unenc[1:]
+ if not '\x00' in unenc:
+ return False
+ pos = unenc.index('\x00')
+ unenc = unenc[pos+1:]
+
+ found = None
+ for k in _hashFuncParams.keys():
+ if self.sigAlg.startswith(k):
+ found = k
+ break
+ if not found:
+ return False
+ hlen, hfunc, digestInfo = _hashFuncParams[k]
+
+ if len(unenc) != (hlen+len(digestInfo)):
+ return False
+
+ if not unenc.startswith(digestInfo):
+ return False
+
+ h = unenc[-hlen:]
+ myh = hfunc(self.tbsCertificate)
+
+ return h == myh
+
+ def chain(self, certlist):
+ """
+ Construct the chain of certificates leading from 'self' to the
+ self signed root using the certificates in 'certlist'. If the
+ list does not provide all the required certs to go to the root
+ the function returns a incomplete chain starting with the
+ certificate. This fact can be tested by tchecking if the last
+ certificate of the returned chain is self signed (if c is the
+ result, c[-1].isSelfSigned())
+ """
+ d = {}
+ for c in certlist:
+ # XXX we should check if we have duplicate
+ d[c.subject] = c
+ res = [self]
+ cur = self
+ while not cur.isSelfSigned():
+ if cur.issuer in d:
+ possible_issuer = d[cur.issuer]
+ if cur.isIssuerCert(possible_issuer):
+ res.append(possible_issuer)
+ cur = possible_issuer
+ else:
+ break
+ return res
+
+ def remainingDays(self, now=None):
+ """
+ Based on the value of notBefore field, returns the number of
+ days the certificate will still be valid. The date used for the
+ comparison is the current and local date, as returned by
+ time.localtime(), except if 'now' argument is provided another
+ one. 'now' argument can be given as either a time tuple or a string
+ representing the date. Accepted format for the string version
+ are:
+
+ - '%b %d %H:%M:%S %Y %Z' e.g. 'Jan 30 07:38:59 2008 GMT'
+ - '%m/%d/%y' e.g. '01/30/08' (less precise)
+
+ If the certificate is no more valid at the date considered, then,
+ a negative value is returned representing the number of days
+ since it has expired.
+
+ The number of days is returned as a float to deal with the unlikely
+ case of certificates that are still just valid.
+ """
+ if now is None:
+ now = time.localtime()
+ elif type(now) is str:
+ try:
+ if '/' in now:
+ now = time.strptime(now, '%m/%d/%y')
+ else:
+ now = time.strptime(now, '%b %d %H:%M:%S %Y %Z')
+ except:
+ warning("Bad time string provided '%s'. Using current time" % now)
+ now = time.localtime()
+
+ now = time.mktime(now)
+ nft = time.mktime(self.notAfter)
+ diff = (nft - now)/(24.*3600)
+ return diff
+
+
+ # return SHA-1 hash of cert embedded public key
+ # !! At the moment, the trailing 0 is in the hashed string if any
+ def keyHash(self):
+ m = self.modulus_hexdump
+ res = []
+ i = 0
+ l = len(m)
+ while i<l: # get a string version of modulus
+ res.append(struct.pack("B", int(m[i:i+2], 16)))
+ i += 2
+ return sha.new("".join(res)).digest()
+
+ def output(self, fmt="DER"):
+ if fmt == "DER":
+ return self.dercert
+ elif fmt == "PEM":
+ return self.pemcert
+ elif fmt == "TXT":
+ return self.textcert
+
+ def export(self, filename, fmt="DER"):
+ """
+ Export certificate in 'fmt' format (PEM, DER or TXT) to file 'filename'
+ """
+ f = open(filename, "wb")
+ f.write(self.output(fmt))
+ f.close()
+
+ def isSelfSigned(self):
+ """
+ Return True if the certificate is self signed:
+ - issuer and subject are the same
+ - the signature of the certificate is valid.
+ """
+ if self.issuer == self.subject:
+ return self.isIssuerCert(self)
+ return False
+
+ # Print main informations stored in certificate
+ def show(self):
+ print("Serial: %s" % self.serial)
+ print("Issuer: " + self.issuer)
+ print("Subject: " + self.subject)
+ print("Validity: %s to %s" % (self.notBefore_str_simple,
+ self.notAfter_str_simple))
+
+ def __repr__(self):
+ return "[X.509 Cert. Subject:%s, Issuer:%s]" % (self.subject, self.issuer)
+
+ def __str__(self):
+ return self.dercert
+
+ def verifychain(self, anchors, untrusted=None):
+ """
+ Perform verification of certificate chains for that certificate. The
+ behavior of verifychain method is mapped (and also based) on openssl
+ verify userland tool (man 1 verify).
+ A list of anchors is required. untrusted parameter can be provided
+ a list of untrusted certificates that can be used to reconstruct the
+ chain.
+
+ If you have a lot of certificates to verify against the same
+ list of anchor, consider constructing this list as a cafile
+ and use .verifychain_from_cafile() instead.
+ """
+ cafile = create_temporary_ca_file(anchors)
+ if not cafile:
+ return False
+ untrusted_file = None
+ if untrusted:
+ untrusted_file = create_temporary_ca_file(untrusted) # hack
+ if not untrusted_file:
+ os.unlink(cafile)
+ return False
+ res = self.verifychain_from_cafile(cafile,
+ untrusted_file=untrusted_file)
+ os.unlink(cafile)
+ if untrusted_file:
+ os.unlink(untrusted_file)
+ return res
+
+ def verifychain_from_cafile(self, cafile, untrusted_file=None):
+ """
+ Does the same job as .verifychain() but using the list of anchors
+ from the cafile. This is useful (because more efficient) if
+ you have a lot of certificates to verify do it that way: it
+ avoids the creation of a cafile from anchors at each call.
+
+ As for .verifychain(), a list of untrusted certificates can be
+ passed (as a file, this time)
+ """
+ cmd = ["openssl", "verify", "-CAfile", cafile]
+ if untrusted_file:
+ cmd += ["-untrusted", untrusted_file]
+ try:
+ pemcert = self.output(fmt="PEM")
+ cmdres = self._apply_ossl_cmd(cmd, pemcert)
+ except:
+ return False
+ return cmdres.endswith("\nOK\n") or cmdres.endswith(": OK\n")
+
+ def verifychain_from_capath(self, capath, untrusted_file=None):
+ """
+ Does the same job as .verifychain_from_cafile() but using the list
+ of anchors in capath directory. The directory should contain
+ certificates files in PEM format with associated links as
+ created using c_rehash utility (man c_rehash).
+
+ As for .verifychain_from_cafile(), a list of untrusted certificates
+ can be passed as a file (concatenation of the certificates in
+ PEM format)
+ """
+ cmd = ["openssl", "verify", "-CApath", capath]
+ if untrusted_file:
+ cmd += ["-untrusted", untrusted_file]
+ try:
+ pemcert = self.output(fmt="PEM")
+ cmdres = self._apply_ossl_cmd(cmd, pemcert)
+ except:
+ return False
+ return cmdres.endswith("\nOK\n") or cmdres.endswith(": OK\n")
+
+ def is_revoked(self, crl_list):
+ """
+ Given a list of trusted CRL (their signature has already been
+ verified with trusted anchors), this function returns True if
+ the certificate is marked as revoked by one of those CRL.
+
+ Note that if the Certificate was on hold in a previous CRL and
+ is now valid again in a new CRL and bot are in the list, it
+ will be considered revoked: this is because _all_ CRLs are
+ checked (not only the freshest) and revocation status is not
+ handled.
+
+ Also note that the check on the issuer is performed on the
+ Authority Key Identifier if available in _both_ the CRL and the
+ Cert. Otherwise, the issuers are simply compared.
+ """
+ for c in crl_list:
+ if (self.authorityKeyID is not None and
+ c.authorityKeyID is not None and
+ self.authorityKeyID == c.authorityKeyID):
+ return self.serial in map(lambda x: x[0], c.revoked_cert_serials)
+ elif (self.issuer == c.issuer):
+ return self.serial in map(lambda x: x[0], c.revoked_cert_serials)
+ return False
+
+def print_chain(l):
+ llen = len(l) - 1
+ if llen < 0:
+ return ""
+ c = l[llen]
+ llen -= 1
+ s = "_ "
+ if not c.isSelfSigned():
+ s = "_ ... [Missing Root]\n"
+ else:
+ s += "%s [Self Signed]\n" % c.subject
+ i = 1
+ while (llen != -1):
+ c = l[llen]
+ s += "%s\_ %s" % (" "*i, c.subject)
+ if llen != 0:
+ s += "\n"
+ i += 2
+ llen -= 1
+ print(s)
+
+# import popen2
+# a=popen3("openssl crl -text -inform DER -noout ", capturestderr=True)
+# a.tochild.write(open("samples/klasa1.crl").read())
+# a.tochild.close()
+# a.poll()
+
+class CRL(OSSLHelper):
+ # Below are the fields we recognize in the -text output of openssl
+ # and from which we extract information. We expect them in that
+ # order. Number of spaces does matter.
+ possible_fields = [ " Version",
+ " Signature Algorithm:",
+ " Issuer:",
+ " Last Update:",
+ " Next Update:",
+ " CRL extensions:",
+ " X509v3 Issuer Alternative Name:",
+ " X509v3 Authority Key Identifier:",
+ " keyid:",
+ " DirName:",
+ " serial:",
+ " X509v3 CRL Number:",
+ "Revoked Certificates:",
+ "No Revoked Certificates.",
+ " Signature Algorithm:" ]
+ possible_fields_count = len(possible_fields)
+
+ def __init__(self, crlpath):
+ error_msg = "Unable to import CRL."
+
+ fields_dict = {}
+ for k in self.possible_fields:
+ fields_dict[k] = None
+
+ self.crlpath = None
+ rawcrl = None
+
+ if (not '\x00' in crlpath) and os.path.isfile(crlpath):
+ self.crlpath = crlpath
+ cert_size = os.path.getsize(crlpath)
+ if cert_size > MAX_CRL_SIZE:
+ raise Exception(error_msg)
+ try:
+ f = open(crlpath)
+ rawcrl = f.read()
+ f.close()
+ except:
+ raise Exception(error_msg)
+ else:
+ rawcrl = crlpath
+
+ if rawcrl is None:
+ raise Exception(error_msg)
+
+ self.rawcrl = rawcrl
+
+ # Let's try to get file format : PEM or DER.
+ fmtstr = 'openssl crl -text -inform %s -noout'
+ convertstr = 'openssl crl -inform %s -outform %s'
+ crl_header = "-----BEGIN X509 CRL-----"
+ crl_footer = "-----END X509 CRL-----"
+ l = rawcrl.split(crl_header, 1)
+ if len(l) == 2: # looks like PEM
+ tmp = l[1]
+ l = tmp.split(crl_footer, 1)
+ if len(l) == 2:
+ tmp = l[0]
+ rawcrl = "%s%s%s\n" % (crl_header, tmp, crl_footer)
+ else:
+ raise Exception(error_msg)
+ r,w,e = popen3((fmtstr % "PEM").split(" "))
+ w.write(rawcrl)
+ w.close()
+ textcrl = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res == '':
+ self.format = "PEM"
+ self.pemcrl = rawcrl
+ self.textcrl = textcrl
+ cmd = (convertstr % ("PEM", "DER")).split(" ")
+ self.dercrl = self._apply_ossl_cmd(cmd, rawcrl)
+ else:
+ raise Exception(error_msg)
+ else: # not PEM, try DER
+ r,w,e = popen3((fmtstr % "DER").split(' '))
+ w.write(rawcrl)
+ w.close()
+ textcrl = r.read()
+ r.close()
+ res = e.read()
+ if res == '':
+ self.format = "DER"
+ self.dercrl = rawcrl
+ self.textcrl = textcrl
+ cmd = (convertstr % ("DER", "PEM")).split(" ")
+ self.pemcrl = self._apply_ossl_cmd(cmd, rawcrl)
+ cmd = (convertstr % ("DER", "DER")).split(" ")
+ self.dercrl = self._apply_ossl_cmd(cmd, rawcrl)
+ else:
+ raise Exception(error_msg)
+
+ self.osslcmdbase = ['openssl', 'crl', '-inform', self.format]
+
+ r,w,e = popen3(('openssl asn1parse -inform DER').split(" "))
+ w.write(self.dercrl)
+ w.close()
+ self.asn1parsecrl = r.read()
+ r.close()
+ res = e.read()
+ e.close()
+ if res != '':
+ raise Exception(error_msg)
+
+ # Grab _raw_ X509v3 Authority Key Identifier, if any.
+ tmp = self.asn1parsecrl.split(":X509v3 Authority Key Identifier", 1)
+ self.authorityKeyID = None
+ if len(tmp) == 2:
+ tmp = tmp[1]
+ tmp = tmp.split("[HEX DUMP]:", 1)[1]
+ self.authorityKeyID=tmp.split('\n',1)[0]
+
+ # Parse the -text output of openssl to make things available
+ tmp = self.textcrl.split('\n', 1)[1]
+ l = tmp.split('\n', 1)
+ if len(l) != 2:
+ raise Exception(error_msg)
+ cur, tmp = l
+ i = 0
+ k = self.possible_fields[i] # Version
+ cur = cur[len(k):] + '\n'
+ while k:
+ l = tmp.split('\n', 1)
+ if len(l) != 2: # Over
+ fields_dict[k] = cur
+ break
+ l, tmp = l
+
+ newkey = 0
+ # skip fields we have already seen, this is the purpose of 'i'
+ for j in range(i, self.possible_fields_count):
+ f = self.possible_fields[j]
+ if l.startswith(f):
+ fields_dict[k] = cur
+ cur = l[len(f):] + '\n'
+ k = f
+ newkey = 1
+ i = j+1
+ break
+ if newkey == 1:
+ continue
+ cur += l + '\n'
+
+ # version
+ v = fields_dict[" Version"]
+ self.version = None
+ if v:
+ self.version = int(v[1:2])
+ if self.version is None:
+ raise Exception(error_msg)
+
+ # signature algorithm
+ v = fields_dict[" Signature Algorithm:"]
+ self.sigAlg = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.sigAlg = v
+ if self.sigAlg is None:
+ raise Exception(error_msg)
+
+ # issuer
+ v = fields_dict[" Issuer:"]
+ self.issuer = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.issuer = v
+ if self.issuer is None:
+ raise Exception(error_msg)
+
+ # last update
+ v = fields_dict[" Last Update:"]
+ self.lastUpdate_str = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.lastUpdate_str = v
+ if self.lastUpdate_str is None:
+ raise Exception(error_msg)
+ self.lastUpdate = time.strptime(self.lastUpdate_str,
+ "%b %d %H:%M:%S %Y %Z")
+ self.lastUpdate_str_simple = time.strftime("%x", self.lastUpdate)
+
+ # next update
+ v = fields_dict[" Next Update:"]
+ self.nextUpdate_str = None
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip()
+ self.nextUpdate_str = v
+ if self.nextUpdate_str is None:
+ raise Exception(error_msg)
+ self.nextUpdate = time.strptime(self.nextUpdate_str,
+ "%b %d %H:%M:%S %Y %Z")
+ self.nextUpdate_str_simple = time.strftime("%x", self.nextUpdate)
+
+ # XXX Do something for Issuer Alternative Name
+
+ # Authority Key Identifier: keyid, dirname and serial
+ self.authorityKeyID_keyid = None
+ self.authorityKeyID_dirname = None
+ self.authorityKeyID_serial = None
+ if self.authorityKeyID: # (hex version already done using asn1parse)
+ v = fields_dict[" keyid:"]
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip().replace(':', '')
+ self.authorityKeyID_keyid = v
+ v = fields_dict[" DirName:"]
+ if v:
+ v = v.split('\n',1)[0]
+ self.authorityKeyID_dirname = v
+ v = fields_dict[" serial:"]
+ if v:
+ v = v.split('\n',1)[0]
+ v = v.strip().replace(':', '')
+ self.authorityKeyID_serial = v
+
+ # number
+ v = fields_dict[" X509v3 CRL Number:"]
+ self.number = None
+ if v:
+ v = v.split('\n',2)[1]
+ v = v.strip()
+ self.number = int(v)
+
+ # Get the list of serial numbers of revoked certificates
+ self.revoked_cert_serials = []
+ v = fields_dict["Revoked Certificates:"]
+ t = fields_dict["No Revoked Certificates."]
+ if (t is None and v is not None):
+ v = v.split("Serial Number: ")[1:]
+ for r in v:
+ s,d = r.split('\n', 1)
+ s = s.split('\n', 1)[0]
+ d = d.split("Revocation Date:", 1)[1]
+ d = time.strptime(d.strip(), "%b %d %H:%M:%S %Y %Z")
+ self.revoked_cert_serials.append((s,d))
+
+ # signature field
+ v = fields_dict[" Signature Algorithm:" ]
+ self.sig = None
+ if v:
+ v = v.split('\n',1)[1]
+ v = v.replace(' ', '').replace('\n', '')
+ self.sig = "".join(map(lambda x: chr(int(x, 16)), v.split(':')))
+ self.sigLen = len(self.sig)
+ if self.sig is None:
+ raise Exception(error_msg)
+
+ def __str__(self):
+ return self.dercrl
+
+ # Print main informations stored in CRL
+ def show(self):
+ print("Version: %d" % self.version)
+ print("sigAlg: " + self.sigAlg)
+ print("Issuer: " + self.issuer)
+ print("lastUpdate: %s" % self.lastUpdate_str_simple)
+ print("nextUpdate: %s" % self.nextUpdate_str_simple)
+
+ def verify(self, anchors):
+ """
+ Return True if the CRL is signed by one of the provided
+ anchors. False on error (invalid signature, missing anchorand, ...)
+ """
+ cafile = create_temporary_ca_file(anchors)
+ if cafile is None:
+ return False
+ try:
+ cmd = self.osslcmdbase + ["-noout", "-CAfile", cafile]
+ cmdres = self._apply_ossl_cmd(cmd, self.rawcrl)
+ except:
+ os.unlink(cafile)
+ return False
+ os.unlink(cafile)
+ return "verify OK" in cmdres
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/dadict.py b/scripts/external_libs/scapy-python3-0.18/scapy/dadict.py
new file mode 100644
index 00000000..0fdcc135
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/dadict.py
@@ -0,0 +1,91 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Direct Access dictionary.
+"""
+
+from .error import Scapy_Exception
+
+###############################
+## Direct Access dictionnary ##
+###############################
+
+def fixname(x):
+ if x and x[0] in "0123456789":
+ x = "n_"+x
+ return x.translate("________________________________________________0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz_____________________________________________________________________________________________________________________________________")
+
+
+class DADict_Exception(Scapy_Exception):
+ pass
+
+class DADict:
+ def __init__(self, _name="DADict", **kargs):
+ self._name=_name
+ self.__dict__.update(kargs)
+ def fixname(self,val):
+ return fixname(val)
+ def __contains__(self, val):
+ return val in self.__dict__
+ def __getitem__(self, attr):
+ return getattr(self, attr)
+ def __setitem__(self, attr, val):
+ return setattr(self, self.fixname(attr), val)
+ def __iter__(self):
+ #return iter(map(lambda (x,y):y,filter(lambda (x,y):x and x[0]!="_", self.__dict__.items())))
+ #return iter(map(lambda a:a[1],filter(lambda a:a[0] and a[0][0]!="_", self.__dict__.items())))
+ return iter([a[1] for a in self.__dict__.items() if a[0] and a[0][0]!=" "])
+ def _show(self):
+ for k in self.__dict__.keys():
+ if k and k[0] != "_":
+ print("%10s = %r" % (k,getattr(self,k)))
+ def __repr__(self):
+ #return "<%s/ %s>" % (self._name," ".join(filter(lambda x:x and x[0]!="_",self.__dict__.keys())))
+ return "<%s/ %s>" % (self._name," ".join([ x for x in self.__dict__.keys() if x and x[0]!="_"]))
+
+ def _branch(self, br, uniq=0):
+ if uniq and br._name in self:
+ raise DADict_Exception("DADict: [%s] already branched in [%s]" % (br._name, self._name))
+ self[br._name] = br
+
+ def _my_find(self, *args, **kargs):
+ if args and self._name not in args:
+ return False
+ for k in kargs:
+ if k not in self or self[k] != kargs[k]:
+ return False
+ return True
+
+ def _find(self, *args, **kargs):
+ return self._recurs_find((), *args, **kargs)
+ def _recurs_find(self, path, *args, **kargs):
+ if self in path:
+ return None
+ if self._my_find(*args, **kargs):
+ return self
+ for o in self:
+ if isinstance(o, DADict):
+ p = o._recurs_find(path+(self,), *args, **kargs)
+ if p is not None:
+ return p
+ return None
+ def _find_all(self, *args, **kargs):
+ return self._recurs_find_all((), *args, **kargs)
+ def _recurs_find_all(self, path, *args, **kargs):
+ r = []
+ if self in path:
+ return r
+ if self._my_find(*args, **kargs):
+ r.append(self)
+ for o in self:
+ if isinstance(o, DADict):
+ p = o._recurs_find_all(path+(self,), *args, **kargs)
+ r += p
+ return r
+ def keys(self):
+ #return filter(lambda x:x and x[0]!="_", self.__dict__.keys())
+ return [ x for x in self.__dict__.keys() if x and x[0]!="_" ]
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/data.py b/scripts/external_libs/scapy-python3-0.18/scapy/data.py
new file mode 100644
index 00000000..fc92ebe2
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/data.py
@@ -0,0 +1,215 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Global variables and functions for handling external data sets.
+"""
+
+import os,sys,re
+from .dadict import DADict
+from .error import log_loading
+
+############
+## Consts ##
+############
+
+ETHER_ANY = b"\x00"*6
+ETHER_BROADCAST = b"\xff"*6
+
+ETH_P_ALL = 3
+ETH_P_IP = 0x800
+ETH_P_ARP = 0x806
+ETH_P_IPV6 = 0x86dd
+
+# From net/if_arp.h
+ARPHDR_ETHER = 1
+ARPHDR_METRICOM = 23
+ARPHDR_PPP = 512
+ARPHDR_LOOPBACK = 772
+ARPHDR_TUN = 65534
+
+
+# From net/ipv6.h on Linux (+ Additions)
+IPV6_ADDR_UNICAST = 0x01
+IPV6_ADDR_MULTICAST = 0x02
+IPV6_ADDR_CAST_MASK = 0x0F
+IPV6_ADDR_LOOPBACK = 0x10
+IPV6_ADDR_GLOBAL = 0x00
+IPV6_ADDR_LINKLOCAL = 0x20
+IPV6_ADDR_SITELOCAL = 0x40 # deprecated since Sept. 2004 by RFC 3879
+IPV6_ADDR_SCOPE_MASK = 0xF0
+#IPV6_ADDR_COMPATv4 = 0x80 # deprecated; i.e. ::/96
+#IPV6_ADDR_MAPPED = 0x1000 # i.e.; ::ffff:0.0.0.0/96
+IPV6_ADDR_6TO4 = 0x0100 # Added to have more specific info (should be 0x0101 ?)
+IPV6_ADDR_UNSPECIFIED = 0x10000
+
+
+
+
+MTU = 0x7fff # a.k.a give me all you have
+
+WINDOWS=sys.platform.startswith("win")
+
+
+# file parsing to get some values :
+
+def load_protocols(filename):
+ spaces = re.compile("[ \t]+|\n")
+ dct = DADict(_name=filename)
+ try:
+ for l in open(filename):
+ try:
+ shrp = l.find("#")
+ if shrp >= 0:
+ l = l[:shrp]
+ l = l.strip()
+ if not l:
+ continue
+ lt = tuple(re.split(spaces, l))
+ if len(lt) < 2 or not lt[0]:
+ continue
+ dct[lt[0]] = int(lt[1])
+ except Exception as e:
+ log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e))
+ except IOError:
+ log_loading.info("Can't open %s file" % filename)
+ return dct
+
+def load_ethertypes(filename):
+ spaces = re.compile("[ \t]+|\n")
+ dct = DADict(_name=filename)
+ try:
+ f=open(filename)
+ for l in f:
+ try:
+ shrp = l.find("#")
+ if shrp >= 0:
+ l = l[:shrp]
+ l = l.strip()
+ if not l:
+ continue
+ lt = tuple(re.split(spaces, l))
+ if len(lt) < 2 or not lt[0]:
+ continue
+ dct[lt[0]] = int(lt[1], 16)
+ except Exception as e:
+ log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e))
+ f.close()
+ except IOError as msg:
+ pass
+ return dct
+
+def load_services(filename):
+ spaces = re.compile("[ \t]+|\n")
+ tdct=DADict(_name="%s-tcp"%filename)
+ udct=DADict(_name="%s-udp"%filename)
+ try:
+ f=open(filename)
+ for l in f:
+ try:
+ shrp = l.find("#")
+ if shrp >= 0:
+ l = l[:shrp]
+ l = l.strip()
+ if not l:
+ continue
+ lt = tuple(re.split(spaces, l))
+ if len(lt) < 2 or not lt[0]:
+ continue
+ if lt[1].endswith("/tcp"):
+ tdct[lt[0]] = int(lt[1].split('/')[0])
+ elif lt[1].endswith("/udp"):
+ udct[lt[0]] = int(lt[1].split('/')[0])
+ except Exception as e:
+ log_loading.warning("Couldn't file [%s]: line [%r] (%s)" % (filename,l,e))
+ f.close()
+ except IOError:
+ log_loading.info("Can't open /etc/services file")
+ return tdct,udct
+
+
+class ManufDA(DADict):
+ def fixname(self, val):
+ return val
+ def _get_manuf_couple(self, mac):
+ oui = ":".join(mac.split(":")[:3]).upper()
+ return self.__dict__.get(oui,(mac,mac))
+ def _get_manuf(self, mac):
+ return self._get_manuf_couple(mac)[1]
+ def _get_short_manuf(self, mac):
+ return self._get_manuf_couple(mac)[0]
+ def _resolve_MAC(self, mac):
+ oui = ":".join(mac.split(":")[:3]).upper()
+ if oui in self:
+ return ":".join([self[oui][0]]+ mac.split(":")[3:])
+ return mac
+
+
+
+
+def load_manuf(filename):
+ try:
+ manufdb=ManufDA(_name=filename)
+ for l in open(filename, "r", encoding = 'utf-8'):
+ try:
+ l = l.strip()
+ if not l or l.startswith("#"):
+ continue
+ oui,shrt=l.split()[:2]
+ i = l.find("#")
+ if i < 0:
+ lng=shrt
+ else:
+ lng = l[i+2:]
+ manufdb[oui] = shrt,lng
+ except Exception as e:
+ log_loading.warning("Couldn't parse one line from [%s] [%r] (%s)" % (filename, l, e))
+ except IOError:
+ #log_loading.warning("Couldn't open [%s] file" % filename)
+ pass
+ return manufdb
+
+
+
+if WINDOWS:
+ ETHER_TYPES=load_ethertypes("ethertypes")
+ IP_PROTOS=load_protocols(os.environ["SystemRoot"]+"\system32\drivers\etc\protocol")
+ TCP_SERVICES,UDP_SERVICES=load_services(os.environ["SystemRoot"] + "\system32\drivers\etc\services")
+ MANUFDB = load_manuf(os.environ["ProgramFiles"] + "\\wireshark\\manuf")
+else:
+ IP_PROTOS=load_protocols("/etc/protocols")
+ ETHER_TYPES=load_ethertypes("/etc/ethertypes")
+ TCP_SERVICES,UDP_SERVICES=load_services("/etc/services")
+ MANUFDB = load_manuf("/usr/share/wireshark/manuf")
+
+
+
+#####################
+## knowledge bases ##
+#####################
+
+class KnowledgeBase:
+ def __init__(self, filename):
+ self.filename = filename
+ self.base = None
+
+ def lazy_init(self):
+ self.base = ""
+
+ def reload(self, filename = None):
+ if filename is not None:
+ self.filename = filename
+ oldbase = self.base
+ self.base = None
+ self.lazy_init()
+ if self.base is None:
+ self.base = oldbase
+
+ def get_base(self):
+ if self.base is None:
+ self.lazy_init()
+ return self.base
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/error.py b/scripts/external_libs/scapy-python3-0.18/scapy/error.py
new file mode 100644
index 00000000..1753d523
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/error.py
@@ -0,0 +1,60 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Logging subsystem and basic exception class.
+"""
+
+#############################
+##### Logging subsystem #####
+#############################
+
+class Scapy_Exception(Exception):
+ pass
+
+import logging,traceback,time
+
+class ScapyFreqFilter(logging.Filter):
+ def __init__(self):
+ logging.Filter.__init__(self)
+ self.warning_table = {}
+ def filter(self, record):
+ from .config import conf
+ wt = conf.warning_threshold
+ if wt > 0:
+ stk = traceback.extract_stack()
+ caller=None
+ for f,l,n,c in stk:
+ if n == 'warning':
+ break
+ caller = l
+ tm,nb = self.warning_table.get(caller, (0,0))
+ ltm = time.time()
+ if ltm-tm > wt:
+ tm = ltm
+ nb = 0
+ else:
+ if nb < 2:
+ nb += 1
+ if nb == 2:
+ record.msg = "more "+record.msg
+ else:
+ return 0
+ self.warning_table[caller] = (tm,nb)
+ return 1
+
+log_scapy = logging.getLogger("scapy")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+log_scapy.addHandler(console_handler)
+log_runtime = logging.getLogger("scapy.runtime") # logs at runtime
+log_runtime.addFilter(ScapyFreqFilter())
+log_interactive = logging.getLogger("scapy.interactive") # logs in interactive functions
+log_loading = logging.getLogger("scapy.loading") # logs when loading scapy
+
+
+def warning(x):
+ log_runtime.warning(x)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/fields.py b/scripts/external_libs/scapy-python3-0.18/scapy/fields.py
new file mode 100644
index 00000000..5482ce87
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/fields.py
@@ -0,0 +1,935 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Fields: basic data structures that make up parts of packets.
+"""
+
+import struct,copy,socket
+from .config import conf
+from .volatile import *
+from .data import *
+from .utils import *
+from .base_classes import BasePacket,Gen,Net
+
+
+############
+## Fields ##
+############
+
+class Field:
+ """For more informations on how this work, please refer to
+ http://www.secdev.org/projects/scapy/files/scapydoc.pdf
+ chapter ``Adding a New Field''"""
+ islist=0
+ holds_packets=0
+ def __init__(self, name, default, fmt="H"):
+ self.name = name
+ if fmt[0] in "@=<>!":
+ self.fmt = fmt
+ else:
+ self.fmt = "!"+fmt
+ self.default = self.any2i(None,default)
+ self.sz = struct.calcsize(self.fmt)
+ self.owners = []
+ self.offset =0;
+
+
+ def get_size_bytes (self):
+ if hasattr(self, 'size'):
+ return 0; # bitfield
+ else:
+ return self.sz
+
+ def register_owner(self, cls):
+ self.owners.append(cls)
+
+ def i2len(self, pkt, x):
+ """Convert internal value to a length usable by a FieldLenField"""
+ return self.sz
+ def i2count(self, pkt, x):
+ """Convert internal value to a number of elements usable by a FieldLenField.
+ Always 1 except for list fields"""
+ return 1
+ def i2b(self, pkt, x):
+ """Convert internal value to internal value"""
+ if type(x) is str:
+ x = bytes([ ord(i) for i in x ])
+ return x
+ def h2i(self, pkt, x):
+ """Convert human value to internal value"""
+ if type(x) is str:
+ x = bytes([ ord(i) for i in x ])
+ return x
+ def i2h(self, pkt, x):
+ """Convert internal value to human value"""
+ return x
+ def m2i(self, pkt, x):
+ """Convert machine value to internal value"""
+ return x
+ def i2m(self, pkt, x):
+ """Convert internal value to machine value"""
+ if x is None:
+ x = 0
+ return x
+ def any2i(self, pkt, x):
+ """Try to understand the most input values possible and make an internal value from them"""
+ return self.h2i(pkt, x)
+ def i2repr(self, pkt, x):
+ """Convert internal value to a nice representation"""
+ return repr(self.i2h(pkt,x))
+ def addfield(self, pkt, s, val):
+ """Add an internal value to a string"""
+ return s+struct.pack(self.fmt, self.i2m(pkt,val))
+ def getfield(self, pkt, s):
+ """Extract an internal value from a string"""
+ return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
+ def do_copy(self, x):
+ if hasattr(x, "copy"):
+ return x.copy()
+ if type(x) is list:
+ x = x[:]
+ for i in range(len(x)):
+ if isinstance(x[i], BasePacket):
+ x[i] = x[i].copy()
+ return x
+ def __repr__(self):
+ return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name)
+ def copy(self):
+ return copy.deepcopy(self)
+ def randval(self):
+ """Return a volatile object whose value is both random and suitable for this field"""
+ fmtt = self.fmt[-1]
+ if fmtt in "BHIQ":
+ return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
+ elif fmtt == "s":
+ if self.fmt[0] in "0123456789":
+ l = int(self.fmt[:-1])
+ else:
+ l = int(self.fmt[1:-1])
+ return RandBin(l)
+ else:
+ warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt))
+
+
+
+
+class Emph:
+ fld = b""
+ def __init__(self, fld):
+ self.fld = fld
+ def __getattr__(self, attr):
+ return getattr(self.fld,attr)
+ def __hash__(self):
+ return hash(self.fld)
+ def __eq__(self, other):
+ return self.fld == other
+
+
+class ActionField:
+ _fld = None
+ def __init__(self, fld, action_method, **kargs):
+ self._fld = fld
+ self._action_method = action_method
+ self._privdata = kargs
+ def any2i(self, pkt, val):
+ getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
+ return getattr(self._fld, "any2i")(pkt, val)
+ def __getattr__(self, attr):
+ return getattr(self._fld,attr)
+
+
+class ConditionalField:
+ fld = None
+ def __init__(self, fld, cond):
+ self.fld = fld
+ self.cond = cond
+ def _evalcond(self,pkt):
+ return self.cond(pkt)
+
+ def getfield(self, pkt, s):
+ if self._evalcond(pkt):
+ return self.fld.getfield(pkt,s)
+ else:
+ return s,None
+
+ def addfield(self, pkt, s, val):
+ if self._evalcond(pkt):
+ return self.fld.addfield(pkt,s,val)
+ else:
+ return s
+ def __getattr__(self, attr):
+ return getattr(self.fld,attr)
+
+
+class PadField:
+ """Add bytes after the proxified field so that it ends at the specified
+ alignment from its begining"""
+ _fld = None
+ def __init__(self, fld, align, padwith=None):
+ self._fld = fld
+ self._align = align
+ self._padwith = padwith or b""
+
+ def padlen(self, flen):
+ return -flen%self._align
+
+ def getfield(self, pkt, s):
+ remain,val = self._fld.getfield(pkt,s)
+ padlen = self.padlen(len(s)-len(remain))
+ return remain[padlen:], val
+
+ def addfield(self, pkt, s, val):
+ sval = self._fld.addfield(pkt, b"", val)
+ return s+sval+struct.pack("%is" % (self.padlen(len(sval))), self._padwith)
+
+ def __getattr__(self, attr):
+ return getattr(self._fld,attr)
+
+
+class MACField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "6s")
+ def i2m(self, pkt, x):
+ if x is None:
+ return b"\0\0\0\0\0\0"
+ return mac2str(x)
+ def m2i(self, pkt, x):
+ return str2mac(x)
+ def any2i(self, pkt, x):
+ if type(x) is bytes and len(x) is 6:
+ x = self.m2i(pkt, x)
+ return x
+ def i2repr(self, pkt, x):
+ x = self.i2h(pkt, x)
+ if self in conf.resolve:
+ x = conf.manufdb._resolve_MAC(x)
+ return x
+ def randval(self):
+ return RandMAC()
+
+
+class IPField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "4s")
+ def h2i(self, pkt, x):
+ if type(x) is str:
+ try:
+ inet_aton(x)
+ except socket.error:
+ x = Net(x)
+ elif type(x) is list:
+ x = [self.h2i(pkt, n) for n in x]
+ return x
+ def resolve(self, x):
+ if self in conf.resolve:
+ try:
+ ret = socket.gethostbyaddr(x)[0]
+ except:
+ pass
+ else:
+ if ret:
+ return ret
+ return x
+ def i2m(self, pkt, x):
+ return inet_aton(x)
+ def m2i(self, pkt, x):
+ return inet_ntoa(x)
+ def any2i(self, pkt, x):
+ return self.h2i(pkt,x)
+ def i2repr(self, pkt, x):
+ return self.resolve(self.i2h(pkt, x))
+ def randval(self):
+ return RandIP()
+
+class SourceIPField(IPField):
+ def __init__(self, name, dstname):
+ IPField.__init__(self, name, None)
+ self.dstname = dstname
+ def i2m(self, pkt, x):
+ if x is None:
+ iff,x,gw = pkt.route()
+ if x is None:
+ x = "0.0.0.0"
+ return IPField.i2m(self, pkt, x)
+ def i2h(self, pkt, x):
+ if x is None:
+ dst=getattr(pkt,self.dstname)
+ if isinstance(dst,Gen):
+ #r = map(conf.route.route, dst)
+ r = [ conf.route.route(i) for i in dst ]
+ r.sort()
+ if r[0] != r[-1]:
+ warning("More than one possible route for %s"%repr(dst))
+ iff,x,gw = r[0]
+ else:
+ iff,x,gw = conf.route.route(dst)
+ return IPField.i2h(self, pkt, x)
+
+
+
+
+class ByteField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "B")
+
+class XByteField(ByteField):
+ def i2repr(self, pkt, x):
+ return lhex(self.i2h(pkt, x))
+
+class OByteField(ByteField):
+ def i2repr(self, pkt, x):
+ return "%03o"%self.i2h(pkt, x)
+
+class X3BytesField(XByteField):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "!I")
+ def addfield(self, pkt, s, val):
+ return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
+ def getfield(self, pkt, s):
+ return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00"+s[:3])[0])
+
+
+class ThreeBytesField(X3BytesField, ByteField):
+ def i2repr(self, pkt, x):
+ return ByteField.i2repr(self, pkt, x)
+
+
+class ShortField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "H")
+
+class LEShortField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "<H")
+
+class XShortField(ShortField):
+ def i2repr(self, pkt, x):
+ return lhex(self.i2h(pkt, x))
+
+
+class IntField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "I")
+
+class SignedIntField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "i")
+ def randval(self):
+ return RandSInt()
+
+class LEIntField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "<I")
+
+class LESignedIntField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "<i")
+ def randval(self):
+ return RandSInt()
+
+class XIntField(IntField):
+ def i2repr(self, pkt, x):
+ return lhex(self.i2h(pkt, x))
+
+
+class LongField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "Q")
+
+class XLongField(LongField):
+ def i2repr(self, pkt, x):
+ return lhex(self.i2h(pkt, x))
+
+class IEEEFloatField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "f")
+
+class IEEEDoubleField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "d")
+
+
+class StrField(Field):
+ def __init__(self, name, default, fmt="H", remain=0):
+ Field.__init__(self,name,default,fmt)
+ self.remain = remain
+ #def i2h(self, pkt, x):
+ def i2repr(self, pkt, x):
+ try:
+ if type(x) is bytes:
+ x = x.decode('ascii')
+ except UnicodeDecodeError:
+ pass
+ return repr(x)
+ #def i2repr(self, pkt, x):
+ # return repr(self.i2h(pkt,x))
+ def i2len(self, pkt, i):
+ return len(i)
+ def i2m(self, pkt, x):
+ if x is None:
+ x = b""
+ elif type(x) is not bytes:
+ x=str(x).encode('ascii')
+ return x
+ def addfield(self, pkt, s, val):
+ return s+self.i2m(pkt, val)
+ def getfield(self, pkt, s):
+ if self.remain == 0:
+ return b"",self.m2i(pkt, s)
+ else:
+ return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
+ def randval(self):
+ return RandBin(RandNum(0,1200))
+
+class PacketField(StrField):
+ holds_packets=1
+ def __init__(self, name, default, cls, remain=0): #is remain used somewhere?
+ StrField.__init__(self, name, default, remain=remain)
+ self.cls = cls
+ def i2m(self, pkt, i):
+ return bytes(i)
+ def m2i(self, pkt, m):
+ return self.cls(m)
+ def getfield(self, pkt, s):
+ i = self.m2i(pkt, s)
+ remain = b""
+ if conf.padding_layer in i:
+ r = i[conf.padding_layer]
+ del(r.underlayer.payload)
+ remain = r.load
+ return remain,i
+
+class PacketLenField(PacketField):
+ holds_packets=1
+ def __init__(self, name, default, cls, length_from=None):
+ PacketField.__init__(self, name, default, cls)
+ self.length_from = length_from
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ try:
+ i = self.m2i(pkt, s[:l])
+ except Exception:
+ if conf.debug_dissector:
+ raise
+ i = conf.raw_layer(load=s[:l])
+ return s[l:],i
+
+
+class PacketListField(PacketField):
+ islist = 1
+ holds_packets=1
+ def __init__(self, name, default, cls, count_from=None, length_from=None):
+ if default is None:
+ default = [] # Create a new list for each instance
+ PacketField.__init__(self, name, default, cls)
+ self.count_from = count_from
+ self.length_from = length_from
+
+
+ def any2i(self, pkt, x):
+ if type(x) is not list:
+ return [x]
+ else:
+ return x
+ def i2count(self, pkt, val):
+ if type(val) is list:
+ return len(val)
+ return 1
+ def i2len(self, pkt, val):
+ return sum( len(p) for p in val )
+ def do_copy(self, x):
+ #return map(lambda p:p.copy(), x)
+ return [ i.copy() for i in x ]
+ def getfield(self, pkt, s):
+ c = l = None
+ if self.length_from is not None:
+ l = self.length_from(pkt)
+ elif self.count_from is not None:
+ c = self.count_from(pkt)
+
+ lst = []
+ ret = b""
+ remain = s
+ if l is not None:
+ remain,ret = s[:l],s[l:]
+ while remain:
+ if c is not None:
+ if c <= 0:
+ break
+ c -= 1
+ try:
+ p = self.m2i(pkt,remain)
+ except Exception:
+ if conf.debug_dissector:
+ raise
+ p = conf.raw_layer(load=remain)
+ remain = b""
+ else:
+ if conf.padding_layer in p:
+ pad = p[conf.padding_layer]
+ remain = pad.load
+ del(pad.underlayer.payload)
+ else:
+ remain = b""
+ lst.append(p)
+ return remain+ret,lst
+ def addfield(self, pkt, s, val):
+ return s+b"".join([ bytes(i) for i in val ])
+
+
+class StrFixedLenField(StrField):
+ def __init__(self, name, default, length=None, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+ if length is not None:
+ self.length_from = lambda pkt,length=length: length
+ def i2repr(self, pkt, v):
+ if type(v) is bytes:
+ v = v.rstrip(b"\0")
+ return repr(v)
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ return s[l:], self.m2i(pkt,s[:l])
+ def addfield(self, pkt, s, val):
+ l = self.length_from(pkt)
+ return s+struct.pack("%is"%l,self.i2m(pkt, val))
+ def randval(self):
+ try:
+ l = self.length_from(None)
+ except:
+ l = RandNum(0,200)
+ return RandBin(l)
+
+class StrFixedLenEnumField(StrFixedLenField):
+ def __init__(self, name, default, length=None, enum=None, length_from=None):
+ StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from)
+ self.enum = enum
+ def i2repr(self, pkt, v):
+ r = v.rstrip("\0")
+ rr = repr(r)
+ if v in self.enum:
+ rr = "%s (%s)" % (rr, self.enum[v])
+ elif r in self.enum:
+ rr = "%s (%s)" % (rr, self.enum[r])
+ return rr
+
+class NetBIOSNameField(StrFixedLenField):
+ def __init__(self, name, default, length=31):
+ StrFixedLenField.__init__(self, name, default, length)
+ def i2m(self, pkt, x):
+ l = self.length_from(pkt)//2
+ if x is None:
+ x = b""
+ x += b" "*(l)
+ x = x[:l]
+ #x = b"".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x))
+ x = b"".join([ bytes([0x41+(i>>4),0x41+(i&0xf)]) for i in x ])
+ x = b" "+x
+ return x
+ def m2i(self, pkt, x):
+ x = x.strip(b"\x00").strip(b" ")
+ #return b"".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2]))
+ return b"".join(map(lambda x,y: bytes([(((x-1)&0xf)<<4)+((y-1)&0xf)]), x[::2],x[1::2]))
+
+class StrLenField(StrField):
+ def __init__(self, name, default, fld=None, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ return s[l:], self.m2i(pkt,s[:l])
+
+class FieldListField(Field):
+ islist=1
+ def __init__(self, name, default, field, length_from=None, count_from=None):
+ if default is None:
+ default = [] # Create a new list for each instance
+ Field.__init__(self, name, default)
+ self.count_from = count_from
+ self.length_from = length_from
+ self.field = field
+
+ def i2count(self, pkt, val):
+ if type(val) is list:
+ return len(val)
+ return 1
+ def i2len(self, pkt, val):
+ return sum( self.field.i2len(pkt,v) for v in val )
+
+ def i2m(self, pkt, val):
+ if val is None:
+ val = []
+ return val
+ def any2i(self, pkt, x):
+ if type(x) is not list:
+ return [x]
+ else:
+ return x
+ def addfield(self, pkt, s, val):
+ val = self.i2m(pkt, val)
+ for v in val:
+ s = self.field.addfield(pkt, s, v)
+ return s
+ def getfield(self, pkt, s):
+ c = l = None
+ if self.length_from is not None:
+ l = self.length_from(pkt)
+ elif self.count_from is not None:
+ c = self.count_from(pkt)
+
+ val = []
+ ret=b""
+ if l is not None:
+ s,ret = s[:l],s[l:]
+
+ while s:
+ if c is not None:
+ if c <= 0:
+ break
+ c -= 1
+ s,v = self.field.getfield(pkt, s)
+ val.append(v)
+ return s+ret, val
+
+class FieldLenField(Field):
+ def __init__(self, name, default, length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
+ Field.__init__(self, name, default, fmt)
+ self.length_of=length_of
+ self.count_of=count_of
+ self.adjust=adjust
+ if fld is not None:
+ FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
+ self.length_of = fld
+ def i2m(self, pkt, x):
+ if x is None:
+ if self.length_of is not None:
+ fld,fval = pkt.getfield_and_val(self.length_of)
+ f = fld.i2len(pkt, fval)
+ else:
+ fld,fval = pkt.getfield_and_val(self.count_of)
+ f = fld.i2count(pkt, fval)
+ x = self.adjust(pkt,f)
+ return x
+
+class StrNullField(StrField):
+ def addfield(self, pkt, s, val):
+ return s+self.i2m(pkt, val)+b"\x00"
+ def getfield(self, pkt, s):
+ l = s.find(b"\x00")
+ if l < 0:
+ #XXX \x00 not found
+ return "",s
+ return s[l+1:],self.m2i(pkt, s[:l])
+ def randval(self):
+ return RandTermString(RandNum(0,1200),b"\x00")
+
+class StrStopField(StrField):
+ def __init__(self, name, default, stop, additionnal=0):
+ Field.__init__(self, name, default)
+ self.stop=stop
+ self.additionnal=additionnal
+ def getfield(self, pkt, s):
+ l = s.find(self.stop)
+ if l < 0:
+ return b"",s
+# raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop
+ l += len(self.stop)+self.additionnal
+ return s[l:],s[:l]
+ def randval(self):
+ return RandTermString(RandNum(0,1200),self.stop)
+
+class LenField(Field):
+ def i2m(self, pkt, x):
+ if x is None:
+ x = len(pkt.payload)
+ return x
+
+class BCDFloatField(Field):
+ def i2m(self, pkt, x):
+ return int(256*x)
+ def m2i(self, pkt, x):
+ return x/256.0
+
+class BitField(Field):
+ def __init__(self, name, default, size):
+ Field.__init__(self, name, default)
+ self.rev = size < 0
+ self.size = abs(size)
+ def reverse(self, val):
+ if self.size == 16:
+ val = socket.ntohs(val)
+ elif self.size == 32:
+ val = socket.ntohl(val)
+ return val
+
+ def addfield(self, pkt, s, val):
+ val = self.i2m(pkt, val)
+ if type(s) is tuple:
+ s,bitsdone,v = s
+ else:
+ bitsdone = 0
+ v = 0
+ if self.rev:
+ val = self.reverse(val)
+ v <<= self.size
+ v |= val & ((1<<self.size) - 1)
+ bitsdone += self.size
+ while bitsdone >= 8:
+ bitsdone -= 8
+ s = s+struct.pack("!B", v >> bitsdone)
+ v &= (1<<bitsdone)-1
+ if bitsdone:
+ return s,bitsdone,v
+ else:
+ return s
+ def getfield(self, pkt, s):
+ if type(s) is tuple:
+ s,bn = s
+ else:
+ bn = 0
+ # we don't want to process all the string
+ nb_bytes = (self.size+bn-1)//8 + 1
+ w = s[:nb_bytes]
+
+ # split the substring byte by byte
+ bs = struct.unpack('!%dB' % nb_bytes , w)
+
+ b = 0
+ for c in range(nb_bytes):
+ b |= int(bs[c]) << (nb_bytes-c-1)*8
+
+ # get rid of high order bits
+ b &= (1 << (nb_bytes*8-bn)) - 1
+
+ # remove low order bits
+ b = b >> (nb_bytes*8 - self.size - bn)
+
+ if self.rev:
+ b = self.reverse(b)
+
+ bn += self.size
+ s = s[bn//8:]
+ bn = bn%8
+ b = self.m2i(pkt, b)
+ if bn:
+ return (s,bn),b
+ else:
+ return s,b
+ def randval(self):
+ return RandNum(0,2**self.size-1)
+
+
+class BitFieldLenField(BitField):
+ def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x):
+ BitField.__init__(self, name, default, size)
+ self.length_of=length_of
+ self.count_of=count_of
+ self.adjust=adjust
+ def i2m(self, pkt, x):
+ #return FieldLenField.i2m.im_func(self, pkt, x)
+ return FieldLenField.i2m(self, pkt, x)
+
+
+class XBitField(BitField):
+ def i2repr(self, pkt, x):
+ return lhex(self.i2h(pkt,x))
+
+
+class EnumField(Field):
+ def __init__(self, name, default, enum, fmt = "H"):
+ i2s = self.i2s = {}
+ s2i = self.s2i = {}
+ if type(enum) is list:
+ keys = range(len(enum))
+ else:
+ keys = enum.keys()
+ if list(filter(lambda x: type(x) is str, keys)):
+ i2s,s2i = s2i,i2s
+ for k in keys:
+ i2s[k] = enum[k]
+ s2i[enum[k]] = k
+ Field.__init__(self, name, default, fmt)
+ def any2i_one(self, pkt, x):
+ if type(x) is str:
+ x = self.s2i[x]
+ return x
+ def i2repr_one(self, pkt, x):
+ if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
+ return self.i2s[x]
+ return repr(x)
+
+ def any2i(self, pkt, x):
+ if type(x) is list:
+ return list(map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x))
+ else:
+ return self.any2i_one(pkt,x)
+ def i2repr(self, pkt, x):
+ if type(x) is list:
+ return list(map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x))
+ else:
+ return self.i2repr_one(pkt,x)
+
+class CharEnumField(EnumField):
+ def __init__(self, name, default, enum, fmt = "1s"):
+ EnumField.__init__(self, name, default, enum, fmt)
+ k = self.i2s.keys()
+ if k and len(k[0]) != 1:
+ self.i2s,self.s2i = self.s2i,self.i2s
+ def any2i_one(self, pkt, x):
+ if len(x) != 1:
+ x = self.s2i[x]
+ return x
+
+class BitEnumField(BitField,EnumField):
+ def __init__(self, name, default, size, enum):
+ EnumField.__init__(self, name, default, enum)
+ self.rev = size < 0
+ self.size = abs(size)
+ def any2i(self, pkt, x):
+ return EnumField.any2i(self, pkt, x)
+ def i2repr(self, pkt, x):
+ return EnumField.i2repr(self, pkt, x)
+
+class ShortEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "H")
+
+class LEShortEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "<H")
+
+class ByteEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "B")
+
+class IntEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "I")
+
+class SignedIntEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "i")
+ def randval(self):
+ return RandSInt()
+
+class LEIntEnumField(EnumField):
+ def __init__(self, name, default, enum):
+ EnumField.__init__(self, name, default, enum, "<I")
+
+class XShortEnumField(ShortEnumField):
+ def i2repr_one(self, pkt, x):
+ if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
+ return self.i2s[x]
+ return lhex(x)
+
+class MultiEnumField(EnumField):
+ def __init__(self, name, default, enum, depends_on, fmt = "H"):
+
+ self.depends_on = depends_on
+ self.i2s_multi = enum
+ self.s2i_multi = {}
+ self.s2i_all = {}
+ for m in enum:
+ self.s2i_multi[m] = s2i = {}
+ for k,v in enum[m].items():
+ s2i[v] = k
+ self.s2i_all[v] = k
+ Field.__init__(self, name, default, fmt)
+ def any2i_one(self, pkt, x):
+ if type (x) is str:
+ v = self.depends_on(pkt)
+ if v in self.s2i_multi:
+ s2i = self.s2i_multi[v]
+ if x in s2i:
+ return s2i[x]
+ return self.s2i_all[x]
+ return x
+ def i2repr_one(self, pkt, x):
+ v = self.depends_on(pkt)
+ if v in self.i2s_multi:
+ return self.i2s_multi[v].get(x,x)
+ return x
+
+class BitMultiEnumField(BitField,MultiEnumField):
+ def __init__(self, name, default, size, enum, depends_on):
+ MultiEnumField.__init__(self, name, default, enum)
+ self.rev = size < 0
+ self.size = abs(size)
+ def any2i(self, pkt, x):
+ return MultiEnumField.any2i(self, pkt, x)
+ def i2repr(self, pkt, x):
+ return MultiEnumField.i2repr(self, pkt, x)
+
+
+# Little endian long field
+class LELongField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "<Q")
+
+# Little endian fixed length field
+class LEFieldLenField(FieldLenField):
+ def __init__(self, name, default, length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None):
+ FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, fld=fld, adjust=adjust)
+
+
+class FlagsField(BitField):
+ def __init__(self, name, default, size, names):
+ self.multi = type(names) is list
+ if self.multi:
+ #self.names = map(lambda x:[x], names)
+ self.names = [ [x] for x in names ]
+ else:
+ self.names = names
+ BitField.__init__(self, name, default, size)
+ def any2i(self, pkt, x):
+ if type(x) is str:
+ if self.multi:
+ #x = map(lambda y:[y], x.split("+"))
+ x = [ [y] for y in x.split("+") ]
+ y = 0
+ for i in x:
+ y |= 1 << self.names.index(i)
+ x = y
+ return x
+ def i2repr(self, pkt, x):
+ if type(x) is list or type(x) is tuple:
+ return repr(x)
+ if self.multi:
+ r = []
+ else:
+ r = ""
+ i=0
+ while x:
+ if x & 1:
+ r += self.names[i]
+ i += 1
+ x >>= 1
+ if self.multi:
+ r = "+".join(r)
+ return r
+
+
+
+
+class FixedPointField(BitField):
+ def __init__(self, name, default, size, frac_bits=16):
+ self.frac_bits = frac_bits
+ BitField.__init__(self, name, default, size)
+
+ def any2i(self, pkt, val):
+ if val is None:
+ return val
+ ival = int(val)
+ fract = int( (val-ival) * 2**self.frac_bits )
+ return (ival << self.frac_bits) | fract
+
+ def i2h(self, pkt, val):
+ int_part = val >> self.frac_bits
+ frac_part = val & (1 << self.frac_bits) - 1
+ frac_part /= 2.0**self.frac_bits
+ return int_part+frac_part
+ def i2repr(self, pkt, val):
+ return self.i2h(pkt, val)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/__init__.py
new file mode 100644
index 00000000..a3f2afb9
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/__init__.py
@@ -0,0 +1,8 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Layer package.
+"""
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/all.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/all.py
new file mode 100644
index 00000000..8104b6a2
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/all.py
@@ -0,0 +1,45 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+All layers. Configurable with conf.load_layers.
+"""
+
+import importlib
+from scapy.config import conf
+from scapy.error import log_loading
+import logging
+log = logging.getLogger("scapy.loading")
+
+#log_loading.info("Please, report issues to https://github.com/phaethon/scapy")
+
+def _import_star(m):
+ #mod = __import__("." + m, globals(), locals())
+ mod = importlib.import_module("scapy.layers." + m)
+ for k,v in mod.__dict__.items():
+ globals()[k] = v
+
+
+for _l in ['l2','inet','inet6']:
+ log_loading.debug("Loading layer %s" % _l)
+ #print "load ",_l
+ _import_star(_l)
+
+#def _import_star(m):
+ #mod = __import__("." + m, globals(), locals())
+# mod = importlib.import_module("scapy.layers." + m)
+# for k,v in mod.__dict__.items():
+# globals()[k] = v
+
+#for _l in conf.load_layers:
+# log_loading.debug("Loading layer %s" % _l)
+# try:
+# _import_star(_l)
+# except Exception as e:
+# log.warning("can't import layer %s: %s" % (_l,e))
+
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/bluetooth.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/bluetooth.py
new file mode 100644
index 00000000..5dd365a4
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/bluetooth.py
@@ -0,0 +1,213 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Bluetooth layers, sockets and send/receive functions.
+"""
+
+import socket,struct
+
+from scapy.config import conf
+from scapy.packet import *
+from scapy.fields import *
+from scapy.supersocket import SuperSocket
+from scapy.data import MTU
+
+
+class HCI_Hdr(Packet):
+ name = "HCI header"
+ fields_desc = [ ByteEnumField("type",2,{1:"command",2:"ACLdata",3:"SCOdata",4:"event",5:"vendor"}),]
+
+ def mysummary(self):
+ return self.sprintf("HCI %type%")
+
+class HCI_ACL_Hdr(Packet):
+ name = "HCI ACL header"
+ fields_desc = [ ByteField("handle",0), # Actually, handle is 12 bits and flags is 4.
+ ByteField("flags",0), # I wait to write a LEBitField
+ LEShortField("len",None), ]
+ def post_build(self, p, pay):
+ p += pay
+ if self.len is None:
+ l = len(p)-4
+ #p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
+ p = p[:2]+bytes([(l&0xff),((l>>8)&0xff)])+p[4:]
+ return p
+
+
+class L2CAP_Hdr(Packet):
+ name = "L2CAP header"
+ fields_desc = [ LEShortField("len",None),
+ LEShortEnumField("cid",0,{1:"control"}),]
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.len is None:
+ l = len(p)-4
+ #p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
+ p = p[:2]+bytes([(l&0xff),((l>>8)&0xff)])+p[4:]
+ return p
+
+
+
+class L2CAP_CmdHdr(Packet):
+ name = "L2CAP command header"
+ fields_desc = [
+ ByteEnumField("code",8,{1:"rej",2:"conn_req",3:"conn_resp",
+ 4:"conf_req",5:"conf_resp",6:"disconn_req",
+ 7:"disconn_resp",8:"echo_req",9:"echo_resp",
+ 10:"info_req",11:"info_resp"}),
+ ByteField("id",0),
+ LEShortField("len",None) ]
+ def post_build(self, p, pay):
+ p += pay
+ if self.len is None:
+ l = len(p)-4
+ #p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
+ p = p[:2]+bytes([(l&0xff),((l>>8)&0xff)])+p[4:]
+ return p
+ def answers(self, other):
+ if other.id == self.id:
+ if self.code == 1:
+ return 1
+ if other.code in [2,4,6,8,10] and self.code == other.code+1:
+ if other.code == 8:
+ return 1
+ return self.payload.answers(other.payload)
+ return 0
+
+class L2CAP_ConnReq(Packet):
+ name = "L2CAP Conn Req"
+ fields_desc = [ LEShortEnumField("psm",0,{1:"SDP",3:"RFCOMM",5:"telephony control"}),
+ LEShortField("scid",0),
+ ]
+
+class L2CAP_ConnResp(Packet):
+ name = "L2CAP Conn Resp"
+ fields_desc = [ LEShortField("dcid",0),
+ LEShortField("scid",0),
+ LEShortEnumField("result",0,["no_info","authen_pend","author_pend"]),
+ LEShortEnumField("status",0,["success","pend","bad_psm",
+ "cr_sec_block","cr_no_mem"]),
+ ]
+ def answers(self, other):
+ return self.scid == other.scid
+
+class L2CAP_CmdRej(Packet):
+ name = "L2CAP Command Rej"
+ fields_desc = [ LEShortField("reason",0),
+ ]
+
+
+class L2CAP_ConfReq(Packet):
+ name = "L2CAP Conf Req"
+ fields_desc = [ LEShortField("dcid",0),
+ LEShortField("flags",0),
+ ]
+
+class L2CAP_ConfResp(Packet):
+ name = "L2CAP Conf Resp"
+ fields_desc = [ LEShortField("scid",0),
+ LEShortField("flags",0),
+ LEShortEnumField("result",0,["success","unaccept","reject","unknown"]),
+ ]
+ def answers(self, other):
+ return self.scid == other.scid
+
+
+class L2CAP_DisconnReq(Packet):
+ name = "L2CAP Disconn Req"
+ fields_desc = [ LEShortField("dcid",0),
+ LEShortField("scid",0), ]
+
+class L2CAP_DisconnResp(Packet):
+ name = "L2CAP Disconn Resp"
+ fields_desc = [ LEShortField("dcid",0),
+ LEShortField("scid",0), ]
+ def answers(self, other):
+ return self.scid == other.scid
+
+
+
+class L2CAP_InfoReq(Packet):
+ name = "L2CAP Info Req"
+ fields_desc = [ LEShortEnumField("type",0,{1:"CL_MTU",2:"FEAT_MASK"}),
+ StrField("data","")
+ ]
+
+
+class L2CAP_InfoResp(Packet):
+ name = "L2CAP Info Resp"
+ fields_desc = [ LEShortField("type",0),
+ LEShortEnumField("result",0,["success","not_supp"]),
+ StrField("data",""), ]
+ def answers(self, other):
+ return self.type == other.type
+
+
+
+bind_layers( HCI_Hdr, HCI_ACL_Hdr, type=2)
+bind_layers( HCI_Hdr, conf.raw_layer, )
+bind_layers( HCI_ACL_Hdr, L2CAP_Hdr, )
+bind_layers( L2CAP_Hdr, L2CAP_CmdHdr, cid=1)
+bind_layers( L2CAP_CmdHdr, L2CAP_CmdRej, code=1)
+bind_layers( L2CAP_CmdHdr, L2CAP_ConnReq, code=2)
+bind_layers( L2CAP_CmdHdr, L2CAP_ConnResp, code=3)
+bind_layers( L2CAP_CmdHdr, L2CAP_ConfReq, code=4)
+bind_layers( L2CAP_CmdHdr, L2CAP_ConfResp, code=5)
+bind_layers( L2CAP_CmdHdr, L2CAP_DisconnReq, code=6)
+bind_layers( L2CAP_CmdHdr, L2CAP_DisconnResp, code=7)
+bind_layers( L2CAP_CmdHdr, L2CAP_InfoReq, code=10)
+bind_layers( L2CAP_CmdHdr, L2CAP_InfoResp, code=11)
+
+class BluetoothL2CAPSocket(SuperSocket):
+ desc = "read/write packets on a connected L2CAP socket"
+ def __init__(self, peer):
+ s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
+ socket.BTPROTO_L2CAP)
+ s.connect((peer,0))
+
+ self.ins = self.outs = s
+
+ def recv(self, x=MTU):
+ return L2CAP_CmdHdr(self.ins.recv(x))
+
+
+class BluetoothHCISocket(SuperSocket):
+ desc = "read/write on a BlueTooth HCI socket"
+ def __init__(self, iface=0x10000, type=None):
+ s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
+ s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR,1)
+ s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP,1)
+ s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffff,0xffffffff,0xffffffff,0)) #type mask, event mask, event mask, opcode
+ s.bind((iface,))
+ self.ins = self.outs = s
+# s.connect((peer,0))
+
+
+ def recv(self, x):
+ return HCI_Hdr(self.ins.recv(x))
+
+## Bluetooth
+
+
+@conf.commands.register
+def srbt(peer, pkts, inter=0.1, *args, **kargs):
+ """send and receive using a bluetooth socket"""
+ s = conf.BTsocket(peer=peer)
+ a,b = sndrcv(s,pkts,inter=inter,*args,**kargs)
+ s.close()
+ return a,b
+
+@conf.commands.register
+def srbt1(peer, pkts, *args, **kargs):
+ """send and receive 1 packet using a bluetooth socket"""
+ a,b = srbt(peer, pkts, *args, **kargs)
+ if len(a) > 0:
+ return a[0][1]
+
+
+
+conf.BTsocket = BluetoothL2CAPSocket
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp.py
new file mode 100644
index 00000000..e2b7c1f1
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp.py
@@ -0,0 +1,381 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+DHCP (Dynamic Host Configuration Protocol) d BOOTP
+"""
+
+import struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.ansmachine import *
+from scapy.layers.inet import UDP,IP
+from scapy.layers.l2 import Ether
+from scapy.base_classes import Net
+from scapy.volatile import RandField
+
+from scapy.arch import get_if_raw_hwaddr
+from scapy.sendrecv import srp1
+from scapy.utils import str2bytes
+
+dhcpmagic=b"c\x82Sc"
+
+
+class BOOTP(Packet):
+ name = "BOOTP"
+ fields_desc = [ ByteEnumField("op",1, {1:"BOOTREQUEST", 2:"BOOTREPLY"}),
+ ByteField("htype",1),
+ ByteField("hlen",6),
+ ByteField("hops",0),
+ IntField("xid",0),
+ ShortField("secs",0),
+ FlagsField("flags", 0, 16, "???????????????B"),
+ IPField("ciaddr","0.0.0.0"),
+ IPField("yiaddr","0.0.0.0"),
+ IPField("siaddr","0.0.0.0"),
+ IPField("giaddr","0.0.0.0"),
+ Field("chaddr",b"", "16s"),
+ Field("sname",b"","64s"),
+ Field("file",b"","128s"),
+ StrField("options",b"") ]
+ def guess_payload_class(self, payload):
+ if self.options[:len(dhcpmagic)] == dhcpmagic:
+ return DHCP
+ else:
+ return Packet.guess_payload_class(self, payload)
+ def extract_padding(self,s):
+ if self.options[:len(dhcpmagic)] == dhcpmagic:
+ # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options
+ payload = self.options[len(dhcpmagic):]
+ self.options = self.options[:len(dhcpmagic)]
+ return payload, None
+ else:
+ return b"", None
+ def hashret(self):
+ return struct.pack("L", self.xid)
+ def answers(self, other):
+ if not isinstance(other, BOOTP):
+ return 0
+ return self.xid == other.xid
+
+
+
+#DHCP_UNKNOWN, DHCP_IP, DHCP_IPLIST, DHCP_TYPE \
+#= range(4)
+#
+
+DHCPTypes = {
+ 1: "discover",
+ 2: "offer",
+ 3: "request",
+ 4: "decline",
+ 5: "ack",
+ 6: "nak",
+ 7: "release",
+ 8: "inform",
+ 9: "force_renew",
+ 10:"lease_query",
+ 11:"lease_unassigned",
+ 12:"lease_unknown",
+ 13:"lease_active",
+ }
+
+DHCPOptions = {
+ 0: "pad",
+ 1: IPField("subnet_mask", "0.0.0.0"),
+ 2: "time_zone",
+ 3: IPField("router","0.0.0.0"),
+ 4: IPField("time_server","0.0.0.0"),
+ 5: IPField("IEN_name_server","0.0.0.0"),
+ 6: IPField("name_server","0.0.0.0"),
+ 7: IPField("log_server","0.0.0.0"),
+ 8: IPField("cookie_server","0.0.0.0"),
+ 9: IPField("lpr_server","0.0.0.0"),
+ 12: "hostname",
+ 14: "dump_path",
+ 15: "domain",
+ 17: "root_disk_path",
+ 22: "max_dgram_reass_size",
+ 23: "default_ttl",
+ 24: "pmtu_timeout",
+ 28: IPField("broadcast_address","0.0.0.0"),
+ 35: "arp_cache_timeout",
+ 36: "ether_or_dot3",
+ 37: "tcp_ttl",
+ 38: "tcp_keepalive_interval",
+ 39: "tcp_keepalive_garbage",
+ 40: "NIS_domain",
+ 41: IPField("NIS_server","0.0.0.0"),
+ 42: IPField("NTP_server","0.0.0.0"),
+ 43: "vendor_specific",
+ 44: IPField("NetBIOS_server","0.0.0.0"),
+ 45: IPField("NetBIOS_dist_server","0.0.0.0"),
+ 50: IPField("requested_addr","0.0.0.0"),
+ 51: IntField("lease_time", 43200),
+ 54: IPField("server_id","0.0.0.0"),
+ 55: "param_req_list",
+ 57: ShortField("max_dhcp_size", 1500),
+ 58: IntField("renewal_time", 21600),
+ 59: IntField("rebinding_time", 37800),
+ 60: "vendor_class_id",
+ 61: "client_id",
+
+ 64: "NISplus_domain",
+ 65: IPField("NISplus_server","0.0.0.0"),
+ 69: IPField("SMTP_server","0.0.0.0"),
+ 70: IPField("POP3_server","0.0.0.0"),
+ 71: IPField("NNTP_server","0.0.0.0"),
+ 72: IPField("WWW_server","0.0.0.0"),
+ 73: IPField("Finger_server","0.0.0.0"),
+ 74: IPField("IRC_server","0.0.0.0"),
+ 75: IPField("StreetTalk_server","0.0.0.0"),
+ 76: "StreetTalk_Dir_Assistance",
+ 82: "relay_agent_Information",
+ 53: ByteEnumField("message-type", 1, DHCPTypes),
+ # 55: DHCPRequestListField("request-list"),
+ 255: "end"
+ }
+
+DHCPRevOptions = {}
+
+for k,v in DHCPOptions.items():
+ if type(v) is str:
+ n = v
+ v = None
+ else:
+ n = v.name
+ DHCPRevOptions[n] = (k,v)
+del(n)
+del(v)
+del(k)
+
+
+
+
+class RandDHCPOptions(RandField):
+ def __init__(self, size=None, rndstr=None):
+ if size is None:
+ size = RandNumExpo(0.05)
+ self.size = size
+ if rndstr is None:
+ rndstr = RandBin(RandNum(0,255))
+ self.rndstr=rndstr
+ self._opts = list(DHCPOptions.values())
+ self._opts.remove("pad")
+ self._opts.remove("end")
+ def _fix(self):
+ op = []
+ for k in range(self.size):
+ o = random.choice(self._opts)
+ if type(o) is str:
+ op.append((o,self.rndstr*1))
+ else:
+ op.append((o.name, o.randval()._fix()))
+ return op
+
+
+class DHCPOptionsField(StrField):
+ islist=1
+ def i2repr(self,pkt,x):
+ s = []
+ for v in x:
+ if type(v) is tuple and len(v) >= 2:
+ if v[0] in DHCPRevOptions and isinstance(DHCPRevOptions[v[0]][1],Field):
+ f = DHCPRevOptions[v[0]][1]
+ vv = ",".join(f.i2repr(pkt,val) for val in v[1:])
+ else:
+ vv = ",".join(repr(val) for val in v[1:])
+ r = "%s=%s" % (v[0],vv)
+ s.append(r)
+ else:
+ s.append(sane(v))
+ return "[%s]" % (" ".join(s))
+
+ def getfield(self, pkt, s):
+ return b"", self.m2i(pkt, s)
+
+ def m2i(self, pkt, x):
+ opt = []
+ while x:
+ #o = ord(x[0])
+ o = x[0]
+ if o == 255:
+ opt.append("end")
+ x = x[1:]
+ continue
+ if o == 0:
+ opt.append("pad")
+ x = x[1:]
+ continue
+ #if len(x) < 2 or len(x) < ord(x[1])+2:
+ if len(x) < 2 or len(x) < x[1]+2:
+ opt.append(x)
+ break
+ elif o in DHCPOptions:
+ f = DHCPOptions[o]
+
+ if isinstance(f, str):
+ #olen = ord(x[1])
+ olen = x[1]
+ opt.append( (f,x[2:olen+2]) )
+ x = x[olen+2:]
+ else:
+ olen = x[1]
+ lval = [f.name]
+ try:
+ left = x[2:olen+2]
+ while left:
+ left, val = f.getfield(pkt,left)
+ lval.append(val)
+ except:
+ opt.append(x)
+ break
+ else:
+ otuple = tuple(lval)
+ opt.append(otuple)
+ x = x[olen+2:]
+ else:
+ #olen = ord(x[1])
+ olen = x[1]
+ opt.append((o, x[2:olen+2]))
+ x = x[olen+2:]
+ return opt
+ def i2m(self, pkt, x):
+ if type(x) is str:
+ return x
+ s = b""
+ for o in x:
+ if type(o) is tuple and len(o) >= 2:
+ name = o[0]
+ lval = o[1:]
+
+ if isinstance(name, int):
+ onum, oval = name, b"".join(lval)
+ elif name in DHCPRevOptions:
+ onum, f = DHCPRevOptions[name]
+ if f is not None:
+ lval = [f.addfield(pkt,b"",f.any2i(pkt,val)) for val in lval]
+ oval = b"".join(lval)
+ else:
+ warning("Unknown field option %s" % name)
+ continue
+
+ s += bytes([onum])
+ s += bytes([len(oval)])
+ s += oval
+
+ elif (type(o) is str and o in DHCPRevOptions and
+ DHCPRevOptions[o][1] == None):
+ s += bytes([DHCPRevOptions[o][0]])
+ elif type(o) is int:
+ s += chr(o)+b"\0"
+ elif type(o) is str:
+ s += str2bytes(o)
+ elif type(o) is bytes:
+ s += o
+ else:
+ warning("Malformed option %s" % o)
+ return s
+
+
+class DHCP(Packet):
+ name = "DHCP options"
+ fields_desc = [ DHCPOptionsField("options",b"") ]
+
+
+bind_layers( UDP, BOOTP, dport=67, sport=68)
+bind_layers( UDP, BOOTP, dport=68, sport=67)
+bind_bottom_up( UDP, BOOTP, dport=67, sport=67)
+bind_layers( BOOTP, DHCP, options=b'c\x82Sc')
+
+def dhcp_request(iface=None,**kargs):
+ if conf.checkIPaddr != 0:
+ warning("conf.checkIPaddr is not 0, I may not be able to match the answer")
+ if iface is None:
+ iface = conf.iface
+ hw = get_if_raw_hwaddr(iface)
+ return srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)
+ /BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"]),iface=iface,**kargs)
+
+
+class BOOTP_am(AnsweringMachine):
+ function_name = "bootpd"
+ filter = "udp and port 68 and port 67"
+ send_function = staticmethod(sendp)
+ def parse_options(self, pool=Net("192.168.1.128/25"), network="192.168.1.0/24",gw="192.168.1.1",
+ domain="localnet", renewal_time=60, lease_time=1800):
+ if type(pool) is str:
+ poom = Net(pool)
+ self.domain = domain
+ netw,msk = (network.split("/")+["32"])[:2]
+ msk = itom(int(msk))
+ self.netmask = ltoa(msk)
+ self.network = ltoa(atol(netw)&msk)
+ self.broadcast = ltoa( atol(self.network) | (0xffffffff&~msk) )
+ self.gw = gw
+ if isinstance(pool,Gen):
+ pool = [k for k in pool if k not in [gw, self.network, self.broadcast]]
+ pool.reverse()
+ if len(pool) == 1:
+ pool, = pool
+ self.pool = pool
+ self.lease_time = lease_time
+ self.renewal_time = renewal_time
+ self.leases = {}
+
+ def is_request(self, req):
+ if not req.haslayer(BOOTP):
+ return 0
+ reqb = req.getlayer(BOOTP)
+ if reqb.op != 1:
+ return 0
+ return 1
+
+ def print_reply(self, req, reply):
+ print("Reply %s to %s" % (reply.getlayer(IP).dst,reply.dst))
+
+ def make_reply(self, req):
+ mac = req.src
+ if type(self.pool) is list:
+ if not mac in self.leases:
+ self.leases[mac] = self.pool.pop()
+ ip = self.leases[mac]
+ else:
+ ip = self.pool
+
+ repb = req.getlayer(BOOTP).copy()
+ repb.op="BOOTREPLY"
+ repb.yiaddr = ip
+ repb.siaddr = self.gw
+ repb.ciaddr = self.gw
+ repb.giaddr = self.gw
+ del(repb.payload)
+ rep=Ether(dst=mac)/IP(dst=ip)/UDP(sport=req.dport,dport=req.sport)/repb
+ return rep
+
+
+class DHCP_am(BOOTP_am):
+ function_name="dhcpd"
+ def make_reply(self, req):
+ resp = BOOTP_am.make_reply(self, req)
+ if DHCP in req:
+ dhcp_options = [(op[0],{1:2,3:5}.get(op[1],op[1]))
+ for op in req[DHCP].options
+ if type(op) is tuple and op[0] == "message-type"]
+ dhcp_options += [("server_id",self.gw),
+ ("domain", self.domain),
+ ("router", self.gw),
+ ("name_server", self.gw),
+ ("broadcast_address", self.broadcast),
+ ("subnet_mask", self.netmask),
+ ("renewal_time", self.renewal_time),
+ ("lease_time", self.lease_time),
+ "end"
+ ]
+ resp /= DHCP(options=dhcp_options)
+ return resp
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
new file mode 100644
index 00000000..a11a4149
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
@@ -0,0 +1,1718 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp>
+## Arnaud Ebalard <arnaud.ebalard@eads.net>
+
+"""
+DHCPv6: Dynamic Host Configuration Protocol for IPv6. [RFC 3315]
+"""
+
+import socket
+from scapy.packet import *
+from scapy.fields import *
+from scapy.utils6 import *
+from scapy.layers.inet6 import *
+from scapy.ansmachine import AnsweringMachine
+
+#############################################################################
+# Helpers ##
+#############################################################################
+
+def get_cls(name, fallback_cls):
+ return globals().get(name, fallback_cls)
+
+
+#############################################################################
+#############################################################################
+### DHCPv6 ###
+#############################################################################
+#############################################################################
+
+All_DHCP_Relay_Agents_and_Servers = "ff02::1:2"
+All_DHCP_Servers = "ff05::1:3" # Site-Local scope : deprecated by 3879
+
+dhcp6opts = { 1: "CLIENTID",
+ 2: "SERVERID",
+ 3: "IA_NA",
+ 4: "IA_TA",
+ 5: "IAADDR",
+ 6: "ORO",
+ 7: "PREFERENCE",
+ 8: "ELAPSED_TIME",
+ 9: "RELAY_MSG",
+ 11: "AUTH",
+ 12: "UNICAST",
+ 13: "STATUS_CODE",
+ 14: "RAPID_COMMIT",
+ 15: "USER_CLASS",
+ 16: "VENDOR_CLASS",
+ 17: "VENDOR_OPTS",
+ 18: "INTERFACE_ID",
+ 19: "RECONF_MSG",
+ 20: "RECONF_ACCEPT",
+ 21: "SIP Servers Domain Name List", #RFC3319
+ 22: "SIP Servers IPv6 Address List", #RFC3319
+ 23: "DNS Recursive Name Server Option", #RFC3646
+ 24: "Domain Search List option", #RFC3646
+ 25: "OPTION_IA_PD", #RFC3633
+ 26: "OPTION_IAPREFIX", #RFC3633
+ 27: "OPTION_NIS_SERVERS", #RFC3898
+ 28: "OPTION_NISP_SERVERS", #RFC3898
+ 29: "OPTION_NIS_DOMAIN_NAME", #RFC3898
+ 30: "OPTION_NISP_DOMAIN_NAME", #RFC3898
+ 31: "OPTION_SNTP_SERVERS", #RFC4075
+ 32: "OPTION_INFORMATION_REFRESH_TIME", #RFC4242
+ 33: "OPTION_BCMCS_SERVER_D", #RFC4280
+ 34: "OPTION_BCMCS_SERVER_A", #RFC4280
+ 36: "OPTION_GEOCONF_CIVIC", #RFC-ietf-geopriv-dhcp-civil-09.txt
+ 37: "OPTION_REMOTE_ID", #RFC4649
+ 38: "OPTION_SUBSCRIBER_ID", #RFC4580
+ 39: "OPTION_CLIENT_FQDN" } #RFC4704
+
+dhcp6opts_by_code = { 1: "DHCP6OptClientId",
+ 2: "DHCP6OptServerId",
+ 3: "DHCP6OptIA_NA",
+ 4: "DHCP6OptIA_TA",
+ 5: "DHCP6OptIAAddress",
+ 6: "DHCP6OptOptReq",
+ 7: "DHCP6OptPref",
+ 8: "DHCP6OptElapsedTime",
+ 9: "DHCP6OptRelayMsg",
+ 11: "DHCP6OptAuth",
+ 12: "DHCP6OptServerUnicast",
+ 13: "DHCP6OptStatusCode",
+ 14: "DHCP6OptRapidCommit",
+ 15: "DHCP6OptUserClass",
+ 16: "DHCP6OptVendorClass",
+ 17: "DHCP6OptVendorSpecificInfo",
+ 18: "DHCP6OptIfaceId",
+ 19: "DHCP6OptReconfMsg",
+ 20: "DHCP6OptReconfAccept",
+ 21: "DHCP6OptSIPDomains", #RFC3319
+ 22: "DHCP6OptSIPServers", #RFC3319
+ 23: "DHCP6OptDNSServers", #RFC3646
+ 24: "DHCP6OptDNSDomains", #RFC3646
+ 25: "DHCP6OptIA_PD", #RFC3633
+ 26: "DHCP6OptIAPrefix", #RFC3633
+ 27: "DHCP6OptNISServers", #RFC3898
+ 28: "DHCP6OptNISPServers", #RFC3898
+ 29: "DHCP6OptNISDomain", #RFC3898
+ 30: "DHCP6OptNISPDomain", #RFC3898
+ 31: "DHCP6OptSNTPServers", #RFC4075
+ 32: "DHCP6OptInfoRefreshTime", #RFC4242
+ 33: "DHCP6OptBCMCSDomains", #RFC4280
+ 34: "DHCP6OptBCMCSServers", #RFC4280
+ #36: "DHCP6OptGeoConf", #RFC-ietf-geopriv-dhcp-civil-09.txt
+ 37: "DHCP6OptRemoteID", #RFC4649
+ 38: "DHCP6OptSubscriberID", #RFC4580
+ 39: "DHCP6OptClientFQDN", #RFC4704
+ #40: "DHCP6OptPANAAgent", #RFC-ietf-dhc-paa-option-05.txt
+ #41: "DHCP6OptNewPOSIXTimeZone, #RFC4833
+ #42: "DHCP6OptNewTZDBTimeZone, #RFC4833
+ 43: "DHCP6OptRelayAgentERO" #RFC4994
+ #44: "DHCP6OptLQQuery", #RFC5007
+ #45: "DHCP6OptLQClientData", #RFC5007
+ #46: "DHCP6OptLQClientTime", #RFC5007
+ #47: "DHCP6OptLQRelayData", #RFC5007
+ #48: "DHCP6OptLQClientLink", #RFC5007
+}
+
+
+# sect 5.3 RFC 3315 : DHCP6 Messages types
+dhcp6types = { 1:"SOLICIT",
+ 2:"ADVERTISE",
+ 3:"REQUEST",
+ 4:"CONFIRM",
+ 5:"RENEW",
+ 6:"REBIND",
+ 7:"REPLY",
+ 8:"RELEASE",
+ 9:"DECLINE",
+ 10:"RECONFIGURE",
+ 11:"INFORMATION-REQUEST",
+ 12:"RELAY-FORW",
+ 13:"RELAY-REPL" }
+
+
+#####################################################################
+### DHCPv6 DUID related stuff ###
+#####################################################################
+
+duidtypes = { 1: "Link-layer address plus time",
+ 2: "Vendor-assigned unique ID based on Enterprise Number",
+ 3: "Link-layer Address" }
+
+# DUID hardware types - RFC 826 - Extracted from
+# http://www.iana.org/assignments/arp-parameters on 31/10/06
+# We should add the length of every kind of address.
+duidhwtypes = { 0: "NET/ROM pseudo", # Not referenced by IANA
+ 1: "Ethernet (10Mb)",
+ 2: "Experimental Ethernet (3Mb)",
+ 3: "Amateur Radio AX.25",
+ 4: "Proteon ProNET Token Ring",
+ 5: "Chaos",
+ 6: "IEEE 802 Networks",
+ 7: "ARCNET",
+ 8: "Hyperchannel",
+ 9: "Lanstar",
+ 10: "Autonet Short Address",
+ 11: "LocalTalk",
+ 12: "LocalNet (IBM PCNet or SYTEK LocalNET)",
+ 13: "Ultra link",
+ 14: "SMDS",
+ 15: "Frame Relay",
+ 16: "Asynchronous Transmission Mode (ATM)",
+ 17: "HDLC",
+ 18: "Fibre Channel",
+ 19: "Asynchronous Transmission Mode (ATM)",
+ 20: "Serial Line",
+ 21: "Asynchronous Transmission Mode (ATM)",
+ 22: "MIL-STD-188-220",
+ 23: "Metricom",
+ 24: "IEEE 1394.1995",
+ 25: "MAPOS",
+ 26: "Twinaxial",
+ 27: "EUI-64",
+ 28: "HIPARP",
+ 29: "IP and ARP over ISO 7816-3",
+ 30: "ARPSec",
+ 31: "IPsec tunnel",
+ 32: "InfiniBand (TM)",
+ 33: "TIA-102 Project 25 Common Air Interface (CAI)" }
+
+class UTCTimeField(IntField):
+ epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0) # required Epoch
+ def i2repr(self, pkt, x):
+ x = self.i2h(pkt, x)
+ from time import gmtime, strftime, mktime
+ delta = mktime(self.epoch) - mktime(gmtime(0))
+ x = x + delta
+ t = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(x))
+ return "%s (%d)" % (t, x)
+
+class _LLAddrField(MACField):
+ pass
+
+# XXX We only support Ethernet addresses at the moment. _LLAddrField
+# will be modified when needed. Ask us. --arno
+class DUID_LLT(Packet): # sect 9.2 RFC 3315
+ name = "DUID - Link-layer address plus time"
+ fields_desc = [ ShortEnumField("type", 1, duidtypes),
+ XShortEnumField("hwtype", 1, duidhwtypes),
+ UTCTimeField("timeval", 0), # i.e. 01 Jan 2000
+ _LLAddrField("lladdr", ETHER_ANY) ]
+
+# In fact, IANA enterprise-numbers file available at
+# http//www.iana.org/asignments/enterprise-numbers)
+# is simply huge (more than 2Mo and 600Ko in bz2). I'll
+# add only most common vendors, and encountered values.
+# -- arno
+iana_enterprise_num = { 9: "ciscoSystems",
+ 35: "Nortel Networks",
+ 43: "3Com",
+ 311: "Microsoft",
+ 2636: "Juniper Networks, Inc.",
+ 4526: "Netgear",
+ 5771: "Cisco Systems, Inc.",
+ 5842: "Cisco Systems",
+ 16885: "Nortel Networks" }
+
+class DUID_EN(Packet): # sect 9.3 RFC 3315
+ name = "DUID - Assigned by Vendor Based on Enterprise Number"
+ fields_desc = [ ShortEnumField("type", 2, duidtypes),
+ IntEnumField("enterprisenum", 311, iana_enterprise_num),
+ StrField("id",b"") ]
+
+class DUID_LL(Packet): # sect 9.4 RFC 3315
+ name = "DUID - Based on Link-layer Address"
+ fields_desc = [ ShortEnumField("type", 3, duidtypes),
+ XShortEnumField("hwtype", 1, duidhwtypes),
+ _LLAddrField("lladdr", ETHER_ANY) ]
+
+duid_cls = { 1: "DUID_LLT",
+ 2: "DUID_EN",
+ 3: "DUID_LL"}
+
+#####################################################################
+### DHCPv6 Options classes ###
+#####################################################################
+
+class _DHCP6OptGuessPayload(Packet):
+ def guess_payload_class(self, payload):
+ cls = conf.raw_layer
+ if len(payload) > 2 :
+ opt = struct.unpack("!H", payload[:2])[0]
+ cls = get_cls(dhcp6opts_by_code.get(opt, "DHCP6OptUnknown"), DHCP6OptUnknown)
+ return cls
+
+class DHCP6OptUnknown(_DHCP6OptGuessPayload): # A generic DHCPv6 Option
+ name = "Unknown DHCPv6 OPtion"
+ fields_desc = [ ShortEnumField("optcode", 0, dhcp6opts),
+ FieldLenField("optlen", None, length_of="data", fmt="!H"),
+ StrLenField("data", b"",
+ length_from = lambda pkt: pkt.optlen)]
+
+class _DUIDField(PacketField):
+ holds_packets=1
+ def __init__(self, name, default, length_from=None):
+ StrField.__init__(self, name, default)
+ self.length_from = length_from
+
+ def i2m(self, pkt, i):
+ return bytes(i)
+
+ def m2i(self, pkt, x):
+ cls = conf.raw_layer
+ if len(x) > 4:
+ o = struct.unpack("!H", x[:2])[0]
+ cls = get_cls(duid_cls.get(o, conf.raw_layer), conf.raw_layer)
+ return cls(x)
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ return s[l:], self.m2i(pkt,s[:l])
+
+
+class DHCP6OptClientId(_DHCP6OptGuessPayload): # RFC sect 22.2
+ name = "DHCP6 Client Identifier Option"
+ fields_desc = [ ShortEnumField("optcode", 1, dhcp6opts),
+ FieldLenField("optlen", None, length_of="duid", fmt="!H"),
+ _DUIDField("duid", "",
+ length_from = lambda pkt: pkt.optlen) ]
+
+
+class DHCP6OptServerId(DHCP6OptClientId): # RFC sect 22.3
+ name = "DHCP6 Server Identifier Option"
+ optcode = 2
+
+# Should be encapsulated in the option field of IA_NA or IA_TA options
+# Can only appear at that location.
+# TODO : last field IAaddr-options is not defined in the reference document
+class DHCP6OptIAAddress(_DHCP6OptGuessPayload): # RFC sect 22.6
+ name = "DHCP6 IA Address Option (IA_TA or IA_NA suboption)"
+ fields_desc = [ ShortEnumField("optcode", 5, dhcp6opts),
+ FieldLenField("optlen", None, length_of="iaaddropts",
+ fmt="!H", adjust = lambda pkt,x: x+24),
+ IP6Field("addr", "::"),
+ IntField("preflft", 0),
+ IntField("validlft", 0),
+ XIntField("iaid", None),
+ StrLenField("iaaddropts", b"",
+ length_from = lambda pkt: pkt.optlen - 24) ]
+ def guess_payload_class(self, payload):
+ return conf.padding_layer
+
+class _IANAOptField(PacketListField):
+ def i2len(self, pkt, z):
+ if z is None or z == []:
+ return 0
+ return sum(map(lambda x: len(bytes(x)) ,z))
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ lst = []
+ remain, payl = s[:l], s[l:]
+ while len(remain)>0:
+ p = self.m2i(pkt,remain)
+ if conf.padding_layer in p:
+ pad = p[conf.padding_layer]
+ remain = pad.load
+ del(pad.underlayer.payload)
+ else:
+ remain = ""
+ lst.append(p)
+ return payl,lst
+
+class DHCP6OptIA_NA(_DHCP6OptGuessPayload): # RFC sect 22.4
+ name = "DHCP6 Identity Association for Non-temporary Addresses Option"
+ fields_desc = [ ShortEnumField("optcode", 3, dhcp6opts),
+ FieldLenField("optlen", None, length_of="ianaopts",
+ fmt="!H", adjust = lambda pkt,x: x+12),
+ XIntField("iaid", None),
+ IntField("T1", None),
+ IntField("T2", None),
+ _IANAOptField("ianaopts", [], DHCP6OptIAAddress,
+ length_from = lambda pkt: pkt.optlen-12) ]
+
+class _IATAOptField(_IANAOptField):
+ pass
+
+class DHCP6OptIA_TA(_DHCP6OptGuessPayload): # RFC sect 22.5
+ name = "DHCP6 Identity Association for Temporary Addresses Option"
+ fields_desc = [ ShortEnumField("optcode", 4, dhcp6opts),
+ FieldLenField("optlen", None, length_of="iataopts",
+ fmt="!H", adjust = lambda pkt,x: x+4),
+ XIntField("iaid", None),
+ _IATAOptField("iataopts", [], DHCP6OptIAAddress,
+ length_from = lambda pkt: pkt.optlen-4) ]
+
+
+#### DHCPv6 Option Request Option ###################################
+
+class _OptReqListField(StrLenField):
+ islist = 1
+ def i2h(self, pkt, x):
+ if x is None:
+ return []
+ return x
+
+ def i2len(self, pkt, x):
+ return 2*len(x)
+
+ def any2i(self, pkt, x):
+ return x
+
+ def i2repr(self, pkt, x):
+ s = []
+ for y in self.i2h(pkt, x):
+ if y in dhcp6opts:
+ s.append(dhcp6opts[y])
+ else:
+ s.append("%d" % y)
+ return "[%s]" % ", ".join(s)
+
+ def m2i(self, pkt, x):
+ r = []
+ while len(x) != 0:
+ if len(x)<2:
+ warning("Odd length for requested option field. Rejecting last byte")
+ return r
+ r.append(struct.unpack("!H", x[:2])[0])
+ x = x[2:]
+ return r
+
+ def i2m(self, pkt, x):
+ return b"".join(map(lambda y: struct.pack("!H", y), x))
+
+# A client may include an ORO in a solicit, Request, Renew, Rebind,
+# Confirm or Information-request
+class DHCP6OptOptReq(_DHCP6OptGuessPayload): # RFC sect 22.7
+ name = "DHCP6 Option Request Option"
+ fields_desc = [ ShortEnumField("optcode", 6, dhcp6opts),
+ FieldLenField("optlen", None, length_of="reqopts", fmt="!H"),
+ _OptReqListField("reqopts", [23, 24],
+ length_from = lambda pkt: pkt.optlen) ]
+
+
+#### DHCPv6 Preference Option #######################################
+
+# emise par un serveur pour affecter le choix fait par le client. Dans
+# les messages Advertise, a priori
+class DHCP6OptPref(_DHCP6OptGuessPayload): # RFC sect 22.8
+ name = "DHCP6 Preference Option"
+ fields_desc = [ ShortEnumField("optcode", 7, dhcp6opts),
+ ShortField("optlen", 1 ),
+ ByteField("prefval",255) ]
+
+
+#### DHCPv6 Elapsed Time Option #####################################
+
+class _ElapsedTimeField(ShortField):
+ def i2repr(self, pkt, x):
+ if x == 0xffff:
+ return "infinity (0xffff)"
+ return "%.2f sec" % (self.i2h(pkt, x)/100.)
+
+class DHCP6OptElapsedTime(_DHCP6OptGuessPayload):# RFC sect 22.9
+ name = "DHCP6 Elapsed Time Option"
+ fields_desc = [ ShortEnumField("optcode", 8, dhcp6opts),
+ ShortField("optlen", 2),
+ _ElapsedTimeField("elapsedtime", 0) ]
+
+
+#### DHCPv6 Relay Message Option ####################################
+
+# Relayed message is seen as a payload.
+class DHCP6OptRelayMsg(_DHCP6OptGuessPayload):# RFC sect 22.10
+ name = "DHCP6 Relay Message Option"
+ fields_desc = [ ShortEnumField("optcode", 9, dhcp6opts),
+ ShortField("optlen", None ) ]
+ def post_build(self, p, pay):
+ if self.optlen is None:
+ l = len(pay)
+ p = p[:2]+struct.pack("!H", l)
+ return p + pay
+
+
+#### DHCPv6 Authentication Option ###################################
+
+# The following fields are set in an Authentication option for the
+# Reconfigure Key Authentication Protocol:
+#
+# protocol 3
+#
+# algorithm 1
+#
+# RDM 0
+#
+# The format of the Authentication information for the Reconfigure Key
+# Authentication Protocol is:
+#
+# 0 1 2 3
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+# | Type | Value (128 bits) |
+# +-+-+-+-+-+-+-+-+ |
+# . .
+# . .
+# . +-+-+-+-+-+-+-+-+
+# | |
+# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+#
+# Type Type of data in Value field carried in this option:
+#
+# 1 Reconfigure Key value (used in Reply message).
+#
+# 2 HMAC-MD5 digest of the message (used in Reconfigure
+# message).
+#
+# Value Data as defined by field.
+
+
+# TODO : Decoding only at the moment
+class DHCP6OptAuth(_DHCP6OptGuessPayload): # RFC sect 22.11
+ name = "DHCP6 Option - Authentication"
+ fields_desc = [ ShortEnumField("optcode", 11, dhcp6opts),
+ FieldLenField("optlen", None, length_of="authinfo",
+ adjust = lambda pkt,x: x+11),
+ ByteField("proto", 3), # TODO : XXX
+ ByteField("alg", 1), # TODO : XXX
+ ByteField("rdm", 0), # TODO : XXX
+ StrFixedLenField("replay", b"A"*8, 8), # TODO: XXX
+ StrLenField("authinfo", b"",
+ length_from = lambda pkt: pkt.optlen - 11) ]
+
+#### DHCPv6 Server Unicast Option ###################################
+
+class _SrvAddrField(IP6Field):
+ def i2h(self, pkt, x):
+ if x is None:
+ return "::"
+ return x
+
+ def i2m(self, pkt, x):
+ return inet_pton(socket.AF_INET6, self.i2h(pkt,x))
+
+class DHCP6OptServerUnicast(_DHCP6OptGuessPayload):# RFC sect 22.12
+ name = "DHCP6 Server Unicast Option"
+ fields_desc = [ ShortEnumField("optcode", 12, dhcp6opts),
+ ShortField("optlen", 16 ),
+ _SrvAddrField("srvaddr",None) ]
+
+
+#### DHCPv6 Status Code Option ######################################
+
+dhcp6statuscodes = { 0:"Success", # sect 24.4
+ 1:"UnspecFail",
+ 2:"NoAddrsAvail",
+ 3:"NoBinding",
+ 4:"NotOnLink",
+ 5:"UseMulticast",
+ 6:"NoPrefixAvail"} # From RFC3633
+
+class DHCP6OptStatusCode(_DHCP6OptGuessPayload):# RFC sect 22.13
+ name = "DHCP6 Status Code Option"
+ fields_desc = [ ShortEnumField("optcode", 13, dhcp6opts),
+ FieldLenField("optlen", None, length_of="statusmsg",
+ fmt="!H", adjust = lambda pkt,x:x+2),
+ ShortEnumField("statuscode",None,dhcp6statuscodes),
+ StrLenField("statusmsg", b"",
+ length_from = lambda pkt: pkt.optlen-2) ]
+
+
+#### DHCPv6 Rapid Commit Option #####################################
+
+class DHCP6OptRapidCommit(_DHCP6OptGuessPayload): # RFC sect 22.14
+ name = "DHCP6 Rapid Commit Option"
+ fields_desc = [ ShortEnumField("optcode", 14, dhcp6opts),
+ ShortField("optlen", 0)]
+
+
+#### DHCPv6 User Class Option #######################################
+
+class _UserClassDataField(PacketListField):
+ def i2len(self, pkt, z):
+ if z is None or z == []:
+ return 0
+ return sum(map(lambda x: len(bytes(x)) ,z))
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ lst = []
+ remain, payl = s[:l], s[l:]
+ while len(remain)>0:
+ p = self.m2i(pkt,remain)
+ if conf.padding_layer in p:
+ pad = p[conf.padding_layer]
+ remain = pad.load
+ del(pad.underlayer.payload)
+ else:
+ remain = b""
+ lst.append(p)
+ return payl,lst
+
+
+class USER_CLASS_DATA(Packet):
+ name = "user class data"
+ fields_desc = [ FieldLenField("len", None, length_of="data"),
+ StrLenField("data", b"",
+ length_from = lambda pkt: pkt.len) ]
+ def guess_payload_class(self, payload):
+ return conf.padding_layer
+
+class DHCP6OptUserClass(_DHCP6OptGuessPayload):# RFC sect 22.15
+ name = "DHCP6 User Class Option"
+ fields_desc = [ ShortEnumField("optcode", 15, dhcp6opts),
+ FieldLenField("optlen", None, fmt="!H",
+ length_of="userclassdata"),
+ _UserClassDataField("userclassdata", [], USER_CLASS_DATA,
+ length_from = lambda pkt: pkt.optlen) ]
+
+
+#### DHCPv6 Vendor Class Option #####################################
+
+class _VendorClassDataField(_UserClassDataField):
+ pass
+
+class VENDOR_CLASS_DATA(USER_CLASS_DATA):
+ name = "vendor class data"
+
+class DHCP6OptVendorClass(_DHCP6OptGuessPayload):# RFC sect 22.16
+ name = "DHCP6 Vendor Class Option"
+ fields_desc = [ ShortEnumField("optcode", 16, dhcp6opts),
+ FieldLenField("optlen", None, length_of="vcdata", fmt="!H",
+ adjust = lambda pkt,x: x+4),
+ IntEnumField("enterprisenum",None , iana_enterprise_num ),
+ _VendorClassDataField("vcdata", [], VENDOR_CLASS_DATA,
+ length_from = lambda pkt: pkt.optlen-4) ]
+
+#### DHCPv6 Vendor-Specific Information Option ######################
+
+class VENDOR_SPECIFIC_OPTION(_DHCP6OptGuessPayload):
+ name = "vendor specific option data"
+ fields_desc = [ ShortField("optcode", None),
+ FieldLenField("optlen", None, length_of="optdata"),
+ StrLenField("optdata", b"",
+ length_from = lambda pkt: pkt.optlen) ]
+ def guess_payload_class(self, payload):
+ return conf.padding_layer
+
+# The third one that will be used for nothing interesting
+class DHCP6OptVendorSpecificInfo(_DHCP6OptGuessPayload):# RFC sect 22.17
+ name = "DHCP6 Vendor-specific Information Option"
+ fields_desc = [ ShortEnumField("optcode", 17, dhcp6opts),
+ FieldLenField("optlen", None, length_of="vso", fmt="!H",
+ adjust = lambda pkt,x: x+4),
+ IntEnumField("enterprisenum",None , iana_enterprise_num),
+ _VendorClassDataField("vso", [], VENDOR_SPECIFIC_OPTION,
+ length_from = lambda pkt: pkt.optlen-4) ]
+
+#### DHCPv6 Interface-ID Option #####################################
+
+# Repasser sur cette option a la fin. Elle a pas l'air d'etre des
+# masses critique.
+class DHCP6OptIfaceId(_DHCP6OptGuessPayload):# RFC sect 22.18
+ name = "DHCP6 Interface-Id Option"
+ fields_desc = [ ShortEnumField("optcode", 18, dhcp6opts),
+ FieldLenField("optlen", None, fmt="!H",
+ length_of="ifaceid"),
+ StrLenField("ifaceid", b"",
+ length_from = lambda pkt: pkt.optlen) ]
+
+
+#### DHCPv6 Reconfigure Message Option ##############################
+
+# A server includes a Reconfigure Message option in a Reconfigure
+# message to indicate to the client whether the client responds with a
+# renew message or an Informatiion-request message.
+class DHCP6OptReconfMsg(_DHCP6OptGuessPayload): # RFC sect 22.19
+ name = "DHCP6 Reconfigure Message Option"
+ fields_desc = [ ShortEnumField("optcode", 19, dhcp6opts),
+ ShortField("optlen", 1 ),
+ ByteEnumField("msgtype", 11, { 5:"Renew Message",
+ 11:"Information Request"}) ]
+
+
+#### DHCPv6 Reconfigure Accept Option ###############################
+
+# A client uses the Reconfigure Accept option to announce to the
+# server whether the client is willing to accept Recoonfigure
+# messages, and a server uses this option to tell the client whether
+# or not to accept Reconfigure messages. The default behavior in the
+# absence of this option, means unwillingness to accept reconfigure
+# messages, or instruction not to accept Reconfigure messages, for the
+# client and server messages, respectively.
+class DHCP6OptReconfAccept(_DHCP6OptGuessPayload): # RFC sect 22.20
+ name = "DHCP6 Reconfigure Accept Option"
+ fields_desc = [ ShortEnumField("optcode", 20, dhcp6opts),
+ ShortField("optlen", 0)]
+
+# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
+# described in section 3.1 of RFC 1035
+# XXX Label should be at most 63 octets in length : we do not enforce it
+# Total length of domain should be 255 : we do not enforce it either
+class DomainNameListField(StrLenField):
+ islist = 1
+
+ def i2len(self, pkt, x):
+ return len(self.i2m(pkt, x))
+
+ def m2i(self, pkt, x):
+ res = []
+ while x:
+ cur = []
+ #while x and x[0] != b'\x00':
+ while x and x[0] != 0:
+ l = (x[0])
+ cur.append(x[1:l+1])
+ x = x[l+1:]
+ res.append(b".".join(cur))
+ if x and x[0] == 0:
+ x = x[1:]
+ return res
+
+ def i2m(self, pkt, x):
+ def conditionalTrailingDot(z):
+ if z and z[-1] == 0:
+ return z
+ return z+b'\x00'
+ res = b""
+ x = [ i.encode('ascii') for i in x if type(i) is str ]
+ tmp = map(lambda y: map((lambda z: chr(len(z)).encode('ascii')+z), y.split(b'.')), x)
+ return b"".join(map(lambda x: conditionalTrailingDot(b"".join(x)), tmp))
+
+class DHCP6OptSIPDomains(_DHCP6OptGuessPayload): #RFC3319
+ name = "DHCP6 Option - SIP Servers Domain Name List"
+ fields_desc = [ ShortEnumField("optcode", 21, dhcp6opts),
+ FieldLenField("optlen", None, length_of="sipdomains"),
+ DomainNameListField("sipdomains", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptSIPServers(_DHCP6OptGuessPayload): #RFC3319
+ name = "DHCP6 Option - SIP Servers IPv6 Address List"
+ fields_desc = [ ShortEnumField("optcode", 22, dhcp6opts),
+ FieldLenField("optlen", None, length_of="sipservers"),
+ IP6ListField("sipservers", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptDNSServers(_DHCP6OptGuessPayload): #RFC3646
+ name = "DHCP6 Option - DNS Recursive Name Server"
+ fields_desc = [ ShortEnumField("optcode", 23, dhcp6opts),
+ FieldLenField("optlen", None, length_of="dnsservers"),
+ IP6ListField("dnsservers", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptDNSDomains(_DHCP6OptGuessPayload): #RFC3646
+ name = "DHCP6 Option - Domain Search List option"
+ fields_desc = [ ShortEnumField("optcode", 24, dhcp6opts),
+ FieldLenField("optlen", None, length_of="dnsdomains"),
+ DomainNameListField("dnsdomains", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+# TODO: Implement iaprefopts correctly when provided with more
+# information about it.
+class DHCP6OptIAPrefix(_DHCP6OptGuessPayload): #RFC3633
+ name = "DHCP6 Option - IA_PD Prefix option"
+ fields_desc = [ ShortEnumField("optcode", 26, dhcp6opts),
+ FieldLenField("optlen", None, length_of="iaprefopts",
+ adjust = lambda pkt,x: x+26),
+ IntField("preflft", 0),
+ IntField("validlft", 0),
+ ByteField("plen", 48), # TODO: Challenge that default value
+ IP6Field("prefix", "2001:db8::"), # At least, global and won't hurt
+ StrLenField("iaprefopts", b"",
+ length_from = lambda pkt: pkt.optlen-26) ]
+
+class DHCP6OptIA_PD(_DHCP6OptGuessPayload): #RFC3633
+ name = "DHCP6 Option - Identity Association for Prefix Delegation"
+ fields_desc = [ ShortEnumField("optcode", 25, dhcp6opts),
+ FieldLenField("optlen", None, length_of="iapdopt",
+ adjust = lambda pkt,x: x+12),
+ IntField("iaid", 0),
+ IntField("T1", 0),
+ IntField("T2", 0),
+ PacketListField("iapdopt", [], DHCP6OptIAPrefix,
+ length_from = lambda pkt: pkt.optlen-12) ]
+
+class DHCP6OptNISServers(_DHCP6OptGuessPayload): #RFC3898
+ name = "DHCP6 Option - NIS Servers"
+ fields_desc = [ ShortEnumField("optcode", 27, dhcp6opts),
+ FieldLenField("optlen", None, length_of="nisservers"),
+ IP6ListField("nisservers", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptNISPServers(_DHCP6OptGuessPayload): #RFC3898
+ name = "DHCP6 Option - NIS+ Servers"
+ fields_desc = [ ShortEnumField("optcode", 28, dhcp6opts),
+ FieldLenField("optlen", None, length_of="nispservers"),
+ IP6ListField("nispservers", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DomainNameField(StrLenField):
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ return s[l:], self.m2i(pkt,s[:l])
+
+ def i2len(self, pkt, x):
+ return len(self.i2m(pkt, x))
+
+ def m2i(self, pkt, x):
+ cur = []
+ while x:
+ l = (x[0])
+ cur.append(x[1:1+l])
+ x = x[l+1:]
+ ret_str = b".".join(cur)
+ return ret_str
+
+ def i2m(self, pkt, x):
+ if not x:
+ return b""
+ tmp = b"".join(map(lambda z: chr(len(z)).encode('ascii')+z, x.split(b'.')))
+ return tmp
+
+class DHCP6OptNISDomain(_DHCP6OptGuessPayload): #RFC3898
+ name = "DHCP6 Option - NIS Domain Name"
+ fields_desc = [ ShortEnumField("optcode", 29, dhcp6opts),
+ FieldLenField("optlen", None, length_of="nisdomain"),
+ DomainNameField("nisdomain", "",
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptNISPDomain(_DHCP6OptGuessPayload): #RFC3898
+ name = "DHCP6 Option - NIS+ Domain Name"
+ fields_desc = [ ShortEnumField("optcode", 30, dhcp6opts),
+ FieldLenField("optlen", None, length_of="nispdomain"),
+ DomainNameField("nispdomain", "",
+ length_from= lambda pkt: pkt.optlen) ]
+
+class DHCP6OptSNTPServers(_DHCP6OptGuessPayload): #RFC4075
+ name = "DHCP6 option - SNTP Servers"
+ fields_desc = [ ShortEnumField("optcode", 31, dhcp6opts),
+ FieldLenField("optlen", None, length_of="sntpservers"),
+ IP6ListField("sntpservers", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+IRT_DEFAULT=86400
+IRT_MINIMUM=600
+class DHCP6OptInfoRefreshTime(_DHCP6OptGuessPayload): #RFC4242
+ name = "DHCP6 Option - Information Refresh Time"
+ fields_desc = [ ShortEnumField("optcode", 32, dhcp6opts),
+ ShortField("optlen", 4),
+ IntField("reftime", IRT_DEFAULT)] # One day
+
+class DHCP6OptBCMCSDomains(_DHCP6OptGuessPayload): #RFC4280
+ name = "DHCP6 Option - BCMCS Domain Name List"
+ fields_desc = [ ShortEnumField("optcode", 33, dhcp6opts),
+ FieldLenField("optlen", None, length_of="bcmcsdomains"),
+ DomainNameListField("bcmcsdomains", [],
+ length_from = lambda pkt: pkt.optlen) ]
+
+class DHCP6OptBCMCSServers(_DHCP6OptGuessPayload): #RFC4280
+ name = "DHCP6 Option - BCMCS Addresses List"
+ fields_desc = [ ShortEnumField("optcode", 34, dhcp6opts),
+ FieldLenField("optlen", None, length_of="bcmcsservers"),
+ IP6ListField("bcmcsservers", [],
+ length_from= lambda pkt: pkt.optlen) ]
+
+# TODO : Does Nothing at the moment
+class DHCP6OptGeoConf(_DHCP6OptGuessPayload): #RFC-ietf-geopriv-dhcp-civil-09.txt
+ name = ""
+ fields_desc = [ ShortEnumField("optcode", 36, dhcp6opts),
+ FieldLenField("optlen", None, length_of="optdata"),
+ StrLenField("optdata", "",
+ length_from = lambda pkt: pkt.optlen) ]
+
+# TODO: see if we encounter opaque values from vendor devices
+class DHCP6OptRemoteID(_DHCP6OptGuessPayload): #RFC4649
+ name = "DHCP6 Option - Relay Agent Remote-ID"
+ fields_desc = [ ShortEnumField("optcode", 37, dhcp6opts),
+ FieldLenField("optlen", None, length_of="remoteid",
+ adjust = lambda pkt,x: x+4),
+ IntEnumField("enterprisenum", None, iana_enterprise_num),
+ StrLenField("remoteid", b"",
+ length_from = lambda pkt: pkt.optlen-4) ]
+
+# TODO : 'subscriberid' default value should be at least 1 byte long
+class DHCP6OptSubscriberID(_DHCP6OptGuessPayload): #RFC4580
+ name = "DHCP6 Option - Subscriber ID"
+ fields_desc = [ ShortEnumField("optcode", 38, dhcp6opts),
+ FieldLenField("optlen", None, length_of="subscriberid"),
+ StrLenField("subscriberid", b"",
+ length_from = lambda pkt: pkt.optlen) ]
+
+# TODO : "The data in the Domain Name field MUST be encoded
+# as described in Section 8 of [5]"
+class DHCP6OptClientFQDN(_DHCP6OptGuessPayload): #RFC4704
+ name = "DHCP6 Option - Client FQDN"
+ fields_desc = [ ShortEnumField("optcode", 39, dhcp6opts),
+ FieldLenField("optlen", None, length_of="fqdn",
+ adjust = lambda pkt,x: x+1),
+ BitField("res", 0, 5),
+ FlagsField("flags", 0, 3, "SON" ),
+ DomainNameField("fqdn", "",
+ length_from = lambda pkt: pkt.optlen-1) ]
+
+class DHCP6OptRelayAgentERO(_DHCP6OptGuessPayload): # RFC4994
+ name = "DHCP6 Option - RelayRequest Option"
+ fields_desc = [ ShortEnumField("optcode", 43, dhcp6opts),
+ FieldLenField("optlen", None, length_of="reqopts", fmt="!H"),
+ _OptReqListField("reqopts", [23, 24],
+ length_from = lambda pkt: pkt.optlen) ]
+
+#####################################################################
+### DHCPv6 messages ###
+#####################################################################
+
+# Some state parameters of the protocols that should probably be
+# useful to have in the configuration (and keep up-to-date)
+DHCP6RelayAgentUnicastAddr=""
+DHCP6RelayHopCount=""
+DHCP6ServerUnicastAddr=""
+DHCP6ClientUnicastAddr=""
+DHCP6ClientIA_TA=""
+DHCP6ClientIA_NA=""
+DHCP6ClientIAID=""
+T1="" # Voir 2462
+T2="" # Voir 2462
+DHCP6ServerDUID=""
+DHCP6CurrentTransactionID="" # devrait etre utilise pour matcher une
+# reponse et mis a jour en mode client par une valeur aleatoire pour
+# laquelle on attend un retour de la part d'un serveur.
+DHCP6PrefVal="" # la valeur de preference a utiliser dans
+# les options preference
+
+# Emitted by :
+# - server : ADVERTISE, REPLY, RECONFIGURE, RELAY-REPL (vers relay)
+# - client : SOLICIT, REQUEST, CONFIRM, RENEW, REBIND, RELEASE, DECLINE,
+# INFORMATION REQUEST
+# - relay : RELAY-FORW (toward server)
+
+class _DHCP6GuessPayload(Packet):
+ def guess_payload_class(self, payload):
+ if len(payload) > 1 :
+ print((payload[0]))
+ return get_cls(dhcp6opts.get(ord(payload[0]),"DHCP6OptUnknown"), conf.raw_layer)
+ return conf.raw_layer
+
+#####################################################################
+## DHCPv6 messages sent between Clients and Servers (types 1 to 11)
+# Comme specifie en section 15.1 de la RFC 3315, les valeurs de
+# transaction id sont selectionnees de maniere aleatoire par le client
+# a chaque emission et doivent matcher dans les reponses faites par
+# les clients
+class DHCP6(_DHCP6OptGuessPayload):
+ name = "DHCPv6 Generic Message)"
+ fields_desc = [ ByteEnumField("msgtype",None,dhcp6types),
+ X3BytesField("trid",0x000000) ]
+ overload_fields = { UDP: {"sport": 546, "dport": 547} }
+
+ def hashret(self):
+ return struct.pack("!I", self.trid)[1:4]
+
+#####################################################################
+# Solicit Message : sect 17.1.1 RFC3315
+# - sent by client
+# - must include a client identifier option
+# - the client may include IA options for any IAs to which it wants the
+# server to assign address
+# - The client use IA_NA options to request the assignment of
+# non-temporary addresses and uses IA_TA options to request the
+# assignment of temporary addresses
+# - The client should include an Option Request option to indicate the
+# options the client is interested in receiving (eventually
+# including hints)
+# - The client includes a Reconfigure Accept option if is willing to
+# accept Reconfigure messages from the server.
+# Le cas du send and reply est assez particulier car suivant la
+# presence d'une option rapid commit dans le solicit, l'attente
+# s'arrete au premier message de reponse recu ou alors apres un
+# timeout. De la meme maniere, si un message Advertise arrive avec une
+# valeur de preference de 255, il arrete l'attente et envoie une
+# Request.
+# - The client announces its intention to use DHCP authentication by
+# including an Authentication option in its solicit message. The
+# server selects a key for the client based on the client's DUID. The
+# client and server use that key to authenticate all DHCP messages
+# exchanged during the session
+
+class DHCP6_Solicit(DHCP6):
+ name = "DHCPv6 Solicit Message"
+ msgtype = 1
+ overload_fields = { UDP: {"sport": 546, "dport": 547} }
+
+#####################################################################
+# Advertise Message
+# - sent by server
+# - Includes a server identifier option
+# - Includes a client identifier option
+# - the client identifier option must match the client's DUID
+# - transaction ID must match
+
+class DHCP6_Advertise(DHCP6):
+ name = "DHCPv6 Advertise Message"
+ msgtype = 2
+ overload_fields = { UDP: {"sport": 547, "dport": 546} }
+
+ def answers(self, other):
+ return (isinstance(other,DHCP6_Solicit) and
+ other.msgtype == 1 and
+ self.trid == other.trid)
+
+#####################################################################
+# Request Message
+# - sent by clients
+# - includes a server identifier option
+# - the content of Server Identifier option must match server's DUID
+# - includes a client identifier option
+# - must include an ORO Option (even with hints) p40
+# - can includes a reconfigure Accept option indicating whether or
+# not the client is willing to accept Reconfigure messages from
+# the server (p40)
+# - When the server receives a Request message via unicast from a
+# client to which the server has not sent a unicast option, the server
+# discards the Request message and responds with a Reply message
+# containinig Status Code option with the value UseMulticast, a Server
+# Identifier Option containing the server's DUID, the client
+# Identifier option from the client message and no other option.
+
+class DHCP6_Request(DHCP6):
+ name = "DHCPv6 Request Message"
+ msgtype = 3
+
+#####################################################################
+# Confirm Message
+# - sent by clients
+# - must include a clien identifier option
+# - When the server receives a Confirm Message, the server determines
+# whether the addresses in the Confirm message are appropriate for the
+# link to which the client is attached. cf p50
+
+class DHCP6_Confirm(DHCP6):
+ name = "DHCPv6 Confirm Message"
+ msgtype = 4
+
+#####################################################################
+# Renew Message
+# - sent by clients
+# - must include a server identifier option
+# - content of server identifier option must match the server's identifier
+# - must include a client identifier option
+# - the clients includes any IA assigned to the interface that may
+# have moved to a new link, along with the addresses associated with
+# those IAs in its confirm messages
+# - When the server receives a Renew message that contains an IA
+# option from a client, it locates the client's binding and verifies
+# that the information in the IA from the client matches the
+# information for that client. If the server cannot find a client
+# entry for the IA the server returns the IA containing no addresses
+# with a status code option est to NoBinding in the Reply message. cf
+# p51 pour le reste.
+
+class DHCP6_Renew(DHCP6):
+ name = "DHCPv6 Renew Message"
+ msgtype = 5
+
+#####################################################################
+# Rebind Message
+# - sent by clients
+# - must include a client identifier option
+# cf p52
+
+class DHCP6_Rebind(DHCP6):
+ name = "DHCPv6 Rebind Message"
+ msgtype = 6
+
+#####################################################################
+# Reply Message
+# - sent by servers
+# - the message must include a server identifier option
+# - transaction-id field must match the value of original message
+# The server includes a Rapid Commit option in the Reply message to
+# indicate that the reply is in response to a solicit message
+# - if the client receives a reply message with a Status code option
+# with the value UseMulticast, the client records the receipt of the
+# message and sends subsequent messages to the server through the
+# interface on which the message was received using multicast. The
+# client resends the original message using multicast
+# - When the client receives a NotOnLink status from the server in
+# response to a Confirm message, the client performs DHCP server
+# solicitation as described in section 17 and client-initiated
+# configuration as descrribed in section 18 (RFC 3315)
+# - when the client receives a NotOnLink status from the server in
+# response to a Request, the client can either re-issue the Request
+# without specifying any addresses or restart the DHCP server
+# discovery process.
+# - the server must include a server identifier option containing the
+# server's DUID in the Reply message
+
+class DHCP6_Reply(DHCP6):
+ name = "DHCPv6 Reply Message"
+ msgtype = 7
+
+ overload_fields = { UDP: {"sport": 547, "dport": 546} }
+
+ def answers(self, other):
+
+ types = (DHCP6_InfoRequest, DHCP6_Confirm, DHCP6_Rebind, DHCP6_Decline, DHCP6_Request, DHCP6_Release, DHCP6_Renew)
+
+ return (isinstance(other, types) and
+ self.trid == other.trid)
+
+#####################################################################
+# Release Message
+# - sent by clients
+# - must include a server identifier option
+# cf p53
+
+class DHCP6_Release(DHCP6):
+ name = "DHCPv6 Release Message"
+ msgtype = 8
+
+#####################################################################
+# Decline Message
+# - sent by clients
+# - must include a client identifier option
+# - Server identifier option must match server identifier
+# - The addresses to be declined must be included in the IAs. Any
+# addresses for the IAs the client wishes to continue to use should
+# not be in added to the IAs.
+# - cf p54
+
+class DHCP6_Decline(DHCP6):
+ name = "DHCPv6 Decline Message"
+ msgtype = 9
+
+#####################################################################
+# Reconfigure Message
+# - sent by servers
+# - must be unicast to the client
+# - must include a server identifier option
+# - must include a client identifier option that contains the client DUID
+# - must contain a Reconfigure Message Option and the message type
+# must be a valid value
+# - the server sets the transaction-id to 0
+# - The server must use DHCP Authentication in the Reconfigure
+# message. Autant dire que ca va pas etre le type de message qu'on va
+# voir le plus souvent.
+
+class DHCP6_Reconf(DHCP6):
+ name = "DHCPv6 Reconfigure Message"
+ msgtype = 10
+ overload_fields = { UDP: { "sport": 547, "dport": 546 } }
+
+
+#####################################################################
+# Information-Request Message
+# - sent by clients when needs configuration information but no
+# addresses.
+# - client should include a client identifier option to identify
+# itself. If it doesn't the server is not able to return client
+# specific options or the server can choose to not respond to the
+# message at all. The client must include a client identifier option
+# if the message will be authenticated.
+# - client must include an ORO of option she's interested in receiving
+# (can include hints)
+
+class DHCP6_InfoRequest(DHCP6):
+ name = "DHCPv6 Information Request Message"
+ msgtype = 11
+
+#####################################################################
+# sent between Relay Agents and Servers
+#
+# Normalement, doit inclure une option "Relay Message Option"
+# peut en inclure d'autres.
+# voir section 7.1 de la 3315
+
+# Relay-Forward Message
+# - sent by relay agents to servers
+# If the relay agent relays messages to the All_DHCP_Servers multicast
+# address or other multicast addresses, it sets the Hop Limit field to
+# 32.
+
+class DHCP6_RelayForward(_DHCP6GuessPayload,Packet):
+ name = "DHCPv6 Relay Forward Message (Relay Agent/Server Message)"
+ fields_desc = [ ByteEnumField("msgtype", 12, dhcp6types),
+ ByteField("hopcount", None),
+ IP6Field("linkaddr", "::"),
+ IP6Field("peeraddr", "::") ]
+ def hashret(self): # we filter on peer address field
+ return inet_pton(socket.AF_INET6, self.peeraddr)
+
+#####################################################################
+# sent between Relay Agents and Servers
+# Normalement, doit inclure une option "Relay Message Option"
+# peut en inclure d'autres.
+# Les valeurs des champs hop-count, link-addr et peer-addr
+# sont copiees du messsage Forward associe. POur le suivi de session.
+# Pour le moment, comme decrit dans le commentaire, le hashret
+# se limite au contenu du champ peer address.
+# Voir section 7.2 de la 3315.
+
+# Relay-Reply Message
+# - sent by servers to relay agents
+# - if the solicit message was received in a Relay-Forward message,
+# the server constructs a relay-reply message with the Advertise
+# message in the payload of a relay-message. cf page 37/101. Envoie de
+# ce message en unicast au relay-agent. utilisation de l'adresse ip
+# presente en ip source du paquet recu
+
+class DHCP6_RelayReply(DHCP6_RelayForward):
+ name = "DHCPv6 Relay Reply Message (Relay Agent/Server Message)"
+ msgtype = 13
+ def hashret(self): # We filter on peer address field.
+ return inet_pton(socket.AF_INET6, self.peeraddr)
+ def answers(self, other):
+ return (isinstance(other, DHCP6_RelayForward) and
+ self.hopcount == other.hopcount and
+ self.linkaddr == other.linkaddr and
+ self.peeraddr == other.peeraddr )
+
+
+dhcp6_cls_by_type = { 1: "DHCP6_Solicit",
+ 2: "DHCP6_Advertise",
+ 3: "DHCP6_Request",
+ 4: "DHCP6_Confirm",
+ 5: "DHCP6_Renew",
+ 6: "DHCP6_Rebind",
+ 7: "DHCP6_Reply",
+ 8: "DHCP6_Release",
+ 9: "DHCP6_Decline",
+ 10: "DHCP6_Reconf",
+ 11: "DHCP6_InfoRequest",
+ 12: "DHCP6_RelayForward",
+ 13: "DHCP6_RelayReply" }
+
+def _dhcp6_dispatcher(x, *args, **kargs):
+ cls = conf.raw_layer
+ if len(x) >= 2:
+ cls = get_cls(dhcp6_cls_by_type.get((x[0]), "Raw"), conf.raw_layer)
+ return cls(x, *args, **kargs)
+
+bind_bottom_up(UDP, _dhcp6_dispatcher, { "dport": 547 } )
+bind_bottom_up(UDP, _dhcp6_dispatcher, { "dport": 546 } )
+
+
+
+class DHCPv6_am(AnsweringMachine):
+ function_name = "dhcp6d"
+ filter = "udp and port 546 and port 547"
+ send_function = staticmethod(send)
+ def usage(self):
+ msg = """
+dhcp6d( 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,
+ bcmcsdomain=None, bcmcsservers=None)
+
+ debug : When set, additional debugging information is printed.
+
+ duid : some DUID class (DUID_LLT, DUID_LL or DUID_EN). If none
+ is provided a DUID_LLT is constructed based on the MAC
+ address of the sending interface and launch time of dhcp6d
+ answering machine.
+
+ iface : the interface to listen/reply on if you do not want to use
+ conf.iface6.
+
+ advpref : Value in [0,255] given to Advertise preference field.
+ By default, 255 is used. Be aware that this specific
+ value makes clients stops waiting for further Advertise
+ messages from other servers.
+
+ dns : list of recursive DNS servers addresses (as a string or list).
+ By default, it is set empty and the associated DHCP6OptDNSServers
+ option is inactive. See RFC 3646 for details.
+ domain : a list of DNS search domain (as a string or list). By default,
+ it is empty and the associated DHCP6OptDomains option is inactive.
+ See RFC 3646 for details.
+
+ sntpservers : a list of SNTP servers IPv6 addresses. By default,
+ it is empty and the associated DHCP6OptSNTPServers option
+ is inactive.
+
+ sipdomains : a list of SIP domains. By default, it is empty and the
+ associated DHCP6OptSIPDomains option is inactive. See RFC 3319
+ for details.
+ sipservers : a list of SIP servers IPv6 addresses. By default, it is
+ empty and the associated DHCP6OptSIPDomains option is inactive.
+ See RFC 3319 for details.
+
+ nisdomain : a list of NIS domains. By default, it is empty and the
+ associated DHCP6OptNISDomains option is inactive. See RFC 3898
+ for details. See RFC 3646 for details.
+ nisservers : a list of NIS servers IPv6 addresses. By default, it is
+ empty and the associated DHCP6OptNISServers option is inactive.
+ See RFC 3646 for details.
+
+ nispdomain : a list of NIS+ domains. By default, it is empty and the
+ associated DHCP6OptNISPDomains option is inactive. See RFC 3898
+ for details.
+ nispservers : a list of NIS+ servers IPv6 addresses. By default, it is
+ empty and the associated DHCP6OptNISServers option is inactive.
+ See RFC 3898 for details.
+
+ bcmcsdomain : a list of BCMCS domains. By default, it is empty and the
+ associated DHCP6OptBCMCSDomains option is inactive. See RFC 4280
+ for details.
+ bcmcsservers : a list of BCMCS servers IPv6 addresses. By default, it is
+ empty and the associated DHCP6OptBCMCSServers option is inactive.
+ See RFC 4280 for details.
+
+ If you have a need for others, just ask ... or provide a patch."""
+ print(msg)
+
+ def parse_options(self, dns="2001:500::1035", domain="localdomain, local",
+ startip="2001:db8::1", endip="2001:db8::20", duid=None,
+ sntpservers=None, sipdomains=None, sipservers=None,
+ nisdomain=None, nisservers=None, nispdomain=None,
+ nispservers=None, bcmcsservers=None, bcmcsdomains=None,
+ iface=None, debug=0, advpref=255):
+ def norm_list(val, param_name):
+ if val is None:
+ return None
+ if type(val) is list:
+ return val
+ elif type(val) is str:
+ l = val.split(',')
+ return map(lambda x: x.strip(), l)
+ else:
+ print("Bad '%s' parameter provided." % param_name)
+ self.usage()
+ return -1
+
+ if iface is None:
+ iface = conf.iface6
+
+ self.debug = debug
+
+ # Dictionary of provided DHCPv6 options, keyed by option type
+ self.dhcpv6_options={}
+
+ for o in [(dns, "dns", 23, lambda x: DHCP6OptDNSServers(dnsservers=x)),
+ (domain, "domain", 24, lambda x: DHCP6OptDNSDomains(dnsdomains=x)),
+ (sntpservers, "sntpservers", 31, lambda x: DHCP6OptSNTPServers(sntpservers=x)),
+ (sipservers, "sipservers", 22, lambda x: DHCP6OptSIPServers(sipservers=x)),
+ (sipdomains, "sipdomains", 21, lambda x: DHCP6OptSIPDomains(sipdomains=x)),
+ (nisservers, "nisservers", 27, lambda x: DHCP6OptNISServers(nisservers=x)),
+ (nisdomain, "nisdomain", 29, lambda x: DHCP6OptNISDomain(nisdomain=(x+[""])[0])),
+ (nispservers, "nispservers", 28, lambda x: DHCP6OptNISPServers(nispservers=x)),
+ (nispdomain, "nispdomain", 30, lambda x: DHCP6OptNISPDomain(nispdomain=(x+[""])[0])),
+ (bcmcsservers, "bcmcsservers", 33, lambda x: DHCP6OptBCMCSServers(bcmcsservers=x)),
+ (bcmcsdomains, "bcmcsdomains", 34, lambda x: DHCP6OptBCMCSDomains(bcmcsdomains=x))]:
+
+ opt = norm_list(o[0], o[1])
+ if opt == -1: # Usage() was triggered
+ return False
+ elif opt is None: # We won't return that option
+ pass
+ else:
+ self.dhcpv6_options[o[2]] = o[3](opt)
+
+ if self.debug:
+ print("\n[+] List of active DHCPv6 options:")
+ opts = self.dhcpv6_options.keys()
+ opts.sort()
+ for i in opts:
+ print(" %d: %s" % (i, repr(self.dhcpv6_options[i])))
+
+ # Preference value used in Advertise.
+ self.advpref = advpref
+
+ # IP Pool
+ self.startip = startip
+ self.endip = endip
+ # XXX TODO Check IPs are in same subnet
+
+ ####
+ # The interface we are listening/replying on
+ self.iface = iface
+
+ ####
+ # Generate a server DUID
+ if duid is not None:
+ self.duid = duid
+ else:
+ # Timeval
+ from time import gmtime, strftime, mktime
+ epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0)
+ delta = mktime(epoch) - mktime(gmtime(0))
+ timeval = time.time() - delta
+
+ # Mac Address
+ rawmac = get_if_raw_hwaddr(iface)
+ mac = ":".join(map(lambda x: "%.02x" % x, rawmac))
+
+ self.duid = DUID_LLT(timeval = timeval, lladdr = mac)
+
+ if self.debug:
+ print("\n[+] Our server DUID:" )
+ self.duid.show(label_lvl=" "*4)
+
+ ####
+ # Find the source address we will use
+ #l = filter(lambda x: x[2] == iface and in6_islladdr(x[0]), in6_getifaddr())
+ l = [ x for x in in6_getifaddr() if x[2] == iface and in6_islladdr(x[0]) ]
+ if not l:
+ warning("Unable to get a Link-Local address")
+ return
+
+ self.src_addr = l[0][0]
+
+ ####
+ # Our leases
+ self.leases = {}
+
+
+ if self.debug:
+ print("\n[+] Starting DHCPv6 service on %s:" % self.iface )
+
+ def is_request(self, p):
+ if not IPv6 in p:
+ return False
+
+ src = p[IPv6].src
+ dst = p[IPv6].dst
+
+ p = p[IPv6].payload
+ if not isinstance(p, UDP) or p.sport != 546 or p.dport != 547 :
+ return False
+
+ p = p.payload
+ if not isinstance(p, DHCP6):
+ return False
+
+ # Message we considered client messages :
+ # Solicit (1), Request (3), Confirm (4), Renew (5), Rebind (6)
+ # Decline (9), Release (8), Information-request (11),
+ if not (p.msgtype in [1, 3, 4, 5, 6, 8, 9, 11]):
+ return False
+
+ # Message validation following section 15 of RFC 3315
+
+ if ((p.msgtype == 1) or # Solicit
+ (p.msgtype == 6) or # Rebind
+ (p.msgtype == 4)): # Confirm
+ if ((not DHCP6OptClientId in p) or
+ DHCP6OptServerId in p):
+ return False
+
+ if (p.msgtype == 6 or # Rebind
+ p.msgtype == 4): # Confirm
+ # XXX We do not reply to Confirm or Rebind as we
+ # XXX do not support address assignment
+ return False
+
+ elif (p.msgtype == 3 or # Request
+ p.msgtype == 5 or # Renew
+ p.msgtype == 8): # Release
+
+ # Both options must be present
+ if ((not DHCP6OptServerId in p) or
+ (not DHCP6OptClientId in p)):
+ return False
+ # provided server DUID must match ours
+ duid = p[DHCP6OptServerId].duid
+ if (type(duid) != type(self.duid)):
+ return False
+ if bytes(duid) != bytes(self.duid):
+ return False
+
+ if (p.msgtype == 5 or # Renew
+ p.msgtype == 8): # Release
+ # XXX We do not reply to Renew or Release as we
+ # XXX do not support address assignment
+ return False
+
+ elif p.msgtype == 9: # Decline
+ # XXX We should check if we are tracking that client
+ if not self.debug:
+ return False
+
+ bo = Color.bold
+ g = Color.green + bo
+ b = Color.blue + bo
+ n = Color.normal
+ r = Color.red
+
+ vendor = in6_addrtovendor(src)
+ if (vendor and vendor != "UNKNOWN"):
+ vendor = " [" + b + vendor + n + "]"
+ else:
+ vendor = ""
+ src = bo + src + n
+
+ it = p
+ addrs = []
+ while it:
+ l = []
+ if isinstance(it, DHCP6OptIA_NA):
+ l = it.ianaopts
+ elif isinstance(it, DHCP6OptIA_TA):
+ l = it.iataopts
+
+ #opsaddr = filter(lambda x: isinstance(x, DHCP6OptIAAddress),l)
+ opsaddr = [ x for x in l if isinstance(x, DHCP6OptIAAddress) ]
+ a=map(lambda x: x.addr, opsaddr)
+ addrs += a
+ it = it.payload
+
+ addrs = map(lambda x: bo + x + n, addrs)
+ if debug:
+ msg = r + "[DEBUG]" + n + " Received " + g + "Decline" + n
+ msg += " from " + bo + src + vendor + " for "
+ msg += ", ".join(addrs)+ n
+ print(msg)
+
+ # See sect 18.1.7
+
+ # Sent by a client to warn us she has determined
+ # one or more addresses assigned to her is already
+ # used on the link.
+ # We should simply log that fact. No messaged should
+ # be sent in return.
+
+ # - Message must include a Server identifier option
+ # - the content of the Server identifier option must
+ # match the server's identifier
+ # - the message must include a Client Identifier option
+ return False
+
+ elif p.msgtype == 11: # Information-Request
+ if DHCP6OptServerId in p:
+ duid = p[DHCP6OptServerId].duid
+ if (type(duid) != type(self.duid)):
+ return False
+ if bytes(duid) != bytes(self.duid):
+ return False
+ if ((DHCP6OptIA_NA in p) or
+ (DHCP6OptIA_TA in p) or
+ (DHCP6OptIA_PD in p)):
+ return False
+ else:
+ return False
+
+ return True
+
+ def print_reply(self, req, reply):
+ def norm(s):
+ if s.startswith("DHCPv6 "):
+ s = s[7:]
+ if s.endswith(" Message"):
+ s = s[:-8]
+ return s
+
+ if reply is None:
+ return
+
+ bo = Color.bold
+ g = Color.green + bo
+ b = Color.blue + bo
+ n = Color.normal
+ reqtype = g + norm(req.getlayer(UDP).payload.name) + n
+ reqsrc = req.getlayer(IPv6).src
+ vendor = in6_addrtovendor(reqsrc)
+ if (vendor and vendor != "UNKNOWN"):
+ vendor = " [" + b + vendor + n + "]"
+ else:
+ vendor = ""
+ reqsrc = bo + reqsrc + n
+ reptype = g + norm(reply.getlayer(UDP).payload.name) + n
+
+ print("Sent %s answering to %s from %s%s" % (reptype, reqtype, reqsrc, vendor))
+
+ def make_reply(self, req):
+ req_mac_src = req.src
+ req_mac_dst = req.dst
+
+ p = req[IPv6]
+ req_src = p.src
+ req_dst = p.dst
+
+ p = p.payload.payload
+
+ msgtype = p.msgtype
+ trid = p.trid
+
+ if msgtype == 1: # SOLICIT (See Sect 17.1 and 17.2 of RFC 3315)
+
+ # XXX We don't support address or prefix assignment
+ # XXX We also do not support relay function --arno
+
+ client_duid = p[DHCP6OptClientId].duid
+ resp = IPv6(src=self.src_addr, dst=req_src)
+ resp /= UDP(sport=547, dport=546)
+
+ if p.haslayer(DHCP6OptRapidCommit):
+ # construct a Reply packet
+ resp /= DHCP6_Reply(trid=trid)
+ resp /= DHCP6OptRapidCommit() # See 17.1.2
+ resp /= DHCP6OptServerId(duid = self.duid)
+ resp /= DHCP6OptClientId(duid = client_duid)
+
+ else: # No Rapid Commit in the packet. Reply with an Advertise
+
+ if (p.haslayer(DHCP6OptIA_NA) or
+ p.haslayer(DHCP6OptIA_TA)):
+ # XXX We don't assign addresses at the moment
+ msg = "Scapy6 dhcp6d does not support address assignment"
+ resp /= DHCP6_Advertise(trid = trid)
+ resp /= DHCP6OptStatusCode(statuscode=2, statusmsg=msg)
+ resp /= DHCP6OptServerId(duid = self.duid)
+ resp /= DHCP6OptClientId(duid = client_duid)
+
+ elif p.haslayer(DHCP6OptIA_PD):
+ # XXX We don't assign prefixes at the moment
+ msg = "Scapy6 dhcp6d does not support prefix assignment"
+ resp /= DHCP6_Advertise(trid = trid)
+ resp /= DHCP6OptStatusCode(statuscode=6, statusmsg=msg)
+ resp /= DHCP6OptServerId(duid = self.duid)
+ resp /= DHCP6OptClientId(duid = client_duid)
+
+ else: # Usual case, no request for prefixes or addresse
+ resp /= DHCP6_Advertise(trid = trid)
+ resp /= DHCP6OptPref(prefval = self.advpref)
+ resp /= DHCP6OptServerId(duid = self.duid)
+ resp /= DHCP6OptClientId(duid = client_duid)
+ resp /= DHCP6OptReconfAccept()
+
+ # See which options should be included
+ reqopts = []
+ if p.haslayer(DHCP6OptOptReq): # add only asked ones
+ reqopts = p[DHCP6OptOptReq].reqopts
+ for o in self.dhcpv6_options.keys():
+ if o in reqopts:
+ resp /= self.dhcpv6_options[o]
+ else: # advertise everything we have available
+ for o in self.dhcpv6_options.keys():
+ resp /= self.dhcpv6_options[o]
+
+ return resp
+
+ elif msgtype == 3: #REQUEST (INFO-REQUEST is further below)
+ client_duid = p[DHCP6OptClientId].duid
+ resp = IPv6(src=self.src_addr, dst=req_src)
+ resp /= UDP(sport=547, dport=546)
+ resp /= DHCP6_Solicit(trid=trid)
+ resp /= DHCP6OptServerId(duid = self.duid)
+ resp /= DHCP6OptClientId(duid = client_duid)
+
+ # See which options should be included
+ reqopts = []
+ if p.haslayer(DHCP6OptOptReq): # add only asked ones
+ reqopts = p[DHCP6OptOptReq].reqopts
+ for o in self.dhcpv6_options.keys():
+ if o in reqopts:
+ resp /= self.dhcpv6_options[o]
+ else:
+ # advertise everything we have available.
+ # Should not happen has clients MUST include
+ # and ORO in requests (sec 18.1.1) -- arno
+ for o in self.dhcpv6_options.keys():
+ resp /= self.dhcpv6_options[o]
+
+ return resp
+
+ elif msgtype == 4: # CONFIRM
+ # see Sect 18.1.2
+
+ # Client want to check if addresses it was assigned
+ # are still appropriate
+
+ # Server must discard any Confirm messages that
+ # do not include a Client Identifier option OR
+ # THAT DO INCLUDE a Server Identifier Option
+
+ # XXX we must discard the SOLICIT if it is received with
+ # a unicast destination address
+
+ pass
+
+ elif msgtype == 5: # RENEW
+ # see Sect 18.1.3
+
+ # Clients want to extend lifetime of assigned addresses
+ # and update configuration parameters. This message is sent
+ # specifically to the server that provided her the info
+
+ # - Received message must include a Server Identifier
+ # option.
+ # - the content of server identifier option must match
+ # the server's identifier.
+ # - the message must include a Client identifier option
+
+ pass
+
+ elif msgtype == 6: # REBIND
+ # see Sect 18.1.4
+
+ # Same purpose as the Renew message but sent to any
+ # available server after he received no response
+ # to its previous Renew message.
+
+
+ # - Message must include a Client Identifier Option
+ # - Message can't include a Server identifier option
+
+ # XXX we must discard the SOLICIT if it is received with
+ # a unicast destination address
+
+ pass
+
+ elif msgtype == 8: # RELEASE
+ # See section 18.1.6
+
+ # Message is sent to the server to indicate that
+ # she will no longer use the addresses that was assigned
+ # We should parse the message and verify our dictionary
+ # to log that fact.
+
+
+ # - The message must include a server identifier option
+ # - The content of the Server Identifier option must
+ # match the server's identifier
+ # - the message must include a Client Identifier option
+
+ pass
+
+ elif msgtype == 9: # DECLINE
+ # See section 18.1.7
+ pass
+
+ elif msgtype == 11: # INFO-REQUEST
+ client_duid = None
+ if not p.haslayer(DHCP6OptClientId):
+ if self.debug:
+ warning("Received Info Request message without Client Id option")
+ else:
+ client_duid = p[DHCP6OptClientId].duid
+
+ resp = IPv6(src=self.src_addr, dst=req_src)
+ resp /= UDP(sport=547, dport=546)
+ resp /= DHCP6_Reply(trid=trid)
+ resp /= DHCP6OptServerId(duid = self.duid)
+
+ if client_duid:
+ resp /= DHCP6OptClientId(duid = client_duid)
+
+ # Stack requested options if available
+ reqopts = []
+ if p.haslayer(DHCP6OptOptReq):
+ reqopts = p[DHCP6OptOptReq].reqopts
+ for o in self.dhcpv6_options.keys():
+ resp /= self.dhcpv6_options[o]
+
+ return resp
+
+ else:
+ # what else ?
+ pass
+
+ # - We won't support reemission
+ # - We won't support relay role, nor relay forwarded messages
+ # at the beginning
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dns.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dns.py
new file mode 100644
index 00000000..8a01e273
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dns.py
@@ -0,0 +1,712 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+DNS: Domain Name System.
+"""
+
+import socket,struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.ansmachine import *
+from scapy.layers.inet import IP, UDP
+from scapy.utils import str2bytes
+
+class DNSStrField(StrField):
+
+ def h2i(self, pkt, x):
+ if type(x) == str:
+ x = x.encode('ascii')
+ if x == b"":
+ return b"."
+ return x
+
+ def i2m(self, pkt, x):
+ if type(x) == str:
+ x = x.encode('ascii')
+ if x == b".":
+ return b"\x00"
+
+ x = [k[:63] for k in x.split(b".")] # Truncate chunks that cannot be encoded (more than 63 bytes..)
+ x = map(lambda y: bytes([len(y)]) + y, x)
+ x = b"".join(x)
+ if x[-1] != 0:
+ x += b"\x00"
+ return x
+
+ def getfield(self, pkt, s):
+ n = b""
+
+ #if ord(s[0]) == 0:
+ if (s[0]) == 0:
+ return s[1:], b"."
+
+ while 1:
+ #l = ord(s[0])
+ l = (s[0])
+ s = s[1:]
+ if not l:
+ break
+ if l & 0xc0:
+ raise Scapy_Exception("DNS message can't be compressed at this point!")
+ else:
+ n += s[:l]+b"."
+ s = s[l:]
+ return s, n
+
+
+class DNSRRCountField(ShortField):
+ holds_packets=1
+ def __init__(self, name, default, rr):
+ ShortField.__init__(self, name, default)
+ self.rr = rr
+ def _countRR(self, pkt):
+ x = getattr(pkt,self.rr)
+ i = 0
+ while isinstance(x, DNSRR) or isinstance(x, DNSQR) or isdnssecRR(x):
+ x = x.payload
+ i += 1
+ return i
+
+ def i2m(self, pkt, x):
+ if x is None:
+ x = self._countRR(pkt)
+ return x
+ def i2h(self, pkt, x):
+ if x is None:
+ x = self._countRR(pkt)
+ return x
+
+
+def DNSgetstr(s,p):
+ name = b""
+ q = 0
+ jpath = [p]
+ while 1:
+ if p >= len(s):
+ warning("DNS RR prematured end (ofs=%i, len=%i)"%(p,len(s)))
+ break
+ #l = ord(s[p])
+ l = s[p]
+ p += 1
+ if l & 0xc0:
+ if not q:
+ q = p+1
+ if p >= len(s):
+ warning("DNS incomplete jump token at (ofs=%i)" % p)
+ break
+ p = ((l & 0x3f) << 8) + s[p] - 12
+ if p in jpath:
+ warning("DNS decompression loop detected")
+ break
+ jpath.append(p)
+ continue
+ elif l > 0:
+ name += s[p:p+l]+b"."
+ p += l
+ continue
+ break
+ if q:
+ p = q
+ return name,p
+
+
+class DNSRRField(StrField):
+ holds_packets=1
+ def __init__(self, name, countfld, passon=1):
+ StrField.__init__(self, name, None)
+ self.countfld = countfld
+ self.passon = passon
+ def i2m(self, pkt, x):
+ if x is None:
+ return b""
+ return bytes(x)
+ def decodeRR(self, name, s, p):
+ ret = s[p:p+10]
+ type,cls,ttl,rdlen = struct.unpack("!HHIH", ret)
+ p += 10
+ rr = DNSRR(b"\x00"+ret+s[p:p+rdlen])
+ if type in [2, 3, 4, 5]:
+ rr.rdata = DNSgetstr(s,p)[0]
+ del(rr.rdlen)
+ elif type in dnsRRdispatcher.keys():
+ rr = dnsRRdispatcher[type](b"\x00"+ret+s[p:p+rdlen])
+ else:
+ del(rr.rdlen)
+
+ p += rdlen
+
+ rr.rrname = name
+ return rr,p
+ def getfield(self, pkt, s):
+ if type(s) is tuple :
+ s,p = s
+ else:
+ p = 0
+ ret = None
+ c = getattr(pkt, self.countfld)
+ if c > len(s):
+ warning("wrong value: DNS.%s=%i" % (self.countfld,c))
+ return s,b""
+ while c:
+ c -= 1
+ name,p = DNSgetstr(s,p)
+ rr,p = self.decodeRR(name, s, p)
+ if ret is None:
+ ret = rr
+ else:
+ ret.add_payload(rr)
+ if self.passon:
+ return (s,p),ret
+ else:
+ return s[p:],ret
+
+
+class DNSQRField(DNSRRField):
+ holds_packets=1
+ def decodeRR(self, name, s, p):
+ ret = s[p:p+4]
+ p += 4
+ rr = DNSQR(b"\x00"+ret)
+ rr.qname = name
+ return rr,p
+
+
+
+class RDataField(StrLenField):
+ def m2i(self, pkt, s):
+ family = None
+ if pkt.type == 1: # A
+ family = socket.AF_INET
+ elif pkt.type == 12: # PTR
+ s = DNSgetstr(s, 0)[0]
+ elif pkt.type == 16: # TXT
+ ret_s = b""
+ tmp_s = s
+ # RDATA contains a list of strings, each are prepended with
+ # a byte containing the size of the following string.
+ while tmp_s:
+ tmp_len = struct.unpack("!B", bytes([tmp_s[0]]))[0] + 1
+ if tmp_len > len(tmp_s):
+ warning("DNS RR TXT prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s)))
+ ret_s += tmp_s[1:tmp_len]
+ tmp_s = tmp_s[tmp_len:]
+ s = ret_s
+ elif pkt.type == 28: # AAAA
+ family = socket.AF_INET6
+ if family is not None:
+ s = inet_ntop(family, s)
+ return s
+ def i2m(self, pkt, s):
+ if pkt.type == 1: # A
+ if s:
+ if type(s) is bytes:
+ s = s.decode('ascii')
+ s = inet_aton(s)
+ elif pkt.type in [2,3,4,5]: # NS, MD, MF, CNAME
+ s = b"".join(map(lambda x: bytes([len(x)]) + x, s.split(b".")))
+ #if ord(s[-1]):
+ if s[-1]:
+ s += b"\x00"
+ elif pkt.type == 16: # TXT
+ if s:
+ ret_s = b""
+ # The initial string must be splitted into a list of strings
+ # prepended with theirs sizes.
+ while len(s) >= 255:
+ ret_s += b"\xff" + s[:255]
+ s = s[255:]
+ # The remaining string is less than 255 bytes long
+ if len(s):
+ ret_s += struct.pack("!B", len(s)) + s
+ s = ret_s
+ elif pkt.type == 28: # AAAA
+ if s:
+ s = inet_pton(socket.AF_INET6, s)
+ return s
+
+class RDLenField(Field):
+ def __init__(self, name):
+ Field.__init__(self, name, None, "H")
+ def i2m(self, pkt, x):
+ if x is None:
+ rdataf = pkt.get_field("rdata")
+ x = len(rdataf.i2m(pkt, pkt.rdata))
+ return x
+ def i2h(self, pkt, x):
+ if x is None:
+ rdataf = pkt.get_field("rdata")
+ x = len(rdataf.i2m(pkt, pkt.rdata))
+ return x
+
+
+class DNS(Packet):
+ name = "DNS"
+ fields_desc = [ ShortField("id", 0),
+ BitField("qr", 0, 1),
+ BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}),
+ BitField("aa", 0, 1),
+ BitField("tc", 0, 1),
+ BitField("rd", 0, 1),
+ BitField("ra", 0, 1),
+ BitField("z", 0, 1),
+ # AD and CD bits are defined in RFC 2535
+ BitField("ad", 0, 1), # Authentic Data
+ BitField("cd", 0, 1), # Checking Disabled
+ BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}),
+ DNSRRCountField("qdcount", None, "qd"),
+ DNSRRCountField("ancount", None, "an"),
+ DNSRRCountField("nscount", None, "ns"),
+ DNSRRCountField("arcount", None, "ar"),
+ DNSQRField("qd", "qdcount"),
+ DNSRRField("an", "ancount"),
+ DNSRRField("ns", "nscount"),
+ DNSRRField("ar", "arcount",0) ]
+ def answers(self, other):
+ return (isinstance(other, DNS)
+ and self.id == other.id
+ and self.qr == 1
+ and other.qr == 0)
+
+ def mysummary(self):
+ type = ["Qry","Ans"][self.qr]
+ name = ""
+ if self.qr:
+ type = "Ans"
+ if self.ancount > 0 and isinstance(self.an, DNSRR):
+ name = ' "%s"' % self.an.getstrval("rdata")
+ else:
+ type = "Qry"
+ if self.qdcount > 0 and isinstance(self.qd, DNSQR):
+ name = ' "%s"' % self.qd.getstrval("qname")
+ return 'DNS %s%s ' % (type, name)
+
+dnstypes = { 0:"ANY", 255:"ALL",
+ 1:"A", 2:"NS", 3:"MD", 4:"MF", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG",
+ 9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",
+ 17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME",
+ 41:"OPT", 43:"DS", 46:"RRSIG", 47:"NSEC", 48:"DNSKEY",
+ 50: "NSEC3", 51: "NSEC3PARAM", 32769:"DLV" }
+
+dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"}
+dnsqtypes.update(dnstypes)
+dnsclasses = {1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'}
+
+
+class DNSQR(Packet):
+ name = "DNS Question Record"
+ show_indent=0
+ fields_desc = [ DNSStrField("qname",b""),
+ ShortEnumField("qtype", 1, dnsqtypes),
+ ShortEnumField("qclass", 1, dnsclasses) ]
+
+
+
+# RFC 2671 - Extension Mechanisms for DNS (EDNS0)
+
+class EDNS0TLV(Packet):
+ name = "DNS EDNS0 TLV"
+ fields_desc = [ ShortEnumField("optcode", 0, { 0: "Reserved", 1: "LLQ", 2: "UL", 3: "NSID", 4: "Reserved", 5: "PING" }),
+ FieldLenField("optlen", None, "optdata", fmt="H"),
+ StrLenField("optdata", b"", length_from=lambda pkt: pkt.optlen) ]
+
+ def extract_padding(self, p):
+ return b"", p
+
+class DNSRROPT(Packet):
+ name = "DNS OPT Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 41, dnstypes),
+ ShortField("rclass", 4096),
+ ByteField("extrcode", 0),
+ ByteField("version", 0),
+ # version 0 means EDNS0
+ BitEnumField("z", 32768, 16, { 32768: "D0" }),
+ # D0 means DNSSEC OK from RFC 3225
+ FieldLenField("rdlen", None, length_of="rdata", fmt="H"),
+ PacketListField("rdata", [], EDNS0TLV, length_from=lambda pkt: pkt.rdlen) ]
+
+# RFC 4034 - Resource Records for the DNS Security Extensions
+
+# 09/2013 from http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+dnssecalgotypes = { 0:"Reserved", 1:"RSA/MD5", 2:"Diffie-Hellman", 3:"DSA/SHA-1",
+ 4:"Reserved", 5:"RSA/SHA-1", 6:"DSA-NSEC3-SHA1",
+ 7:"RSASHA1-NSEC3-SHA1", 8:"RSA/SHA-256", 9:"Reserved",
+ 10:"RSA/SHA-512", 11:"Reserved", 12:"GOST R 34.10-2001",
+ 13:"ECDSA Curve P-256 with SHA-256", 14: "ECDSA Curve P-384 with SHA-384",
+ 252:"Reserved for Indirect Keys", 253:"Private algorithms - domain name",
+ 254:"Private algorithms - OID", 255:"Reserved" }
+
+# 09/2013 from http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
+dnssecdigesttypes = { 0:"Reserved", 1:"SHA-1", 2:"SHA-256", 3:"GOST R 34.11-94", 4:"SHA-384" }
+
+
+class TimeField(IntField):
+
+ def any2i(self, pkt, x):
+ if type(x) == str:
+ import time, calendar
+ t = time.strptime(x, "%Y%m%d%H%M%S")
+ return int(calendar.timegm(t))
+ return x
+
+ def i2repr(self, pkt, x):
+ import time
+ x = self.i2h(pkt, x)
+ t = time.strftime("%Y%m%d%H%M%S", time.gmtime(x))
+ return "%s (%d)" % (t ,x)
+
+
+def bitmap2RRlist(bitmap):
+ """
+ Decode the 'Type Bit Maps' field of the NSEC Resource Record into an
+ integer list.
+ """
+ # RFC 4034, 4.1.2. The Type Bit Maps Field
+
+ RRlist = []
+
+ while bitmap:
+
+ if len(bitmap) < 2:
+ warning("bitmap too short (%i)" % len(bitmap))
+ return
+
+ #window_block = ord(bitmap[0]) # window number
+ window_block = (bitmap[0]) # window number
+ offset = 256*window_block # offset of the Ressource Record
+ #bitmap_len = ord(bitmap[0]) # length of the bitmap in bytes
+ bitmap_len = (bitmap[1]) # length of the bitmap in bytes
+
+ if bitmap_len <= 0 or bitmap_len > 32:
+ warning("bitmap length is no valid (%i)" % bitmap_len)
+ return
+
+ tmp_bitmap = bitmap[2:2+bitmap_len]
+
+ # Let's compare each bit of tmp_bitmap and compute the real RR value
+ for b in range(len(tmp_bitmap)):
+ v = 128
+ for i in range(8):
+ #if ord(tmp_bitmap[b]) & v:
+ if (tmp_bitmap[b]) & v:
+ # each of the RR is encoded as a bit
+ RRlist += [ offset + b*8 + i ]
+ v = v >> 1
+
+# Next block if any
+ bitmap = bitmap[2+bitmap_len:]
+
+ return RRlist
+
+
+def RRlist2bitmap(lst):
+ """
+ Encode a list of integers representing Resource Records to a bitmap field
+ used in the NSEC Resource Record.
+ """
+ # RFC 4034, 4.1.2. The Type Bit Maps Field
+
+ import math
+
+ bitmap = b""
+ lst = list(set(lst))
+ lst.sort()
+
+ #lst = filter(lambda x: x <= 65535, lst)
+ #lst = map(lambda x: abs(x), lst)
+ lst = [ abs(x) for x in lst if x<= 65535 ]
+
+ # number of window blocks
+ max_window_blocks = int(math.ceil(lst[-1] / 256.))
+ min_window_blocks = int(math.floor(lst[0] / 256.))
+ if min_window_blocks == max_window_blocks:
+ max_window_blocks += 1
+
+ for wb in range(min_window_blocks, max_window_blocks+1):
+ # First, filter out RR not encoded in the current window block
+ # i.e. keep everything between 256*wb <= 256*(wb+1)
+ #rrlist = filter(lambda x: 256*wb <= x and x < 256*(wb+1), lst)
+ rrlist = [ x for x in lst if 256*wb <= x and x < 256*(wb+1) ]
+ rrlist.sort()
+ if rrlist == []:
+ continue
+
+ # Compute the number of bytes used to store the bitmap
+ if rrlist[-1] == 0: # only one element in the list
+ bs = 1
+ else:
+ max = rrlist[-1] - 256*wb
+ #bs = int(math.ceil(max / 8)) + 1 # use at least 1 byte
+ bs = int(max // 8) + 1 # use at least 1 byte
+ if bs > 32: # Don't encode more than 256 bits / values
+ bs = 32
+
+ bitmap += struct.pack("B", wb)
+ bitmap += struct.pack("B", bs)
+
+ # Generate the bitmap
+ for tmp in range(bs):
+ v = 0
+ # Remove out of range Ressource Records
+ #tmp_rrlist = filter(lambda x: 256*wb+8*tmp <= x and x < 256*wb+8*tmp+8, rrlist)
+ tmp_rrlist = [ x for x in rrlist if 256*wb+8*tmp <= x and x < 256*wb+8*tmp+8 ]
+ if not tmp_rrlist == []:
+ # 1. rescale to fit into 8 bits
+ tmp_rrlist = map(lambda x: (x-256*wb)-(tmp*8), tmp_rrlist)
+ # 2. x gives the bit position ; compute the corresponding value
+ tmp_rrlist = map(lambda x: 2**(7-x) , tmp_rrlist)
+ # 3. sum everything
+ #v = reduce(lambda x,y: x+y, tmp_rrlist)
+ v = sum(tmp_rrlist)
+ bitmap += struct.pack("B", v)
+
+ return bitmap
+
+
+class RRlistField(StrField):
+ def h2i(self, pkt, x):
+ if type(x) == list:
+ return RRlist2bitmap(x)
+ return x
+
+ def i2repr(self, pkt, x):
+ x = self.i2h(pkt, x)
+ rrlist = bitmap2RRlist(x)
+ return [ dnstypes.get(rr, rr) for rr in rrlist ]
+
+
+class _DNSRRdummy(Packet):
+ name = "Dummy class that implements post_build() for Ressource Records"
+ def post_build(self, pkt, pay):
+ if not self.rdlen == None:
+ return pkt
+
+ lrrname = len(self.fields_desc[0].i2m(b"", self.getfieldval("rrname")))
+ l = len(pkt) - lrrname - 10
+ pkt = pkt[:lrrname+8] + struct.pack("!H", l) + pkt[lrrname+8+2:]
+
+ return pkt
+
+class DNSRRSOA(_DNSRRdummy):
+ name = "DNS SOA Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 6, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ DNSStrField("mname", b""),
+ DNSStrField("rname", b""),
+ IntField("serial", 0),
+ IntField("refresh", 0),
+ IntField("retry", 0),
+ IntField("expire", 0),
+ IntField("minimum", 0)
+ ]
+
+class DNSRRRSIG(_DNSRRdummy):
+ name = "DNS RRSIG Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 46, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ ShortEnumField("typecovered", 1, dnstypes),
+ ByteEnumField("algorithm", 5, dnssecalgotypes),
+ ByteField("labels", 0),
+ IntField("originalttl", 0),
+ TimeField("expiration", 0),
+ TimeField("inception", 0),
+ ShortField("keytag", 0),
+ DNSStrField("signersname", b""),
+ StrField("signature", b"")
+ ]
+
+
+class DNSRRNSEC(_DNSRRdummy):
+ name = "DNS NSEC Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 47, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ DNSStrField("nextname", b""),
+ RRlistField("typebitmaps", b"")
+ ]
+
+
+class DNSRRDNSKEY(_DNSRRdummy):
+ name = "DNS DNSKEY Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 48, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ FlagsField("flags", 256, 16, "S???????Z???????"),
+ # S: Secure Entry Point
+ # Z: Zone Key
+ ByteField("protocol", 3),
+ ByteEnumField("algorithm", 5, dnssecalgotypes),
+ StrField("publickey", b"")
+ ]
+
+
+class DNSRRDS(_DNSRRdummy):
+ name = "DNS DS Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 43, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ ShortField("keytag", 0),
+ ByteEnumField("algorithm", 5, dnssecalgotypes),
+ ByteEnumField("digesttype", 5, dnssecdigesttypes),
+ StrField("digest", b"")
+ ]
+
+
+# RFC 5074 - DNSSEC Lookaside Validation (DLV)
+class DNSRRDLV(DNSRRDS):
+ name = "DNS DLV Resource Record"
+ def __init__(self, *args, **kargs):
+ DNSRRDS.__init__(self, *args, **kargs)
+ if not kargs.get('type', 0):
+ self.type = 32769
+
+# RFC 5155 - DNS Security (DNSSEC) Hashed Authenticated Denial of Existence
+class DNSRRNSEC3(_DNSRRdummy):
+ name = "DNS NSEC3 Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 50, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ ByteField("hashalg", 0),
+ BitEnumField("flags", 0, 8, {1:"Opt-Out"}),
+ ShortField("iterations", 0),
+ FieldLenField("saltlength", 0, fmt="!B", length_of="salt"),
+ StrLenField("salt", b"", length_from=lambda x: x.saltlength),
+ FieldLenField("hashlength", 0, fmt="!B", length_of="nexthashedownername"),
+ StrLenField("nexthashedownername", b"", length_from=lambda x: x.hashlength),
+ RRlistField("typebitmaps", b"")
+ ]
+
+
+class DNSRRNSEC3PARAM(_DNSRRdummy):
+ name = "DNS NSEC3PARAM Resource Record"
+ fields_desc = [ DNSStrField("rrname",b""),
+ ShortEnumField("type", 51, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ ShortField("rdlen", None),
+ ByteField("hashalg", 0),
+ ByteField("flags", 0),
+ ShortField("iterations", 0),
+ FieldLenField("saltlength", 0, fmt="!B", length_of="salt"),
+ StrLenField("salt", b"", length_from=lambda pkt: pkt.saltlength)
+ ]
+
+
+dnssecclasses = [ DNSRROPT, DNSRRRSIG, DNSRRDLV, DNSRRDNSKEY, DNSRRNSEC, DNSRRDS, DNSRRNSEC3, DNSRRNSEC3PARAM ]
+
+def isdnssecRR(obj):
+ list = [ isinstance (obj, cls) for cls in dnssecclasses ]
+ ret = False
+ for i in list:
+ ret = ret or i
+ return ret
+
+dnsRRdispatcher = { #6: DNSRRSOA,
+ 41: DNSRROPT, # RFC 1671
+ 43: DNSRRDS, # RFC 4034
+ 46: DNSRRRSIG, # RFC 4034
+ 47: DNSRRNSEC, # RFC 4034
+ 48: DNSRRDNSKEY, # RFC 4034
+ 50: DNSRRNSEC3, # RFC 5155
+ 51: DNSRRNSEC3PARAM, # RFC 5155
+ 32769: DNSRRDLV # RFC 4431
+ }
+
+class DNSRR(Packet):
+ name = "DNS Resource Record"
+ show_indent=0
+ fields_desc = [ DNSStrField("rrname",""),
+ ShortEnumField("type", 1, dnstypes),
+ ShortEnumField("rclass", 1, dnsclasses),
+ IntField("ttl", 0),
+ RDLenField("rdlen"),
+ RDataField("rdata", "", length_from=lambda pkt:pkt.rdlen) ]
+
+bind_layers( UDP, DNS, dport=53)
+bind_layers( UDP, DNS, sport=53)
+
+
+@conf.commands.register
+def dyndns_add(nameserver, name, rdata, type="A", ttl=10):
+ """Send a DNS add message to a nameserver for "name" to have a new "rdata"
+dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok)
+
+example: dyndns_add("ns1.toto.com", "dyn.toto.com", "127.0.0.1")
+RFC2136
+"""
+ zone = name[name.find(".")+1:]
+ r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
+ qd=[DNSQR(qname=zone, qtype="SOA")],
+ ns=[DNSRR(rrname=name, type="A",
+ ttl=ttl, rdata=rdata)]),
+ verbose=0, timeout=5)
+ if r and r.haslayer(DNS):
+ return r.getlayer(DNS).rcode
+ else:
+ return -1
+
+
+
+
+@conf.commands.register
+def dyndns_del(nameserver, name, type="ALL", ttl=10):
+ """Send a DNS delete message to a nameserver for "name"
+dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok)
+
+example: dyndns_del("ns1.toto.com", "dyn.toto.com")
+RFC2136
+"""
+ zone = name[name.find(".")+1:]
+ r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
+ qd=[DNSQR(qname=zone, qtype="SOA")],
+ ns=[DNSRR(rrname=name, type=type,
+ rclass="ANY", ttl=0, rdata=b"")]),
+ verbose=0, timeout=5)
+ if r and r.haslayer(DNS):
+ return r.getlayer(DNS).rcode
+ else:
+ return -1
+
+
+class DNS_am(AnsweringMachine):
+ function_name="dns_spoof"
+ filter = "udp port 53"
+
+ def parse_options(self, joker="192.168.1.1", match=None):
+ if match is None:
+ self.match = {}
+ else:
+ self.match = match
+ self.joker=joker
+
+ def is_request(self, req):
+ return req.haslayer(DNS) and req.getlayer(DNS).qr == 0
+
+ def make_reply(self, req):
+ ip = req.getlayer(IP)
+ dns = req.getlayer(DNS)
+ resp = IP(dst=ip.src, src=ip.dst)/UDP(dport=ip.sport,sport=ip.dport)
+ rdata = self.match.get(dns.qd.qname, self.joker)
+ resp /= DNS(id=dns.id, qr=1, qd=dns.qd,
+ an=DNSRR(rrname=dns.qd.qname, ttl=10, rdata=rdata))
+ return resp
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dot11.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dot11.py
new file mode 100644
index 00000000..417a470e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dot11.py
@@ -0,0 +1,560 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Wireless LAN according to IEEE 802.11.
+"""
+
+import re,struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.plist import PacketList
+from scapy.layers.l2 import *
+
+
+try:
+ from Crypto.Cipher import ARC4
+except ImportError:
+ log_loading.info("Can't import python Crypto lib. Won't be able to decrypt WEP.")
+
+
+### Fields
+
+class Dot11AddrMACField(MACField):
+ def is_applicable(self, pkt):
+ return 1
+ def addfield(self, pkt, s, val):
+ if self.is_applicable(pkt):
+ return MACField.addfield(self, pkt, s, val)
+ else:
+ return s
+ def getfield(self, pkt, s):
+ if self.is_applicable(pkt):
+ return MACField.getfield(self, pkt, s)
+ else:
+ return s,None
+
+class Dot11Addr2MACField(Dot11AddrMACField):
+ def is_applicable(self, pkt):
+ if pkt.type == 1:
+ return pkt.subtype in [ 0xb, 0xa, 0xe, 0xf] # RTS, PS-Poll, CF-End, CF-End+CF-Ack
+ return 1
+
+class Dot11Addr3MACField(Dot11AddrMACField):
+ def is_applicable(self, pkt):
+ if pkt.type in [0,2]:
+ return 1
+ return 0
+
+class Dot11Addr4MACField(Dot11AddrMACField):
+ def is_applicable(self, pkt):
+ if pkt.type == 2:
+ if pkt.FCfield & 0x3 == 0x3: # To-DS and From-DS are set
+ return 1
+ return 0
+
+
+### Layers
+
+
+class PrismHeader(Packet):
+ """ iwpriv wlan0 monitor 3 """
+ name = "Prism header"
+ fields_desc = [ LEIntField("msgcode",68),
+ LEIntField("len",144),
+ StrFixedLenField("dev","",16),
+ LEIntField("hosttime_did",0),
+ LEShortField("hosttime_status",0),
+ LEShortField("hosttime_len",0),
+ LEIntField("hosttime",0),
+ LEIntField("mactime_did",0),
+ LEShortField("mactime_status",0),
+ LEShortField("mactime_len",0),
+ LEIntField("mactime",0),
+ LEIntField("channel_did",0),
+ LEShortField("channel_status",0),
+ LEShortField("channel_len",0),
+ LEIntField("channel",0),
+ LEIntField("rssi_did",0),
+ LEShortField("rssi_status",0),
+ LEShortField("rssi_len",0),
+ LEIntField("rssi",0),
+ LEIntField("sq_did",0),
+ LEShortField("sq_status",0),
+ LEShortField("sq_len",0),
+ LEIntField("sq",0),
+ LEIntField("signal_did",0),
+ LEShortField("signal_status",0),
+ LEShortField("signal_len",0),
+ LESignedIntField("signal",0),
+ LEIntField("noise_did",0),
+ LEShortField("noise_status",0),
+ LEShortField("noise_len",0),
+ LEIntField("noise",0),
+ LEIntField("rate_did",0),
+ LEShortField("rate_status",0),
+ LEShortField("rate_len",0),
+ LEIntField("rate",0),
+ LEIntField("istx_did",0),
+ LEShortField("istx_status",0),
+ LEShortField("istx_len",0),
+ LEIntField("istx",0),
+ LEIntField("frmlen_did",0),
+ LEShortField("frmlen_status",0),
+ LEShortField("frmlen_len",0),
+ LEIntField("frmlen",0),
+ ]
+ def answers(self, other):
+ if isinstance(other, PrismHeader):
+ return self.payload.answers(other.payload)
+ else:
+ return self.payload.answers(other)
+
+class RadioTap(Packet):
+ name = "RadioTap dummy"
+ fields_desc = [ ByteField('version', 0),
+ ByteField('pad', 0),
+ FieldLenField('len', None, 'notdecoded', '<H', adjust=lambda pkt,x:x+8),
+ FlagsField('present', None, -32, ['TSFT','Flags','Rate','Channel','FHSS','dBm_AntSignal',
+ 'dBm_AntNoise','Lock_Quality','TX_Attenuation','dB_TX_Attenuation',
+ 'dBm_TX_Power', 'Antenna', 'dB_AntSignal', 'dB_AntNoise',
+ 'b14', 'b15','b16','b17','b18','b19','b20','b21','b22','b23',
+ 'b24','b25','b26','b27','b28','b29','b30','Ext']),
+ StrLenField('notdecoded', "", length_from= lambda pkt:pkt.len-8) ]
+
+class PPI(Packet):
+ name = "Per-Packet Information header (partial)"
+ fields_desc = [ ByteField("version", 0),
+ ByteField("flags", 0),
+ FieldLenField("len", None, fmt="<H", length_of="fields", adjust=lambda pkt,x:x+8),
+ LEIntField("dlt", 0),
+ StrLenField("notdecoded", "", length_from = lambda pkt:pkt.len-8)
+ ]
+
+
+
+class Dot11SCField(LEShortField):
+ def is_applicable(self, pkt):
+ return pkt.type != 1 # control frame
+ def addfield(self, pkt, s, val):
+ if self.is_applicable(pkt):
+ return LEShortField.addfield(self, pkt, s, val)
+ else:
+ return s
+ def getfield(self, pkt, s):
+ if self.is_applicable(pkt):
+ return LEShortField.getfield(self, pkt, s)
+ else:
+ return s,None
+
+class Dot11(Packet):
+ name = "802.11"
+ fields_desc = [
+ BitField("subtype", 0, 4),
+ BitEnumField("type", 0, 2, ["Management", "Control", "Data", "Reserved"]),
+ BitField("proto", 0, 2),
+ FlagsField("FCfield", 0, 8, ["to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "wep", "order"]),
+ ShortField("ID",0),
+ MACField("addr1", ETHER_ANY),
+ Dot11Addr2MACField("addr2", ETHER_ANY),
+ Dot11Addr3MACField("addr3", ETHER_ANY),
+ Dot11SCField("SC", 0),
+ Dot11Addr4MACField("addr4", ETHER_ANY)
+ ]
+ def mysummary(self):
+ return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%")
+ def guess_payload_class(self, payload):
+ if self.type == 0x02 and (self.subtype >= 0x08 and self.subtype <=0xF and self.subtype != 0xD):
+ return Dot11QoS
+ elif self.FCfield & 0x40:
+ return Dot11WEP
+ else:
+ return Packet.guess_payload_class(self, payload)
+ def answers(self, other):
+ if isinstance(other,Dot11):
+ if self.type == 0: # management
+ if self.addr1.lower() != other.addr2.lower(): # check resp DA w/ req SA
+ return 0
+ if (other.subtype,self.subtype) in [(0,1),(2,3),(4,5)]:
+ return 1
+ if self.subtype == other.subtype == 11: # auth
+ return self.payload.answers(other.payload)
+ elif self.type == 1: # control
+ return 0
+ elif self.type == 2: # data
+ return self.payload.answers(other.payload)
+ elif self.type == 3: # reserved
+ return 0
+ return 0
+ def unwep(self, key=None, warn=1):
+ if self.FCfield & 0x40 == 0:
+ if warn:
+ warning("No WEP to remove")
+ return
+ if isinstance(self.payload.payload, NoPayload):
+ if key or conf.wepkey:
+ self.payload.decrypt(key)
+ if isinstance(self.payload.payload, NoPayload):
+ if warn:
+ warning("Dot11 can't be decrypted. Check conf.wepkey.")
+ return
+ self.FCfield &= ~0x40
+ self.payload=self.payload.payload
+
+
+class Dot11QoS(Packet):
+ name = "802.11 QoS"
+ fields_desc = [ BitField("TID",None,4),
+ BitField("EOSP",None,1),
+ BitField("Ack Policy",None,2),
+ BitField("Reserved",None,1),
+ ByteField("TXOP",None) ]
+ def guess_payload_class(self, payload):
+ if isinstance(self.underlayer, Dot11):
+ if self.underlayer.FCfield & 0x40:
+ return Dot11WEP
+ return Packet.guess_payload_class(self, payload)
+
+
+capability_list = [ "res8", "res9", "short-slot", "res11",
+ "res12", "DSSS-OFDM", "res14", "res15",
+ "ESS", "IBSS", "CFP", "CFP-req",
+ "privacy", "short-preamble", "PBCC", "agility"]
+
+reason_code = {0:"reserved",1:"unspec", 2:"auth-expired",
+ 3:"deauth-ST-leaving",
+ 4:"inactivity", 5:"AP-full", 6:"class2-from-nonauth",
+ 7:"class3-from-nonass", 8:"disas-ST-leaving",
+ 9:"ST-not-auth"}
+
+status_code = {0:"success", 1:"failure", 10:"cannot-support-all-cap",
+ 11:"inexist-asso", 12:"asso-denied", 13:"algo-unsupported",
+ 14:"bad-seq-num", 15:"challenge-failure",
+ 16:"timeout", 17:"AP-full",18:"rate-unsupported" }
+
+class Dot11Beacon(Packet):
+ name = "802.11 Beacon"
+ fields_desc = [ LELongField("timestamp", 0),
+ LEShortField("beacon_interval", 0x0064),
+ FlagsField("cap", 0, 16, capability_list) ]
+
+
+class Dot11Elt(Packet):
+ name = "802.11 Information Element"
+ fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge",
+ 42:"ERPinfo", 46:"QoS Capability", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}),
+ FieldLenField("len", None, "info", "B"),
+ StrLenField("info", "", length_from=lambda x:x.len) ]
+ def mysummary(self):
+ if self.ID == 0:
+ return "SSID=%s"%repr(self.info),[Dot11]
+ else:
+ return ""
+
+class Dot11ATIM(Packet):
+ name = "802.11 ATIM"
+
+class Dot11Disas(Packet):
+ name = "802.11 Disassociation"
+ fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
+
+class Dot11AssoReq(Packet):
+ name = "802.11 Association Request"
+ fields_desc = [ FlagsField("cap", 0, 16, capability_list),
+ LEShortField("listen_interval", 0x00c8) ]
+
+
+class Dot11AssoResp(Packet):
+ name = "802.11 Association Response"
+ fields_desc = [ FlagsField("cap", 0, 16, capability_list),
+ LEShortField("status", 0),
+ LEShortField("AID", 0) ]
+
+class Dot11ReassoReq(Packet):
+ name = "802.11 Reassociation Request"
+ fields_desc = [ FlagsField("cap", 0, 16, capability_list),
+ LEShortField("listen_interval", 0x00c8),
+ MACField("current_AP", ETHER_ANY) ]
+
+
+class Dot11ReassoResp(Dot11AssoResp):
+ name = "802.11 Reassociation Response"
+
+class Dot11ProbeReq(Packet):
+ name = "802.11 Probe Request"
+
+class Dot11ProbeResp(Packet):
+ name = "802.11 Probe Response"
+ fields_desc = [ LELongField("timestamp", 0),
+ LEShortField("beacon_interval", 0x0064),
+ FlagsField("cap", 0, 16, capability_list) ]
+
+class Dot11Auth(Packet):
+ name = "802.11 Authentication"
+ fields_desc = [ LEShortEnumField("algo", 0, ["open", "sharedkey"]),
+ LEShortField("seqnum", 0),
+ LEShortEnumField("status", 0, status_code) ]
+ def answers(self, other):
+ if self.seqnum == other.seqnum+1:
+ return 1
+ return 0
+
+class Dot11Deauth(Packet):
+ name = "802.11 Deauthentication"
+ fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
+
+
+
+class Dot11WEP(Packet):
+ name = "802.11 WEP packet"
+ fields_desc = [ StrFixedLenField("iv", b"\0\0\0", 3),
+ ByteField("keyid", 0),
+ StrField("wepdata",None,remain=4),
+ IntField("icv",None) ]
+
+ def post_dissect(self, s):
+# self.icv, = struct.unpack("!I",self.wepdata[-4:])
+# self.wepdata = self.wepdata[:-4]
+ self.decrypt()
+
+ def build_payload(self):
+ if self.wepdata is None:
+ return Packet.build_payload(self)
+ return b""
+
+ def post_build(self, p, pay):
+ if self.wepdata is None:
+ key = conf.wepkey
+ if key:
+ if self.icv is None:
+ pay += struct.pack("<I",crc32(pay))
+ icv = b""
+ else:
+ icv = p[4:8]
+ c = ARC4.new(self.iv+key)
+ p = p[:4]+c.encrypt(pay)+icv
+ else:
+ warning("No WEP key set (conf.wepkey).. strange results expected..")
+ return p
+
+
+ def decrypt(self,key=None):
+ if key is None:
+ key = conf.wepkey
+ if key:
+ c = ARC4.new(self.iv+key)
+ self.add_payload(LLC(c.decrypt(self.wepdata)))
+
+
+bind_layers( PrismHeader, Dot11, )
+bind_layers( RadioTap, Dot11, )
+bind_layers( PPI, Dot11, dlt=105)
+bind_layers( Dot11, LLC, type=2)
+bind_layers( Dot11QoS, LLC, )
+bind_layers( Dot11, Dot11AssoReq, subtype=0, type=0)
+bind_layers( Dot11, Dot11AssoResp, subtype=1, type=0)
+bind_layers( Dot11, Dot11ReassoReq, subtype=2, type=0)
+bind_layers( Dot11, Dot11ReassoResp, subtype=3, type=0)
+bind_layers( Dot11, Dot11ProbeReq, subtype=4, type=0)
+bind_layers( Dot11, Dot11ProbeResp, subtype=5, type=0)
+bind_layers( Dot11, Dot11Beacon, subtype=8, type=0)
+bind_layers( Dot11, Dot11ATIM, subtype=9, type=0)
+bind_layers( Dot11, Dot11Disas, subtype=10, type=0)
+bind_layers( Dot11, Dot11Auth, subtype=11, type=0)
+bind_layers( Dot11, Dot11Deauth, subtype=12, type=0)
+bind_layers( Dot11Beacon, Dot11Elt, )
+bind_layers( Dot11AssoReq, Dot11Elt, )
+bind_layers( Dot11AssoResp, Dot11Elt, )
+bind_layers( Dot11ReassoReq, Dot11Elt, )
+bind_layers( Dot11ReassoResp, Dot11Elt, )
+bind_layers( Dot11ProbeReq, Dot11Elt, )
+bind_layers( Dot11ProbeResp, Dot11Elt, )
+bind_layers( Dot11Auth, Dot11Elt, )
+bind_layers( Dot11Elt, Dot11Elt, )
+
+
+conf.l2types.register(105, Dot11)
+conf.l2types.register_num2layer(801, Dot11)
+conf.l2types.register(119, PrismHeader)
+conf.l2types.register_num2layer(802, PrismHeader)
+conf.l2types.register(127, RadioTap)
+conf.l2types.register(0xc0, PPI)
+conf.l2types.register_num2layer(803, RadioTap)
+
+
+class WiFi_am(AnsweringMachine):
+ """Before using this, initialize "iffrom" and "ifto" interfaces:
+iwconfig iffrom mode monitor
+iwpriv orig_ifto hostapd 1
+ifconfig ifto up
+note: if ifto=wlan0ap then orig_ifto=wlan0
+note: ifto and iffrom must be set on the same channel
+ex:
+ifconfig eth1 up
+iwconfig eth1 mode monitor
+iwconfig eth1 channel 11
+iwpriv wlan0 hostapd 1
+ifconfig wlan0ap up
+iwconfig wlan0 channel 11
+iwconfig wlan0 essid dontexist
+iwconfig wlan0 mode managed
+"""
+ function_name = "airpwn"
+ filter = None
+
+ def parse_options(self, iffrom, ifto, replace, pattern="", ignorepattern=""):
+ self.iffrom = iffrom
+ self.ifto = ifto
+ ptrn = re.compile(pattern)
+ iptrn = re.compile(ignorepattern)
+
+ def is_request(self, pkt):
+ if not isinstance(pkt,Dot11):
+ return 0
+ if not pkt.FCfield & 1:
+ return 0
+ if not pkt.haslayer(TCP):
+ return 0
+ ip = pkt.getlayer(IP)
+ tcp = pkt.getlayer(TCP)
+ pay = str(tcp.payload)
+ if not self.ptrn.match(pay):
+ return 0
+ if self.iptrn.match(pay):
+ return 0
+
+ def make_reply(self, p):
+ ip = p.getlayer(IP)
+ tcp = p.getlayer(TCP)
+ pay = str(tcp.payload)
+ del(p.payload.payload.payload)
+ p.FCfield="from-DS"
+ p.addr1,p.addr2 = p.addr2,p.addr1
+ p /= IP(src=ip.dst,dst=ip.src)
+ p /= TCP(sport=tcp.dport, dport=tcp.sport,
+ seq=tcp.ack, ack=tcp.seq+len(pay),
+ flags="PA")
+ q = p.copy()
+ p /= self.replace
+ q.ID += 1
+ q.getlayer(TCP).flags="RA"
+ q.getlayer(TCP).seq+=len(replace)
+ return [p,q]
+
+ def print_reply(self):
+ print(p.sprintf("Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%"))
+
+ def send_reply(self, reply):
+ sendp(reply, iface=self.ifto, **self.optsend)
+
+ def sniff(self):
+ sniff(iface=self.iffrom, **self.optsniff)
+
+
+
+plst=[]
+def get_toDS():
+ global plst
+ while 1:
+ p,=sniff(iface="eth1",count=1)
+ if not isinstance(p,Dot11):
+ continue
+ if p.FCfield & 1:
+ plst.append(p)
+ print(".")
+
+
+# if not ifto.endswith("ap"):
+# print("iwpriv %s hostapd 1" % ifto)
+# os.system("iwpriv %s hostapd 1" % ifto)
+# ifto += "ap"
+#
+# os.system("iwconfig %s mode monitor" % iffrom)
+#
+
+def airpwn(iffrom, ifto, replace, pattern="", ignorepattern=""):
+ """Before using this, initialize "iffrom" and "ifto" interfaces:
+iwconfig iffrom mode monitor
+iwpriv orig_ifto hostapd 1
+ifconfig ifto up
+note: if ifto=wlan0ap then orig_ifto=wlan0
+note: ifto and iffrom must be set on the same channel
+ex:
+ifconfig eth1 up
+iwconfig eth1 mode monitor
+iwconfig eth1 channel 11
+iwpriv wlan0 hostapd 1
+ifconfig wlan0ap up
+iwconfig wlan0 channel 11
+iwconfig wlan0 essid dontexist
+iwconfig wlan0 mode managed
+"""
+
+ ptrn = re.compile(pattern)
+ iptrn = re.compile(ignorepattern)
+ def do_airpwn(p, ifto=ifto, replace=replace, ptrn=ptrn, iptrn=iptrn):
+ if not isinstance(p,Dot11):
+ return
+ if not p.FCfield & 1:
+ return
+ if not p.haslayer(TCP):
+ return
+ ip = p.getlayer(IP)
+ tcp = p.getlayer(TCP)
+ pay = str(tcp.payload)
+# print "got tcp"
+ if not ptrn.match(pay):
+ return
+# print "match 1"
+ if iptrn.match(pay):
+ return
+# print "match 2"
+ del(p.payload.payload.payload)
+ p.FCfield="from-DS"
+ p.addr1,p.addr2 = p.addr2,p.addr1
+ q = p.copy()
+ p /= IP(src=ip.dst,dst=ip.src)
+ p /= TCP(sport=tcp.dport, dport=tcp.sport,
+ seq=tcp.ack, ack=tcp.seq+len(pay),
+ flags="PA")
+ q = p.copy()
+ p /= replace
+ q.ID += 1
+ q.getlayer(TCP).flags="RA"
+ q.getlayer(TCP).seq+=len(replace)
+
+ sendp([p,q], iface=ifto, verbose=0)
+# print "send",repr(p)
+# print "send",repr(q)
+ print(p.sprintf("Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%"))
+
+ sniff(iface=iffrom,prn=do_airpwn)
+
+
+
+conf.stats_dot11_protocols += [Dot11WEP, Dot11Beacon, ]
+
+
+
+
+
+class Dot11PacketList(PacketList):
+ def __init__(self, res=None, name="Dot11List", stats=None):
+ if stats is None:
+ stats = conf.stats_dot11_protocols
+
+ PacketList.__init__(self, res, name, stats)
+ def toEthernet(self):
+ #data = map(lambda x:x.getlayer(Dot11), filter(lambda x : x.haslayer(Dot11) and x.type == 2, self.res))
+ data = [ x.getlayer(Dot11) for x in self.res if x.haslayer(Dot11) and x.type == 2 ]
+ r2 = []
+ for p in data:
+ q = p.copy()
+ q.unwep()
+ r2.append(Ether()/q.payload.payload.payload) #Dot11/LLC/SNAP/IP
+ return PacketList(r2,name="Ether from %s"%self.listname)
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/gprs.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/gprs.py
new file mode 100644
index 00000000..31a931fe
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/gprs.py
@@ -0,0 +1,21 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+GPRS (General Packet Radio Service) for mobile data communication.
+"""
+
+from scapy.fields import *
+from scapy.packet import *
+from scapy.layers.inet import IP
+
+class GPRS(Packet):
+ name = "GPRSdummy"
+ fields_desc = [
+ StrStopField("dummy","","\x65\x00\x00",1)
+ ]
+
+
+bind_layers( GPRS, IP, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/hsrp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/hsrp.py
new file mode 100644
index 00000000..7193b97e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/hsrp.py
@@ -0,0 +1,79 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+#############################################################################
+## ##
+## hsrp.py --- HSRP protocol support for Scapy ##
+## ##
+## Copyright (C) 2010 Mathieu RENARD mathieu.renard(at)gmail.com ##
+## ##
+## This program is free software; you can redistribute it and/or modify it ##
+## under the terms of the GNU General Public License version 2 as ##
+## published by the Free Software Foundation; version 2. ##
+## ##
+## This program is distributed in the hope that it will be useful, but ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of ##
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
+## General Public License for more details. ##
+## ##
+#############################################################################
+## HSRP Version 1
+## Ref. RFC 2281
+## HSRP Version 2
+## Ref. http://www.smartnetworks.jp/2006/02/hsrp_8_hsrp_version_2.html
+##
+## $Log: hsrp.py,v $
+## Revision 0.2 2011/05/01 15:23:34 mrenard
+## Cleanup code
+
+"""
+HSRP (Hot Standby Router Protocol): proprietary redundancy protocol for Cisco routers.
+"""
+
+from scapy.fields import *
+from scapy.packet import *
+from scapy.layers.inet import UDP
+
+
+class HSRP(Packet):
+ name = "HSRP"
+ fields_desc = [
+ ByteField("version", 0),
+ ByteEnumField("opcode", 0, {0: "Hello", 1: "Coup", 2: "Resign", 3: "Advertise"}),
+ ByteEnumField("state", 16, {0: "Initial", 1: "Learn", 2: "Listen", 4: "Speak", 8: "Standby", 16: "Active"}),
+ ByteField("hellotime", 3),
+ ByteField("holdtime", 10),
+ ByteField("priority", 120),
+ ByteField("group", 1),
+ ByteField("reserved", 0),
+ StrFixedLenField("auth", "cisco" + "\00" * 3, 8),
+ IPField("virtualIP", "192.168.1.1")]
+
+ def guess_payload_class(self, payload):
+ if self.underlayer.len > 28:
+ return HSRPmd5
+ else:
+ return Packet.guess_payload_class(self, payload)
+
+
+class HSRPmd5(Packet):
+ name = "HSRP MD5 Authentication"
+ fields_desc = [
+ ByteEnumField("type", 4, {4: "MD5 authentication"}),
+ ByteField("len", None),
+ ByteEnumField("algo", 0, {1: "MD5"}),
+ ByteField("padding", 0x00),
+ XShortField("flags", 0x00),
+ IPField("sourceip", None),
+ XIntField("keyid", 0x00),
+ StrFixedLenField("authdigest", "\00" * 16, 16)]
+
+ def post_build(self, p, pay):
+ if self.len is None and pay:
+ l = len(pay)
+ p = p[:1] + hex(l)[30:] + p[30:]
+ return p
+
+bind_layers(UDP, HSRP, dport=1985, sport=1985)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet.py
new file mode 100644
index 00000000..04b99e89
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet.py
@@ -0,0 +1,1569 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+IPv4 (Internet Protocol v4).
+"""
+
+import os,time,struct,re,socket,types
+from select import select
+from collections import defaultdict
+from scapy.utils import checksum
+from scapy.layers.l2 import *
+from scapy.config import conf
+from scapy.fields import *
+from scapy.packet import *
+from scapy.volatile import *
+from scapy.sendrecv import sr,sr1,srp1
+from scapy.plist import PacketList,SndRcvList
+from scapy.automaton import Automaton,ATMT
+
+import scapy.as_resolvers
+
+
+####################
+## IP Tools class ##
+####################
+
+class IPTools:
+ """Add more powers to a class that have a "src" attribute."""
+ def whois(self):
+ os.system("whois %s" % self.src)
+ def ottl(self):
+ t = [32,64,128,255]+[self.ttl]
+ t.sort()
+ return t[t.index(self.ttl)+1]
+ def hops(self):
+ return self.ottl()-self.ttl-1
+
+
+_ip_options_names = { 0: "end_of_list",
+ 1: "nop",
+ 2: "security",
+ 3: "loose_source_route",
+ 4: "timestamp",
+ 5: "extended_security",
+ 6: "commercial_security",
+ 7: "record_route",
+ 8: "stream_id",
+ 9: "strict_source_route",
+ 10: "experimental_measurement",
+ 11: "mtu_probe",
+ 12: "mtu_reply",
+ 13: "flow_control",
+ 14: "access_control",
+ 15: "encode",
+ 16: "imi_traffic_descriptor",
+ 17: "extended_IP",
+ 18: "traceroute",
+ 19: "address_extension",
+ 20: "router_alert",
+ 21: "selective_directed_broadcast_mode",
+ 23: "dynamic_packet_state",
+ 24: "upstream_multicast_packet",
+ 25: "quick_start",
+ 30: "rfc4727_experiment",
+ }
+
+
+class _IPOption_HDR(Packet):
+ fields_desc = [ BitField("copy_flag",0, 1),
+ BitEnumField("optclass",0,2,{0:"control",2:"debug"}),
+ BitEnumField("option",0,5, _ip_options_names) ]
+
+class IPOption(Packet):
+ name = "IP Option"
+ fields_desc = [ _IPOption_HDR,
+ FieldLenField("length", None, fmt="B", # Only option 0 and 1 have no length and value
+ length_of="value", adjust=lambda pkt,l:l+2),
+ StrLenField("value", "",length_from=lambda pkt:pkt.length-2) ]
+
+ def extract_padding(self, p):
+ return b"",p
+
+ registered_ip_options = {}
+ @classmethod
+ def register_variant(cls):
+ cls.registered_ip_options[cls.option.default] = cls
+ @classmethod
+ def dispatch_hook(cls, pkt=None, *args, **kargs):
+ if pkt:
+ opt = pkt[0]&0x1f
+ if opt in cls.registered_ip_options:
+ return cls.registered_ip_options[opt]
+ return cls
+
+class IPOption_EOL(IPOption):
+ name = "IP Option End of Options List"
+ option = 0
+ fields_desc = [ _IPOption_HDR ]
+
+
+class IPOption_NOP(IPOption):
+ name = "IP Option No Operation"
+ option=1
+ fields_desc = [ _IPOption_HDR ]
+
+class IPOption_Security(IPOption):
+ name = "IP Option Security"
+ copy_flag = 1
+ option = 2
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 11),
+ ShortField("security",0),
+ ShortField("compartment",0),
+ ShortField("handling_restrictions",0),
+ StrFixedLenField("transmission_control_code","xxx",3),
+ ]
+
+class IPOption_LSRR(IPOption):
+ name = "IP Option Loose Source and Record Route"
+ copy_flag = 1
+ option = 3
+ fields_desc = [ _IPOption_HDR,
+ FieldLenField("length", None, fmt="B",
+ length_of="routers", adjust=lambda pkt,l:l+3),
+ ByteField("pointer",4), # 4 is first IP
+ FieldListField("routers",[],IPField("","0.0.0.0"),
+ length_from=lambda pkt:pkt.length-3)
+ ]
+ def get_current_router(self):
+ return self.routers[self.pointer//4-1]
+
+class IPOption_RR(IPOption_LSRR):
+ name = "IP Option Record Route"
+ option = 7
+
+class IPOption_SSRR(IPOption_LSRR):
+ name = "IP Option Strict Source and Record Route"
+ option = 9
+
+class IPOption_Stream_Id(IPOption):
+ name = "IP Option Stream ID"
+ option = 8
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 4),
+ ShortField("security",0), ]
+
+class IPOption_MTU_Probe(IPOption):
+ name = "IP Option MTU Probe"
+ option = 11
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 4),
+ ShortField("mtu",0), ]
+
+class IPOption_MTU_Reply(IPOption_MTU_Probe):
+ name = "IP Option MTU Reply"
+ option = 12
+
+class IPOption_Traceroute(IPOption):
+ name = "IP Option Traceroute"
+ copy_flag = 1
+ option = 18
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 12),
+ ShortField("id",0),
+ ShortField("outbound_hops",0),
+ ShortField("return_hops",0),
+ IPField("originator_ip","0.0.0.0") ]
+
+class IPOption_Address_Extension(IPOption):
+ name = "IP Option Address Extension"
+ copy_flag = 1
+ option = 19
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 10),
+ IPField("src_ext","0.0.0.0"),
+ IPField("dst_ext","0.0.0.0") ]
+
+class IPOption_Router_Alert(IPOption):
+ name = "IP Option Router Alert"
+ copy_flag = 1
+ option = 20
+ fields_desc = [ _IPOption_HDR,
+ ByteField("length", 4),
+ ShortEnumField("alert",0, {0:"router_shall_examine_packet"}), ]
+
+
+class IPOption_SDBM(IPOption):
+ name = "IP Option Selective Directed Broadcast Mode"
+ copy_flag = 1
+ option = 21
+ fields_desc = [ _IPOption_HDR,
+ FieldLenField("length", None, fmt="B",
+ length_of="addresses", adjust=lambda pkt,l:l+2),
+ FieldListField("addresses",[],IPField("","0.0.0.0"),
+ length_from=lambda pkt:pkt.length-2)
+ ]
+
+
+
+TCPOptions = (
+ { 0 : ("EOL",None),
+ 1 : ("NOP",None),
+ 2 : ("MSS","!H"),
+ 3 : ("WScale","!B"),
+ 4 : ("SAckOK",None),
+ 5 : ("SAck","!"),
+ 8 : ("Timestamp","!II"),
+ 14 : ("AltChkSum","!BH"),
+ 15 : ("AltChkSumOpt",None),
+ 25 : ("Mood","!p")
+ },
+ { "EOL":0,
+ "NOP":1,
+ "MSS":2,
+ "WScale":3,
+ "SAckOK":4,
+ "SAck":5,
+ "Timestamp":8,
+ "AltChkSum":14,
+ "AltChkSumOpt":15,
+ "Mood":25
+ } )
+
+class TCPOptionsField(StrField):
+ islist=1
+ def getfield(self, pkt, s):
+ opsz = (pkt.dataofs-5)*4
+ if opsz < 0:
+ warning("bad dataofs (%i). Assuming dataofs=5"%pkt.dataofs)
+ opsz = 0
+ return s[opsz:],self.m2i(pkt,s[:opsz])
+ def m2i(self, pkt, x):
+ opt = []
+ while x:
+ onum = x[0]
+ if onum == 0:
+ opt.append(("EOL",None))
+ x=x[1:]
+ break
+ if onum == 1:
+ opt.append(("NOP",None))
+ x=x[1:]
+ continue
+ olen = x[1]
+ if olen < 2:
+ warning("Malformed TCP option (announced length is %i)" % olen)
+ olen = 2
+ oval = x[2:olen]
+ if onum in TCPOptions[0]:
+ oname, ofmt = TCPOptions[0][onum]
+ if onum == 5: #SAck
+ ofmt += "%iI" % (len(oval)//4)
+ if ofmt and struct.calcsize(ofmt) == len(oval):
+ oval = struct.unpack(ofmt, oval)
+ if len(oval) == 1:
+ oval = oval[0]
+ opt.append((oname, oval))
+ else:
+ opt.append((onum, oval))
+ x = x[olen:]
+ return opt
+
+ def i2m(self, pkt, x):
+ opt = b""
+ for oname,oval in x:
+ if type(oname) is str:
+ if oname == "NOP":
+ opt += b"\x01"
+ continue
+ elif oname == "EOL":
+ opt += b"\x00"
+ continue
+ elif oname in TCPOptions[1]:
+ onum = TCPOptions[1][oname]
+ ofmt = TCPOptions[0][onum][1]
+ if onum == 5: #SAck
+ ofmt += b"%iI" % len(oval)
+ if ofmt is not None and (type(oval) is not str or "s" in ofmt):
+ if type(oval) is not tuple:
+ oval = (oval,)
+ oval = struct.pack(ofmt, *oval)
+ else:
+ warning("option [%s] unknown. Skipped."%oname)
+ continue
+ else:
+ onum = oname
+ if type(oval) is not str:
+ warning("option [%i] is not string."%onum)
+ continue
+ opt += bytes([(onum), (2+len(oval))]) + oval
+ return opt+b"\x00"*(3-((len(opt)+3)%4))
+ def randval(self):
+ return [] # XXX
+
+
+class ICMPTimeStampField(IntField):
+ re_hmsm = re.compile("([0-2]?[0-9])[Hh:](([0-5]?[0-9])([Mm:]([0-5]?[0-9])([sS:.]([0-9]{0,3}))?)?)?$")
+ def i2repr(self, pkt, val):
+ if val is None:
+ return "--"
+ else:
+ sec, milli = divmod(val, 1000)
+ min, sec = divmod(sec, 60)
+ hour, min = divmod(min, 60)
+ return "%d:%d:%d.%d" %(hour, min, sec, int(milli))
+ def any2i(self, pkt, val):
+ if type(val) is str:
+ hmsms = self.re_hmsm.match(val)
+ if hmsms:
+ h,_,m,_,s,_,ms = hmsms = hmsms.groups()
+ ms = int(((ms or "")+"000")[:3])
+ val = ((int(h)*60+int(m or 0))*60+int(s or 0))*1000+ms
+ else:
+ val = 0
+ elif val is None:
+ val = int((time.time()%(24*60*60))*1000)
+ return val
+
+
+class IP(Packet, IPTools):
+ name = "IP"
+ fields_desc = [ BitField("version" , 4 , 4),
+ BitField("ihl", None, 4),
+ XByteField("tos", 0),
+ ShortField("len", None),
+ ShortField("id", 1),
+ FlagsField("flags", 0, 3, ["MF","DF","evil"]),
+ BitField("frag", 0, 13),
+ ByteField("ttl", 64),
+ ByteEnumField("proto", 0, IP_PROTOS),
+ XShortField("chksum", None),
+ #IPField("src", "127.0.0.1"),
+ #Emph(SourceIPField("src","dst")),
+ #Emph(IPField("dst", "127.0.0.1")),
+
+ Emph(IPField("src", "16.0.0.1")),
+ Emph(IPField("dst", "48.0.0.1")),
+ PacketListField("options", [], IPOption, length_from=lambda p:p.ihl*4-20) ]
+ def post_build(self, p, pay):
+ ihl = self.ihl
+ p += b"\0"*((-len(p))%4) # pad IP options if needed
+ if ihl is None:
+ ihl = len(p)//4
+ p = bytes([((self.version&0xf)<<4) | ihl&0x0f])+p[1:]
+ if self.len is None:
+ l = len(p)+len(pay)
+ p = p[:2]+struct.pack("!H", l)+p[4:]
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:10]+bytes([ck>>8])+bytes([ck&0xff])+p[12:]
+ return p+pay
+
+ def extract_padding(self, s):
+ l = self.len - (self.ihl << 2)
+ return s[:l],s[l:]
+
+ def send(self, s, slp=0):
+ for p in self:
+ try:
+ s.sendto(bytes(p), (p.dst,0))
+ except socket.error as msg:
+ log_runtime.error(msg)
+ if slp:
+ time.sleep(slp)
+ def route(self):
+ dst = self.dst
+ if isinstance(dst,Gen):
+ dst = next(iter(dst))
+ return conf.route.route(dst)
+ def hashret(self):
+ if ( (self.proto == socket.IPPROTO_ICMP)
+ and (isinstance(self.payload, ICMP))
+ and (self.payload.type in [3,4,5,11,12]) ):
+ return self.payload.payload.hashret()
+ else:
+ if conf.checkIPsrc and conf.checkIPaddr:
+ return strxor(inet_aton(self.src),inet_aton(self.dst))+struct.pack("B",self.proto)+self.payload.hashret()
+ else:
+ return struct.pack("B", self.proto)+self.payload.hashret()
+ def answers(self, other):
+ if not isinstance(other,IP):
+ return 0
+ if conf.checkIPaddr and (self.dst != other.src):
+ return 0
+ if ( (self.proto == socket.IPPROTO_ICMP) and
+ (isinstance(self.payload, ICMP)) and
+ (self.payload.type in [3,4,5,11,12]) ):
+ # ICMP error message
+ return self.payload.payload.answers(other)
+
+ else:
+ if ( (conf.checkIPaddr and (self.src != other.dst)) or
+ (self.proto != other.proto) ):
+ return 0
+ return self.payload.answers(other.payload)
+ def mysummary(self):
+ s = self.sprintf("%IP.src% > %IP.dst% %IP.proto%")
+ if self.frag:
+ s += " frag:%i" % self.frag
+ return s
+
+ def fragment(self, fragsize=1480):
+ """Fragment IP datagrams"""
+ fragsize = (fragsize+7)//8*8
+ lst = []
+ fnb = 0
+ fl = self
+ while fl.underlayer is not None:
+ fnb += 1
+ fl = fl.underlayer
+
+ for p in fl:
+ s = bytes(p[fnb].payload)
+ nb = (len(s)+fragsize-1)//fragsize
+ for i in range(nb):
+ q = p.copy()
+ del(q[fnb].payload)
+ del(q[fnb].chksum)
+ del(q[fnb].len)
+ if i == nb-1:
+ q[IP].flags &= ~1
+ else:
+ q[IP].flags |= 1
+ q[IP].frag = i*fragsize//8
+ r = conf.raw_layer(load=s[i*fragsize:(i+1)*fragsize])
+ r.overload_fields = p[IP].payload.overload_fields.copy()
+ q.add_payload(r)
+ lst.append(q)
+ return lst
+
+
+class TCP(Packet):
+ name = "TCP"
+ fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES),
+ ShortEnumField("dport", 80, TCP_SERVICES),
+ IntField("seq", 0),
+ IntField("ack", 0),
+ BitField("dataofs", None, 4),
+ BitField("reserved", 0, 4),
+ FlagsField("flags", 0x2, 8, "FSRPAUEC"),
+ ShortField("window", 8192),
+ XShortField("chksum", None),
+ ShortField("urgptr", 0),
+ TCPOptionsField("options", {}) ]
+ def post_build(self, p, pay):
+ p += pay
+ dataofs = self.dataofs
+ if dataofs is None:
+ dataofs = 5+((len(self.get_field("options").i2m(self,self.options))+3)//4)
+ p = p[:12]+bytes([(dataofs << 4) | (p[12])&0x0f])+p[13:]
+ if self.chksum is None:
+ if isinstance(self.underlayer, IP):
+ if self.underlayer.len is not None:
+ ln = self.underlayer.len-20
+ else:
+ ln = len(p)
+ psdhdr = struct.pack("!4s4sHH",
+ inet_aton(self.underlayer.src),
+ inet_aton(self.underlayer.dst),
+ self.underlayer.proto,
+ ln)
+ ck=checksum(psdhdr+p)
+ p = p[:16]+struct.pack("!H", ck)+p[18:]
+ elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):
+ ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
+ p = p[:16]+struct.pack("!H", ck)+p[18:]
+ else:
+ warning("No IP underlayer to compute checksum. Leaving null.")
+ return p
+ def hashret(self):
+ if conf.checkIPsrc:
+ return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret()
+ else:
+ return self.payload.hashret()
+ def answers(self, other):
+ if not isinstance(other, TCP):
+ return 0
+ if conf.checkIPsrc:
+ if not ((self.sport == other.dport) and
+ (self.dport == other.sport)):
+ return 0
+ if (abs(other.seq-self.ack) > 2+len(other.payload)):
+ return 0
+ return 1
+ def mysummary(self):
+ if isinstance(self.underlayer, IP):
+ return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")
+ elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6):
+ return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")
+ else:
+ return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%")
+
+class UDP(Packet):
+ name = "UDP"
+ fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES),
+ ShortEnumField("dport", 53, UDP_SERVICES),
+ ShortField("len", None),
+ XShortField("chksum", None), ]
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+ if l is None:
+ l = len(p)
+ p = p[:4]+struct.pack("!H",l)+p[6:]
+ if self.chksum is None:
+ if isinstance(self.underlayer, IP):
+ if self.underlayer.len is not None:
+ ln = self.underlayer.len-20
+ else:
+ ln = len(p)
+ psdhdr = struct.pack("!4s4sHH",
+ inet_aton(self.underlayer.src),
+ inet_aton(self.underlayer.dst),
+ self.underlayer.proto,
+ ln)
+ ck=checksum(psdhdr+p)
+ p = p[:6]+struct.pack("!H", ck)+p[8:]
+ elif isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):
+ ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)
+ p = p[:6]+struct.pack("!H", ck)+p[8:]
+ else:
+ warning("No IP underlayer to compute checksum. Leaving null.")
+ return p
+ def extract_padding(self, s):
+ l = self.len - 8
+ return s[:l],s[l:]
+ def hashret(self):
+ return self.payload.hashret()
+ def answers(self, other):
+ if not isinstance(other, UDP):
+ return 0
+ if conf.checkIPsrc:
+ if self.dport != other.sport:
+ return 0
+ return self.payload.answers(other.payload)
+ def mysummary(self):
+ if isinstance(self.underlayer, IP):
+ return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")
+ elif isinstance(self.underlayer, scapy.layers.inet6.IPv6):
+ return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")
+ else:
+ return self.sprintf("UDP %UDP.sport% > %UDP.dport%")
+
+icmptypes = { 0 : "echo-reply",
+ 3 : "dest-unreach",
+ 4 : "source-quench",
+ 5 : "redirect",
+ 8 : "echo-request",
+ 9 : "router-advertisement",
+ 10 : "router-solicitation",
+ 11 : "time-exceeded",
+ 12 : "parameter-problem",
+ 13 : "timestamp-request",
+ 14 : "timestamp-reply",
+ 15 : "information-request",
+ 16 : "information-response",
+ 17 : "address-mask-request",
+ 18 : "address-mask-reply" }
+
+icmpcodes = { 3 : { 0 : "network-unreachable",
+ 1 : "host-unreachable",
+ 2 : "protocol-unreachable",
+ 3 : "port-unreachable",
+ 4 : "fragmentation-needed",
+ 5 : "source-route-failed",
+ 6 : "network-unknown",
+ 7 : "host-unknown",
+ 9 : "network-prohibited",
+ 10 : "host-prohibited",
+ 11 : "TOS-network-unreachable",
+ 12 : "TOS-host-unreachable",
+ 13 : "communication-prohibited",
+ 14 : "host-precedence-violation",
+ 15 : "precedence-cutoff", },
+ 5 : { 0 : "network-redirect",
+ 1 : "host-redirect",
+ 2 : "TOS-network-redirect",
+ 3 : "TOS-host-redirect", },
+ 11 : { 0 : "ttl-zero-during-transit",
+ 1 : "ttl-zero-during-reassembly", },
+ 12 : { 0 : "ip-header-bad",
+ 1 : "required-option-missing", }, }
+
+
+
+
+class ICMP(Packet):
+ name = "ICMP"
+ fields_desc = [ ByteEnumField("type",8, icmptypes),
+ MultiEnumField("code",0, icmpcodes, depends_on=lambda pkt:pkt.type,fmt="B"),
+ XShortField("chksum", None),
+ ConditionalField(XShortField("id",0), lambda pkt:pkt.type in [0,8,13,14,15,16,17,18]),
+ ConditionalField(XShortField("seq",0), lambda pkt:pkt.type in [0,8,13,14,15,16,17,18]),
+ ConditionalField(ICMPTimeStampField("ts_ori", None), lambda pkt:pkt.type in [13,14]),
+ ConditionalField(ICMPTimeStampField("ts_rx", None), lambda pkt:pkt.type in [13,14]),
+ ConditionalField(ICMPTimeStampField("ts_tx", None), lambda pkt:pkt.type in [13,14]),
+ ConditionalField(IPField("gw","0.0.0.0"), lambda pkt:pkt.type==5),
+ ConditionalField(ByteField("ptr",0), lambda pkt:pkt.type==12),
+ ConditionalField(X3BytesField("reserved",0), lambda pkt:pkt.type==12),
+ ConditionalField(IPField("addr_mask","0.0.0.0"), lambda pkt:pkt.type in [17,18]),
+ ConditionalField(IntField("unused",0), lambda pkt:pkt.type not in [0,5,8,12,13,14,15,16,17,18]),
+
+ ]
+ def post_build(self, p, pay):
+ p += pay
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:2]+bytes([ck>>8, ck&0xff])+p[4:]
+ return p
+
+ def hashret(self):
+ if self.type in [0,8,13,14,15,16,17,18]:
+ return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
+ return self.payload.hashret()
+ def answers(self, other):
+ if not isinstance(other,ICMP):
+ return 0
+ if ( (other.type,self.type) in [(8,0),(13,14),(15,16),(17,18)] and
+ self.id == other.id and
+ self.seq == other.seq ):
+ return 1
+ return 0
+
+ def guess_payload_class(self, payload):
+ if self.type in [3,4,5,11,12]:
+ return IPerror
+ else:
+ return None
+ def mysummary(self):
+ if isinstance(self.underlayer, IP):
+ return self.underlayer.sprintf("ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%")
+ else:
+ return self.sprintf("ICMP %ICMP.type% %ICMP.code%")
+
+
+
+
+
+class IPerror(IP):
+ name = "IP in ICMP"
+ def answers(self, other):
+ if not isinstance(other, IP):
+ return 0
+ if not ( ((conf.checkIPsrc == 0) or (self.dst == other.dst)) and
+ (self.src == other.src) and
+ ( ((conf.checkIPID == 0)
+ or (self.id == other.id)
+ or (conf.checkIPID == 1 and self.id == socket.htons(other.id)))) and
+ (self.proto == other.proto) ):
+ return 0
+ return self.payload.answers(other.payload)
+ def mysummary(self):
+ return Packet.mysummary(self)
+
+
+class TCPerror(TCP):
+ fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES),
+ ShortEnumField("dport", 80, TCP_SERVICES),
+ IntField("seq", 0) ]
+ name = "TCP in ICMP"
+ def post_build(self, p, pay):
+ p += pay
+ return p
+ def answers(self, other):
+ if not isinstance(other, TCP):
+ return 0
+ if conf.checkIPsrc:
+ if not ((self.sport == other.sport) and
+ (self.dport == other.dport)):
+ return 0
+ if conf.check_TCPerror_seqack:
+ if self.seq is not None:
+ if self.seq != other.seq:
+ return 0
+ if self.ack is not None:
+ if self.ack != other.ack:
+ return 0
+ return 1
+ def mysummary(self):
+ return Packet.mysummary(self)
+
+
+class UDPerror(UDP):
+ name = "UDP in ICMP"
+ def answers(self, other):
+ if not isinstance(other, UDP):
+ return 0
+ if conf.checkIPsrc:
+ if not ((self.sport == other.sport) and
+ (self.dport == other.dport)):
+ return 0
+ return 1
+ def mysummary(self):
+ return Packet.mysummary(self)
+
+
+
+class ICMPerror(ICMP):
+ name = "ICMP in ICMP"
+ def answers(self, other):
+ if not isinstance(other,ICMP):
+ return 0
+ if not ((self.type == other.type) and
+ (self.code == other.code)):
+ return 0
+ if self.code in [0,8,13,14,17,18]:
+ if (self.id == other.id and
+ self.seq == other.seq):
+ return 1
+ else:
+ return 0
+ else:
+ return 1
+ def mysummary(self):
+ return Packet.mysummary(self)
+
+bind_layers( Ether, IP, type=2048)
+bind_layers( CookedLinux, IP, proto=2048)
+bind_layers( GRE, IP, proto=2048)
+bind_layers( SNAP, IP, code=2048)
+bind_layers( IPerror, IPerror, frag=0, proto=4)
+bind_layers( IPerror, ICMPerror, frag=0, proto=1)
+bind_layers( IPerror, TCPerror, frag=0, proto=6)
+bind_layers( IPerror, UDPerror, frag=0, proto=17)
+bind_layers( IP, IP, frag=0, proto=4)
+bind_layers( IP, ICMP, frag=0, proto=1)
+bind_layers( IP, TCP, frag=0, proto=6)
+bind_layers( IP, UDP, frag=0, proto=17)
+bind_layers( IP, GRE, frag=0, proto=47)
+
+conf.l2types.register(101, IP)
+conf.l2types.register_num2layer(12, IP)
+
+conf.l3types.register(ETH_P_IP, IP)
+conf.l3types.register_num2layer(ETH_P_ALL, IP)
+
+
+conf.neighbor.register_l3(Ether, IP, lambda l2,l3: getmacbyip(l3.dst))
+conf.neighbor.register_l3(Dot3, IP, lambda l2,l3: getmacbyip(l3.dst))
+
+
+###################
+## Fragmentation ##
+###################
+
+@conf.commands.register
+def fragment(pkt, fragsize=1480):
+ """Fragment a big IP datagram"""
+ fragsize = (fragsize+7)//8*8
+ lst = []
+ for p in pkt:
+ s = bytes(p[IP].payload)
+ nb = (len(s)+fragsize-1)//fragsize
+ for i in range(nb):
+ q = p.copy()
+ del(q[IP].payload)
+ del(q[IP].chksum)
+ del(q[IP].len)
+ if i == nb-1:
+ q[IP].flags &= ~1
+ else:
+ q[IP].flags |= 1
+ q[IP].frag = i*fragsize//8
+ r = conf.raw_layer(load=s[i*fragsize:(i+1)*fragsize])
+ r.overload_fields = p[IP].payload.overload_fields.copy()
+ q.add_payload(r)
+ lst.append(q)
+ return lst
+
+def overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None):
+ if overlap_fragsize is None:
+ overlap_fragsize = fragsize
+ q = p.copy()
+ del(q[IP].payload)
+ q[IP].add_payload(overlap)
+
+ qfrag = fragment(q, overlap_fragsize)
+ qfrag[-1][IP].flags |= 1
+ return qfrag+fragment(p, fragsize)
+
+@conf.commands.register
+def defrag(plist):
+ """defrag(plist) -> ([not fragmented], [defragmented],
+ [ [bad fragments], [bad fragments], ... ])"""
+ frags = defaultdict(PacketList)
+ nofrag = PacketList()
+ for p in plist:
+ ip = p[IP]
+ if IP not in p:
+ nofrag.append(p)
+ continue
+ if ip.frag == 0 and ip.flags & 1 == 0:
+ nofrag.append(p)
+ continue
+ uniq = (ip.id,ip.src,ip.dst,ip.proto)
+ frags[uniq].append(p)
+ defrag = []
+ missfrag = []
+ for lst in frags.values():
+ lst.sort(key=lambda x: x.frag)
+ p = lst[0]
+ lastp = lst[-1]
+ if p.frag > 0 or lastp.flags & 1 != 0: # first or last fragment missing
+ missfrag.append(lst)
+ continue
+ p = p.copy()
+ if conf.padding_layer in p:
+ del(p[conf.padding_layer].underlayer.payload)
+ ip = p[IP]
+ if ip.len is None or ip.ihl is None:
+ clen = len(ip.payload)
+ else:
+ clen = ip.len - (ip.ihl<<2)
+ txt = conf.raw_layer()
+ for q in lst[1:]:
+ if clen != q.frag<<3: # Wrong fragmentation offset
+ if clen > q.frag<<3:
+ warning("Fragment overlap (%i > %i) %r || %r || %r" % (clen, q.frag<<3, p,txt,q))
+ missfrag.append(lst)
+ break
+ if q[IP].len is None or q[IP].ihl is None:
+ clen += len(q[IP].payload)
+ else:
+ clen += q[IP].len - (q[IP].ihl<<2)
+ if conf.padding_layer in q:
+ del(q[conf.padding_layer].underlayer.payload)
+ txt.add_payload(q[IP].payload.copy())
+ else:
+ ip.flags &= ~1 # !MF
+ del(ip.chksum)
+ del(ip.len)
+ p = p/txt
+ defrag.append(p)
+ defrag2=PacketList()
+ for p in defrag:
+ defrag2.append(p.__class__(bytes(p)))
+ return nofrag,defrag2,missfrag
+
+@conf.commands.register
+def defragment(plist):
+ """defragment(plist) -> plist defragmented as much as possible """
+ frags = defaultdict(lambda:[])
+ final = []
+
+ pos = 0
+ for p in plist:
+ p._defrag_pos = pos
+ pos += 1
+ if IP in p:
+ ip = p[IP]
+ if ip.frag != 0 or ip.flags & 1:
+ ip = p[IP]
+ uniq = (ip.id,ip.src,ip.dst,ip.proto)
+ frags[uniq].append(p)
+ continue
+ final.append(p)
+
+ defrag = []
+ missfrag = []
+ for lst in frags.values():
+ lst.sort(key=lambda x: x.frag)
+ p = lst[0]
+ lastp = lst[-1]
+ if p.frag > 0 or lastp.flags & 1 != 0: # first or last fragment missing
+ missfrag += lst
+ continue
+ p = p.copy()
+ if conf.padding_layer in p:
+ del(p[conf.padding_layer].underlayer.payload)
+ ip = p[IP]
+ if ip.len is None or ip.ihl is None:
+ clen = len(ip.payload)
+ else:
+ clen = ip.len - (ip.ihl<<2)
+ txt = conf.raw_layer()
+ for q in lst[1:]:
+ if clen != q.frag<<3: # Wrong fragmentation offset
+ if clen > q.frag<<3:
+ warning("Fragment overlap (%i > %i) %r || %r || %r" % (clen, q.frag<<3, p,txt,q))
+ missfrag += lst
+ break
+ if q[IP].len is None or q[IP].ihl is None:
+ clen += len(q[IP].payload)
+ else:
+ clen += q[IP].len - (q[IP].ihl<<2)
+ if conf.padding_layer in q:
+ del(q[conf.padding_layer].underlayer.payload)
+ txt.add_payload(q[IP].payload.copy())
+ else:
+ ip.flags &= ~1 # !MF
+ del(ip.chksum)
+ del(ip.len)
+ p = p/txt
+ p._defrag_pos = max(x._defrag_pos for x in lst)
+ defrag.append(p)
+ defrag2=[]
+ for p in defrag:
+ q = p.__class__(bytes(p))
+ q._defrag_pos = p._defrag_pos
+ defrag2.append(q)
+ final += defrag2
+ final += missfrag
+ final.sort(key=lambda x: x._defrag_pos)
+ for p in final:
+ del(p._defrag_pos)
+
+ if hasattr(plist, "listname"):
+ name = "Defragmented %s" % plist.listname
+ else:
+ name = "Defragmented"
+
+ return PacketList(final, name=name)
+
+
+
+### Add timeskew_graph() method to PacketList
+def _packetlist_timeskew_graph(self, ip, **kargs):
+ """Tries to graph the timeskew between the timestamps and real time for a given ip"""
+ res = map(lambda x: self._elt2pkt(x), self.res)
+ b = filter(lambda x:x.haslayer(IP) and x.getlayer(IP).src == ip and x.haslayer(TCP), res)
+ c = []
+ for p in b:
+ opts = p.getlayer(TCP).options
+ for o in opts:
+ if o[0] == "Timestamp":
+ c.append((p.time,o[1][0]))
+ if not c:
+ warning("No timestamps found in packet list")
+ return
+ #d = map(lambda (x,y): (x%2000,((x-c[0][0])-((y-c[0][1])/1000.0))),c)
+ d = map(lambda a: (a[0]%2000,((a[0]-c[0][0])-((a[1]-c[0][1])/1000.0))),c)
+ return plt.plot(d, **kargs)
+
+#PacketList.timeskew_graph = types.MethodType(_packetlist_timeskew_graph, None)
+
+
+### Create a new packet list
+class TracerouteResult(SndRcvList):
+ def __init__(self, res=None, name="Traceroute", stats=None):
+ PacketList.__init__(self, res, name, stats, vector_index = 1)
+ self.graphdef = None
+ self.graphASres = 0
+ self.padding = 0
+ self.hloc = None
+ self.nloc = None
+
+ def show(self):
+ #return self.make_table(lambda (s,r): (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),
+ return self.make_table(lambda s,r: (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),
+ s.ttl,
+ r.sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")))
+
+
+ def get_trace(self):
+ raw_trace = {}
+ for s,r in self.res:
+ if IP not in s:
+ continue
+ d = s[IP].dst
+ if d not in raw_trace:
+ raw_trace[d] = {}
+ raw_trace[d][s[IP].ttl] = r[IP].src, ICMP not in r
+
+ trace = {}
+ for k in raw_trace.keys():
+ m = [ x for x in raw_trace[k].keys() if raw_trace[k][x][1] ]
+ if not m:
+ trace[k] = raw_trace[k]
+ else:
+ m = min(m)
+ trace[k] = {i: raw_trace[k][i] for i in raw_trace[k].keys() if not raw_trace[k][i][1] or i<=m}
+
+ return trace
+
+ def trace3D(self):
+ """Give a 3D representation of the traceroute.
+ right button: rotate the scene
+ middle button: zoom
+ left button: move the scene
+ left button on a ball: toggle IP displaying
+ ctrl-left button on a ball: scan ports 21,22,23,25,80 and 443 and display the result"""
+ trace = self.get_trace()
+ import visual
+
+ class IPsphere(visual.sphere):
+ def __init__(self, ip, **kargs):
+ visual.sphere.__init__(self, **kargs)
+ self.ip=ip
+ self.label=None
+ self.setlabel(self.ip)
+ def setlabel(self, txt,visible=None):
+ if self.label is not None:
+ if visible is None:
+ visible = self.label.visible
+ self.label.visible = 0
+ elif visible is None:
+ visible=0
+ self.label=visual.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)
+ def action(self):
+ self.label.visible ^= 1
+
+ visual.scene = visual.display()
+ visual.scene.exit = True
+ start = visual.box()
+ rings={}
+ tr3d = {}
+ for i in trace:
+ tr = trace[i]
+ tr3d[i] = []
+ ttl = tr.keys()
+ for t in range(1,max(ttl)+1):
+ if t not in rings:
+ rings[t] = []
+ if t in tr:
+ if tr[t] not in rings[t]:
+ rings[t].append(tr[t])
+ tr3d[i].append(rings[t].index(tr[t]))
+ else:
+ rings[t].append(("unk",-1))
+ tr3d[i].append(len(rings[t])-1)
+ for t in rings:
+ r = rings[t]
+ l = len(r)
+ for i in range(l):
+ if r[i][1] == -1:
+ col = (0.75,0.75,0.75)
+ elif r[i][1]:
+ col = visual.color.green
+ else:
+ col = visual.color.blue
+
+ s = IPsphere(pos=((l-1)*visual.cos(2*i*visual.pi/l),(l-1)*visual.sin(2*i*visual.pi/l),2*t),
+ ip = r[i][0],
+ color = col)
+ for trlst in tr3d.values():
+ if t <= len(trlst):
+ if trlst[t-1] == i:
+ trlst[t-1] = s
+ forecol = colgen(0.625, 0.4375, 0.25, 0.125)
+ for trlst in tr3d.values():
+ col = next(forecol)
+ start = (0,0,0)
+ for ip in trlst:
+ visual.cylinder(pos=start,axis=ip.pos-start,color=col,radius=0.2)
+ start = ip.pos
+
+ movcenter=None
+ while 1:
+ visual.rate(50)
+ if visual.scene.kb.keys:
+ k = visual.scene.kb.getkey()
+ if k == "esc" or k == "q":
+ break
+ if visual.scene.mouse.events:
+ ev = visual.scene.mouse.getevent()
+ if ev.press == "left":
+ o = ev.pick
+ if o:
+ if ev.ctrl:
+ if o.ip == "unk":
+ continue
+ savcolor = o.color
+ o.color = (1,0,0)
+ a,b=sr(IP(dst=o.ip)/TCP(dport=[21,22,23,25,80,443]),timeout=2)
+ o.color = savcolor
+ if len(a) == 0:
+ txt = "%s:\nno results" % o.ip
+ else:
+ txt = "%s:\n" % o.ip
+ for s,r in a:
+ txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n")
+ o.setlabel(txt, visible=1)
+ else:
+ if hasattr(o, "action"):
+ o.action()
+ elif ev.drag == "left":
+ movcenter = ev.pos
+ elif ev.drop == "left":
+ movcenter = None
+ if movcenter:
+ visual.scene.center -= visual.scene.mouse.pos-movcenter
+ movcenter = visual.scene.mouse.pos
+
+## world_trace needs to be reimplemented as gnuplot dependency is removed
+# def world_trace(self):
+# from modules.geo import locate_ip
+# ips = {}
+# rt = {}
+# ports_done = {}
+# for s,r in self.res:
+# ips[r.src] = None
+# if s.haslayer(TCP) or s.haslayer(UDP):
+# trace_id = (s.src,s.dst,s.proto,s.dport)
+# elif s.haslayer(ICMP):
+# trace_id = (s.src,s.dst,s.proto,s.type)
+# else:
+# trace_id = (s.src,s.dst,s.proto,0)
+# trace = rt.get(trace_id,{})
+# if not r.haslayer(ICMP) or r.type != 11:
+# if trace_id in ports_done:
+# continue
+# ports_done[trace_id] = None
+# trace[s.ttl] = r.src
+# rt[trace_id] = trace
+#
+# trt = {}
+# for trace_id in rt:
+# trace = rt[trace_id]
+# loctrace = []
+# for i in range(max(trace.keys())):
+# ip = trace.get(i,None)
+# if ip is None:
+# continue
+# loc = locate_ip(ip)
+# if loc is None:
+# continue
+## loctrace.append((ip,loc)) # no labels yet
+# loctrace.append(loc)
+# if loctrace:
+# trt[trace_id] = loctrace
+#
+# tr = map(lambda x: Gnuplot.Data(x,with_="lines"), trt.values())
+# g = Gnuplot.Gnuplot()
+# world = Gnuplot.File(conf.gnuplot_world,with_="lines")
+# g.plot(world,*tr)
+# return g
+
+ def make_graph(self,ASres=None,padding=0):
+ if ASres is None:
+ ASres = conf.AS_resolver
+ self.graphASres = ASres
+ self.graphpadding = padding
+ ips = {}
+ rt = {}
+ ports = {}
+ ports_done = {}
+ for s,r in self.res:
+ r = r.getlayer(IP) or (conf.ipv6_enabled and r[scapy.layers.inet6.IPv6]) or r
+ s = s.getlayer(IP) or (conf.ipv6_enabled and s[scapy.layers.inet6.IPv6]) or s
+ ips[r.src] = None
+ if TCP in s:
+ trace_id = (s.src,s.dst,6,s.dport)
+ elif UDP in s:
+ trace_id = (s.src,s.dst,17,s.dport)
+ elif ICMP in s:
+ trace_id = (s.src,s.dst,1,s.type)
+ else:
+ trace_id = (s.src,s.dst,s.proto,0)
+ trace = rt.get(trace_id,{})
+ ttl = conf.ipv6_enabled and scapy.layers.inet6.IPv6 in s and s.hlim or s.ttl
+ if not (ICMP in r and r[ICMP].type == 11) and not (conf.ipv6_enabled and scapy.layers.inet6.IPv6 in r and scapy.layers.inet6.ICMPv6TimeExceeded in r):
+ if trace_id in ports_done:
+ continue
+ ports_done[trace_id] = None
+ p = ports.get(r.src,[])
+ if TCP in r:
+ p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%"))
+ trace[ttl] = r.sprintf('"%r,src%":T%ir,TCP.sport%')
+ elif UDP in r:
+ p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
+ trace[ttl] = r.sprintf('"%r,src%":U%ir,UDP.sport%')
+ elif ICMP in r:
+ p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
+ trace[ttl] = r.sprintf('"%r,src%":I%ir,ICMP.type%')
+ else:
+ p.append(r.sprintf("{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}"))
+ trace[ttl] = r.sprintf('"%r,src%":{IP:P%ir,proto%}{IPv6:P%ir,nh%}')
+ ports[r.src] = p
+ else:
+ trace[ttl] = r.sprintf('"%r,src%"')
+ rt[trace_id] = trace
+
+ # Fill holes with unk%i nodes
+ unknown_label = incremental_label("unk%i")
+ blackholes = []
+ bhip = {}
+ for rtk in rt:
+ trace = rt[rtk]
+ k = trace.keys()
+ for n in range(min(k), max(k)):
+ if not n in trace:
+ trace[n] = next(unknown_label)
+ if not rtk in ports_done:
+ if rtk[2] == 1: #ICMP
+ bh = "%s %i/icmp" % (rtk[1],rtk[3])
+ elif rtk[2] == 6: #TCP
+ bh = "%s %i/tcp" % (rtk[1],rtk[3])
+ elif rtk[2] == 17: #UDP
+ bh = '%s %i/udp' % (rtk[1],rtk[3])
+ else:
+ bh = '%s %i/proto' % (rtk[1],rtk[2])
+ ips[bh] = None
+ bhip[rtk[1]] = bh
+ bh = '"%s"' % bh
+ trace[max(k)+1] = bh
+ blackholes.append(bh)
+
+ # Find AS numbers
+ ASN_query_list = dict.fromkeys(map(lambda x:x.rsplit(" ",1)[0],ips)).keys()
+ if ASres is None:
+ ASNlist = []
+ else:
+ ASNlist = ASres.resolve(*ASN_query_list)
+
+ ASNs = {}
+ ASDs = {}
+ for ip,asn,desc, in ASNlist:
+ if asn is None:
+ continue
+ iplist = ASNs.get(asn,[])
+ if ip in bhip:
+ if ip in ports:
+ iplist.append(ip)
+ iplist.append(bhip[ip])
+ else:
+ iplist.append(ip)
+ ASNs[asn] = iplist
+ ASDs[asn] = desc
+
+
+ backcolorlist=colgen("60","86","ba","ff")
+ forecolorlist=colgen("a0","70","40","20")
+
+ s = "digraph trace {\n"
+
+ s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
+
+ s += "\n#ASN clustering\n"
+ for asn in ASNs:
+ s += '\tsubgraph cluster_%s {\n' % asn
+ col = next(backcolorlist)
+ s += '\t\tcolor="#%s%s%s";' % col
+ s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col
+ s += '\t\tfontsize = 10;'
+ s += '\t\tlabel = "%s\\n[%s]"\n' % (asn,ASDs[asn])
+ for ip in ASNs[asn]:
+
+ s += '\t\t"%s";\n'%ip
+ s += "\t}\n"
+
+
+
+
+ s += "#endpoints\n"
+ for p in ports:
+ s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p,p,"|".join(ports[p]))
+
+ s += "\n#Blackholes\n"
+ for bh in blackholes:
+ s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh
+
+ if padding:
+ s += "\n#Padding\n"
+ pad={}
+ for snd,rcv in self.res:
+ if rcv.src not in ports and rcv.haslayer(conf.padding_layer):
+ p = rcv.getlayer(conf.padding_layer).load
+ if p != "\x00"*len(p):
+ pad[rcv.src]=None
+ for rcv in pad:
+ s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv
+
+
+
+ s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
+
+
+ for rtk in rt:
+ s += "#---[%s\n" % repr(rtk)
+ s += '\t\tedge [color="#%s%s%s"];\n' % next(forecolorlist)
+ trace = rt[rtk]
+ k = trace.keys()
+ for n in range(min(k), max(k)):
+ s += '\t%s ->\n' % trace[n]
+ s += '\t%s;\n' % trace[max(k)]
+
+ s += "}\n";
+ self.graphdef = s
+
+ def graph(self, ASres=None, padding=0, **kargs):
+ """x.graph(ASres=conf.AS_resolver, other args):
+ ASres=None : no AS resolver => no clustering
+ ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net)
+ ASres=AS_resolver_cymru(): use whois.cymru.com whois database
+ ASres=AS_resolver(server="whois.ra.net")
+ format: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
+ figsize: w,h tuple in inches. See matplotlib documentation
+ target: filename. If None uses matplotlib to display
+ prog: which graphviz program to use"""
+ if ASres is None:
+ ASres = conf.AS_resolver
+ if (self.graphdef is None or
+ self.graphASres != ASres or
+ self.graphpadding != padding):
+ self.make_graph(ASres,padding)
+
+ return do_graph(self.graphdef, **kargs)
+
+
+
+@conf.commands.register
+def traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, verbose=None, **kargs):
+ """Instant TCP traceroute
+traceroute(target, [maxttl=30,] [dport=80,] [sport=80,] [verbose=conf.verb]) -> None
+"""
+ if verbose is None:
+ verbose = conf.verb
+ if filter is None:
+ # we only consider ICMP error packets and TCP packets with at
+ # least the ACK flag set *and* either the SYN or the RST flag
+ # set
+ filter="(icmp and (icmp[0]=3 or icmp[0]=4 or icmp[0]=5 or icmp[0]=11 or icmp[0]=12)) or (tcp and (tcp[13] & 0x16 > 0x10))"
+ if l4 is None:
+ a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
+ timeout=timeout, filter=filter, verbose=verbose, **kargs)
+ else:
+ # this should always work
+ filter="ip"
+ a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4,
+ timeout=timeout, filter=filter, verbose=verbose, **kargs)
+
+ a = TracerouteResult(a.res)
+
+ if verbose:
+ a.show()
+ return a,b
+
+
+
+#############################
+## Simple TCP client stack ##
+#############################
+
+class TCP_client(Automaton):
+
+ def parse_args(self, ip, port, *args, **kargs):
+ self.dst = next(iter(Net(ip)))
+ self.dport = port
+ self.sport = random.randrange(0,2**16)
+ self.l4 = IP(dst=ip)/TCP(sport=self.sport, dport=self.dport, flags=0,
+ seq=random.randrange(0,2**32))
+ self.src = self.l4.src
+ self.swin=self.l4[TCP].window
+ self.dwin=1
+ self.rcvbuf=""
+ bpf = "host %s and host %s and port %i and port %i" % (self.src,
+ self.dst,
+ self.sport,
+ self.dport)
+
+# bpf=None
+ Automaton.parse_args(self, filter=bpf, **kargs)
+
+
+ def master_filter(self, pkt):
+ return (IP in pkt and
+ pkt[IP].src == self.dst and
+ pkt[IP].dst == self.src and
+ TCP in pkt and
+ pkt[TCP].sport == self.dport and
+ pkt[TCP].dport == self.sport and
+ self.l4[TCP].seq >= pkt[TCP].ack and # XXX: seq/ack 2^32 wrap up
+ ((self.l4[TCP].ack == 0) or (self.l4[TCP].ack <= pkt[TCP].seq <= self.l4[TCP].ack+self.swin)) )
+
+
+ @ATMT.state(initial=1)
+ def START(self):
+ pass
+
+ @ATMT.state()
+ def SYN_SENT(self):
+ pass
+
+ @ATMT.state()
+ def ESTABLISHED(self):
+ pass
+
+ @ATMT.state()
+ def LAST_ACK(self):
+ pass
+
+ @ATMT.state(final=1)
+ def CLOSED(self):
+ pass
+
+
+ @ATMT.condition(START)
+ def connect(self):
+ raise self.SYN_SENT()
+ @ATMT.action(connect)
+ def send_syn(self):
+ self.l4[TCP].flags = "S"
+ self.send(self.l4)
+ self.l4[TCP].seq += 1
+
+
+ @ATMT.receive_condition(SYN_SENT)
+ def synack_received(self, pkt):
+ if pkt[TCP].flags & 0x3f == 0x12:
+ raise self.ESTABLISHED().action_parameters(pkt)
+ @ATMT.action(synack_received)
+ def send_ack_of_synack(self, pkt):
+ self.l4[TCP].ack = pkt[TCP].seq+1
+ self.l4[TCP].flags = "A"
+ self.send(self.l4)
+
+ @ATMT.receive_condition(ESTABLISHED)
+ def incoming_data_received(self, pkt):
+ if not isinstance(pkt[TCP].payload, NoPayload) and not isinstance(pkt[TCP].payload, conf.padding_layer):
+ raise self.ESTABLISHED().action_parameters(pkt)
+ @ATMT.action(incoming_data_received)
+ def receive_data(self,pkt):
+ data = (bytes(pkt[TCP].payload))
+ if data and self.l4[TCP].ack == pkt[TCP].seq:
+ self.l4[TCP].ack += len(data)
+ self.l4[TCP].flags = "A"
+ self.send(self.l4)
+ self.rcvbuf += data
+ if pkt[TCP].flags & 8 != 0: #PUSH
+ self.oi.tcp.send(self.rcvbuf)
+ self.rcvbuf = ""
+
+ @ATMT.ioevent(ESTABLISHED,name="tcp", as_supersocket="tcplink")
+ def outgoing_data_received(self, fd):
+ raise self.ESTABLISHED().action_parameters(fd.recv())
+ @ATMT.action(outgoing_data_received)
+ def send_data(self, d):
+ self.l4[TCP].flags = "PA"
+ self.send(self.l4/d)
+ self.l4[TCP].seq += len(d)
+
+
+ @ATMT.receive_condition(ESTABLISHED)
+ def reset_received(self, pkt):
+ if pkt[TCP].flags & 4 != 0:
+ raise self.CLOSED()
+
+ @ATMT.receive_condition(ESTABLISHED)
+ def fin_received(self, pkt):
+ if pkt[TCP].flags & 0x1 == 1:
+ raise self.LAST_ACK().action_parameters(pkt)
+ @ATMT.action(fin_received)
+ def send_finack(self, pkt):
+ self.l4[TCP].flags = "FA"
+ self.l4[TCP].ack = pkt[TCP].seq+1
+ self.send(self.l4)
+ self.l4[TCP].seq += 1
+
+ @ATMT.receive_condition(LAST_ACK)
+ def ack_of_fin_received(self, pkt):
+ if pkt[TCP].flags & 0x3f == 0x10:
+ raise self.CLOSED()
+
+
+
+
+#####################
+## Reporting stuff ##
+#####################
+
+def report_ports(target, ports):
+ """portscan a target and output a LaTeX table
+report_ports(target, ports) -> string"""
+ ans,unans = sr(IP(dst=target)/TCP(dport=ports),timeout=5)
+ rep = "\\begin{tabular}{|r|l|l|}\n\\hline\n"
+ for s,r in ans:
+ if not r.haslayer(ICMP):
+ if r.payload.flags == 0x12:
+ rep += r.sprintf("%TCP.sport% & open & SA \\\\\n")
+ rep += "\\hline\n"
+ for s,r in ans:
+ if r.haslayer(ICMP):
+ rep += r.sprintf("%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\n")
+ elif r.payload.flags != 0x12:
+ rep += r.sprintf("%TCP.sport% & closed & TCP %TCP.flags% \\\\\n")
+ rep += "\\hline\n"
+ for i in unans:
+ rep += i.sprintf("%TCP.dport% & ? & unanswered \\\\\n")
+ rep += "\\hline\n\\end{tabular}\n"
+ return rep
+
+
+
+def IPID_count(lst, funcID=lambda x:x[1].id, funcpres=lambda x:x[1].summary()):
+ idlst = map(funcID, lst)
+ idlst.sort()
+ #classes = [idlst[0]]+map(lambda x:x[1],filter(lambda (x,y): abs(x-y)>50, map(lambda x,y: (x,y),idlst[:-1], idlst[1:])))
+ classes = [idlst[0]]+list(map(lambda x:x[1],filter(lambda a: abs(a[0]-a[1])>50, map(lambda x,y: (x,y),idlst[:-1], idlst[1:]))))
+ lst = map(lambda x:(funcID(x), funcpres(x)), lst)
+ lst.sort()
+ print("Probably %i classes:" % len(classes), classes)
+ for id,pr in lst:
+ print("%5i" % id, pr)
+
+
+def fragleak(target,sport=123, dport=123, timeout=0.2, onlyasc=0):
+ load = "XXXXYYYYYYYYYY"
+# getmacbyip(target)
+# pkt = IP(dst=target, id=RandShort(), options="\x22"*40)/UDP()/load
+ pkt = IP(dst=target, id=RandShort(), options="\x00"*40, flags=1)/UDP(sport=sport, dport=sport)/load
+ s=conf.L3socket()
+ intr=0
+ found={}
+ try:
+ while 1:
+ try:
+ if not intr:
+ s.send(pkt)
+ sin,sout,serr = select([s],[],[],timeout)
+ if not sin:
+ continue
+ ans=s.recv(1600)
+ if not isinstance(ans, IP): #TODO: IPv6
+ continue
+ if not isinstance(ans.payload, ICMP):
+ continue
+ if not isinstance(ans.payload.payload, IPerror):
+ continue
+ if ans.payload.payload.dst != target:
+ continue
+ if ans.src != target:
+ print("leak from", ans.src,end=" ")
+
+
+# print repr(ans)
+ if not ans.haslayer(conf.padding_layer):
+ continue
+
+
+# print repr(ans.payload.payload.payload.payload)
+
+# if not isinstance(ans.payload.payload.payload.payload, conf.raw_layer):
+# continue
+# leak = ans.payload.payload.payload.payload.load[len(load):]
+ leak = ans.getlayer(conf.padding_layer).load
+ if leak not in found:
+ found[leak]=None
+ linehexdump(leak, onlyasc=onlyasc)
+ except KeyboardInterrupt:
+ if intr:
+ raise
+ intr=1
+ except KeyboardInterrupt:
+ pass
+
+def fragleak2(target, timeout=0.4, onlyasc=0):
+ found={}
+ try:
+ while 1:
+ p = sr1(IP(dst=target, options="\x00"*40, proto=200)/"XXXXYYYYYYYYYYYY",timeout=timeout,verbose=0)
+ if not p:
+ continue
+ if conf.padding_layer in p:
+ leak = p[conf.padding_layer].load
+ if leak not in found:
+ found[leak]=None
+ linehexdump(leak,onlyasc=onlyasc)
+ except:
+ pass
+
+
+conf.stats_classic_protocols += [TCP,UDP,ICMP]
+conf.stats_dot11_protocols += [TCP,UDP,ICMP]
+
+if conf.ipv6_enabled:
+ import scapy.layers.inet6
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet6.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet6.py
new file mode 100644
index 00000000..c2e4a037
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/inet6.py
@@ -0,0 +1,3047 @@
+#! /usr/bin/env python
+#############################################################################
+## ##
+## inet6.py --- IPv6 support for Scapy ##
+## see http://natisbad.org/IPv6/ ##
+## for more informations ##
+## ##
+## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp> ##
+## Arnaud Ebalard <arnaud.ebalard@eads.net> ##
+## ##
+## This program is free software; you can redistribute it and/or modify it ##
+## under the terms of the GNU General Public License version 2 as ##
+## published by the Free Software Foundation. ##
+## ##
+## This program is distributed in the hope that it will be useful, but ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of ##
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
+## General Public License for more details. ##
+## ##
+#############################################################################
+
+"""
+IPv6 (Internet Protocol v6).
+"""
+
+
+import socket
+if not socket.has_ipv6:
+ raise socket.error("can't use AF_INET6, IPv6 is disabled")
+if not hasattr(socket, "IPPROTO_IPV6"):
+ # Workaround for http://bugs.python.org/issue6926
+ socket.IPPROTO_IPV6 = 41
+
+if not hasattr(socket, "IPPROTO_IPIP"):
+ socket.IPPROTO_IPIP = 4
+
+if not ('IPPROTO_IPIP ' in globals()):
+ IPPROTO_IPIP=4
+
+
+
+from scapy.config import conf
+from scapy.layers.l2 import *
+from scapy.layers.inet import *
+from scapy.fields import *
+from scapy.packet import *
+from scapy.volatile import *
+from scapy.sendrecv import sr,sr1,srp1
+from scapy.as_resolvers import AS_resolver_riswhois
+from scapy.supersocket import SuperSocket,L3RawSocket
+from scapy.arch import *
+from scapy.utils6 import *
+
+
+#############################################################################
+# Helpers ##
+#############################################################################
+
+def get_cls(name, fallback_cls):
+ return globals().get(name, fallback_cls)
+
+
+##########################
+## Neighbor cache stuff ##
+##########################
+
+conf.netcache.new_cache("in6_neighbor", 120)
+
+def neighsol(addr, src, iface, timeout=1, chainCC=0):
+ """
+ Sends an ICMPv6 Neighbor Solicitation message to get the MAC address
+ of the neighbor with specified IPv6 address addr. 'src' address is
+ used as source of the message. Message is sent on iface. By default,
+ timeout waiting for an answer is 1 second.
+
+ If no answer is gathered, None is returned. Else, the answer is
+ returned (ethernet frame).
+ """
+
+ nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
+ d = inet_ntop(socket.AF_INET6, nsma)
+ dm = in6_getnsmac(nsma)
+ p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
+ p /= ICMPv6ND_NS(tgt=addr)
+ p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
+ res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
+ chainCC=chainCC)
+
+ return res
+
+def getmacbyip6(ip6, chainCC=0):
+ """
+ Returns the mac address to be used for provided 'ip6' peer.
+ neighborCache.get() method is used on instantiated neighbor cache.
+ Resolution mechanism is described in associated doc string.
+
+ (chainCC parameter value ends up being passed to sending function
+ used to perform the resolution, if needed)
+ """
+
+ if in6_ismaddr(ip6): # Multicast
+ mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
+ return mac
+
+ iff,a,nh = conf.route6.route(ip6, dev=conf.iface6)
+
+ if iff == LOOPBACK_NAME:
+ return "ff:ff:ff:ff:ff:ff"
+
+ if nh != '::':
+ ip6 = nh # Found next hop
+
+ mac = conf.netcache.in6_neighbor.get(ip6)
+ if mac:
+ return mac
+
+ res = neighsol(ip6, a, iff, chainCC=chainCC)
+
+ if res is not None:
+ if ICMPv6NDOptDstLLAddr in res:
+ mac = res[ICMPv6NDOptDstLLAddr].lladdr
+ else:
+ mac = res.src
+ conf.netcache.in6_neighbor[ip6] = mac
+ return mac
+
+ return None
+
+
+#############################################################################
+#############################################################################
+### IPv6 addresses manipulation routines ###
+#############################################################################
+#############################################################################
+
+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])?$")
+
+ def __init__(self, net):
+ self.repr = net
+
+ tmp = net.split('/')+["128"]
+ if not self.ipaddress.match(net):
+ tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
+
+ netmask = int(tmp[1])
+ self.net = inet_pton(socket.AF_INET6, tmp[0])
+ self.mask = in6_cidr2mask(netmask)
+ self.plen = netmask
+
+ def __iter__(self):
+ def m8(i):
+ if i % 8 == 0:
+ return i
+ #tuple = filter(lambda x: m8(x), range(8, 129))
+ tuple = [ x for x in range(8, 129) if m8(x) ]
+
+ a = in6_and(self.net, self.mask)
+ tmp = map(lambda x: x, struct.unpack('16B', a))
+
+ def parse_digit(a, netmask):
+ netmask = min(8,max(netmask,0))
+ a = (int(a) & (0xff<<netmask),(int(a) | (0xff>>(8-netmask)))+1)
+ return a
+ self.parsed = map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple))
+
+ def rec(n, l):
+ if n and n % 2 == 0:
+ sep = ':'
+ else:
+ sep = ''
+ if n == 16:
+ return l
+ else:
+ ll = []
+ for i in range(*self.parsed[n]):
+ for y in l:
+ ll += [y+sep+'%.2x'%i]
+ return rec(n+1, ll)
+
+ return iter(rec(0, ['']))
+
+ def __repr__(self):
+ return "<Net6 %s>" % self.repr
+
+
+
+
+
+
+#############################################################################
+#############################################################################
+### IPv6 Class ###
+#############################################################################
+#############################################################################
+
+class IP6Field(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "16s")
+ def h2i(self, pkt, x):
+ if type(x) is str:
+ try:
+ x = in6_ptop(x)
+ except socket.error:
+ x = Net6(x)
+ elif type(x) is list:
+ x = map(Net6, x)
+ return x
+ def i2m(self, pkt, x):
+ return inet_pton(socket.AF_INET6, x)
+ def m2i(self, pkt, x):
+ return inet_ntop(socket.AF_INET6, x)
+ def any2i(self, pkt, x):
+ return self.h2i(pkt,x)
+ def i2repr(self, pkt, x):
+ if x is None:
+ return self.i2h(pkt,x)
+ elif not isinstance(x, Net6) and not type(x) is list:
+ if in6_isaddrTeredo(x): # print Teredo info
+ server, flag, maddr, mport = teredoAddrExtractInfo(x)
+ return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
+ elif in6_isaddr6to4(x): # print encapsulated address
+ vaddr = in6_6to4ExtractAddr(x)
+ return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
+ return self.i2h(pkt, x) # No specific information to return
+ def randval(self):
+ return RandIP6()
+
+class SourceIP6Field(IP6Field):
+ def __init__(self, name, dstname):
+ IP6Field.__init__(self, name, None)
+ self.dstname = dstname
+ def i2m(self, pkt, x):
+ if x is None:
+ dst=getattr(pkt,self.dstname)
+ iff,x,nh = conf.route6.route(dst)
+ return IP6Field.i2m(self, pkt, x)
+ def i2h(self, pkt, x):
+ if x is None:
+ dst=getattr(pkt,self.dstname)
+ if isinstance(dst,Gen):
+ r = map(conf.route6.route, dst)
+ r.sort()
+ if r[0] == r[-1]:
+ x=r[0][1]
+ else:
+ warning("More than one possible route for %s"%repr(dst))
+ return None
+ else:
+ iff,x,nh = conf.route6.route(dst)
+ return IP6Field.i2h(self, pkt, x)
+
+ipv6nh = { 0:"Hop-by-Hop Option Header",
+ 4:"IP",
+ 6:"TCP",
+ 17:"UDP",
+ 41:"IPv6",
+ 43:"Routing Header",
+ 44:"Fragment Header",
+ 47:"GRE",
+ 50:"ESP Header",
+ 51:"AH Header",
+ 58:"ICMPv6",
+ 59:"No Next Header",
+ 60:"Destination Option Header",
+ 135:"Mobility Header"}
+
+ipv6nhcls = { 0: "IPv6ExtHdrHopByHop",
+ 4: "IP",
+ 6: "TCP",
+ 17: "UDP",
+ 43: "IPv6ExtHdrRouting",
+ 44: "IPv6ExtHdrFragment",
+ #50: "IPv6ExtHrESP",
+ #51: "IPv6ExtHdrAH",
+ 58: "ICMPv6Unknown",
+ 59: "Raw",
+ 60: "IPv6ExtHdrDestOpt" }
+
+class IP6ListField(StrField):
+ islist = 1
+ def __init__(self, name, default, count_from=None, length_from=None):
+ if default is None:
+ default = []
+ StrField.__init__(self, name, default)
+ self.count_from = count_from
+ self.length_from = length_from
+
+ def i2len(self, pkt, i):
+ return 16*len(i)
+
+ def i2count(self, pkt, i):
+ if type(i) is list:
+ return len(i)
+ return 0
+
+ def getfield(self, pkt, s):
+ c = l = None
+ if self.length_from is not None:
+ l = self.length_from(pkt)
+ elif self.count_from is not None:
+ c = self.count_from(pkt)
+
+ lst = []
+ ret = b""
+ remain = s
+ if l is not None:
+ remain,ret = s[:l],s[l:]
+ while remain:
+ if c is not None:
+ if c <= 0:
+ break
+ c -= 1
+ addr = inet_ntop(socket.AF_INET6, remain[:16])
+ lst.append(addr)
+ remain = remain[16:]
+ return remain+ret,lst
+
+ def i2m(self, pkt, x):
+ s = b''
+ for y in x:
+ try:
+ y = inet_pton(socket.AF_INET6, y)
+ except:
+ y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
+ y = inet_pton(socket.AF_INET6, y)
+ s += y
+ return s
+
+ def i2repr(self,pkt,x):
+ s = []
+ if x == None:
+ return "[]"
+ for y in x:
+ s.append('%s' % y)
+ return "[ %s ]" % (", ".join(s))
+
+class _IPv6GuessPayload:
+ name = "Dummy class that implements guess_payload_class() for IPv6"
+ def default_payload_class(self,p):
+ if self.nh == 58: # ICMPv6
+ #t = ord(p[0])
+ t = p[0]
+ if len(p) > 2 and t == 139 or t == 140: # Node Info Query
+ return _niquery_guesser(p)
+ if len(p) >= icmp6typesminhdrlen.get(t, sys.maxsize): # Other ICMPv6 messages
+ return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
+ return Raw
+ elif self.nh == 135 and len(p) > 3: # Mobile IPv6
+ #return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic)
+ return _mip6_mhtype2cls.get(p[2], MIP6MH_Generic)
+ else:
+ return get_cls(ipv6nhcls.get(self.nh,"Raw"), "Raw")
+
+class IPv6(_IPv6GuessPayload, Packet, IPTools):
+ name = "IPv6"
+ fields_desc = [ BitField("version" , 6 , 4),
+ BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
+ BitField("fl", 0, 20),
+ ShortField("plen", None),
+ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("hlim", 64),
+ IP6Field("src", "::2"),
+ #SourceIP6Field("src", "dst"), # dst is for src @ selection
+ IP6Field("dst", "::1") ]
+
+ def route(self):
+ dst = self.dst
+ if isinstance(dst,Gen):
+ dst = next(iter(dst))
+ return conf.route6.route(dst)
+
+ def mysummary(self):
+ return "%s > %s (%i)" % (self.src,self.dst, self.nh)
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.plen is None:
+ l = len(p) - 40
+ p = p[:4]+struct.pack("!H", l)+p[6:]
+ return p
+
+ def extract_padding(self, s):
+ l = self.plen
+ return s[:l], s[l:]
+
+ def hashret(self):
+ if self.nh == 58 and isinstance(self.payload, _ICMPv6):
+ if self.payload.type < 128:
+ return self.payload.payload.hashret()
+ elif (self.payload.type in [133,134,135,136,144,145]):
+ return struct.pack("B", self.nh)+self.payload.hashret()
+
+ nh = self.nh
+ sd = self.dst
+ ss = self.src
+ if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
+ # With routing header, the destination is the last
+ # address of the IPv6 list if segleft > 0
+ nh = self.payload.nh
+ try:
+ sd = self.addresses[-1]
+ except IndexError:
+ sd = '::1'
+ # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
+ # could be anything from the original list ...
+ if 1:
+ sd = inet_pton(socket.AF_INET6, sd)
+ for a in self.addresses:
+ a = inet_pton(socket.AF_INET6, a)
+ sd = strxor(sd, a)
+ sd = inet_ntop(socket.AF_INET6, sd)
+
+ if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
+ nh = self.payload.nh
+
+ if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
+ nh = self.payload.nh
+
+ if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
+ foundhao = None
+ for o in self.payload.options:
+ if isinstance(o, HAO):
+ foundhao = o
+ if foundhao:
+ nh = self.payload.nh # XXX what if another extension follows ?
+ ss = foundhao.hoa
+
+ if conf.checkIPsrc and conf.checkIPaddr:
+ sd = inet_pton(socket.AF_INET6, sd)
+ ss = inet_pton(socket.AF_INET6, self.src)
+ return struct.pack("B",nh)+self.payload.hashret()
+ else:
+ return struct.pack("B", nh)+self.payload.hashret()
+
+ def answers(self, other):
+ if not isinstance(other, IPv6): # self is reply, other is request
+ return False
+ if conf.checkIPaddr:
+ ss = inet_pton(socket.AF_INET6, self.src)
+ sd = inet_pton(socket.AF_INET6, self.dst)
+ os = inet_pton(socket.AF_INET6, other.src)
+ od = inet_pton(socket.AF_INET6, other.dst)
+ # request was sent to a multicast address (other.dst)
+ # Check reply destination addr matches request source addr (i.e
+ # sd == os) except when reply is multicasted too
+ # XXX test mcast scope matching ?
+ if in6_ismaddr(other.dst):
+ if in6_ismaddr(self.dst):
+ if ((od == sd) or
+ (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
+ return self.payload.answers(other.payload)
+ return False
+ if (os == sd):
+ return self.payload.answers(other.payload)
+ return False
+ elif (sd != os): # or ss != od): <- removed for ICMP errors
+ return False
+ if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
+ # ICMPv6 Error message -> generated by IPv6 packet
+ # Note : at the moment, we jump the ICMPv6 specific class
+ # to call answers() method of erroneous packet (over
+ # initial packet). There can be cases where an ICMPv6 error
+ # class could implement a specific answers method that perform
+ # a specific task. Currently, don't see any use ...
+ return self.payload.payload.answers(other)
+ elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
+ return self.payload.answers(other.payload.payload)
+ elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
+ return self.payload.answers(other.payload.payload)
+ elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
+ return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
+ elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
+ return self.payload.payload.answers(other.payload.payload)
+ elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
+ return self.payload.payload.answers(other.payload)
+ else:
+ if (self.nh != other.nh):
+ return False
+ return self.payload.answers(other.payload)
+
+
+conf.neighbor.register_l3(Ether, IPv6, lambda l2,l3: getmacbyip6(l3.dst))
+
+
+class IPerror6(IPv6):
+ name = "IPv6 in ICMPv6"
+ def answers(self, other):
+ if not isinstance(other, IPv6):
+ return False
+ sd = inet_pton(socket.AF_INET6, self.dst)
+ ss = inet_pton(socket.AF_INET6, self.src)
+ od = inet_pton(socket.AF_INET6, other.dst)
+ os = inet_pton(socket.AF_INET6, other.src)
+
+ # Make sure that the ICMPv6 error is related to the packet scapy sent
+ if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
+
+ # find upper layer for self (possible citation)
+ selfup = self.payload
+ while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
+ selfup = selfup.payload
+
+ # find upper layer for other (initial packet). Also look for RH
+ otherup = other.payload
+ request_has_rh = False
+ while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
+ if isinstance(otherup, IPv6ExtHdrRouting):
+ request_has_rh = True
+ otherup = otherup.payload
+
+ if ((ss == os and sd == od) or # <- Basic case
+ (ss == os and request_has_rh)): # <- Request has a RH :
+ # don't check dst address
+
+ # Let's deal with possible MSS Clamping
+ if (isinstance(selfup, TCP) and
+ isinstance(otherup, TCP) and
+ selfup.options != otherup.options): # seems clamped
+
+ # Save fields modified by MSS clamping
+ old_otherup_opts = otherup.options
+ old_otherup_cksum = otherup.chksum
+ old_otherup_dataofs = otherup.dataofs
+ old_selfup_opts = selfup.options
+ old_selfup_cksum = selfup.chksum
+ old_selfup_dataofs = selfup.dataofs
+
+ # Nullify them
+ otherup.options = []
+ otherup.chksum = 0
+ otherup.dataofs = 0
+ selfup.options = []
+ selfup.chksum = 0
+ selfup.dataofs = 0
+
+ # Test it and save result
+ s1 = bytes(selfup)
+ s2 = bytes(otherup)
+ l = min(len(s1), len(s2))
+ res = s1[:l] == s2[:l]
+
+ # recall saved values
+ otherup.options = old_otherup_opts
+ otherup.chksum = old_otherup_cksum
+ otherup.dataofs = old_otherup_dataofs
+ selfup.options = old_selfup_opts
+ selfup.chksum = old_selfup_cksum
+ selfup.dataofs = old_selfup_dataofs
+
+ return res
+
+ s1 = bytes(selfup)
+ s2 = bytes(otherup)
+ l = min(len(s1), len(s2))
+ return s1[:l] == s2[:l]
+
+ return False
+
+ def mysummary(self):
+ return Packet.mysummary(self)
+
+
+#############################################################################
+#############################################################################
+### Upper Layer Checksum computation ###
+#############################################################################
+#############################################################################
+
+class PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
+ name = "Pseudo IPv6 Header"
+ fields_desc = [ IP6Field("src", "::"),
+ IP6Field("dst", "::"),
+ ShortField("uplen", None),
+ BitField("zero", 0, 24),
+ ByteField("nh", 0) ]
+
+def in6_chksum(nh, u, p):
+ """
+ Performs IPv6 Upper Layer checksum computation. Provided parameters are:
+
+ - 'nh' : value of upper layer protocol
+ - 'u' : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
+ provided with all under layers (IPv6 and all extension headers,
+ for example)
+ - 'p' : the payload of the upper layer provided as a string
+
+ Functions operate by filling a pseudo header class instance (PseudoIPv6)
+ with
+ - Next Header value
+ - the address of _final_ destination (if some Routing Header with non
+ segleft field is present in underlayer classes, last address is used.)
+ - the address of _real_ source (basically the source address of an
+ IPv6 class instance available in the underlayer or the source address
+ in HAO option if some Destination Option header found in underlayer
+ includes this option).
+ - the length is the length of provided payload string ('p')
+ """
+
+ ph6 = PseudoIPv6()
+ ph6.nh = nh
+ rthdr = 0
+ hahdr = 0
+ final_dest_addr_found = 0
+ while u != None and not isinstance(u, IPv6):
+ if (isinstance(u, IPv6ExtHdrRouting) and
+ u.segleft != 0 and len(u.addresses) != 0 and
+ final_dest_addr_found == 0):
+ rthdr = u.addresses[-1]
+ final_dest_addr_found = 1
+ elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
+ isinstance(u.options[0], HAO)):
+ hahdr = u.options[0].hoa
+ u = u.underlayer
+ if u is None:
+ warning("No IPv6 underlayer to compute checksum. Leaving null.")
+ return 0
+ if hahdr:
+ ph6.src = hahdr
+ else:
+ ph6.src = u.src
+ if rthdr:
+ ph6.dst = rthdr
+ else:
+ ph6.dst = u.dst
+ ph6.uplen = len(p)
+ ph6s = bytes(ph6)
+ return checksum(ph6s+p)
+
+
+#############################################################################
+#############################################################################
+### Extension Headers ###
+#############################################################################
+#############################################################################
+
+
+# Inherited by all extension header classes
+class _IPv6ExtHdr(_IPv6GuessPayload, Packet):
+ name = 'Abstract IPV6 Option Header'
+ aliastypes = [IPv6, IPerror6] # TODO ...
+
+
+#################### IPv6 options for Extension Headers #####################
+
+_hbhopts = { 0x00: "Pad1",
+ 0x01: "PadN",
+ 0x04: "Tunnel Encapsulation Limit",
+ 0x05: "Router Alert",
+ 0x06: "Quick-Start",
+ 0xc2: "Jumbo Payload",
+ 0xc9: "Home Address Option" }
+
+class _OTypeField(ByteEnumField):
+ """
+ Modified BytEnumField that displays information regarding the IPv6 option
+ based on its option type value (What should be done by nodes that process
+ the option if they do not understand it ...)
+
+ It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
+ """
+ pol = {0x00: "00: skip",
+ 0x40: "01: discard",
+ 0x80: "10: discard+ICMP",
+ 0xC0: "11: discard+ICMP not mcast"}
+
+ enroutechange = {0x00: "0: Don't change en-route",
+ 0x20: "1: May change en-route" }
+
+ def i2repr(self, pkt, x):
+ s = self.i2s.get(x, repr(x))
+ polstr = self.pol[(x & 0xC0)]
+ enroutechangestr = self.enroutechange[(x & 0x20)]
+ return "%s [%s, %s]" % (s, polstr, enroutechangestr)
+
+class HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
+ name = "Scapy6 Unknown Option"
+ fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
+ FieldLenField("optlen", None, length_of="optdata", fmt="B"),
+ StrLenField("optdata", "",
+ length_from = lambda pkt: pkt.optlen) ]
+ def alignment_delta(self, curpos): # By default, no alignment requirement
+ """
+ As specified in section 4.2 of RFC 2460, every options has
+ an alignment requirement ususally expressed xn+y, meaning
+ the Option Type must appear at an integer multiple of x octest
+ from the start of the header, plus y octet.
+
+ That function is provided the current position from the
+ start of the header and returns required padding length.
+ """
+ return 0
+
+class Pad1(Packet): # IPv6 Hop-By-Hop Option
+ name = "Pad1"
+ fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
+ def alignment_delta(self, curpos): # No alignment requirement
+ return 0
+
+class PadN(Packet): # IPv6 Hop-By-Hop Option
+ name = "PadN"
+ fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
+ FieldLenField("optlen", None, length_of="optdata", fmt="B"),
+ StrLenField("optdata", "",
+ length_from = lambda pkt: pkt.optlen)]
+ def alignment_delta(self, curpos): # No alignment requirement
+ return 0
+
+class RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
+ name = "Router Alert"
+ fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
+ ByteField("optlen", 2),
+ ShortEnumField("value", None,
+ { 0: "Datagram contains a MLD message",
+ 1: "Datagram contains RSVP message",
+ 2: "Datagram contains an Active Network message" }) ]
+ # TODO : Check IANA has not defined new values for value field of RouterAlertOption
+ # TODO : now that we have that option, we should do something in MLD class that need it
+ def alignment_delta(self, curpos): # alignment requirement : 2n+0
+ x = 2 ; y = 0
+ delta = x*((curpos - y + x - 1)//x) + y - curpos
+ return delta
+
+class Jumbo(Packet): # IPv6 Hop-By-Hop Option
+ name = "Jumbo Payload"
+ fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
+ ByteField("optlen", 4),
+ IntField("jumboplen", None) ]
+ def alignment_delta(self, curpos): # alignment requirement : 4n+2
+ x = 4 ; y = 2
+ delta = x*((curpos - y + x - 1)//x) + y - curpos
+ return delta
+
+class HAO(Packet): # IPv6 Destination Options Header Option
+ name = "Home Address Option"
+ fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
+ ByteField("optlen", 16),
+ IP6Field("hoa", "::") ]
+ def alignment_delta(self, curpos): # alignment requirement : 8n+6
+ x = 8 ; y = 6
+ delta = x*((curpos - y + x - 1)//x) + y - curpos
+ return delta
+
+_hbhoptcls = { 0x00: Pad1,
+ 0x01: PadN,
+ 0x05: RouterAlert,
+ 0xC2: Jumbo,
+ 0xC9: HAO }
+
+
+######################## Hop-by-Hop Extension Header ########################
+
+class _HopByHopOptionsField(PacketListField):
+ islist = 1
+ holds_packet = 1
+ def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
+ self.curpos = curpos
+ PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
+
+ def i2len(self, pkt, i):
+ l = len(self.i2m(pkt, i))
+ return l
+
+ def i2count(self, pkt, i):
+ if type(i) is list:
+ return len(i)
+ return 0
+
+ def getfield(self, pkt, s):
+ c = l = None
+ if self.length_from is not None:
+ l = self.length_from(pkt)
+ elif self.count_from is not None:
+ c = self.count_from(pkt)
+
+ opt = []
+ ret = b""
+ x = s
+ if l is not None:
+ x,ret = s[:l],s[l:]
+ while x:
+ if c is not None:
+ if c <= 0:
+ break
+ c -= 1
+ #o = ord(x[0]) # Option type
+ o = x[0] # Option type
+ cls = self.cls
+ if o in _hbhoptcls:
+ cls = _hbhoptcls[o]
+ try:
+ op = cls(x)
+ except:
+ op = self.cls(x)
+ opt.append(op)
+ if isinstance(op.payload, conf.raw_layer):
+ x = op.payload.load
+ del(op.payload)
+ else:
+ x = b""
+ return x+ret,opt
+
+ def i2m(self, pkt, x):
+ autopad = None
+ try:
+ autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
+ except:
+ autopad = 1
+
+ if not autopad:
+ return b"".join(map(bytes, x))
+
+ curpos = self.curpos
+ s = b""
+ for p in x:
+ d = p.alignment_delta(curpos)
+ curpos += d
+ if d == 1:
+ s += bytes(Pad1())
+ elif d != 0:
+ s += bytes(PadN(optdata=b'\x00'*(d-2)))
+ pstr = bytes(p)
+ curpos += len(pstr)
+ s += pstr
+
+ # Let's make the class including our option field
+ # a multiple of 8 octets long
+ d = curpos % 8
+ if d == 0:
+ return s
+ d = 8 - d
+ if d == 1:
+ s += bytes(Pad1())
+ elif d != 0:
+ s += bytes(PadN(optdata=b'\x00'*(d-2)))
+
+ return s
+
+ def addfield(self, pkt, s, val):
+ return s+self.i2m(pkt, val)
+
+class _PhantomAutoPadField(ByteField):
+ def addfield(self, pkt, s, val):
+ return s
+
+ def getfield(self, pkt, s):
+ return s, 1
+
+ def i2repr(self, pkt, x):
+ if x:
+ return "On"
+ return "Off"
+
+
+class IPv6ExtHdrHopByHop(_IPv6ExtHdr):
+ name = "IPv6 Extension Header - Hop-by-Hop Options Header"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ FieldLenField("len", None, length_of="options", fmt="B",
+ adjust = lambda pkt,x: (x+2+7)//8 - 1),
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
+ length_from = lambda pkt: (8*(pkt.len+1))-2) ]
+ overload_fields = {IPv6: { "nh": 0 }}
+
+
+######################## Destination Option Header ##########################
+
+class IPv6ExtHdrDestOpt(_IPv6ExtHdr):
+ name = "IPv6 Extension Header - Destination Options Header"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ FieldLenField("len", None, length_of="options", fmt="B",
+ adjust = lambda pkt,x: (x+2+7)//8 - 1),
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
+ length_from = lambda pkt: (8*(pkt.len+1))-2) ]
+ overload_fields = {IPv6: { "nh": 60 }}
+
+
+############################# Routing Header ################################
+
+class IPv6ExtHdrRouting(_IPv6ExtHdr):
+ name = "IPv6 Option Header Routing"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ FieldLenField("len", None, count_of="addresses", fmt="B",
+ adjust = lambda pkt,x:2*x), # in 8 bytes blocks
+ ByteField("type", 0),
+ ByteField("segleft", None),
+ BitField("reserved", 0, 32), # There is meaning in this field ...
+ IP6ListField("addresses", [],
+ length_from = lambda pkt: 8*pkt.len)]
+ overload_fields = {IPv6: { "nh": 43 }}
+
+ def post_build(self, pkt, pay):
+ if self.segleft is None:
+ pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
+ return _IPv6ExtHdr.post_build(self, pkt, pay)
+
+########################### Fragmentation Header ############################
+
+class IPv6ExtHdrFragment(_IPv6ExtHdr):
+ name = "IPv6 Extension Header - Fragmentation header"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ BitField("res1", 0, 8),
+ BitField("offset", 0, 13),
+ BitField("res2", 0, 2),
+ BitField("m", 0, 1),
+ IntField("id", None) ]
+ overload_fields = {IPv6: { "nh": 44 }}
+
+
+def defragment6(pktlist):
+ """
+ Performs defragmentation of a list of IPv6 packets. Packets are reordered.
+ Crap is dropped. What lacks is completed by 'X' characters.
+ """
+
+ l = [ x for x in pktlist if IPv6ExtHdrFragment in x ] # remove non fragments
+ if not l:
+ return []
+
+ id = l[0][IPv6ExtHdrFragment].id
+
+ llen = len(l)
+ l = [ x for x in l if x[IPv6ExtHdrFragment].id == id ]
+ if len(l) != llen:
+ warning("defragment6: some fragmented packets have been removed from list")
+ llen = len(l)
+
+ # reorder fragments
+ i = 0
+ res = []
+ while l:
+ min_pos = 0
+ min_offset = l[0][IPv6ExtHdrFragment].offset
+ for p in l:
+ cur_offset = p[IPv6ExtHdrFragment].offset
+ if cur_offset < min_offset:
+ min_pos = 0
+ min_offset = cur_offset
+ res.append(l[min_pos])
+ del(l[min_pos])
+
+ # regenerate the fragmentable part
+ fragmentable = b""
+ for p in res:
+ q=p[IPv6ExtHdrFragment]
+ offset = 8*q.offset
+ if offset != len(fragmentable):
+ warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
+ fragmentable += b"X"*(offset - len(fragmentable))
+ fragmentable += bytes(q.payload)
+
+ # Regenerate the unfragmentable part.
+ q = res[0]
+ nh = q[IPv6ExtHdrFragment].nh
+ q[IPv6ExtHdrFragment].underlayer.nh = nh
+ q[IPv6ExtHdrFragment].underlayer.payload = None
+ q /= conf.raw_layer(load=fragmentable)
+
+ return IPv6(bytes(q))
+
+
+def fragment6(pkt, fragSize):
+ """
+ Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
+ contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
+ maximum size of fragments (MTU). The list of packets is returned.
+
+ If packet does not contain an IPv6ExtHdrFragment class, it is returned in
+ result list.
+ """
+
+ pkt = pkt.copy()
+
+ if not IPv6ExtHdrFragment in pkt:
+ # TODO : automatically add a fragment before upper Layer
+ # at the moment, we do nothing and return initial packet
+ # as single element of a list
+ return [pkt]
+
+ # If the payload is bigger than 65535, a Jumbo payload must be used, as
+ # an IPv6 packet can't be bigger than 65535 bytes.
+ if len(bytes(pkt[IPv6ExtHdrFragment])) > 65535:
+ warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")
+ return []
+
+ s = bytes(pkt) # for instantiation to get upper layer checksum right
+
+ if len(s) <= fragSize:
+ return [pkt]
+
+ # Fragmentable part : fake IPv6 for Fragmentable part length computation
+ fragPart = pkt[IPv6ExtHdrFragment].payload
+ tmp = bytes(IPv6(src="::1", dst="::1")/fragPart)
+ fragPartLen = len(tmp) - 40 # basic IPv6 header length
+ fragPartStr = s[-fragPartLen:]
+
+ # Grab Next Header for use in Fragment Header
+ nh = IPv6(tmp[:40]).nh
+
+ # Keep fragment header
+ fragHeader = pkt[IPv6ExtHdrFragment]
+ fragHeader.payload = None # detach payload
+
+ # Unfragmentable Part
+ unfragPartLen = len(s) - fragPartLen - 8
+ unfragPart = pkt
+ pkt[IPv6ExtHdrFragment].underlayer.payload = None # detach payload
+
+ # Cut the fragmentable part to fit fragSize. Inner fragments have
+ # a length that is an integer multiple of 8 octets. last Frag MTU
+ # can be anything below MTU
+ lastFragSize = fragSize - unfragPartLen - 8
+ innerFragSize = lastFragSize - (lastFragSize % 8)
+
+ if lastFragSize <= 0 or innerFragSize == 0:
+ warning("Provided fragment size value is too low. " +
+ "Should be more than %d" % (unfragPartLen + 8))
+ return [unfragPart/fragHeader/fragPart]
+
+ remain = fragPartStr
+ res = []
+ fragOffset = 0 # offset, incremeted during creation
+ fragId = random.randint(0,0xffffffff) # random id ...
+ if fragHeader.id is not None: # ... except id provided by user
+ fragId = fragHeader.id
+ fragHeader.m = 1
+ fragHeader.id = fragId
+ fragHeader.nh = nh
+
+ # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
+ while True:
+ if (len(remain) > lastFragSize):
+ tmp = remain[:innerFragSize]
+ remain = remain[innerFragSize:]
+ fragHeader.offset = fragOffset # update offset
+ fragOffset += (innerFragSize // 8) # compute new one
+ if IPv6 in unfragPart:
+ unfragPart[IPv6].plen = None
+ tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp)
+ res.append(tempo)
+ else:
+ fragHeader.offset = fragOffset # update offSet
+ fragHeader.m = 0
+ if IPv6 in unfragPart:
+ unfragPart[IPv6].plen = None
+ tempo = unfragPart/fragHeader/conf.raw_layer(load=remain)
+ res.append(tempo)
+ break
+ return res
+
+
+############################### AH Header ###################################
+
+# class _AHFieldLenField(FieldLenField):
+# def getfield(self, pkt, s):
+# l = getattr(pkt, self.fld)
+# l = (l*8)-self.shift
+# i = self.m2i(pkt, s[:l])
+# return s[l:],i
+
+# class _AHICVStrLenField(StrLenField):
+# def i2len(self, pkt, x):
+
+
+
+# class IPv6ExtHdrAH(_IPv6ExtHdr):
+# name = "IPv6 Extension Header - AH"
+# fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+# _AHFieldLenField("len", None, "icv"),
+# ShortField("res", 0),
+# IntField("spi", 0),
+# IntField("sn", 0),
+# _AHICVStrLenField("icv", None, "len", shift=2) ]
+# overload_fields = {IPv6: { "nh": 51 }}
+
+# def post_build(self, pkt, pay):
+# if self.len is None:
+# pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
+# if self.segleft is None:
+# pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
+# return _IPv6ExtHdr.post_build(self, pkt, pay)
+
+
+############################### ESP Header ##################################
+
+# class IPv6ExtHdrESP(_IPv6extHdr):
+# name = "IPv6 Extension Header - ESP"
+# fields_desc = [ IntField("spi", 0),
+# IntField("sn", 0),
+# # there is things to extract from IKE work
+# ]
+# overloads_fields = {IPv6: { "nh": 50 }}
+
+
+
+#############################################################################
+#############################################################################
+### ICMPv6* Classes ###
+#############################################################################
+#############################################################################
+
+icmp6typescls = { 1: "ICMPv6DestUnreach",
+ 2: "ICMPv6PacketTooBig",
+ 3: "ICMPv6TimeExceeded",
+ 4: "ICMPv6ParamProblem",
+ 128: "ICMPv6EchoRequest",
+ 129: "ICMPv6EchoReply",
+ 130: "ICMPv6MLQuery",
+ 131: "ICMPv6MLReport",
+ 132: "ICMPv6MLDone",
+ 133: "ICMPv6ND_RS",
+ 134: "ICMPv6ND_RA",
+ 135: "ICMPv6ND_NS",
+ 136: "ICMPv6ND_NA",
+ 137: "ICMPv6ND_Redirect",
+ #138: Do Me - RFC 2894 - Seems painful
+ 139: "ICMPv6NIQuery",
+ 140: "ICMPv6NIReply",
+ 141: "ICMPv6ND_INDSol",
+ 142: "ICMPv6ND_INDAdv",
+ #143: Do Me - RFC 3810
+ 144: "ICMPv6HAADRequest",
+ 145: "ICMPv6HAADReply",
+ 146: "ICMPv6MPSol",
+ 147: "ICMPv6MPAdv",
+ #148: Do Me - SEND related - RFC 3971
+ #149: Do Me - SEND related - RFC 3971
+ 151: "ICMPv6MRD_Advertisement",
+ 152: "ICMPv6MRD_Solicitation",
+ 153: "ICMPv6MRD_Termination",
+ }
+
+icmp6typesminhdrlen = { 1: 8,
+ 2: 8,
+ 3: 8,
+ 4: 8,
+ 128: 8,
+ 129: 8,
+ 130: 24,
+ 131: 24,
+ 132: 24,
+ 133: 8,
+ 134: 16,
+ 135: 24,
+ 136: 24,
+ 137: 40,
+ #139:
+ #140
+ 141: 8,
+ 142: 8,
+ 144: 8,
+ 145: 8,
+ 146: 8,
+ 147: 8,
+ 151: 8,
+ 152: 4,
+ 153: 4
+ }
+
+icmp6types = { 1 : "Destination unreachable",
+ 2 : "Packet too big",
+ 3 : "Time exceeded",
+ 4 : "Parameter problem",
+ 100 : "Private Experimentation",
+ 101 : "Private Experimentation",
+ 128 : "Echo Request",
+ 129 : "Echo Reply",
+ 130 : "MLD Query",
+ 131 : "MLD Report",
+ 132 : "MLD Done",
+ 133 : "Router Solicitation",
+ 134 : "Router Advertisement",
+ 135 : "Neighbor Solicitation",
+ 136 : "Neighbor Advertisement",
+ 137 : "Redirect Message",
+ 138 : "Router Renumbering",
+ 139 : "ICMP Node Information Query",
+ 140 : "ICMP Node Information Response",
+ 141 : "Inverse Neighbor Discovery Solicitation Message",
+ 142 : "Inverse Neighbor Discovery Advertisement Message",
+ 143 : "Version 2 Multicast Listener Report",
+ 144 : "Home Agent Address Discovery Request Message",
+ 145 : "Home Agent Address Discovery Reply Message",
+ 146 : "Mobile Prefix Solicitation",
+ 147 : "Mobile Prefix Advertisement",
+ 148 : "Certification Path Solicitation",
+ 149 : "Certification Path Advertisement",
+ 151 : "Multicast Router Advertisement",
+ 152 : "Multicast Router Solicitation",
+ 153 : "Multicast Router Termination",
+ 200 : "Private Experimentation",
+ 201 : "Private Experimentation" }
+
+
+class _ICMPv6(Packet):
+ name = "ICMPv6 dummy class"
+ overload_fields = {IPv6: {"nh": 58}}
+ def post_build(self, p, pay):
+ p += pay
+ if self.cksum == None:
+ chksum = in6_chksum(58, self.underlayer, p)
+ p = p[:2]+struct.pack("!H", chksum)+p[4:]
+ return p
+
+ def hashret(self):
+ return self.payload.hashret()
+
+ def answers(self, other):
+ # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
+ if (isinstance(self.underlayer, IPerror6) or
+ isinstance(self.underlayer, _IPv6ExtHdr) and
+ isinstance(other, _ICMPv6)):
+ if not ((self.type == other.type) and
+ (self.code == other.code)):
+ return 0
+ return 1
+ return 0
+
+
+class _ICMPv6Error(_ICMPv6):
+ name = "ICMPv6 errors dummy class"
+ def guess_payload_class(self,p):
+ return IPerror6
+
+class ICMPv6Unknown(_ICMPv6):
+ name = "Scapy6 ICMPv6 fallback class"
+ fields_desc = [ ByteEnumField("type",1, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ StrField("msgbody", "")]
+
+
+################################## RFC 2460 #################################
+
+class ICMPv6DestUnreach(_ICMPv6Error):
+ name = "ICMPv6 Destination Unreachable"
+ fields_desc = [ ByteEnumField("type",1, icmp6types),
+ ByteEnumField("code",0, { 0: "No route to destination",
+ 1: "Communication with destination administratively prohibited",
+ 2: "Beyond scope of source address",
+ 3: "Address unreachable",
+ 4: "Port unreachable" }),
+ XShortField("cksum", None),
+ XIntField("unused",0x00000000)]
+
+class ICMPv6PacketTooBig(_ICMPv6Error):
+ name = "ICMPv6 Packet Too Big"
+ fields_desc = [ ByteEnumField("type",2, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ IntField("mtu",1280)]
+
+class ICMPv6TimeExceeded(_ICMPv6Error):
+ name = "ICMPv6 Time Exceeded"
+ fields_desc = [ ByteEnumField("type",3, icmp6types),
+ ByteEnumField("code",0, { 0: "hop limit exceeded in transit",
+ 1: "fragment reassembly time exceeded"}),
+ XShortField("cksum", None),
+ XIntField("unused",0x00000000)]
+
+# The default pointer value is set to the next header field of
+# the encapsulated IPv6 packet
+class ICMPv6ParamProblem(_ICMPv6Error):
+ name = "ICMPv6 Parameter Problem"
+ fields_desc = [ ByteEnumField("type",4, icmp6types),
+ ByteEnumField("code",0, {0: "erroneous header field encountered",
+ 1: "unrecognized Next Header type encountered",
+ 2: "unrecognized IPv6 option encountered"}),
+ XShortField("cksum", None),
+ IntField("ptr",6)]
+
+class ICMPv6EchoRequest(_ICMPv6):
+ name = "ICMPv6 Echo Request"
+ fields_desc = [ ByteEnumField("type", 128, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ XShortField("id",0),
+ XShortField("seq",0),
+ StrField("data", "")]
+ def mysummary(self):
+ return self.sprintf("%name% (id: %id% seq: %seq%)")
+ def hashret(self):
+ return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
+
+
+class ICMPv6EchoReply(ICMPv6EchoRequest):
+ name = "ICMPv6 Echo Reply"
+ type = 129
+ def answers(self, other):
+ # We could match data content between request and reply.
+ return (isinstance(other, ICMPv6EchoRequest) and
+ self.id == other.id and self.seq == other.seq and
+ self.data == other.data)
+
+
+############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
+
+# tous les messages MLD sont emis avec une adresse source lien-locale
+# -> Y veiller dans le post_build si aucune n'est specifiee
+# La valeur de Hop-Limit doit etre de 1
+# "and an IPv6 Router Alert option in a Hop-by-Hop Options
+# header. (The router alert option is necessary to cause routers to
+# examine MLD messages sent to multicast addresses in which the router
+# itself has no interest"
+class _ICMPv6ML(_ICMPv6):
+ fields_desc = [ ByteEnumField("type", 130, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ ShortField("mrd", 0),
+ ShortField("reserved", 0),
+ IP6Field("mladdr","::")]
+
+# general queries are sent to the link-scope all-nodes multicast
+# address ff02::1, with a multicast address field of 0 and a MRD of
+# [Query Response Interval]
+# Default value for mladdr is set to 0 for a General Query, and
+# overloaded by the user for a Multicast Address specific query
+# TODO : See what we can do to automatically include a Router Alert
+# Option in a Destination Option Header.
+class ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
+ name = "MLD - Multicast Listener Query"
+ type = 130
+ mrd = 10000
+ mladdr = "::" # 10s for mrd
+ overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }}
+ def hashret(self):
+ if self.mladdr != "::":
+ return struct.pack("HH",self.mladdr)+self.payload.hashret()
+ else:
+ return self.payload.hashret()
+
+
+# TODO : See what we can do to automatically include a Router Alert
+# Option in a Destination Option Header.
+class ICMPv6MLReport(_ICMPv6ML): # RFC 2710
+ name = "MLD - Multicast Listener Report"
+ type = 131
+ overload_fields = {IPv6: {"hlim": 1, "nh": 58}}
+ # implementer le hashret et le answers
+
+# When a node ceases to listen to a multicast address on an interface,
+# it SHOULD send a single Done message to the link-scope all-routers
+# multicast address (FF02::2), carrying in its multicast address field
+# the address to which it is ceasing to listen
+# TODO : See what we can do to automatically include a Router Alert
+# Option in a Destination Option Header.
+class ICMPv6MLDone(_ICMPv6ML): # RFC 2710
+ name = "MLD - Multicast Listener Done"
+ type = 132
+ overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}}
+
+
+########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
+
+# TODO:
+# - 04/09/06 troglocan : find a way to automatically add a router alert
+# option for all MRD packets. This could be done in a specific
+# way when IPv6 is the under layer with some specific keyword
+# like 'exthdr'. This would allow to keep compatibility with
+# providing IPv6 fields to be overloaded in fields_desc.
+#
+# At the moment, if user inserts an IPv6 Router alert option
+# none of the IPv6 default values of IPv6 layer will be set.
+
+class ICMPv6MRD_Advertisement(_ICMPv6):
+ name = "ICMPv6 Multicast Router Discovery Advertisement"
+ fields_desc = [ByteEnumField("type", 151, icmp6types),
+ ByteField("advinter", 20),
+ XShortField("cksum", None),
+ ShortField("queryint", 0),
+ ShortField("robustness", 0)]
+ overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
+ # IPv6 Router Alert requires manual inclusion
+ def extract_padding(self, s):
+ return s[:8], s[8:]
+
+class ICMPv6MRD_Solicitation(_ICMPv6):
+ name = "ICMPv6 Multicast Router Discovery Solicitation"
+ fields_desc = [ByteEnumField("type", 152, icmp6types),
+ ByteField("res", 0),
+ XShortField("cksum", None) ]
+ overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
+ # IPv6 Router Alert requires manual inclusion
+ def extract_padding(self, s):
+ return s[:4], s[4:]
+
+class ICMPv6MRD_Termination(_ICMPv6):
+ name = "ICMPv6 Multicast Router Discovery Termination"
+ fields_desc = [ByteEnumField("type", 153, icmp6types),
+ ByteField("res", 0),
+ XShortField("cksum", None) ]
+ overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
+ # IPv6 Router Alert requires manual inclusion
+ def extract_padding(self, s):
+ return s[:4], s[4:]
+
+
+################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
+
+icmp6ndopts = { 1: "Source Link-Layer Address",
+ 2: "Target Link-Layer Address",
+ 3: "Prefix Information",
+ 4: "Redirected Header",
+ 5: "MTU",
+ 6: "NBMA Shortcut Limit Option", # RFC2491
+ 7: "Advertisement Interval Option",
+ 8: "Home Agent Information Option",
+ 9: "Source Address List",
+ 10: "Target Address List",
+ 11: "CGA Option", # RFC 3971
+ 12: "RSA Signature Option", # RFC 3971
+ 13: "Timestamp Option", # RFC 3971
+ 14: "Nonce option", # RFC 3971
+ 15: "Trust Anchor Option", # RFC 3971
+ 16: "Certificate Option", # RFC 3971
+ 17: "IP Address Option", # RFC 4068
+ 18: "New Router Prefix Information Option", # RFC 4068
+ 19: "Link-layer Address Option", # RFC 4068
+ 20: "Neighbor Advertisement Acknowledgement Option",
+ 21: "CARD Request Option", # RFC 4065/4066/4067
+ 22: "CARD Reply Option", # RFC 4065/4066/4067
+ 23: "MAP Option", # RFC 4140
+ 24: "Route Information Option", # RFC 4191
+ 25: "Recusive DNS Server Option",
+ 26: "IPv6 Router Advertisement Flags Option"
+ }
+
+icmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
+ 2: "ICMPv6NDOptDstLLAddr",
+ 3: "ICMPv6NDOptPrefixInfo",
+ 4: "ICMPv6NDOptRedirectedHdr",
+ 5: "ICMPv6NDOptMTU",
+ 6: "ICMPv6NDOptShortcutLimit",
+ 7: "ICMPv6NDOptAdvInterval",
+ 8: "ICMPv6NDOptHAInfo",
+ 9: "ICMPv6NDOptSrcAddrList",
+ 10: "ICMPv6NDOptTgtAddrList",
+ #11: Do Me,
+ #12: Do Me,
+ #13: Do Me,
+ #14: Do Me,
+ #15: Do Me,
+ #16: Do Me,
+ 17: "ICMPv6NDOptIPAddr",
+ 18: "ICMPv6NDOptNewRtrPrefix",
+ 19: "ICMPv6NDOptLLA",
+ #18: Do Me,
+ #19: Do Me,
+ #20: Do Me,
+ #21: Do Me,
+ #22: Do Me,
+ 23: "ICMPv6NDOptMAP",
+ 24: "ICMPv6NDOptRouteInfo",
+ 25: "ICMPv6NDOptRDNSS",
+ 26: "ICMPv6NDOptEFA"
+ }
+
+class _ICMPv6NDGuessPayload:
+ name = "Dummy ND class that implements guess_payload_class()"
+ def guess_payload_class(self,p):
+ if len(p) > 1:
+ #return get_cls(icmp6ndoptscls.get(ord(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
+ return get_cls(icmp6ndoptscls.get(p[0],"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
+
+
+# Beginning of ICMPv6 Neighbor Discovery Options.
+
+class ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
+ fields_desc = [ ByteField("type",None),
+ FieldLenField("len",None,length_of="data",fmt="B",
+ adjust = lambda pkt,x: x+2),
+ StrLenField("data","",
+ length_from = lambda pkt: pkt.len-2) ]
+
+# NOTE: len includes type and len field. Expressed in unit of 8 bytes
+# TODO: Revoir le coup du ETHER_ANY
+class ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
+ fields_desc = [ ByteField("type", 1),
+ ByteField("len", 1),
+ MACField("lladdr", ETHER_ANY) ]
+ def mysummary(self):
+ return self.sprintf("%name% %lladdr%")
+
+class ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
+ name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
+ type = 2
+
+class ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
+ fields_desc = [ ByteField("type",3),
+ ByteField("len",4),
+ ByteField("prefixlen",None),
+ BitField("L",1,1),
+ BitField("A",1,1),
+ BitField("R",0,1),
+ BitField("res1",0,5),
+ XIntField("validlifetime",0xffffffff),
+ XIntField("preferredlifetime",0xffffffff),
+ XIntField("res2",0x00000000),
+ IP6Field("prefix","::") ]
+ def mysummary(self):
+ return self.sprintf("%name% %prefix%")
+
+# TODO: We should also limit the size of included packet to something
+# like (initiallen - 40 - 2)
+class TruncPktLenField(PacketLenField):
+
+ def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
+ PacketLenField.__init__(self, name, default, cls, length_from=length_from)
+ self.cur_shift = cur_shift
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ i = self.m2i(pkt, s[:l])
+ return s[l:],i
+
+ def m2i(self, pkt, m):
+ s = None
+ try: # It can happen we have sth shorter than 40 bytes
+ s = self.cls(m)
+ except:
+ return conf.raw_layer(m)
+ return s
+
+ def i2m(self, pkt, x):
+ s = bytes(x)
+ l = len(s)
+ r = (l + self.cur_shift) % 8
+ l = l - r
+ return s[:l]
+
+ def i2len(self, pkt, i):
+ return len(self.i2m(pkt, i))
+
+
+# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
+class ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
+ fields_desc = [ ByteField("type",4),
+ FieldLenField("len", None, length_of="pkt", fmt="B",
+ adjust = lambda pkt,x:(x+8)//8),
+ StrFixedLenField("res", b"\x00"*6, 6),
+ TruncPktLenField("pkt", b"", IPv6, 8,
+ length_from = lambda pkt: 8*pkt.len-8) ]
+
+# See which value should be used for default MTU instead of 1280
+class ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery Option - MTU"
+ fields_desc = [ ByteField("type",5),
+ ByteField("len",1),
+ XShortField("res",0),
+ IntField("mtu",1280)]
+
+class ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
+ name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
+ fields_desc = [ ByteField("type", 6),
+ ByteField("len", 1),
+ ByteField("shortcutlim", 40), # XXX
+ ByteField("res1", 0),
+ IntField("res2", 0) ]
+
+class ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
+ fields_desc = [ ByteField("type",7),
+ ByteField("len",1),
+ ShortField("res", 0),
+ IntField("advint", 0) ]
+ def mysummary(self):
+ return self.sprintf("%name% %advint% milliseconds")
+
+class ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Neighbor Discovery - Home Agent Information"
+ fields_desc = [ ByteField("type",8),
+ ByteField("len",1),
+ ShortField("res", 0),
+ ShortField("pref", 0),
+ ShortField("lifetime", 1)]
+ def mysummary(self):
+ return self.sprintf("%name% %pref% %lifetime% seconds")
+
+# type 9 : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
+
+# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
+
+class ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet): # RFC 4068
+ name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
+ fields_desc = [ ByteField("type",17),
+ ByteField("len", 3),
+ ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
+ 2: "New Care-Of Address",
+ 3: "NAR's IP address" }),
+ ByteField("plen", 64),
+ IntField("res", 0),
+ IP6Field("addr", "::") ]
+
+class ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
+ name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
+ fields_desc = [ ByteField("type",18),
+ ByteField("len", 3),
+ ByteField("optcode", 0),
+ ByteField("plen", 64),
+ IntField("res", 0),
+ IP6Field("prefix", "::") ]
+
+_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
+ 1: "LLA for the new AP",
+ 2: "LLA of the MN",
+ 3: "LLA of the NAR",
+ 4: "LLA of the src of TrSolPr or PrRtAdv msg",
+ 5: "AP identified by LLA belongs to current iface of router",
+ 6: "No preifx info available for AP identified by the LLA",
+ 7: "No fast handovers support for AP identified by the LLA" }
+
+class ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet): # RFC 4068
+ name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
+ fields_desc = [ ByteField("type", 19),
+ ByteField("len", 1),
+ ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
+ MACField("lla", ETHER_ANY) ] # We only support ethernet
+
+class ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet): # RFC 4140
+ name = "ICMPv6 Neighbor Discovery - MAP Option"
+ fields_desc = [ ByteField("type", 23),
+ ByteField("len", 3),
+ BitField("dist", 1, 4),
+ BitField("pref", 15, 4), # highest availability
+ BitField("R", 1, 1),
+ BitField("res", 0, 7),
+ IntField("validlifetime", 0xffffffff),
+ IP6Field("addr", "::") ]
+
+
+class IP6PrefixField(IP6Field):
+ def __init__(self, name, default):
+ IP6Field.__init__(self, name, default)
+ self.length_from = lambda pkt: 8*(pkt.len - 1)
+
+ def addfield(self, pkt, s, val):
+ return s + self.i2m(pkt, val)
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ p = s[:l]
+ if l < 16:
+ p += b'\x00'*(16-l)
+ return s[l:], self.m2i(pkt,p)
+
+ def i2len(self, pkt, x):
+ return len(self.i2m(pkt, x))
+
+ def i2m(self, pkt, x):
+ l = pkt.len
+
+ if x is None:
+ x = "::"
+ if l is None:
+ l = 1
+ x = inet_pton(socket.AF_INET6, x)
+
+ if l is None:
+ return x
+ if l in [0, 1]:
+ return b""
+ if l in [2, 3]:
+ return x[:8*(l-1)]
+
+ return x + b'\x00'*8*(l-3)
+
+class ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
+ name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
+ fields_desc = [ ByteField("type",24),
+ FieldLenField("len", None, length_of="prefix", fmt="B",
+ adjust = lambda pkt,x: x//8 + 1),
+ ByteField("plen", None),
+ BitField("res1",0,3),
+ BitField("prf",0,2),
+ BitField("res2",0,3),
+ IntField("rtlifetime", 0xffffffff),
+ IP6PrefixField("prefix", None) ]
+
+class ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
+ name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
+ fields_desc = [ ByteField("type", 25),
+ FieldLenField("len", None, count_of="dns", fmt="B",
+ adjust = lambda pkt,x: 2*x+1),
+ ShortField("res", None),
+ IntField("lifetime", 0xffffffff),
+ IP6ListField("dns", [],
+ length_from = lambda pkt: 8*(pkt.len-1)) ]
+
+class ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
+ name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
+ fields_desc = [ ByteField("type", 26),
+ ByteField("len", 1),
+ BitField("res", 0, 48) ]
+
+# End of ICMPv6 Neighbor Discovery Options.
+
+class ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
+ name = "ICMPv6 Neighbor Discovery - Router Solicitation"
+ fields_desc = [ ByteEnumField("type", 133, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ IntField("res",0) ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
+
+class ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
+ name = "ICMPv6 Neighbor Discovery - Router Advertisement"
+ fields_desc = [ ByteEnumField("type", 134, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ ByteField("chlim",0),
+ BitField("M",0,1),
+ BitField("O",0,1),
+ BitField("H",0,1),
+ BitEnumField("prf",1,2, { 0: "Medium (default)",
+ 1: "High",
+ 2: "Reserved",
+ 3: "Low" } ), # RFC 4191
+ BitField("P",0,1),
+ BitField("res",0,2),
+ ShortField("routerlifetime",1800),
+ IntField("reachabletime",0),
+ IntField("retranstimer",0) ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+ def answers(self, other):
+ return isinstance(other, ICMPv6ND_RS)
+
+class ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
+ name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
+ fields_desc = [ ByteEnumField("type",135, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ IntField("res", 0),
+ IP6Field("tgt","::") ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+ def mysummary(self):
+ return self.sprintf("%name% (tgt: %tgt%)")
+
+ def hashret(self):
+ return self.getbyteval("tgt")+self.payload.hashret()
+
+class ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
+ name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
+ fields_desc = [ ByteEnumField("type",136, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ BitField("R",1,1),
+ BitField("S",0,1),
+ BitField("O",1,1),
+ XBitField("res",0,29),
+ IP6Field("tgt","::") ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+ def mysummary(self):
+ return self.sprintf("%name% (tgt: %tgt%)")
+
+ def hashret(self):
+ return self.getbyteval("tgt")+self.payload.hashret()
+
+ def answers(self, other):
+ return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
+
+# associated possible options : target link-layer option, Redirected header
+class ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
+ name = "ICMPv6 Neighbor Discovery - Redirect"
+ fields_desc = [ ByteEnumField("type",137, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum", None),
+ XIntField("res",0),
+ IP6Field("tgt","::"),
+ IP6Field("dst","::") ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+
+
+################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
+
+class ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
+ name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
+ fields_desc = [ ByteField("type",9),
+ FieldLenField("len", None, count_of="addrlist", fmt="B",
+ adjust = lambda pkt,x: 2*x+1),
+ StrFixedLenField("res", "\x00"*6, 6),
+ IP6ListField("addrlist", [],
+ length_from = lambda pkt: 8*(pkt.len-1)) ]
+
+class ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
+ name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
+ type = 10
+
+
+# RFC3122
+# Options requises : source lladdr et target lladdr
+# Autres options valides : source address list, MTU
+# - Comme precise dans le document, il serait bien de prendre l'adresse L2
+# demandee dans l'option requise target lladdr et l'utiliser au niveau
+# de l'adresse destination ethernet si aucune adresse n'est precisee
+# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
+# les options.
+# Ether() must use the target lladdr as destination
+class ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
+ name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
+ fields_desc = [ ByteEnumField("type",141, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum",None),
+ XIntField("reserved",0) ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+# Options requises : target lladdr, target address list
+# Autres options valides : MTU
+class ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
+ name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
+ fields_desc = [ ByteEnumField("type",142, icmp6types),
+ ByteField("code",0),
+ XShortField("cksum",None),
+ XIntField("reserved",0) ]
+ overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
+
+
+###############################################################################
+# ICMPv6 Node Information Queries (RFC 4620)
+###############################################################################
+
+# [ ] Add automatic destination address computation using computeNIGroupAddr
+# in IPv6 class (Scapy6 modification when integrated) if :
+# - it is not provided
+# - upper layer is ICMPv6NIQueryName() with a valid value
+# [ ] Try to be liberal in what we accept as internal values for _explicit_
+# DNS elements provided by users. Any string should be considered
+# valid and kept like it has been provided. At the moment, i2repr() will
+# crash on many inputs
+# [ ] Do the documentation
+# [ ] Add regression tests
+# [ ] Perform test against real machines (NOOP reply is proof of implementation).
+# [ ] Check if there are differences between different stacks. Among *BSD,
+# with others.
+# [ ] Deal with flags in a consistent way.
+# [ ] Implement compression in names2dnsrepr() and decompresiion in
+# dnsrepr2names(). Should be deactivable.
+
+icmp6_niqtypes = { 0: "NOOP",
+ 2: "Node Name",
+ 3: "IPv6 Address",
+ 4: "IPv4 Address" }
+
+
+class _ICMPv6NIHashret:
+ def hashret(self):
+ return self.nonce
+
+class _ICMPv6NIAnswers:
+ def answers(self, other):
+ return self.nonce == other.nonce
+
+# Buggy; always returns the same value during a session
+class NonceField(StrFixedLenField):
+ def __init__(self, name, default=None):
+ StrFixedLenField.__init__(self, name, default, 8)
+ if default is None:
+ self.default = self.randval()
+
+# Compute the NI group Address. Can take a FQDN as input parameter
+def computeNIGroupAddr(name):
+ import md5
+ name = name.lower().split(".")[0]
+ record = chr(len(name))+name
+ h = md5.new(record)
+ h = h.digest()
+ addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
+ return addr
+
+
+# Here is the deal. First, that protocol is a piece of shit. Then, we
+# provide 4 classes for the different kinds of Requests (one for every
+# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
+# data field class that is made to be smart by guessing the specifc
+# type of value provided :
+#
+# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
+# if not overriden by user
+# - IPv4 if acceptable for inet_pton(AF_INET, ): code is set to 2,
+# if not overriden
+# - Name in the other cases: code is set to 0, if not overriden by user
+#
+# Internal storage, is not only the value, but the a pair providing
+# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
+#
+# Note : I merged getfield() and m2i(). m2i() should not be called
+# directly anyway. Same remark for addfield() and i2m()
+#
+# -- arno
+
+# "The type of information present in the Data field of a query is
+# declared by the ICMP Code, whereas the type of information in a
+# Reply is determined by the Qtype"
+
+def names2dnsrepr(x):
+ """
+ Take as input a list of DNS names or a single DNS name
+ and encode it in DNS format (with possible compression)
+ If a string that is already a DNS name in DNS format
+ is passed, it is returned unmodified. Result is a string.
+ !!! At the moment, compression is not implemented !!!
+ """
+
+ if type(x) is str:
+ if x and x[-1] == '\x00': # stupid heuristic
+ return x.encode('ascii')
+ x = [x.encode('ascii')]
+ elif type(x) is bytes:
+ if x and x[-1] == 0:
+ return x
+ x = [x]
+
+ res = []
+ for n in x:
+ if type(n) is str:
+ n = n.encode('ascii')
+ termin = b"\x00"
+ if n.count(b'.') == 0: # single-component gets one more
+ termin += bytes([0])
+ n = b"".join(map(lambda y: chr(len(y)).encode('ascii')+y, n.split(b"."))) + termin
+ res.append(n)
+ return b"".join(res)
+
+
+def dnsrepr2names(x):
+ """
+ Take as input a DNS encoded string (possibly compressed)
+ and returns a list of DNS names contained in it.
+ If provided string is already in printable format
+ (does not end with a null character, a one element list
+ is returned). Result is a list.
+ """
+ res = []
+ cur = b""
+ if type(x) is str:
+ x = x.encode('ascii')
+ while x:
+ #l = ord(x[0])
+ l = x[0]
+ x = x[1:]
+ if l == 0:
+ if cur and cur[-1] == ord('.'):
+ cur = cur[:-1]
+ res.append(cur)
+ cur = b""
+ #if x and ord(x[0]) == 0: # single component
+ if x and x[0] == 0: # single component
+ x = x[1:]
+ continue
+ if l & 0xc0: # XXX TODO : work on that -- arno
+ raise Exception("DNS message can't be compressed at this point!")
+ else:
+ cur += x[:l]+b"."
+ x = x[l:]
+ return res
+
+
+class NIQueryDataField(StrField):
+ def __init__(self, name, default):
+ StrField.__init__(self, name, default)
+
+ def i2h(self, pkt, x):
+ if x is None:
+ return x
+ t,val = x
+ if t == 1:
+ val = dnsrepr2names(val)[0]
+ return val
+
+ def h2i(self, pkt, x):
+ if x is tuple and type(x[0]) is int:
+ return x
+
+ val = None
+ try: # Try IPv6
+ inet_pton(socket.AF_INET6, x)
+ val = (0, x)
+ except:
+ try: # Try IPv4
+ inet_pton(socket.AF_INET, x)
+ val = (2, x)
+ except: # Try DNS
+ if x is None:
+ x = b""
+ x = names2dnsrepr(x)
+ val = (1, x)
+ return val
+
+ def i2repr(self, pkt, x):
+ t,val = x
+ if t == 1: # DNS Name
+ # we don't use dnsrepr2names() to deal with
+ # possible weird data extracted info
+ res = []
+ weird = None
+ while val:
+ #l = ord(val[0])
+ l = val[0]
+ val = val[1:]
+ if l == 0:
+ if (len(res) > 1 and val): # fqdn with data behind
+ weird = val
+ elif len(val) > 1: # single label with data behind
+ weird = val[1:]
+ break
+ res.append(val[:l]+".")
+ val = val[l:]
+ tmp = "".join(res)
+ if tmp and tmp[-1] == '.':
+ tmp = tmp[:-1]
+ return tmp
+ return repr(val)
+
+ def getfield(self, pkt, s):
+ qtype = getattr(pkt, "qtype")
+ if qtype == 0: # NOOP
+ return s, (0, b"")
+ else:
+ code = getattr(pkt, "code")
+ if code == 0: # IPv6 Addr
+ return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
+ elif code == 2: # IPv4 Addr
+ return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
+ else: # Name or Unknown
+ return b"", (1, s)
+
+ def addfield(self, pkt, s, val):
+ if ((type(val) is tuple and val[1] is None) or
+ val is None):
+ val = (1, b"")
+ t = val[0]
+ if t == 1:
+ if type(val[1]) is str:
+ tmp = val[1].encode('ascii')
+ else:
+ tmp = val[1]
+ return s + tmp
+ elif t == 0:
+ return s + inet_pton(socket.AF_INET6, val[1])
+ else:
+ return s + inet_pton(socket.AF_INET, val[1])
+
+class NIQueryCodeField(ByteEnumField):
+ def i2m(self, pkt, x):
+ if x is None:
+ d = pkt.getfieldval("data")
+ if d is None:
+ return 1
+ elif d[0] == 0: # IPv6 address
+ return 0
+ elif d[0] == 1: # Name
+ return 1
+ elif d[0] == 2: # IPv4 address
+ return 2
+ else:
+ return 1
+ return x
+
+
+_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
+
+#_niquery_flags = { 2: "All unicast addresses", 4: "IPv4 addresses",
+# 8: "Link-local addresses", 16: "Site-local addresses",
+# 32: "Global addresses" }
+
+# "This NI type has no defined flags and never has a Data Field". Used
+# to know if the destination is up and implements NI protocol.
+class ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
+ name = "ICMPv6 Node Information Query - NOOP Query"
+ fields_desc = [ ByteEnumField("type", 139, icmp6types),
+ NIQueryCodeField("code", None, _niquery_code),
+ XShortField("cksum", None),
+ ShortEnumField("qtype", 0, icmp6_niqtypes),
+ BitField("unused", 0, 10),
+ FlagsField("flags", 0, 6, "TACLSG"),
+ NonceField("nonce", None),
+ NIQueryDataField("data", None) ]
+
+class ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
+ name = "ICMPv6 Node Information Query - IPv6 Name Query"
+ qtype = 2
+
+# We ask for the IPv6 address of the peer
+class ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
+ name = "ICMPv6 Node Information Query - IPv6 Address Query"
+ qtype = 3
+ flags = 0x3E
+
+class ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
+ name = "ICMPv6 Node Information Query - IPv4 Address Query"
+ qtype = 4
+
+_nireply_code = { 0: "Successful Reply",
+ 1: "Response Refusal",
+ 3: "Unknown query type" }
+
+_nireply_flags = { 1: "Reply set incomplete",
+ 2: "All unicast addresses",
+ 4: "IPv4 addresses",
+ 8: "Link-local addresses",
+ 16: "Site-local addresses",
+ 32: "Global addresses" }
+
+# Internal repr is one of those :
+# (0, "some string") : unknow qtype value are mapped to that one
+# (3, [ (ttl, ip6), ... ])
+# (4, [ (ttl, ip4), ... ])
+# (2, [ttl, dns_names]) : dns_names is one string that contains
+# all the DNS names. Internally it is kept ready to be sent
+# (undissected). i2repr() decode it for user. This is to
+# make build after dissection bijective.
+#
+# I also merged getfield() and m2i(), and addfield() and i2m().
+class NIReplyDataField(StrField):
+
+ def i2h(self, pkt, x):
+ if x is None:
+ return x
+ t,val = x
+ if t == 2:
+ ttl, dnsnames = val
+ val = [ttl] + dnsrepr2names(dnsnames)
+ return val
+
+ def h2i(self, pkt, x):
+ qtype = 0 # We will decode it as string if not
+ # overridden through 'qtype' in pkt
+
+ # No user hint, let's use 'qtype' value for that purpose
+ if type(x) is not tuple:
+ if pkt is not None:
+ qtype = getattr(pkt, "qtype")
+ else:
+ qtype = x[0]
+ x = x[1]
+
+ # From that point on, x is the value (second element of the tuple)
+
+ if qtype == 2: # DNS name
+ if type(x) is str: # listify the string
+ x = x.encode('ascii')
+ x = [x]
+ elif type(x) is bytes:
+ x = [x]
+ if type(x) is list and x and type(x[0]) is not int: # ttl was omitted : use 0
+ x = [0] + x
+ ttl = x[0]
+ names = x[1:]
+ return (2, [ttl, names2dnsrepr(names)])
+
+ elif qtype in [3, 4]: # IPv4 or IPv6 addr
+ if type(x) is str or type(x) is bytes:
+ x = [x] # User directly provided an IP, instead of list
+
+ # List elements are not tuples, user probably
+ # omitted ttl value : we will use 0 instead
+ def addttl(x):
+ if type(x) is str or type(x) is bytes:
+ return (0, x)
+ return x
+
+ return (qtype, list(map(addttl, x)))
+
+ return (qtype, x)
+
+
+ def addfield(self, pkt, s, val):
+ t,tmp = val
+ if tmp is None:
+ tmp = b""
+ if t == 2:
+ ttl,dnsstr = tmp
+ return s+ struct.pack("!I", ttl) + dnsstr
+ elif t == 3:
+ #return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET6, y), tmp))
+ return s + b"".join(map(lambda a: struct.pack("!I", a[0])+inet_pton(socket.AF_INET6, a[1]), tmp))
+ elif t == 4:
+ #return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET, y), tmp))
+ return s + b"".join(map(lambda a: struct.pack("!I", a[0])+inet_pton(socket.AF_INET, a[1]), tmp))
+ else:
+ return s + tmp
+
+ def getfield(self, pkt, s):
+ code = getattr(pkt, "code")
+ if code != 0:
+ return s, (0, b"")
+
+ qtype = getattr(pkt, "qtype")
+ if qtype == 0: # NOOP
+ return s, (0, b"")
+
+ elif qtype == 2:
+ if len(s) < 4:
+ return s, (0, b"")
+ ttl = struct.unpack("!I", s[:4])[0]
+ return b"", (2, [ttl, s[4:]])
+
+ elif qtype == 3: # IPv6 addresses with TTLs
+ # XXX TODO : get the real length
+ res = []
+ while len(s) >= 20: # 4 + 16
+ ttl = struct.unpack("!I", s[:4])[0]
+ ip = inet_ntop(socket.AF_INET6, s[4:20])
+ res.append((ttl, ip))
+ s = s[20:]
+ return s, (3, res)
+
+ elif qtype == 4: # IPv4 addresses with TTLs
+ # XXX TODO : get the real length
+ res = []
+ while len(s) >= 8: # 4 + 4
+ ttl = struct.unpack("!I", s[:4])[0]
+ ip = inet_ntop(socket.AF_INET, s[4:8])
+ res.append((ttl, ip))
+ s = s[8:]
+ return s, (4, res)
+ else:
+ # XXX TODO : implement me and deal with real length
+ return b"", (0, s)
+
+ def i2repr(self, pkt, x):
+ if x is None:
+ return "[]"
+
+ if type(x) is tuple and len(x) == 2:
+ t, val = x
+ if t == 2: # DNS names
+ ttl,l = val
+ l = dnsrepr2names(l)
+ return "ttl:%d %s" % (ttl, ", ".join(l))
+ elif t == 3 or t == 4:
+ #return "[ %s ]" % (", ".join(map(lambda (x,y): "(%d, %s)" % (x, y), val)))
+ return "[ %s ]" % (", ".join(map(lambda a: "(%d, %s)" % a, val)))
+ return repr(val)
+ return repr(x) # XXX should not happen
+
+# By default, sent responses have code set to 0 (successful)
+class ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
+ name = "ICMPv6 Node Information Reply - NOOP Reply"
+ fields_desc = [ ByteEnumField("type", 140, icmp6types),
+ ByteEnumField("code", 0, _nireply_code),
+ XShortField("cksum", None),
+ ShortEnumField("qtype", 0, icmp6_niqtypes),
+ BitField("unused", 0, 10),
+ FlagsField("flags", 0, 6, "TACLSG"),
+ NonceField("nonce", None),
+ NIReplyDataField("data", None)]
+
+class ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
+ name = "ICMPv6 Node Information Reply - Node Names"
+ qtype = 2
+
+class ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
+ name = "ICMPv6 Node Information Reply - IPv6 addresses"
+ qtype = 3
+
+class ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
+ name = "ICMPv6 Node Information Reply - IPv4 addresses"
+ qtype = 4
+
+class ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
+ name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
+ code = 1
+
+class ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
+ name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
+ code = 2
+
+
+def _niquery_guesser(p):
+ cls = conf.raw_layer
+ #type = ord(p[0])
+ type = p[0]
+ if type == 139: # Node Info Query specific stuff
+ if len(p) > 6:
+ qtype, = struct.unpack("!H", p[4:6])
+ cls = { 0: ICMPv6NIQueryNOOP,
+ 2: ICMPv6NIQueryName,
+ 3: ICMPv6NIQueryIPv6,
+ 4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer)
+ elif type == 140: # Node Info Reply specific stuff
+ #code = ord(p[1])
+ code = p[1]
+ if code == 0:
+ if len(p) > 6:
+ qtype, = struct.unpack("!H", p[4:6])
+ cls = { 2: ICMPv6NIReplyName,
+ 3: ICMPv6NIReplyIPv6,
+ 4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
+ elif code == 1:
+ cls = ICMPv6NIReplyRefuse
+ elif code == 2:
+ cls = ICMPv6NIReplyUnknown
+ return cls
+
+
+#############################################################################
+#############################################################################
+### Mobile IPv6 (RFC 3775) and Nemo (RFC 3963) ###
+#############################################################################
+#############################################################################
+
+# Mobile IPv6 ICMPv6 related classes
+
+class ICMPv6HAADRequest(_ICMPv6):
+ name = 'ICMPv6 Home Agent Address Discovery Request'
+ fields_desc = [ ByteEnumField("type", 144, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ XShortField("id", None),
+ BitEnumField("R", 1, 1, {1: 'MR'}),
+ XBitField("res", 0, 15) ]
+ def hashret(self):
+ return struct.pack("!H",self.id)+self.payload.hashret()
+
+class ICMPv6HAADReply(_ICMPv6):
+ name = 'ICMPv6 Home Agent Address Discovery Reply'
+ fields_desc = [ ByteEnumField("type", 145, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ XShortField("id", None),
+ BitEnumField("R", 1, 1, {1: 'MR'}),
+ XBitField("res", 0, 15),
+ IP6ListField('addresses', None) ]
+ def hashret(self):
+ return struct.pack("!H",self.id)+self.payload.hashret()
+
+ def answers(self, other):
+ if not isinstance(other, ICMPv6HAADRequest):
+ return 0
+ return self.id == other.id
+
+class ICMPv6MPSol(_ICMPv6):
+ name = 'ICMPv6 Mobile Prefix Solicitation'
+ fields_desc = [ ByteEnumField("type", 146, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ XShortField("id", None),
+ XShortField("res", 0) ]
+ def _hashret(self):
+ return struct.pack("!H",self.id)
+
+class ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
+ name = 'ICMPv6 Mobile Prefix Advertisement'
+ fields_desc = [ ByteEnumField("type", 147, icmp6types),
+ ByteField("code", 0),
+ XShortField("cksum", None),
+ XShortField("id", None),
+ BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
+ XBitField("res", 0, 14) ]
+ def hashret(self):
+ return struct.pack("!H",self.id)
+
+ def answers(self, other):
+ return isinstance(other, ICMPv6MPSol)
+
+# Mobile IPv6 Options classes
+
+
+_mobopttypes = { 2: "Binding Refresh Advice",
+ 3: "Alternate Care-of Address",
+ 4: "Nonce Indices",
+ 5: "Binding Authorization Data",
+ 6: "Mobile Network Prefix (RFC3963)",
+ 7: "Link-Layer Address (RFC4068)",
+ 8: "Mobile Node Identifier (RFC4283)",
+ 9: "Mobility Message Authentication (RFC4285)",
+ 10: "Replay Protection (RFC4285)",
+ 11: "CGA Parameters Request (RFC4866)",
+ 12: "CGA Parameters (RFC4866)",
+ 13: "Signature (RFC4866)",
+ 14: "Home Keygen Token (RFC4866)",
+ 15: "Care-of Test Init (RFC4866)",
+ 16: "Care-of Test (RFC4866)" }
+
+
+class _MIP6OptAlign:
+ """ Mobile IPv6 options have alignment requirements of the form x*n+y.
+ This class is inherited by all MIPv6 options to help in computing the
+ required Padding for that option, i.e. the need for a Pad1 or PadN
+ option before it. They only need to provide x and y as class
+ parameters. (x=0 and y=0 are used when no alignment is required)"""
+ def alignment_delta(self, curpos):
+ x = self.x ; y = self.y
+ if x == 0 and y ==0:
+ return 0
+ delta = x*((curpos - y + x - 1)//x) + y - curpos
+ return delta
+
+
+class MIP6OptBRAdvice(_MIP6OptAlign, Packet):
+ name = 'Mobile IPv6 Option - Binding Refresh Advice'
+ fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
+ ByteField('olen', 2),
+ ShortField('rinter', 0) ]
+ x = 2 ; y = 0# alignment requirement: 2n
+
+class MIP6OptAltCoA(_MIP6OptAlign, Packet):
+ name = 'MIPv6 Option - Alternate Care-of Address'
+ fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
+ ByteField('olen', 16),
+ IP6Field("acoa", "::") ]
+ x = 8 ; y = 6 # alignment requirement: 8n+6
+
+class MIP6OptNonceIndices(_MIP6OptAlign, Packet):
+ name = 'MIPv6 Option - Nonce Indices'
+ fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
+ ByteField('olen', 16),
+ ShortField('hni', 0),
+ ShortField('coni', 0) ]
+ x = 2 ; y = 0 # alignment requirement: 2n
+
+class MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
+ name = 'MIPv6 Option - Binding Authorization Data'
+ fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
+ ByteField('olen', 16),
+ BitField('authenticator', 0, 96) ]
+ x = 8 ; y = 2 # alignment requirement: 8n+2
+
+class MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
+ name = 'NEMO Option - Mobile Network Prefix'
+ fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
+ ByteField("olen", 18),
+ ByteField("reserved", 0),
+ ByteField("plen", 64),
+ IP6Field("prefix", "::") ]
+ x = 8 ; y = 4 # alignment requirement: 8n+4
+
+class MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
+ name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
+ fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
+ ByteField("olen", 7),
+ ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
+ ByteField("pad", 0),
+ MACField("lla", ETHER_ANY) ] # Only support ethernet
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
+ name = "MIPv6 Option - Mobile Node Identifier"
+ fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
+ FieldLenField("olen", None, length_of="id", fmt="B",
+ adjust = lambda pkt,x: x+1),
+ ByteEnumField("subtype", 1, {1: "NAI"}),
+ StrLenField("id", "",
+ length_from = lambda pkt: pkt.olen-1) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+# We only support decoding and basic build. Automatic HMAC computation is
+# too much work for our current needs. It is left to the user (I mean ...
+# you). --arno
+class MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
+ name = "MIPv6 Option - Mobility Message Authentication"
+ fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
+ FieldLenField("olen", None, length_of="authdata", fmt="B",
+ adjust = lambda pkt,x: x+5),
+ ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
+ 2: "MN-AAA authentication mobility option"}),
+ IntField("mspi", None),
+ StrLenField("authdata", "A"*12,
+ length_from = lambda pkt: pkt.olen-5) ]
+ x = 4 ; y = 1 # alignment requirement: 4n+1
+
+# Extracted from RFC 1305 (NTP) :
+# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
+# in seconds relative to 0h on 1 January 1900. The integer part is in the
+# first 32 bits and the fraction part in the last 32 bits.
+class NTPTimestampField(LongField):
+ epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0)
+ def i2repr(self, pkt, x):
+ if x < ((50*31536000)<<32):
+ return "Some date a few decades ago (%d)" % x
+
+ # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
+ # January 1st 1970 :
+ delta = -2209075761
+ i = int(x >> 32)
+ j = float(x & 0xffffffff) * 2.0**-32
+ res = i + j + delta
+ from time import strftime
+ t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res))
+
+ return "%s (%d)" % (t, x)
+
+class MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
+ name = "MIPv6 option - Replay Protection"
+ fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
+ ByteField("olen", 8),
+ NTPTimestampField("timestamp", 0) ]
+ x = 8 ; y = 2 # alignment requirement: 8n+2
+
+class MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
+ name = "MIPv6 option - CGA Parameters Request"
+ fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
+ ByteField("olen", 0) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+# XXX TODO: deal with CGA param fragmentation and build of defragmented
+# XXX version. Passing of a big CGAParam structure should be
+# XXX simplified. Make it hold packets, by the way --arno
+class MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
+ name = "MIPv6 option - CGA Parameters"
+ fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
+ FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
+ StrLenField("cgaparams", "",
+ length_from = lambda pkt: pkt.olen) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
+ name = "MIPv6 option - Signature"
+ fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
+ FieldLenField("olen", None, length_of="sig", fmt="B"),
+ StrLenField("sig", "",
+ length_from = lambda pkt: pkt.olen) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
+ name = "MIPv6 option - Home Keygen Token"
+ fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
+ FieldLenField("olen", None, length_of="hkt", fmt="B"),
+ StrLenField("hkt", "",
+ length_from = lambda pkt: pkt.olen) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
+ name = "MIPv6 option - Care-of Test Init"
+ fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
+ ByteField("olen", 0) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
+ name = "MIPv6 option - Care-of Test"
+ fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
+ FieldLenField("olen", None, length_of="cokt", fmt="B"),
+ StrLenField("cokt", '\x00'*8,
+ length_from = lambda pkt: pkt.olen) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+class MIP6OptUnknown(_MIP6OptAlign, Packet):
+ name = 'Scapy6 - Unknown Mobility Option'
+ fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
+ FieldLenField("olen", None, length_of="odata", fmt="B"),
+ StrLenField("odata", "",
+ length_from = lambda pkt: pkt.olen) ]
+ x = 0 ; y = 0 # alignment requirement: none
+
+moboptcls = { 0: Pad1,
+ 1: PadN,
+ 2: MIP6OptBRAdvice,
+ 3: MIP6OptAltCoA,
+ 4: MIP6OptNonceIndices,
+ 5: MIP6OptBindingAuthData,
+ 6: MIP6OptMobNetPrefix,
+ 7: MIP6OptLLAddr,
+ 8: MIP6OptMNID,
+ 9: MIP6OptMsgAuth,
+ 10: MIP6OptReplayProtection,
+ 11: MIP6OptCGAParamsReq,
+ 12: MIP6OptCGAParams,
+ 13: MIP6OptSignature,
+ 14: MIP6OptHomeKeygenToken,
+ 15: MIP6OptCareOfTestInit,
+ 16: MIP6OptCareOfTest }
+
+
+# Main Mobile IPv6 Classes
+
+mhtypes = { 0: 'BRR',
+ 1: 'HoTI',
+ 2: 'CoTI',
+ 3: 'HoT',
+ 4: 'CoT',
+ 5: 'BU',
+ 6: 'BA',
+ 7: 'BE',
+ 8: 'Fast BU',
+ 9: 'Fast BA',
+ 10: 'Fast NA' }
+
+# From http://www.iana.org/assignments/mobility-parameters
+bastatus = { 0: 'Binding Update accepted',
+ 1: 'Accepted but prefix discovery necessary',
+ 128: 'Reason unspecified',
+ 129: 'Administratively prohibited',
+ 130: 'Insufficient resources',
+ 131: 'Home registration not supported',
+ 132: 'Not home subnet',
+ 133: 'Not home agent for this mobile node',
+ 134: 'Duplicate Address Detection failed',
+ 135: 'Sequence number out of window',
+ 136: 'Expired home nonce index',
+ 137: 'Expired care-of nonce index',
+ 138: 'Expired nonces',
+ 139: 'Registration type change disallowed',
+ 140: 'Mobile Router Operation not permitted',
+ 141: 'Invalid Prefix',
+ 142: 'Not Authorized for Prefix',
+ 143: 'Forwarding Setup failed (prefixes missing)',
+ 144: 'MIPV6-ID-MISMATCH',
+ 145: 'MIPV6-MESG-ID-REQD',
+ 146: 'MIPV6-AUTH-FAIL',
+ 147: 'Permanent home keygen token unavailable',
+ 148: 'CGA and signature verification failed',
+ 149: 'Permanent home keygen token exists',
+ 150: 'Non-null home nonce index expected' }
+
+
+class _MobilityHeader(Packet):
+ name = 'Dummy IPv6 Mobility Header'
+ overload_fields = { IPv6: { "nh": 135 }}
+
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+ if self.len is None:
+ l = (len(p)-8)//8
+ p = bytes([p[0]]) + struct.pack("B", l) + p[2:]
+ if self.cksum is None:
+ cksum = in6_chksum(135, self.underlayer, p)
+ else:
+ cksum = self.cksum
+ p = p[:4]+struct.pack("!H", cksum)+p[6:]
+ return p
+
+
+class MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
+ name = "IPv6 Mobility Header - Generic Message"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None),
+ ByteEnumField("mhtype", None, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ StrLenField("msg", b"\x00"*2,
+ length_from = lambda pkt: 8*pkt.len-6) ]
+
+
+
+# TODO: make a generic _OptionsField
+class _MobilityOptionsField(PacketListField):
+ islist = 1
+ holds_packet = 1
+
+ def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
+ self.curpos = curpos
+ PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
+
+ def getfield(self, pkt, s):
+ l = self.length_from(pkt)
+ return s[l:],self.m2i(pkt, s[:l])
+
+ def i2len(self, pkt, i):
+ return len(self.i2m(pkt, i))
+
+ def m2i(self, pkt, x):
+ opt = []
+ while x:
+ #o = ord(x[0]) # Option type
+ o = x[0] # Option type
+ cls = self.cls
+ if o in moboptcls:
+ cls = moboptcls[o]
+ try:
+ op = cls(x)
+ except:
+ op = self.cls(x)
+ opt.append(op)
+ if isinstance(op.payload, conf.raw_layer):
+ x = op.payload.load
+ del(op.payload)
+ else:
+ x = b""
+ return opt
+
+ def i2m(self, pkt, x):
+ autopad = None
+ try:
+ autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
+ except:
+ autopad = 1
+
+ if not autopad:
+ return b"".join(map(str, x))
+
+ curpos = self.curpos
+ s = b""
+ for p in x:
+ d = p.alignment_delta(curpos)
+ curpos += d
+ if d == 1:
+ s += bytes(Pad1())
+ elif d != 0:
+ s += bytes(PadN(optdata=b'\x00'*(d-2)))
+ pstr = bytes(p)
+ curpos += len(pstr)
+ s += pstr
+
+ # Let's make the class including our option field
+ # a multiple of 8 octets long
+ d = curpos % 8
+ if d == 0:
+ return s
+ d = 8 - d
+ if d == 1:
+ s +=bytes(Pad1())
+ elif d != 0:
+ s += bytes(PadN(optdata=b'\x00'*(d-2)))
+
+ return s
+
+ def addfield(self, pkt, s, val):
+ return s+self.i2m(pkt, val)
+
+class MIP6MH_BRR(_MobilityHeader):
+ name = "IPv6 Mobility Header - Binding Refresh Request"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None),
+ ByteEnumField("mhtype", 0, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ ShortField("res2", None),
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
+ length_from = lambda pkt: 8*pkt.len) ]
+ overload_fields = { IPv6: { "nh": 135 } }
+ def hashret(self):
+ # Hack: BRR, BU and BA have the same hashret that returns the same
+ # value "\x00\x08\x09" (concatenation of mhtypes). This is
+ # because we need match BA with BU and BU with BRR. --arno
+ return b"\x00\x08\x09"
+
+class MIP6MH_HoTI(_MobilityHeader):
+ name = "IPv6 Mobility Header - Home Test Init"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None),
+ ByteEnumField("mhtype", 1, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ StrFixedLenField("reserved", "\x00"*2, 2),
+ StrFixedLenField("cookie", "\x00"*8, 8),
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
+ length_from = lambda pkt: 8*(pkt.len-1)) ]
+ overload_fields = { IPv6: { "nh": 135 } }
+ def hashret(self):
+ return self.cookie
+
+class MIP6MH_CoTI(MIP6MH_HoTI):
+ name = "IPv6 Mobility Header - Care-of Test Init"
+ mhtype = 2
+ def hashret(self):
+ return self.cookie
+
+class MIP6MH_HoT(_MobilityHeader):
+ name = "IPv6 Mobility Header - Home Test"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None),
+ ByteEnumField("mhtype", 3, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ ShortField("index", None),
+ StrFixedLenField("cookie", "\x00"*8, 8),
+ StrFixedLenField("token", "\x00"*8, 8),
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
+ length_from = lambda pkt: 8*(pkt.len-2)) ]
+ overload_fields = { IPv6: { "nh": 135 } }
+ def hashret(self):
+ return self.cookie
+ def answers(self):
+ if (isinstance(other, MIP6MH_HoTI) and
+ self.cookie == other.cookie):
+ return 1
+ return 0
+
+class MIP6MH_CoT(MIP6MH_HoT):
+ name = "IPv6 Mobility Header - Care-of Test"
+ mhtype = 4
+ def hashret(self):
+ return self.cookie
+
+ def answers(self):
+ if (isinstance(other, MIP6MH_CoTI) and
+ self.cookie == other.cookie):
+ return 1
+ return 0
+
+class LifetimeField(ShortField):
+ def i2repr(self, pkt, x):
+ return "%d sec" % (4*x)
+
+class MIP6MH_BU(_MobilityHeader):
+ name = "IPv6 Mobility Header - Binding Update"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
+ ByteEnumField("mhtype", 5, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ XShortField("seq", None), # TODO: ShortNonceField
+ FlagsField("flags", "KHA", 7, "PRMKLHA"),
+ XBitField("reserved", 0, 9),
+ LifetimeField("mhtime", 3), # unit == 4 seconds
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
+ length_from = lambda pkt: 8*pkt.len - 4) ]
+ overload_fields = { IPv6: { "nh": 135 } }
+
+ def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
+ return "\x00\x08\x09"
+
+ def answers(self, other):
+ if isinstance(other, MIP6MH_BRR):
+ return 1
+ return 0
+
+class MIP6MH_BA(_MobilityHeader):
+ name = "IPv6 Mobility Header - Binding ACK"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
+ ByteEnumField("mhtype", 6, mhtypes),
+ ByteField("res", None),
+ XShortField("cksum", None),
+ ByteEnumField("status", 0, bastatus),
+ FlagsField("flags", "K", 3, "PRK"),
+ XBitField("res2", None, 5),
+ XShortField("seq", None), # TODO: ShortNonceField
+ XShortField("mhtime", 0), # unit == 4 seconds
+ _PhantomAutoPadField("autopad", 1), # autopad activated by default
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
+ length_from = lambda pkt: 8*pkt.len-4) ]
+ overload_fields = { IPv6: { "nh": 135 }}
+
+ def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
+ return "\x00\x08\x09"
+
+ def answers(self, other):
+ if (isinstance(other, MIP6MH_BU) and
+ other.mhtype == 5 and
+ self.mhtype == 6 and
+ other.flags & 0x1 and # Ack request flags is set
+ self.seq == other.seq):
+ return 1
+ return 0
+
+_bestatus = { 1: 'Unknown binding for Home Address destination option',
+ 2: 'Unrecognized MH Type value' }
+
+# TODO: match Binding Error to its stimulus
+class MIP6MH_BE(_MobilityHeader):
+ name = "IPv6 Mobility Header - Binding Error"
+ fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
+ ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
+ ByteEnumField("mhtype", 7, mhtypes),
+ ByteField("res", 0),
+ XShortField("cksum", None),
+ ByteEnumField("status", 0, _bestatus),
+ ByteField("reserved", 0),
+ IP6Field("ha", "::"),
+ _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
+ length_from = lambda pkt: 8*(pkt.len-2)) ]
+ overload_fields = { IPv6: { "nh": 135 }}
+
+_mip6_mhtype2cls = { 0: MIP6MH_BRR,
+ 1: MIP6MH_HoTI,
+ 2: MIP6MH_CoTI,
+ 3: MIP6MH_HoT,
+ 4: MIP6MH_CoT,
+ 5: MIP6MH_BU,
+ 6: MIP6MH_BA,
+ 7: MIP6MH_BE }
+
+
+#############################################################################
+#############################################################################
+### Traceroute6 ###
+#############################################################################
+#############################################################################
+
+class AS_resolver6(AS_resolver_riswhois):
+ def _resolve_one(self, ip):
+ """
+ overloaded version to provide a Whois resolution on the
+ embedded IPv4 address if the address is 6to4 or Teredo.
+ Otherwise, the native IPv6 address is passed.
+ """
+
+ if in6_isaddr6to4(ip): # for 6to4, use embedded @
+ tmp = inet_pton(socket.AF_INET6, ip)
+ addr = inet_ntop(socket.AF_INET, tmp[2:6])
+ elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
+ addr = teredoAddrExtractInfo(ip)[2]
+ else:
+ addr = ip
+
+ _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
+
+ return ip,asn,desc
+
+class TracerouteResult6(TracerouteResult):
+ def show(self):
+ #return self.make_table(lambda (s,r): (s.sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 !
+ return self.make_table(lambda s,r: (s.sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 !
+ s.hlim,
+ r.sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
+ "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
+ "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
+ "{ICMPv6EchoReply:%ir,type%}")))
+
+ def get_trace(self):
+ trace = {}
+
+ for s,r in self.res:
+ if IPv6 not in s:
+ continue
+ d = s[IPv6].dst
+ if d not in trace:
+ trace[d] = {}
+
+ t = not (ICMPv6TimeExceeded in r or
+ ICMPv6DestUnreach in r or
+ ICMPv6PacketTooBig in r or
+ ICMPv6ParamProblem in r)
+
+ trace[d][s[IPv6].hlim] = r[IPv6].src, t
+
+ for k in trace.values():
+ #m = filter(lambda x: k[x][1], k.keys())
+ m = [ x for x in k.keys() if k[x][1] ]
+ if not m:
+ continue
+ m = min(m)
+ for l in k.keys():
+ if l > m:
+ del(k[l])
+
+ return trace
+
+ def graph(self, ASres=AS_resolver6(), **kargs):
+ TracerouteResult.graph(self, ASres=ASres, **kargs)
+
+def traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
+ l4 = None, timeout=2, verbose=None, **kargs):
+ """
+ Instant TCP traceroute using IPv6 :
+ traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
+ """
+ if verbose is None:
+ verbose = conf.verb
+
+ if l4 is None:
+ a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
+ timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
+ else:
+ a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
+ timeout=timeout, verbose=verbose, **kargs)
+
+ a = TracerouteResult6(a.res)
+
+ if verbose:
+ a.display()
+
+ return a,b
+
+#############################################################################
+#############################################################################
+### Sockets ###
+#############################################################################
+#############################################################################
+
+class L3RawSocket6(L3RawSocket):
+ def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
+ L3RawSocket.__init__(self, type, filter, iface, promisc)
+ # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
+ self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
+ self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+
+def IPv6inIP(dst='203.178.135.36', src=None):
+ _IPv6inIP.dst = dst
+ _IPv6inIP.src = src
+ if not conf.L3socket == _IPv6inIP:
+ _IPv6inIP.cls = conf.L3socket
+ else:
+ del(conf.L3socket)
+ return _IPv6inIP
+
+class _IPv6inIP(SuperSocket):
+ dst = '127.0.0.1'
+ src = None
+ cls = None
+
+ def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
+ SuperSocket.__init__(self, family, type, proto)
+ self.worker = self.cls(**args)
+
+ def set(self, dst, src=None):
+ _IPv6inIP.src = src
+ _IPv6inIP.dst = dst
+
+ def nonblock_recv(self):
+ p = self.worker.nonblock_recv()
+ return self._recv(p)
+
+ def recv(self, x):
+ p = self.worker.recv(x)
+ return self._recv(p, x)
+
+ def _recv(self, p, x=MTU):
+ if p is None:
+ return p
+ elif isinstance(p, IP):
+ # TODO: verify checksum
+ if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
+ if isinstance(p.payload, IPv6):
+ return p.payload
+ return p
+
+ def send(self, x):
+ return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
+
+
+#############################################################################
+#############################################################################
+### Layers binding ###
+#############################################################################
+#############################################################################
+
+conf.l3types.register(ETH_P_IPV6, IPv6)
+conf.l2types.register(31, IPv6)
+
+bind_layers(Ether, IPv6, type = 0x86dd )
+bind_layers(CookedLinux, IPv6, proto = 0x86dd )
+bind_layers(IPerror6, TCPerror, nh = socket.IPPROTO_TCP )
+bind_layers(IPerror6, UDPerror, nh = socket.IPPROTO_UDP )
+bind_layers(IPv6, TCP, nh = socket.IPPROTO_TCP )
+bind_layers(IPv6, UDP, nh = socket.IPPROTO_UDP )
+bind_layers(IP, IPv6, proto = socket.IPPROTO_IPV6 )
+bind_layers(IPv6, IPv6, nh = socket.IPPROTO_IPV6 )
+
+bind_layers(IPv6, IP, nh = IPPROTO_IPIP )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/ipsec.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ipsec.py
new file mode 100644
index 00000000..a14925fb
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ipsec.py
@@ -0,0 +1,995 @@
+#############################################################################
+## ipsec.py --- IPSec support for Scapy ##
+## ##
+## Copyright (C) 2014 6WIND ##
+## ##
+## This program is free software; you can redistribute it and/or modify it ##
+## under the terms of the GNU General Public License version 2 as ##
+## published by the Free Software Foundation. ##
+## ##
+## This program is distributed in the hope that it will be useful, but ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of ##
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
+## General Public License for more details. ##
+#############################################################################
+"""
+IPSec layer
+===========
+
+Example of use:
+
+>>> sa = SecurityAssociation(ESP, spi=0xdeadbeef, crypt_algo='AES-CBC',
+... crypt_key='sixteenbytes key')
+>>> p = IP(src='1.1.1.1', dst='2.2.2.2')
+>>> p /= TCP(sport=45012, dport=80)
+>>> p /= Raw(b'testdata')
+>>> p = IP(bytes(p))
+>>> p
+<IP version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 options=[] |<TCP sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw load='testdata' |>>>
+>>>
+>>> e = sa.encrypt(p)
+>>> e
+<IP version=4L ihl=5L tos=0x0 len=76 id=1 flags= frag=0L ttl=64 proto=esp chksum=0x747a src=1.1.1.1 dst=2.2.2.2 |<ESP spi=0xdeadbeef seq=1 data='\xf8\xdb\x1e\x83[T\xab\\\xd2\x1b\xed\xd1\xe5\xc8Y\xc2\xa5d\x92\xc1\x05\x17\xa6\x92\x831\xe6\xc1]\x9a\xd6K}W\x8bFfd\xa5B*+\xde\xc8\x89\xbf{\xa9' |>>
+>>>
+>>> d = sa.decrypt(e)
+>>> d
+<IP version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 |<TCP sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw load='testdata' |>>>
+>>>
+>>> d == p
+True
+"""
+
+import socket
+
+if not hasattr(socket, 'IPPROTO_AH'):
+ socket.IPPROTO_AH = 51
+if not hasattr(socket, 'IPPROTO_ESP'):
+ socket.IPPROTO_ESP = 50
+
+
+import fractions
+
+from scapy.data import IP_PROTOS
+
+from scapy.fields import ByteEnumField, ByteField, StrField, XIntField, IntField, \
+ ShortField, PacketField
+
+from scapy.packet import Packet, bind_layers, Raw
+
+from scapy.layers.inet import IP, UDP
+from scapy.layers.inet6 import IPv6, IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, \
+ IPv6ExtHdrRouting
+
+
+#------------------------------------------------------------------------------
+class AH(Packet):
+ """
+ Authentication Header
+
+ See https://tools.ietf.org/rfc/rfc4302.txt
+ """
+
+ name = 'AH'
+
+ fields_desc = [
+ ByteEnumField('nh', None, IP_PROTOS),
+ ByteField('payloadlen', None),
+ ShortField('reserved', None),
+ XIntField('spi', 0x0),
+ IntField('seq', 0),
+ StrField('icv', None),
+ StrField('padding', None),
+ ]
+
+ overload_fields = {
+ IP: {'proto': socket.IPPROTO_AH},
+ IPv6: {'nh': socket.IPPROTO_AH},
+ IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_AH},
+ IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_AH},
+ IPv6ExtHdrRouting: {'nh': socket.IPPROTO_AH},
+ }
+
+bind_layers(IP, AH, proto=socket.IPPROTO_AH)
+bind_layers(IPv6, AH, nh=socket.IPPROTO_AH)
+
+#------------------------------------------------------------------------------
+class ESP(Packet):
+ """
+ Encapsulated Security Payload
+
+ See https://tools.ietf.org/rfc/rfc4303.txt
+ """
+ name = 'ESP'
+
+ fields_desc = [
+ XIntField('spi', 0x0),
+ IntField('seq', 0),
+ StrField('data', None),
+ ]
+
+ overload_fields = {
+ IP: {'proto': socket.IPPROTO_ESP},
+ IPv6: {'nh': socket.IPPROTO_ESP},
+ IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_ESP},
+ IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_ESP},
+ IPv6ExtHdrRouting: {'nh': socket.IPPROTO_ESP},
+ }
+
+bind_layers(IP, ESP, proto=socket.IPPROTO_ESP)
+bind_layers(IPv6, ESP, nh=socket.IPPROTO_ESP)
+bind_layers(UDP, ESP, dport=4500) # NAT-Traversal encapsulation
+bind_layers(UDP, ESP, sport=4500) # NAT-Traversal encapsulation
+
+#------------------------------------------------------------------------------
+class _ESPPlain(Packet):
+ """
+ Internal class to represent unencrypted ESP packets.
+ """
+ name = 'ESP'
+
+ fields_desc = [
+ XIntField('spi', 0x0),
+ IntField('seq', 0),
+
+ StrField('iv', ''),
+ PacketField('data', '', Raw),
+ StrField('padding', ''),
+
+ ByteField('padlen', 0),
+ ByteEnumField('nh', 0, IP_PROTOS),
+ StrField('icv', ''),
+ ]
+
+ def data_for_encryption(self):
+ return bytes(self.data) + self.padding + chr(self.padlen).encode('ascii') + chr(self.nh).encode('ascii')
+
+#------------------------------------------------------------------------------
+try:
+ from Crypto.Cipher import AES
+ from Crypto.Cipher import DES
+ from Crypto.Cipher import DES3
+ from Crypto.Cipher import CAST
+ from Crypto.Cipher import Blowfish
+ from Crypto.Util import Counter
+ from Crypto import Random
+except ImportError:
+ # no error if pycrypto is not available but encryption won't be supported
+ AES = None
+ DES = None
+ DES3 = None
+ CAST = None
+ Blowfish = None
+ Random = None
+
+#------------------------------------------------------------------------------
+def _lcm(a, b):
+ """
+ Least Common Multiple between 2 integers.
+ """
+ if a == 0 or b == 0:
+ return 0
+ else:
+ return abs(a * b) // fractions.gcd(a, b)
+
+class CryptAlgo(object):
+ """
+ IPSec encryption algorithm
+ """
+
+ def __init__(self, name, cipher, mode, block_size=None, iv_size=None, key_size=None):
+ """
+ @param name: the name of this encryption algorithm
+ @param cipher: a Cipher module
+ @param mode: the mode used with the cipher module
+ @param block_size: the length a block for this algo. Defaults to the
+ `block_size` of the cipher.
+ @param iv_size: the length of the initialization vector of this algo.
+ Defaults to the `block_size` of the cipher.
+ @param key_size: an integer or list/tuple of integers. If specified,
+ force the secret keys length to one of the values.
+ Defaults to the `key_size` of the cipher.
+ """
+ self.name = name
+ self.cipher = cipher
+ self.mode = mode
+
+ if block_size is not None:
+ self.block_size = block_size
+ elif cipher is not None:
+ self.block_size = cipher.block_size
+ else:
+ self.block_size = 1
+
+ if iv_size is None:
+ self.iv_size = self.block_size
+ else:
+ self.iv_size = iv_size
+
+ if key_size is not None:
+ self.key_size = key_size
+ elif cipher is not None:
+ self.key_size = cipher.key_size
+ else:
+ self.key_size = None
+
+ def check_key(self, key):
+ """
+ Check that the key length is valid.
+
+ @param key: a byte string
+ """
+ if self.key_size and not (len(key) == self.key_size or len(key) in self.key_size):
+ raise TypeError('invalid key size %s, must be %s' %
+ (len(key), self.key_size))
+
+ def generate_iv(self):
+ """
+ Generate a random initialization vector. If pycrypto is not available,
+ return a buffer of the correct length filled with only '\x00'.
+ """
+ if Random:
+ return Random.get_random_bytes(self.iv_size)
+ else:
+ return chr(0) * self.iv_size
+
+ def new_cipher(self, key, iv):
+ """
+ @param key: the secret key, a byte string
+ @param iv: the initialization vector, a byte string
+ @return: an initialized cipher object for this algo
+ """
+ if type(key) is str:
+ key = key.encode('ascii')
+ if (hasattr(self.cipher, 'MODE_CTR') and self.mode == self.cipher.MODE_CTR
+ or hasattr(self.cipher, 'MODE_GCM') and self.mode == self.cipher.MODE_GCM):
+ # in counter mode, the "iv" must be incremented for each block
+ # it is calculated like this:
+ # +---------+------------------+---------+
+ # | nonce | IV | counter |
+ # +---------+------------------+---------+
+ # m bytes n bytes 4 bytes
+ # <-------------------------------------->
+ # block_size
+ nonce_size = self.cipher.block_size - self.iv_size - 4
+
+ # instead of asking for an extra parameter, we extract the last
+ # nonce_size bytes of the key and use them as the nonce.
+ # +----------------------------+---------+
+ # | cipher key | nonce |
+ # +----------------------------+---------+
+ # <--------->
+ # nonce_size
+ cipher_key, nonce = key[:-nonce_size], key[-nonce_size:]
+
+ return self.cipher.new(cipher_key, self.mode,
+ counter=Counter.new(4 * 8, prefix=nonce + iv))
+ else:
+ return self.cipher.new(key, self.mode, iv)
+
+ def pad(self, esp):
+ """
+ Add the correct amount of padding so that the data to encrypt is
+ exactly a multiple of the algorithm's block size.
+
+ Also, make sure that the total ESP packet length is a multiple of 4 or
+ 8 bytes with IP or IPv6 respectively.
+
+ @param esp: an unencrypted _ESPPlain packet
+ """
+ # 2 extra bytes for padlen and nh
+ data_len = len(esp.data) + 2
+
+ # according to the RFC4303, section 2.4. Padding (for Encryption)
+ # the size of the ESP payload must be a multiple of 32 bits
+ align = _lcm(self.block_size, 4)
+
+ # pad for block size
+ esp.padlen = -data_len % align
+
+ # padding must be an array of bytes starting from 1 to padlen
+ esp.padding = ''
+ for b in range(1, esp.padlen + 1):
+ esp.padding += bytes([b])
+
+ # If the following test fails, it means that this algo does not comply
+ # with the RFC
+ payload_len = len(esp.iv) + len(esp.data) + len(esp.padding) + 2
+ if payload_len % 4 != 0:
+ raise ValueError('The size of the ESP data is not aligned to 32 bits after padding.')
+
+ return esp
+
+ def encrypt(self, esp, key):
+ """
+ Encrypt an ESP packet
+
+ @param esp: an unencrypted _ESPPlain packet with valid padding
+ @param key: the secret key used for encryption
+
+ @return: a valid ESP packet encrypted with this algorithm
+ """
+ data = esp.data_for_encryption()
+
+ if self.cipher:
+ self.check_key(key)
+ cipher = self.new_cipher(key, esp.iv)
+ data = cipher.encrypt(data)
+
+ return ESP(spi=esp.spi, seq=esp.seq, data=esp.iv + data)
+
+ def decrypt(self, esp, key, icv_size=0):
+ """
+ Decrypt an ESP packet
+
+ @param esp: an encrypted ESP packet
+ @param key: the secret key used for encryption
+ @param icv_size: the length of the icv used for integrity check
+
+ @return: a valid ESP packet encrypted with this algorithm
+ """
+ self.check_key(key)
+
+ iv = esp.data[:self.iv_size]
+ data = esp.data[self.iv_size:len(esp.data) - icv_size]
+ icv = esp.data[len(esp.data) - icv_size:]
+
+ if self.cipher:
+ cipher = self.new_cipher(key, iv)
+ data = cipher.decrypt(data)
+
+ # extract padlen and nh
+ #padlen = ord(data[-2])
+ padlen = (data[-2])
+ #nh = ord(data[-1])
+ nh = (data[-1])
+
+ # then use padlen to determine data and padding
+ data = data[:len(data) - padlen - 2]
+ padding = data[len(data) - padlen - 2: len(data) - 2]
+
+ return _ESPPlain(spi=esp.spi,
+ seq=esp.seq,
+ iv=iv,
+ data=data,
+ padding=padding,
+ padlen=padlen,
+ nh=nh,
+ icv=icv)
+
+#------------------------------------------------------------------------------
+# The names of the encryption algorithms are the same than in scapy.contrib.ikev2
+# see http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml
+
+CRYPT_ALGOS = {
+ 'NULL': CryptAlgo('NULL', cipher=None, mode=None, iv_size=0),
+}
+
+if AES:
+ CRYPT_ALGOS['AES-CBC'] = CryptAlgo('AES-CBC',
+ cipher=AES,
+ mode=AES.MODE_CBC)
+ # specific case for counter mode:
+ # the last 4 bytes of the key are used to carry the nonce of the counter
+ CRYPT_ALGOS['AES-CTR'] = CryptAlgo('AES-CTR',
+ cipher=AES,
+ mode=AES.MODE_CTR,
+ block_size=1,
+ iv_size=8,
+ key_size=(16 + 4, 24 + 4, 32 + 4))
+if DES:
+ CRYPT_ALGOS['DES'] = CryptAlgo('DES',
+ cipher=DES,
+ mode=DES.MODE_CBC)
+if Blowfish:
+ CRYPT_ALGOS['Blowfish'] = CryptAlgo('Blowfish',
+ cipher=Blowfish,
+ mode=Blowfish.MODE_CBC)
+if DES3:
+ CRYPT_ALGOS['3DES'] = CryptAlgo('3DES',
+ cipher=DES3,
+ mode=DES3.MODE_CBC)
+if CAST:
+ CRYPT_ALGOS['CAST'] = CryptAlgo('CAST',
+ cipher=CAST,
+ mode=CAST.MODE_CBC)
+
+#------------------------------------------------------------------------------
+try:
+ from Crypto.Hash import HMAC
+ from Crypto.Hash import SHA
+ from Crypto.Hash import MD5
+ from Crypto.Hash import SHA256
+ from Crypto.Hash import SHA384
+ from Crypto.Hash import SHA512
+except ImportError:
+ # no error if pycrypto is not available but authentication won't be supported
+ HMAC = None
+ SHA = None
+ MD5 = None
+ SHA256 = None
+ SHA384 = None
+try:
+ from Crypto.Hash import XCBCMAC
+except ImportError:
+ XCBCMAC = None
+
+#------------------------------------------------------------------------------
+class IPSecIntegrityError(Exception):
+ """
+ Error risen when the integrity check fails.
+ """
+ pass
+
+class AuthAlgo(object):
+ """
+ IPSec integrity algorithm
+ """
+
+ def __init__(self, name, mac, digestmod, icv_size, key_size=None):
+ """
+ @param name: the name of this integrity algorithm
+ @param mac: a Message Authentication Code module
+ @param digestmod: a Hash or Cipher module
+ @param icv_size: the length of the integrity check value of this algo
+ @param key_size: an integer or list/tuple of integers. If specified,
+ force the secret keys length to one of the values.
+ Defaults to the `key_size` of the cipher.
+ """
+ self.name = name
+ self.mac = mac
+ self.digestmod = digestmod
+ self.icv_size = icv_size
+ self.key_size = key_size
+
+ def check_key(self, key):
+ """
+ Check that the key length is valid.
+
+ @param key: a byte string
+ """
+ if self.key_size and len(key) not in self.key_size:
+ raise TypeError('invalid key size %s, must be one of %s' %
+ (len(key), self.key_size))
+
+ def new_mac(self, key):
+ """
+ @param key: a byte string
+ @return: an initialized mac object for this algo
+ """
+ if type(key) is str:
+ key = key.encode('ascii')
+ if self.mac is XCBCMAC:
+ # specific case here, ciphermod instead of digestmod
+ return self.mac.new(key, ciphermod=self.digestmod)
+ else:
+ print(self.mac)
+ return self.mac.new(key, digestmod=self.digestmod)
+
+ def sign(self, pkt, key):
+ """
+ Sign an IPSec (ESP or AH) packet with this algo.
+
+ @param pkt: a packet that contains a valid encrypted ESP or AH layer
+ @param key: the authentication key, a byte string
+
+ @return: the signed packet
+ """
+ if not self.mac:
+ return pkt
+
+ self.check_key(key)
+
+ mac = self.new_mac(key)
+
+ if pkt.haslayer(ESP):
+ mac.update(bytes(pkt[ESP]))
+ pkt[ESP].data += mac.digest()[:self.icv_size]
+
+ elif pkt.haslayer(AH):
+ clone = zero_mutable_fields(pkt.copy(), sending=True)
+ mac.update(bytes(clone))
+ pkt[AH].icv = mac.digest()[:self.icv_size]
+
+ return pkt
+
+ def verify(self, pkt, key):
+ """
+ Check that the integrity check value (icv) of a packet is valid.
+
+ @param pkt: a packet that contains a valid encrypted ESP or AH layer
+ @param key: the authentication key, a byte string
+
+ @raise IPSecIntegrityError: if the integrity check fails
+ """
+ if not self.mac or self.icv_size == 0:
+ return
+
+ self.check_key(key)
+
+ mac = self.new_mac(key)
+
+ pkt_icv = 'not found'
+ computed_icv = 'not computed'
+
+ if isinstance(pkt, ESP):
+ pkt_icv = pkt.data[len(pkt.data) - self.icv_size:]
+
+ pkt = pkt.copy()
+ pkt.data = pkt.data[:len(pkt.data) - self.icv_size]
+ mac.update(bytes(pkt))
+ computed_icv = mac.digest()[:self.icv_size]
+
+ elif pkt.haslayer(AH):
+ pkt_icv = pkt[AH].icv[:self.icv_size]
+
+ clone = zero_mutable_fields(pkt.copy(), sending=False)
+ mac.update(bytes(clone))
+ computed_icv = mac.digest()[:self.icv_size]
+
+ if pkt_icv != computed_icv:
+ raise IPSecIntegrityError('pkt_icv=%r, computed_icv=%r' %
+ (pkt_icv, computed_icv))
+
+#------------------------------------------------------------------------------
+# The names of the integrity algorithms are the same than in scapy.contrib.ikev2
+# see http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml
+
+AUTH_ALGOS = {
+ 'NULL': AuthAlgo('NULL', mac=None, digestmod=None, icv_size=0),
+}
+
+if HMAC:
+ if SHA:
+ AUTH_ALGOS['HMAC-SHA1-96'] = AuthAlgo('HMAC-SHA1-96',
+ mac=HMAC,
+ digestmod=SHA,
+ icv_size=12)
+ if SHA256:
+ AUTH_ALGOS['SHA2-256-128'] = AuthAlgo('SHA2-256-128',
+ mac=HMAC,
+ digestmod=SHA256,
+ icv_size=16)
+ if SHA384:
+ AUTH_ALGOS['SHA2-384-192'] = AuthAlgo('SHA2-384-192',
+ mac=HMAC,
+ digestmod=SHA384,
+ icv_size=24)
+ if SHA512:
+ AUTH_ALGOS['SHA2-512-256'] = AuthAlgo('SHA2-512-256',
+ mac=HMAC,
+ digestmod=SHA512,
+ icv_size=32)
+ if MD5:
+ AUTH_ALGOS['HMAC-MD5-96'] = AuthAlgo('HMAC-MD5-96',
+ mac=HMAC,
+ digestmod=MD5,
+ icv_size=12)
+if AES and XCBCMAC:
+ AUTH_ALGOS['AES-XCBC-96'] = AuthAlgo('AES-XCBC-96',
+ mac=XCBCMAC,
+ digestmod=AES,
+ icv_size=12,
+ key_size=(16,))
+
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+def split_for_transport(orig_pkt, transport_proto):
+ """
+ Split an IP(v6) packet in the correct location to insert an ESP or AH
+ header.
+
+ @param orig_pkt: the packet to split. Must be an IP or IPv6 packet
+ @param transport_proto: the IPSec protocol number that will be inserted
+ at the split position.
+ @return: a tuple (header, nh, payload) where nh is the protocol number of
+ payload.
+ """
+ header = orig_pkt.copy()
+ next_hdr = header.payload
+ nh = None
+
+ if header.version == 4:
+ nh = header.proto
+ header.proto = transport_proto
+ header.remove_payload()
+ del header.chksum
+ del header.len
+
+ return header, nh, next_hdr
+ else:
+ found_rt_hdr = False
+ prev = header
+
+ # Since the RFC 4302 is vague about where the ESP/AH headers should be
+ # inserted in IPv6, I chose to follow the linux implementation.
+ while isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)):
+ if isinstance(next_hdr, IPv6ExtHdrHopByHop):
+ pass
+ if isinstance(next_hdr, IPv6ExtHdrRouting):
+ found_rt_hdr = True
+ elif isinstance(next_hdr, IPv6ExtHdrDestOpt) and found_rt_hdr:
+ break
+
+ prev = next_hdr
+ next_hdr = next_hdr.payload
+
+ nh = prev.nh
+ prev.nh = transport_proto
+ prev.remove_payload()
+ del header.plen
+
+ return header, nh, next_hdr
+
+#------------------------------------------------------------------------------
+# see RFC 4302 - Appendix A. Mutability of IP Options/Extension Headers
+IMMUTABLE_IPV4_OPTIONS = (
+ 0, # End Of List
+ 1, # No OPeration
+ 2, # Security
+ 5, # Extended Security
+ 6, # Commercial Security
+ 20, # Router Alert
+ 21, # Sender Directed Multi-Destination Delivery
+)
+def zero_mutable_fields(pkt, sending=False):
+ """
+ When using AH, all "mutable" fields must be "zeroed" before calculating
+ the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields.
+
+ @param pkt: an IP(v6) packet containing an AH layer.
+ NOTE: The packet will be modified
+ @param sending: if true, ipv6 routing headers will not be reordered
+ """
+
+ if pkt.haslayer(AH):
+ pkt[AH].icv = chr(0) * len(pkt[AH].icv)
+ else:
+ raise TypeError('no AH layer found')
+
+ if pkt.version == 4:
+ # the tos field has been replaced by DSCP and ECN
+ # Routers may rewrite the DS field as needed to provide a
+ # desired local or end-to-end service
+ pkt.tos = 0
+ # an intermediate router might set the DF bit, even if the source
+ # did not select it.
+ pkt.flags = 0
+ # changed en route as a normal course of processing by routers
+ pkt.ttl = 0
+ # will change if any of these other fields change
+ pkt.chksum = 0
+
+ immutable_opts = []
+ for opt in pkt.options:
+ if opt.option in IMMUTABLE_IPV4_OPTIONS:
+ immutable_opts.append(opt)
+ else:
+ immutable_opts.append(Raw(chr(0) * len(opt)))
+ pkt.options = immutable_opts
+
+ else:
+ # holds DSCP and ECN
+ pkt.tc = 0
+ # The flow label described in AHv1 was mutable, and in RFC 2460 [DH98]
+ # was potentially mutable. To retain compatibility with existing AH
+ # implementations, the flow label is not included in the ICV in AHv2.
+ pkt.fl = 0
+ # same as ttl
+ pkt.hlim = 0
+
+ next_hdr = pkt.payload
+
+ while isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)):
+ if isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt)):
+ for opt in next_hdr.options:
+ if opt.otype & 0x20:
+ # option data can change en-route and must be zeroed
+ opt.optdata = chr(0) * opt.optlen
+ elif isinstance(next_hdr, IPv6ExtHdrRouting) and sending:
+ # The sender must order the field so that it appears as it
+ # will at the receiver, prior to performing the ICV computation.
+ next_hdr.segleft = 0
+ if next_hdr.addresses:
+ final = next_hdr.addresses.pop()
+ next_hdr.addresses.insert(0, pkt.dst)
+ pkt.dst = final
+ else:
+ break
+
+ next_hdr = next_hdr.payload
+
+ return pkt
+
+#------------------------------------------------------------------------------
+class SecurityAssociation(object):
+ """
+ This class is responsible of "encryption" and "decryption" of IPSec packets.
+ """
+
+ SUPPORTED_PROTOS = (IP, IPv6)
+
+ def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None,
+ auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None):
+ """
+ @param proto: the IPSec proto to use (ESP or AH)
+ @param spi: the Security Parameters Index of this SA
+ @param seq_num: the initial value for the sequence number on encrypted
+ packets
+ @param crypt_algo: the encryption algorithm name (only used with ESP)
+ @param crypt_key: the encryption key (only used with ESP)
+ @param auth_algo: the integrity algorithm name
+ @param auth_key: the integrity key
+ @param tunnel_header: an instance of a IP(v6) header that will be used
+ to encapsulate the encrypted packets.
+ @param nat_t_header: an instance of a UDP header that will be used
+ for NAT-Traversal.
+ """
+
+ if proto not in (ESP, AH, ESP.name, AH.name):
+ raise ValueError("proto must be either ESP or AH")
+ if isinstance(proto, str):
+ self.proto = eval(proto)
+ else:
+ self.proto = proto
+
+ self.spi = spi
+ self.seq_num = seq_num
+
+ if crypt_algo:
+ if crypt_algo not in CRYPT_ALGOS:
+ raise TypeError('unsupported encryption algo %r, try %r' %
+ (crypt_algo, CRYPT_ALGOS.keys()))
+ self.crypt_algo = CRYPT_ALGOS[crypt_algo]
+ self.crypt_algo.check_key(crypt_key)
+ self.crypt_key = crypt_key
+ else:
+ self.crypt_algo = CRYPT_ALGOS['NULL']
+ self.crypt_key = None
+
+ if auth_algo:
+ if auth_algo not in AUTH_ALGOS:
+ raise TypeError('unsupported integrity algo %r, try %r' %
+ (auth_algo, AUTH_ALGOS.keys()))
+ self.auth_algo = AUTH_ALGOS[auth_algo]
+ self.auth_algo.check_key(auth_key)
+ self.auth_key = auth_key
+ else:
+ self.auth_algo = AUTH_ALGOS['NULL']
+ self.auth_key = None
+
+ if tunnel_header and not isinstance(tunnel_header, (IP, IPv6)):
+ raise TypeError('tunnel_header must be %s or %s' % (IP.name, IPv6.name))
+ self.tunnel_header = tunnel_header
+
+ if nat_t_header:
+ if proto is not ESP:
+ raise TypeError('nat_t_header is only allowed with ESP')
+ if not isinstance(nat_t_header, UDP):
+ raise TypeError('nat_t_header must be %s' % UDP.name)
+ self.nat_t_header = nat_t_header
+
+ def check_spi(self, pkt):
+ if pkt.spi != self.spi:
+ raise TypeError('packet spi=0x%x does not match the SA spi=0x%x' %
+ (pkt.spi, self.spi))
+
+ def _encrypt_esp(self, pkt, seq_num=None, iv=None):
+
+ if iv is None:
+ iv = self.crypt_algo.generate_iv()
+ else:
+ if len(iv) != self.crypt_algo.iv_size:
+ raise TypeError('iv length must be %s' % self.crypt_algo.iv_size)
+
+ esp = _ESPPlain(spi=self.spi, seq=seq_num or self.seq_num, iv=iv)
+
+ if self.tunnel_header:
+ tunnel = self.tunnel_header.copy()
+
+ if tunnel.version == 4:
+ del tunnel.proto
+ del tunnel.len
+ del tunnel.chksum
+ else:
+ del tunnel.nh
+ del tunnel.plen
+
+ pkt = tunnel.__class__(bytes(tunnel / pkt))
+
+ ip_header, nh, payload = split_for_transport(pkt, socket.IPPROTO_ESP)
+ esp.data = payload
+ esp.nh = nh
+
+ esp = self.crypt_algo.pad(esp)
+ esp = self.crypt_algo.encrypt(esp, self.crypt_key)
+
+ self.auth_algo.sign(esp, self.auth_key)
+
+ if self.nat_t_header:
+ nat_t_header = self.nat_t_header.copy()
+ nat_t_header.chksum = 0
+ del nat_t_header.len
+ if ip_header.version == 4:
+ del ip_header.proto
+ else:
+ del ip_header.nh
+ ip_header /= nat_t_header
+
+ if ip_header.version == 4:
+ ip_header.len = len(ip_header) + len(esp)
+ del ip_header.chksum
+ ip_header = ip_header.__class__(bytes(ip_header))
+ else:
+ ip_header.plen = len(ip_header.payload) + len(esp)
+
+ # sequence number must always change, unless specified by the user
+ if seq_num is None:
+ self.seq_num += 1
+
+ return ip_header / esp
+
+ def _encrypt_ah(self, pkt, seq_num=None):
+
+ ah = AH(spi=self.spi, seq=seq_num or self.seq_num,
+ icv=chr(0) * self.auth_algo.icv_size)
+
+ if self.tunnel_header:
+ tunnel = self.tunnel_header.copy()
+
+ if tunnel.version == 4:
+ del tunnel.proto
+ del tunnel.len
+ del tunnel.chksum
+ else:
+ del tunnel.nh
+ del tunnel.plen
+
+ pkt = tunnel.__class__(bytes(tunnel / pkt))
+
+ ip_header, nh, payload = split_for_transport(pkt, socket.IPPROTO_AH)
+ ah.nh = nh
+
+ if ip_header.version == 6 and len(ah) % 8 != 0:
+ # For IPv6, the total length of the header must be a multiple of
+ # 8-octet units.
+ ah.padding = chr(0) * (-len(ah) % 8)
+ elif len(ah) % 4 != 0:
+ # For IPv4, the total length of the header must be a multiple of
+ # 4-octet units.
+ ah.padding = chr(0) * (-len(ah) % 4)
+
+ # RFC 4302 - Section 2.2. Payload Length
+ # This 8-bit field specifies the length of AH in 32-bit words (4-byte
+ # units), minus "2".
+ ah.payloadlen = len(ah) // 4 - 2
+
+ if ip_header.version == 4:
+ ip_header.len = len(ip_header) + len(ah) + len(payload)
+ del ip_header.chksum
+ ip_header = ip_header.__class__(bytes(ip_header))
+ else:
+ ip_header.plen = len(ip_header.payload) + len(ah) + len(payload)
+
+ signed_pkt = self.auth_algo.sign(ip_header / ah / payload, self.auth_key)
+
+ # sequence number must always change, unless specified by the user
+ if seq_num is None:
+ self.seq_num += 1
+
+ return signed_pkt
+
+ def encrypt(self, pkt, seq_num=None, iv=None):
+ """
+ Encrypt (and encapsulate) an IP(v6) packet with ESP or AH according
+ to this SecurityAssociation.
+
+ @param pkt: the packet to encrypt
+ @param seq_num: if specified, use this sequence number instead of the
+ generated one
+ @param iv: if specified, use this initialization vector for
+ encryption instead of a random one.
+
+ @return: the encrypted/encapsulated packet
+ """
+ if not isinstance(pkt, self.SUPPORTED_PROTOS):
+ raise TypeError('cannot encrypt %s, supported protos are %s'
+ % (pkt.__class__, self.SUPPORTED_PROTOS))
+ if self.proto is ESP:
+ return self._encrypt_esp(pkt, seq_num=seq_num, iv=iv)
+ else:
+ return self._encrypt_ah(pkt, seq_num=seq_num)
+
+ def _decrypt_esp(self, pkt, verify=True):
+
+ encrypted = pkt[ESP]
+
+ if verify:
+ self.check_spi(pkt)
+ self.auth_algo.verify(encrypted, self.auth_key)
+
+ esp = self.crypt_algo.decrypt(encrypted, self.crypt_key,
+ self.auth_algo.icv_size)
+
+ if self.tunnel_header:
+ # drop the tunnel header and return the payload untouched
+
+ pkt.remove_payload()
+ if pkt.version == 4:
+ pkt.proto = esp.nh
+ else:
+ pkt.nh = esp.nh
+ cls = pkt.guess_payload_class(esp.data)
+
+ return cls(esp.data)
+ else:
+ ip_header = pkt
+
+ if ip_header.version == 4:
+ ip_header.proto = esp.nh
+ del ip_header.chksum
+ ip_header.remove_payload()
+ ip_header.len = len(ip_header) + len(esp.data)
+ # recompute checksum
+ ip_header = ip_header.__class__(bytes(ip_header))
+ else:
+ encrypted.underlayer.nh = esp.nh
+ encrypted.underlayer.remove_payload()
+ ip_header.plen = len(ip_header.payload) + len(esp.data)
+
+ cls = ip_header.guess_payload_class(esp.data)
+
+ # reassemble the ip_header with the ESP payload
+ return ip_header / cls(esp.data)
+
+ def _decrypt_ah(self, pkt, verify=True):
+
+ if verify:
+ self.check_spi(pkt)
+ self.auth_algo.verify(pkt, self.auth_key)
+
+ ah = pkt[AH]
+ payload = ah.payload
+ payload.remove_underlayer(None) # useless argument...
+
+ if self.tunnel_header:
+ return payload
+ else:
+ ip_header = pkt
+
+ if ip_header.version == 4:
+ ip_header.proto = ah.nh
+ del ip_header.chksum
+ ip_header.remove_payload()
+ ip_header.len = len(ip_header) + len(payload)
+ # recompute checksum
+ ip_header = ip_header.__class__(bytes(ip_header))
+ else:
+ ah.underlayer.nh = ah.nh
+ ah.underlayer.remove_payload()
+ ip_header.plen = len(ip_header.payload) + len(payload)
+
+ # reassemble the ip_header with the AH payload
+ return ip_header / payload
+
+ def decrypt(self, pkt, verify=True):
+ """
+ Decrypt (and decapsulate) an IP(v6) packet containing ESP or AH.
+
+ @param pkt: the packet to decrypt
+ @param verify: if False, do not perform the integrity check
+
+ @return: the decrypted/decapsulated packet
+ @raise IPSecIntegrityError: if the integrity check fails
+ """
+ if not isinstance(pkt, self.SUPPORTED_PROTOS):
+ raise TypeError('cannot decrypt %s, supported protos are %s'
+ % (pkt.__class__, self.SUPPORTED_PROTOS))
+
+ if self.proto is ESP and pkt.haslayer(ESP):
+ return self._decrypt_esp(pkt, verify=verify)
+ elif self.proto is AH and pkt.haslayer(AH):
+ return self._decrypt_ah(pkt, verify=verify)
+ else:
+ raise TypeError('%s has no %s layer' % (pkt, self.proto.name))
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/ir.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ir.py
new file mode 100644
index 00000000..90935aa3
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ir.py
@@ -0,0 +1,44 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+IrDA infrared data communication.
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.l2 import CookedLinux
+
+
+
+# IR
+
+class IrLAPHead(Packet):
+ name = "IrDA Link Access Protocol Header"
+ fields_desc = [ XBitField("Address", 0x7f, 7),
+ BitEnumField("Type", 1, 1, {"Response":0,
+ "Command":1})]
+
+class IrLAPCommand(Packet):
+ name = "IrDA Link Access Protocol Command"
+ fields_desc = [ XByteField("Control", 0),
+ XByteField("Format identifier", 0),
+ XIntField("Source address", 0),
+ XIntField("Destination address", 0xffffffff),
+ XByteField("Discovery flags", 0x1),
+ ByteEnumField("Slot number", 255, {"final":255}),
+ XByteField("Version", 0)]
+
+
+class IrLMP(Packet):
+ name = "IrDA Link Management Protocol"
+ fields_desc = [ XShortField("Service hints", 0),
+ XByteField("Character set", 0),
+ StrField("Device name", "") ]
+
+
+bind_layers( CookedLinux, IrLAPHead, proto=23)
+bind_layers( IrLAPHead, IrLAPCommand, Type=1)
+bind_layers( IrLAPCommand, IrLMP, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/isakmp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/isakmp.py
new file mode 100644
index 00000000..97def8f5
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/isakmp.py
@@ -0,0 +1,355 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+ISAKMP (Internet Security Association and Key Management Protocol).
+"""
+
+import struct
+from scapy.packet import *
+from scapy.fields import *
+from scapy.ansmachine import *
+from scapy.layers.inet import IP,UDP
+from scapy.sendrecv import sr
+
+
+# see http://www.iana.org/assignments/ipsec-registry for details
+ISAKMPAttributeTypes= { "Encryption": (1, { "DES-CBC" : 1,
+ "IDEA-CBC" : 2,
+ "Blowfish-CBC" : 3,
+ "RC5-R16-B64-CBC" : 4,
+ "3DES-CBC" : 5,
+ "CAST-CBC" : 6,
+ "AES-CBC" : 7,
+ "CAMELLIA-CBC" : 8, }, 0),
+ "Hash": (2, { "MD5": 1,
+ "SHA": 2,
+ "Tiger": 3,
+ "SHA2-256": 4,
+ "SHA2-384": 5,
+ "SHA2-512": 6,}, 0),
+ "Authentication":(3, { "PSK": 1,
+ "DSS": 2,
+ "RSA Sig": 3,
+ "RSA Encryption": 4,
+ "RSA Encryption Revised": 5,
+ "ElGamal Encryption": 6,
+ "ElGamal Encryption Revised": 7,
+ "ECDSA Sig": 8,
+ "HybridInitRSA": 64221,
+ "HybridRespRSA": 64222,
+ "HybridInitDSS": 64223,
+ "HybridRespDSS": 64224,
+ "XAUTHInitPreShared": 65001,
+ "XAUTHRespPreShared": 65002,
+ "XAUTHInitDSS": 65003,
+ "XAUTHRespDSS": 65004,
+ "XAUTHInitRSA": 65005,
+ "XAUTHRespRSA": 65006,
+ "XAUTHInitRSAEncryption": 65007,
+ "XAUTHRespRSAEncryption": 65008,
+ "XAUTHInitRSARevisedEncryption": 65009,
+ "XAUTHRespRSARevisedEncryptio": 65010, }, 0),
+ "GroupDesc": (4, { "768MODPgr" : 1,
+ "1024MODPgr" : 2,
+ "EC2Ngr155" : 3,
+ "EC2Ngr185" : 4,
+ "1536MODPgr" : 5,
+ "2048MODPgr" : 14,
+ "3072MODPgr" : 15,
+ "4096MODPgr" : 16,
+ "6144MODPgr" : 17,
+ "8192MODPgr" : 18, }, 0),
+ "GroupType": (5, {"MODP": 1,
+ "ECP": 2,
+ "EC2N": 3}, 0),
+ "GroupPrime": (6, {}, 1),
+ "GroupGenerator1":(7, {}, 1),
+ "GroupGenerator2":(8, {}, 1),
+ "GroupCurveA": (9, {}, 1),
+ "GroupCurveB": (10, {}, 1),
+ "LifeType": (11, {"Seconds": 1,
+ "Kilobytes": 2, }, 0),
+ "LifeDuration": (12, {}, 1),
+ "PRF": (13, {}, 0),
+ "KeyLength": (14, {}, 0),
+ "FieldSize": (15, {}, 0),
+ "GroupOrder": (16, {}, 1),
+ }
+
+# the name 'ISAKMPTransformTypes' is actually a misnomer (since the table
+# holds info for all ISAKMP Attribute types, not just transforms, but we'll
+# keep it for backwards compatibility... for now at least
+ISAKMPTransformTypes = ISAKMPAttributeTypes
+
+ISAKMPTransformNum = {}
+for n in ISAKMPTransformTypes:
+ val = ISAKMPTransformTypes[n]
+ tmp = {}
+ for e in val[1]:
+ tmp[val[1][e]] = e
+ ISAKMPTransformNum[val[0]] = (n,tmp, val[2])
+del(n)
+del(e)
+del(tmp)
+del(val)
+
+
+class ISAKMPTransformSetField(StrLenField):
+ islist=1
+ #def type2num(self, (typ,val)):
+ def type2num(self, typval):
+ typ = typval[0]
+ val = typval[1]
+ type_val,enc_dict,tlv = ISAKMPTransformTypes.get(typval[0], (typval[0],{},0))
+ val = enc_dict.get(val, val)
+ s = b""
+ if (val & ~0xffff):
+ if not tlv:
+ warning("%r should not be TLV but is too big => using TLV encoding" % typval[0])
+ n = 0
+ while val:
+ s = bytes([(val&0xff)])+s
+ val >>= 8
+ n += 1
+ val = n
+ else:
+ type_val |= 0x8000
+ return struct.pack("!HH",type_val, val)+s
+ def num2type(self, typ, enc):
+ val = ISAKMPTransformNum.get(typ,(typ,{}))
+ enc = val[1].get(enc,enc)
+ return (val[0],enc)
+ def i2m(self, pkt, i):
+ if i is None:
+ return b""
+ i = map(self.type2num, i)
+ return b"".join(i)
+ def m2i(self, pkt, m):
+ # I try to ensure that we don't read off the end of our packet based
+ # on bad length fields we're provided in the packet. There are still
+ # conditions where struct.unpack() may not get enough packet data, but
+ # worst case that should result in broken attributes (which would
+ # be expected). (wam)
+ lst = []
+ while len(m) >= 4:
+ trans_type, = struct.unpack("!H", m[:2])
+ is_tlv = not (trans_type & 0x8000)
+ if is_tlv:
+ # We should probably check to make sure the attribute type we
+ # are looking at is allowed to have a TLV format and issue a
+ # warning if we're given an TLV on a basic attribute.
+ value_len, = struct.unpack("!H", m[2:4])
+ if value_len+4 > len(m):
+ warning("Bad length for ISAKMP tranform type=%#6x" % trans_type)
+ value = m[4:4+value_len]
+ r = 0
+ for i in struct.unpack("!%s" % ("B"*len(value),), value):
+ r = (r << 8) | i
+ value = r
+ #value = reduce(lambda x,y: (x<<8)|y, struct.unpack("!%s" % ("B"*len(value),), value),0)
+ else:
+ trans_type &= 0x7fff
+ value_len=0
+ value, = struct.unpack("!H", m[2:4])
+ m=m[4+value_len:]
+ lst.append(self.num2type(trans_type, value))
+ if len(m) > 0:
+ warning("Extra bytes after ISAKMP transform dissection [%r]" % m)
+ return lst
+
+
+ISAKMP_payload_type = ["None","SA","Proposal","Transform","KE","ID","CERT","CR","Hash",
+ "SIG","Nonce","Notification","Delete","VendorID"]
+
+ISAKMP_exchange_type = ["None","base","identity prot.",
+ "auth only", "aggressive", "info"]
+
+
+class ISAKMP_class(Packet):
+ def guess_payload_class(self, payload):
+ np = self.next_payload
+ if np == 0:
+ return conf.raw_layer
+ elif np < len(ISAKMP_payload_type):
+ pt = ISAKMP_payload_type[np]
+ return globals().get("ISAKMP_payload_%s" % pt, ISAKMP_payload)
+ else:
+ return ISAKMP_payload
+
+
+class ISAKMP(ISAKMP_class): # rfc2408
+ name = "ISAKMP"
+ fields_desc = [
+ StrFixedLenField("init_cookie","",8),
+ StrFixedLenField("resp_cookie","",8),
+ ByteEnumField("next_payload",0,ISAKMP_payload_type),
+ XByteField("version",0x10),
+ ByteEnumField("exch_type",0,ISAKMP_exchange_type),
+ FlagsField("flags",0, 8, ["encryption","commit","auth_only","res3","res4","res5","res6","res7"]), # XXX use a Flag field
+ IntField("id",0),
+ IntField("length",None)
+ ]
+
+ def guess_payload_class(self, payload):
+ if self.flags & 1:
+ return conf.raw_layer
+ return ISAKMP_class.guess_payload_class(self, payload)
+
+ def answers(self, other):
+ if isinstance(other, ISAKMP):
+ if other.init_cookie == self.init_cookie:
+ return 1
+ return 0
+ def post_build(self, p, pay):
+ p += pay
+ if self.length is None:
+ p = p[:24]+struct.pack("!I",len(p))+p[28:]
+ return p
+
+
+
+
+class ISAKMP_payload_Transform(ISAKMP_class):
+ name = "IKE Transform"
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+# ShortField("len",None),
+ ShortField("length",None),
+ ByteField("num",None),
+ ByteEnumField("id",1,{1:"KEY_IKE"}),
+ ShortField("res2",0),
+ ISAKMPTransformSetField("transforms",None,length_from=lambda x:x.length-8)
+# XIntField("enc",0x80010005L),
+# XIntField("hash",0x80020002L),
+# XIntField("auth",0x80030001L),
+# XIntField("group",0x80040002L),
+# XIntField("life_type",0x800b0001L),
+# XIntField("durationh",0x000c0004L),
+# XIntField("durationl",0x00007080L),
+ ]
+ def post_build(self, p, pay):
+ if self.length is None:
+ l = len(p)
+ p = p[:2]+bytes([((l>>8)&0xff),(l&0xff)])+p[4:]
+ p += pay
+ return p
+
+
+
+
+class ISAKMP_payload_Proposal(ISAKMP_class):
+ name = "IKE proposal"
+# ISAKMP_payload_type = 0
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"trans","H", adjust=lambda pkt,x:x+8),
+ ByteField("proposal",1),
+ ByteEnumField("proto",1,{1:"ISAKMP"}),
+ FieldLenField("SPIsize",None,"SPI","B"),
+ ByteField("trans_nb",None),
+ StrLenField("SPI","",length_from=lambda x:x.SPIsize),
+ PacketLenField("trans",conf.raw_layer(),ISAKMP_payload_Transform,length_from=lambda x:x.length-8),
+ ]
+
+
+class ISAKMP_payload(ISAKMP_class):
+ name = "ISAKMP payload"
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+
+class ISAKMP_payload_VendorID(ISAKMP_class):
+ name = "ISAKMP Vendor ID"
+ overload_fields = { ISAKMP: { "next_payload":13 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"vendorID","H", adjust=lambda pkt,x:x+4),
+ StrLenField("vendorID","",length_from=lambda x:x.length-4),
+ ]
+
+class ISAKMP_payload_SA(ISAKMP_class):
+ name = "ISAKMP SA"
+ overload_fields = { ISAKMP: { "next_payload":1 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"prop","H", adjust=lambda pkt,x:x+12),
+ IntEnumField("DOI",1,{1:"IPSEC"}),
+ IntEnumField("situation",1,{1:"identity"}),
+ PacketLenField("prop",conf.raw_layer(),ISAKMP_payload_Proposal,length_from=lambda x:x.length-12),
+ ]
+
+class ISAKMP_payload_Nonce(ISAKMP_class):
+ name = "ISAKMP Nonce"
+ overload_fields = { ISAKMP: { "next_payload":10 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+class ISAKMP_payload_KE(ISAKMP_class):
+ name = "ISAKMP Key Exchange"
+ overload_fields = { ISAKMP: { "next_payload":4 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+class ISAKMP_payload_ID(ISAKMP_class):
+ name = "ISAKMP Identification"
+ overload_fields = { ISAKMP: { "next_payload":5 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+8),
+ ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
+ ByteEnumField("ProtoID",0,{0:"Unused"}),
+ ShortEnumField("Port",0,{0:"Unused"}),
+# IPField("IdentData","127.0.0.1"),
+ StrLenField("load","",length_from=lambda x:x.length-8),
+ ]
+
+
+
+class ISAKMP_payload_Hash(ISAKMP_class):
+ name = "ISAKMP Hash"
+ overload_fields = { ISAKMP: { "next_payload":8 }}
+ fields_desc = [
+ ByteEnumField("next_payload",None,ISAKMP_payload_type),
+ ByteField("res",0),
+ FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+4),
+ StrLenField("load","",length_from=lambda x:x.length-4),
+ ]
+
+
+
+ISAKMP_payload_type_overload = {}
+for i in range(len(ISAKMP_payload_type)):
+ name = "ISAKMP_payload_%s" % ISAKMP_payload_type[i]
+ if name in globals():
+ ISAKMP_payload_type_overload[globals()[name]] = {"next_payload":i}
+
+del(i)
+del(name)
+ISAKMP_class.overload_fields = ISAKMP_payload_type_overload.copy()
+
+
+bind_layers( UDP, ISAKMP, dport=500, sport=500)
+def ikescan(ip):
+ return sr(IP(dst=ip)/UDP()/ISAKMP(init_cookie=RandString(8),
+ exch_type=2)/ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()))
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2.py
new file mode 100644
index 00000000..0d0a1c78
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2.py
@@ -0,0 +1,543 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Classes and functions for layer 2 protocols.
+"""
+
+import os,struct,time
+from scapy.base_classes import Net
+from scapy.config import conf
+from scapy.packet import *
+from scapy.ansmachine import *
+from scapy.plist import SndRcvList
+from scapy.fields import *
+from scapy.sendrecv import srp,srp1
+from scapy.arch import get_if_hwaddr
+
+
+
+
+#################
+## Tools ##
+#################
+
+
+class Neighbor:
+ def __init__(self):
+ self.resolvers = {}
+
+ def register_l3(self, l2, l3, resolve_method):
+ self.resolvers[l2,l3]=resolve_method
+
+ def resolve(self, l2inst, l3inst):
+ k = l2inst.__class__,l3inst.__class__
+ if k in self.resolvers:
+ return self.resolvers[k](l2inst,l3inst)
+
+ def __repr__(self):
+ return "\n".join("%-15s -> %-15s" % (l2.__name__, l3.__name__) for l2,l3 in self.resolvers)
+
+conf.neighbor = Neighbor()
+
+conf.netcache.new_cache("arp_cache", 120) # cache entries expire after 120s
+
+
+@conf.commands.register
+def getmacbyip(ip, chainCC=0):
+ """Return MAC address corresponding to a given IP address"""
+ if isinstance(ip,Net):
+ ip = next(iter(ip))
+ ip = inet_ntoa(inet_aton(ip))
+ tmp = inet_aton(ip)
+ 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 == "lo") or (ip == conf.route.get_if_bcast(iff)) ):
+ return "ff:ff:ff:ff:ff:ff"
+ if gw != "0.0.0.0":
+ ip = gw
+
+ mac = conf.netcache.arp_cache.get(ip)
+ if mac:
+ return mac
+
+ res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip),
+ type=ETH_P_ARP,
+ iface = iff,
+ timeout=2,
+ verbose=0,
+ chainCC=chainCC,
+ nofilter=1)
+ if res is not None:
+ mac = res.payload.hwsrc
+ conf.netcache.arp_cache[ip] = mac
+ return mac
+ return None
+
+
+
+### Fields
+
+class DestMACField(MACField):
+ def __init__(self, name):
+ MACField.__init__(self, name, None)
+ def i2h(self, pkt, x):
+ if x is None:
+ x = conf.neighbor.resolve(pkt,pkt.payload)
+ if x is None:
+ x = "ff:ff:ff:ff:ff:ff"
+ warning("Mac address to reach destination not found. Using broadcast.")
+ return MACField.i2h(self, pkt, x)
+ def i2m(self, pkt, x):
+ return MACField.i2m(self, pkt, self.i2h(pkt, x))
+
+class SourceMACField(MACField):
+ def __init__(self, name):
+ MACField.__init__(self, name, None)
+ def i2h(self, pkt, x):
+ if x is None:
+ iff,a,gw = pkt.payload.route()
+ if iff:
+ try:
+ x = get_if_hwaddr(iff)
+ except:
+ pass
+ if x is None:
+ x = "00:00:00:00:00:00"
+ return MACField.i2h(self, pkt, x)
+ def i2m(self, pkt, x):
+ return MACField.i2m(self, pkt, self.i2h(pkt, x))
+
+class ARPSourceMACField(MACField):
+ def __init__(self, name):
+ MACField.__init__(self, name, None)
+ def i2h(self, pkt, x):
+ if x is None:
+ iff,a,gw = pkt.route()
+ if iff:
+ try:
+ x = get_if_hwaddr(iff)
+ except:
+ pass
+ if x is None:
+ x = "00:00:00:00:00:00"
+ return MACField.i2h(self, pkt, x)
+ def i2m(self, pkt, x):
+ return MACField.i2m(self, pkt, self.i2h(pkt, x))
+
+
+
+### Layers
+
+
+class Ether(Packet):
+ name = "Ethernet"
+ fields_desc = [ MACField("dst","00:00:00:01:00:00"),
+ MACField("src","00:00:00:02:00:00"),
+ XShortEnumField("type", 0x9000, ETHER_TYPES) ]
+ def hashret(self):
+ return struct.pack("H",self.type)+self.payload.hashret()
+ def answers(self, other):
+ if isinstance(other,Ether):
+ if self.type == other.type:
+ return self.payload.answers(other.payload)
+ return 0
+ def mysummary(self):
+ return self.sprintf("%src% > %dst% (%type%)")
+ @classmethod
+ def dispatch_hook(cls, _pkt=None, *args, **kargs):
+ if _pkt and len(_pkt) >= 14:
+ if struct.unpack("!H", _pkt[12:14])[0] <= 1500:
+ return Dot3
+ return cls
+
+
+class Dot3(Packet):
+ name = "802.3"
+ fields_desc = [ DestMACField("dst"),
+ MACField("src", ETHER_ANY),
+ LenField("len", None, "H") ]
+ def extract_padding(self,s):
+ l = self.len
+ return s[:l],s[l:]
+ def answers(self, other):
+ if isinstance(other,Dot3):
+ return self.payload.answers(other.payload)
+ return 0
+ def mysummary(self):
+ return "802.3 %s > %s" % (self.src, self.dst)
+ @classmethod
+ def dispatch_hook(cls, _pkt=None, *args, **kargs):
+ if _pkt and len(_pkt) >= 14:
+ if struct.unpack("!H", _pkt[12:14])[0] > 1500:
+ return Ether
+ return cls
+
+
+class LLC(Packet):
+ name = "LLC"
+ fields_desc = [ XByteField("dsap", 0x00),
+ XByteField("ssap", 0x00),
+ ByteField("ctrl", 0) ]
+
+conf.neighbor.register_l3(Ether, LLC, lambda l2,l3: conf.neighbor.resolve(l2,l3.payload))
+conf.neighbor.register_l3(Dot3, LLC, lambda l2,l3: conf.neighbor.resolve(l2,l3.payload))
+
+
+class CookedLinux(Packet):
+ name = "cooked linux"
+ fields_desc = [ ShortEnumField("pkttype",0, {0: "unicast",
+ 4:"sent-by-us"}), #XXX incomplete
+ XShortField("lladdrtype",512),
+ ShortField("lladdrlen",0),
+ StrFixedLenField("src","",8),
+ XShortEnumField("proto",0x800,ETHER_TYPES) ]
+
+
+
+class SNAP(Packet):
+ name = "SNAP"
+ fields_desc = [ X3BytesField("OUI",0x000000),
+ XShortEnumField("code", 0x000, ETHER_TYPES) ]
+
+conf.neighbor.register_l3(Dot3, SNAP, lambda l2,l3: conf.neighbor.resolve(l2,l3.payload))
+
+
+class Dot1Q(Packet):
+ name = "802.1Q"
+ aliastypes = [ Ether ]
+ fields_desc = [ BitField("prio", 0, 3),
+ BitField("id", 0, 1),
+ BitField("vlan", 1, 12),
+ XShortEnumField("type", 0x0000, ETHER_TYPES) ]
+ def answers(self, other):
+ if isinstance(other,Dot1Q):
+ if ( (self.type == other.type) and
+ (self.vlan == other.vlan) ):
+ return self.payload.answers(other.payload)
+ else:
+ return self.payload.answers(other)
+ return 0
+ def default_payload_class(self, pay):
+ if self.type <= 1500:
+ return LLC
+ return conf.raw_layer
+ def extract_padding(self,s):
+ if self.type <= 1500:
+ return s[:self.type],s[self.type:]
+ return s,None
+ def mysummary(self):
+ if isinstance(self.underlayer, Ether):
+ return self.underlayer.sprintf("802.1q %Ether.src% > %Ether.dst% (%Dot1Q.type%) vlan %Dot1Q.vlan%")
+ else:
+ return self.sprintf("802.1q (%Dot1Q.type%) vlan %Dot1Q.vlan%")
+
+
+conf.neighbor.register_l3(Ether, Dot1Q, lambda l2,l3: conf.neighbor.resolve(l2,l3.payload))
+
+class STP(Packet):
+ name = "Spanning Tree Protocol"
+ fields_desc = [ ShortField("proto", 0),
+ ByteField("version", 0),
+ ByteField("bpdutype", 0),
+ ByteField("bpduflags", 0),
+ ShortField("rootid", 0),
+ MACField("rootmac", ETHER_ANY),
+ IntField("pathcost", 0),
+ ShortField("bridgeid", 0),
+ MACField("bridgemac", ETHER_ANY),
+ ShortField("portid", 0),
+ BCDFloatField("age", 1),
+ BCDFloatField("maxage", 20),
+ BCDFloatField("hellotime", 2),
+ BCDFloatField("fwddelay", 15) ]
+
+
+class EAPOL(Packet):
+ name = "EAPOL"
+ fields_desc = [ ByteField("version", 1),
+ ByteEnumField("type", 0, ["EAP_PACKET", "START", "LOGOFF", "KEY", "ASF"]),
+ LenField("len", None, "H") ]
+
+ EAP_PACKET= 0
+ START = 1
+ LOGOFF = 2
+ KEY = 3
+ ASF = 4
+ def extract_padding(self, s):
+ l = self.len
+ return s[:l],s[l:]
+ def hashret(self):
+ #return chr(self.type)+self.payload.hashret()
+ return bytes([self.type])+self.payload.hashret()
+ def answers(self, other):
+ if isinstance(other,EAPOL):
+ if ( (self.type == self.EAP_PACKET) and
+ (other.type == self.EAP_PACKET) ):
+ return self.payload.answers(other.payload)
+ return 0
+ def mysummary(self):
+ return self.sprintf("EAPOL %EAPOL.type%")
+
+
+class EAP(Packet):
+ name = "EAP"
+ fields_desc = [ ByteEnumField("code", 4, {1:"REQUEST",2:"RESPONSE",3:"SUCCESS",4:"FAILURE"}),
+ ByteField("id", 0),
+ ShortField("len",None),
+ ConditionalField(ByteEnumField("type",0, {1:"ID",4:"MD5"}), lambda pkt:pkt.code not in [EAP.SUCCESS, EAP.FAILURE])
+
+ ]
+
+ REQUEST = 1
+ RESPONSE = 2
+ SUCCESS = 3
+ FAILURE = 4
+ TYPE_ID = 1
+ TYPE_MD5 = 4
+ def answers(self, other):
+ if isinstance(other,EAP):
+ if self.code == self.REQUEST:
+ return 0
+ elif self.code == self.RESPONSE:
+ if ( (other.code == self.REQUEST) and
+ (other.type == self.type) ):
+ return 1
+ elif other.code == self.RESPONSE:
+ return 1
+ return 0
+
+ def post_build(self, p, pay):
+ if self.len is None:
+ l = len(p)+len(pay)
+ p = p[:2]+bytes([((l>>8)&0xff),(l&0xff)])+p[4:]
+ return p+pay
+
+
+class ARP(Packet):
+ name = "ARP"
+ fields_desc = [ XShortField("hwtype", 0x0001),
+ XShortEnumField("ptype", 0x0800, ETHER_TYPES),
+ ByteField("hwlen", 6),
+ ByteField("plen", 4),
+ ShortEnumField("op", 1, {"who-has":1, "is-at":2, "RARP-req":3, "RARP-rep":4, "Dyn-RARP-req":5, "Dyn-RAR-rep":6, "Dyn-RARP-err":7, "InARP-req":8, "InARP-rep":9}),
+ ARPSourceMACField("hwsrc"),
+ SourceIPField("psrc","pdst"),
+ MACField("hwdst", ETHER_ANY),
+ IPField("pdst", "0.0.0.0") ]
+ who_has = 1
+ is_at = 2
+ def answers(self, other):
+ if isinstance(other,ARP):
+ if ( (self.op == self.is_at) and
+ (other.op == self.who_has) and
+ (self.psrc == other.pdst) ):
+ return 1
+ return 0
+ def route(self):
+ dst = self.pdst
+ if isinstance(dst,Gen):
+ dst = next(iter(dst))
+ return conf.route.route(dst)
+ def extract_padding(self, s):
+ return b"",s
+ def mysummary(self):
+ if self.op == self.is_at:
+ return self.sprintf("ARP is at %hwsrc% says %psrc%")
+ elif self.op == self.who_has:
+ return self.sprintf("ARP who has %pdst% says %psrc%")
+ else:
+ return self.sprintf("ARP %op% %psrc% > %pdst%")
+
+conf.neighbor.register_l3(Ether, ARP, lambda l2,l3: getmacbyip(l3.pdst))
+
+class GRErouting(Packet):
+ name = "GRE routing informations"
+ fields_desc = [ ShortField("address_family",0),
+ ByteField("SRE_offset", 0),
+ FieldLenField("SRE_len", None, "routing_info", "B"),
+ StrLenField("routing_info", "", "SRE_len"),
+ ]
+
+
+class GRE(Packet):
+ name = "GRE"
+ fields_desc = [ BitField("chksum_present",0,1),
+ BitField("routing_present",0,1),
+ BitField("key_present",0,1),
+ BitField("seqnum_present",0,1),
+ BitField("strict_route_source",0,1),
+ BitField("recursion_control",0,3),
+ BitField("flags",0,5),
+ BitField("version",0,3),
+ XShortEnumField("proto", 0x0000, ETHER_TYPES),
+ ConditionalField(XShortField("chksum",None), lambda pkt:pkt.chksum_present==1 or pkt.routing_present==1),
+ ConditionalField(XShortField("offset",None), lambda pkt:pkt.chksum_present==1 or pkt.routing_present==1),
+ ConditionalField(XIntField("key",None), lambda pkt:pkt.key_present==1),
+ ConditionalField(XIntField("seqence_number",None), lambda pkt:pkt.seqnum_present==1),
+ ]
+ def post_build(self, p, pay):
+ p += pay
+ if self.chksum_present and self.chksum is None:
+ c = checksum(p)
+ p = p[:4]+bytes([((c>>8)&0xff),(c&0xff)])+p[6:]
+ return p
+
+
+
+
+bind_layers( Dot3, LLC, )
+bind_layers( Ether, LLC, type=122)
+bind_layers( Ether, Dot1Q, type=33024)
+bind_layers( Ether, Ether, type=1)
+bind_layers( Ether, ARP, type=2054)
+bind_layers( Ether, EAPOL, type=34958)
+bind_layers( Ether, EAPOL, dst='01:80:c2:00:00:03', type=34958)
+bind_layers( CookedLinux, LLC, proto=122)
+bind_layers( CookedLinux, Dot1Q, proto=33024)
+bind_layers( CookedLinux, Ether, proto=1)
+bind_layers( CookedLinux, ARP, proto=2054)
+bind_layers( CookedLinux, EAPOL, proto=34958)
+bind_layers( GRE, LLC, proto=122)
+bind_layers( GRE, Dot1Q, proto=33024)
+bind_layers( GRE, Ether, proto=1)
+bind_layers( GRE, ARP, proto=2054)
+bind_layers( GRE, EAPOL, proto=34958)
+bind_layers( GRE, GRErouting, { "routing_present" : 1 } )
+bind_layers( GRErouting, conf.raw_layer,{ "address_family" : 0, "SRE_len" : 0 })
+bind_layers( GRErouting, GRErouting, { } )
+bind_layers( EAPOL, EAP, type=0)
+bind_layers( LLC, STP, dsap=66, ssap=66, ctrl=3)
+bind_layers( LLC, SNAP, dsap=170, ssap=170, ctrl=3)
+bind_layers( SNAP, Dot1Q, code=33024)
+bind_layers( SNAP, Ether, code=1)
+bind_layers( SNAP, ARP, code=2054)
+bind_layers( SNAP, EAPOL, code=34958)
+bind_layers( SNAP, STP, code=267)
+
+conf.l2types.register(ARPHDR_ETHER, Ether)
+conf.l2types.register_num2layer(ARPHDR_METRICOM, Ether)
+conf.l2types.register_num2layer(ARPHDR_LOOPBACK, Ether)
+conf.l2types.register_layer2num(ARPHDR_ETHER, Dot3)
+conf.l2types.register(144, CookedLinux) # called LINUX_IRDA, similar to CookedLinux
+conf.l2types.register(113, CookedLinux)
+
+conf.l3types.register(ETH_P_ARP, ARP)
+
+
+
+
+### Technics
+
+
+
+@conf.commands.register
+def arpcachepoison(target, victim, interval=60):
+ """Poison target's cache with (your MAC,victim's IP) couple
+arpcachepoison(target, victim, [interval=60]) -> None
+"""
+ tmac = getmacbyip(target)
+ p = Ether(dst=tmac)/ARP(op="who-has", psrc=victim, pdst=target)
+ try:
+ while 1:
+ sendp(p, iface_hint=target)
+ if conf.verb > 1:
+ os.write(1,b".")
+ time.sleep(interval)
+ except KeyboardInterrupt:
+ pass
+
+
+class ARPingResult(SndRcvList):
+ def __init__(self, res=None, name="ARPing", stats=None):
+ SndRcvList.__init__(self, res, name, stats)
+
+ def show(self):
+ for s,r in self.res:
+ print(r.sprintf("%19s,Ether.src% %ARP.psrc%"))
+
+
+
+@conf.commands.register
+def arping(net, timeout=2, cache=0, verbose=None, **kargs):
+ """Send ARP who-has requests to determine which hosts are up
+arping(net, [cache=0,] [iface=conf.iface,] [verbose=conf.verb]) -> None
+Set cache=True if you want arping to modify internal ARP-Cache"""
+ if verbose is None:
+ verbose = conf.verb
+ ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=net), verbose=verbose,
+ filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
+ ans = ARPingResult(ans.res)
+
+ if cache and ans is not None:
+ for pair in ans:
+ conf.netcache.arp_cache[pair[1].psrc] = (pair[1].hwsrc, time.time())
+ if verbose:
+ ans.show()
+ return ans,unans
+
+@conf.commands.register
+def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
+ """Try to guess if target is in Promisc mode. The target is provided by its ip."""
+
+ responses = srp1(Ether(dst=fake_bcast) / ARP(op="who-has", pdst=ip),type=ETH_P_ARP, iface_hint=ip, timeout=1, verbose=0,**kargs)
+
+ return responses is not None
+
+@conf.commands.register
+def promiscping(net, timeout=2, fake_bcast="ff:ff:ff:ff:ff:fe", **kargs):
+ """Send ARP who-has requests to determine which hosts are in promiscuous mode
+ promiscping(net, iface=conf.iface)"""
+ ans,unans = srp(Ether(dst=fake_bcast)/ARP(pdst=net),
+ filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
+ ans = ARPingResult(ans.res, name="PROMISCPing")
+
+ ans.display()
+ return ans,unans
+
+
+class ARP_am(AnsweringMachine):
+ function_name="farpd"
+ filter = "arp"
+ send_function = staticmethod(sendp)
+
+ def parse_options(self, IP_addr=None, iface=None, ARP_addr=None):
+ self.IP_addr=IP_addr
+ self.iface=iface
+ self.ARP_addr=ARP_addr
+
+ def is_request(self, req):
+ return (req.haslayer(ARP) and
+ req.getlayer(ARP).op == 1 and
+ (self.IP_addr == None or self.IP_addr == req.getlayer(ARP).pdst))
+
+ def make_reply(self, req):
+ ether = req.getlayer(Ether)
+ arp = req.getlayer(ARP)
+ iff,a,gw = conf.route.route(arp.psrc)
+ if self.iface != None:
+ iff = iface
+ ARP_addr = self.ARP_addr
+ IP_addr = arp.pdst
+ resp = Ether(dst=ether.src,
+ src=ARP_addr)/ARP(op="is-at",
+ hwsrc=ARP_addr,
+ psrc=IP_addr,
+ hwdst=arp.hwsrc,
+ pdst=arp.pdst)
+ return resp
+
+ def sniff(self):
+ sniff(iface=self.iface, **self.optsniff)
+
+@conf.commands.register
+def etherleak(target, **kargs):
+ """Exploit Etherleak flaw"""
+ return srpflood(Ether()/ARP(pdst=target),
+ prn=lambda a: conf.padding_layer in a[1] and hexstr(a[1][conf.padding_layer].load),
+ filter="arp", **kargs)
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2tp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2tp.py
new file mode 100644
index 00000000..0b56db21
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/l2tp.py
@@ -0,0 +1,36 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+L2TP (Layer 2 Tunneling Protocol) for VPNs.
+
+[RFC 2661]
+"""
+
+import struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+from scapy.layers.ppp import PPP
+
+class L2TP(Packet):
+ fields_desc = [ ShortEnumField("pkt_type",2,{2:"data"}),
+ ShortField("len", None),
+ ShortField("tunnel_id", 0),
+ ShortField("session_id", 0),
+ ShortField("ns", 0),
+ ShortField("nr", 0),
+ ShortField("offset", 0) ]
+
+ def post_build(self, pkt, pay):
+ if self.len is None:
+ l = len(pkt)+len(pay)
+ pkt = pkt[:2]+struct.pack("!H", l)+pkt[4:]
+ return pkt+pay
+
+
+bind_layers( UDP, L2TP, sport=1701, dport=1701)
+bind_layers( L2TP, PPP, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/llmnr.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/llmnr.py
new file mode 100644
index 00000000..65ecad41
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/llmnr.py
@@ -0,0 +1,65 @@
+from scapy.fields import *
+from scapy.packet import *
+from scapy.layers.inet import UDP
+from scapy.layers.dns import DNSQRField, DNSRRField, DNSRRCountField
+
+"""
+LLMNR (Link Local Multicast Node Resolution).
+
+[RFC 4795]
+"""
+
+#############################################################################
+### LLMNR (RFC4795) ###
+#############################################################################
+# LLMNR is based on the DNS packet format (RFC1035 Section 4)
+# RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno
+
+_LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3"
+_LLMNR_IPv4_mcast_addr = "224.0.0.252"
+
+class LLMNRQuery(Packet):
+ name = "Link Local Multicast Node Resolution - Query"
+ fields_desc = [ ShortField("id", 0),
+ BitField("qr", 0, 1),
+ BitEnumField("opcode", 0, 4, { 0:"QUERY" }),
+ BitField("c", 0, 1),
+ BitField("tc", 0, 2),
+ BitField("z", 0, 4),
+ BitEnumField("rcode", 0, 4, { 0:"ok" }),
+ DNSRRCountField("qdcount", None, "qd"),
+ DNSRRCountField("ancount", None, "an"),
+ DNSRRCountField("nscount", None, "ns"),
+ DNSRRCountField("arcount", None, "ar"),
+ DNSQRField("qd", "qdcount"),
+ DNSRRField("an", "ancount"),
+ DNSRRField("ns", "nscount"),
+ DNSRRField("ar", "arcount",0)]
+ overload_fields = {UDP: {"sport": 5355, "dport": 5355 }}
+ def hashret(self):
+ return struct.pack("!H", self.id)
+
+class LLMNRResponse(LLMNRQuery):
+ name = "Link Local Multicast Node Resolution - Response"
+ qr = 1
+ def answers(self, other):
+ return (isinstance(other, LLMNRQuery) and
+ self.id == other.id and
+ self.qr == 1 and
+ other.qr == 0)
+
+def _llmnr_dispatcher(x, *args, **kargs):
+ cls = conf.raw_layer
+ if len(x) >= 3:
+ if (ord(x[4]) & 0x80): # Response
+ cls = LLMNRResponse
+ else: # Query
+ cls = LLMNRQuery
+ return cls(x, *args, **kargs)
+
+bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 })
+bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 })
+
+# LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista.")))
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/mgcp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/mgcp.py
new file mode 100644
index 00000000..5d8a064e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/mgcp.py
@@ -0,0 +1,45 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+MGCP (Media Gateway Control Protocol)
+
+[RFC 2805]
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+
+class MGCP(Packet):
+ name = "MGCP"
+ longname = "Media Gateway Control Protocol"
+ fields_desc = [ StrStopField("verb","AUEP"," ", -1),
+ StrFixedLenField("sep1"," ",1),
+ StrStopField("transaction_id","1234567"," ", -1),
+ StrFixedLenField("sep2"," ",1),
+ StrStopField("endpoint","dummy@dummy.net"," ", -1),
+ StrFixedLenField("sep3"," ",1),
+ StrStopField("version","MGCP 1.0 NCS 1.0","\x0a", -1),
+ StrFixedLenField("sep4","\x0a",1),
+ ]
+
+
+#class MGCP(Packet):
+# name = "MGCP"
+# longname = "Media Gateway Control Protocol"
+# fields_desc = [ ByteEnumField("type",0, ["request","response","others"]),
+# ByteField("code0",0),
+# ByteField("code1",0),
+# ByteField("code2",0),
+# ByteField("code3",0),
+# ByteField("code4",0),
+# IntField("trasid",0),
+# IntField("req_time",0),
+# ByteField("is_duplicate",0),
+# ByteField("req_available",0) ]
+#
+bind_layers( UDP, MGCP, dport=2727)
+bind_layers( UDP, MGCP, sport=2727)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/mobileip.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/mobileip.py
new file mode 100644
index 00000000..bbaa8ce7
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/mobileip.py
@@ -0,0 +1,47 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Mobile IP.
+"""
+
+from scapy.fields import *
+from scapy.packet import *
+from scapy.layers.inet import IP,UDP
+
+
+class MobileIP(Packet):
+ name = "Mobile IP (RFC3344)"
+ fields_desc = [ ByteEnumField("type", 1, {1:"RRQ", 3:"RRP"}) ]
+
+class MobileIPRRQ(Packet):
+ name = "Mobile IP Registration Request (RFC3344)"
+ fields_desc = [ XByteField("flags", 0),
+ ShortField("lifetime", 180),
+ IPField("homeaddr", "0.0.0.0"),
+ IPField("haaddr", "0.0.0.0"),
+ IPField("coaddr", "0.0.0.0"),
+ LongField("id", 0), ]
+
+class MobileIPRRP(Packet):
+ name = "Mobile IP Registration Reply (RFC3344)"
+ fields_desc = [ ByteField("code", 0),
+ ShortField("lifetime", 180),
+ IPField("homeaddr", "0.0.0.0"),
+ IPField("haaddr", "0.0.0.0"),
+ LongField("id", 0), ]
+
+class MobileIPTunnelData(Packet):
+ name = "Mobile IP Tunnel Data Message (RFC3519)"
+ fields_desc = [ ByteField("nexthdr", 4),
+ ShortField("res", 0) ]
+
+
+bind_layers( UDP, MobileIP, sport=434)
+bind_layers( UDP, MobileIP, dport=434)
+bind_layers( MobileIP, MobileIPRRQ, type=1)
+bind_layers( MobileIP, MobileIPRRP, type=3)
+bind_layers( MobileIP, MobileIPTunnelData, type=4)
+bind_layers( MobileIPTunnelData, IP, nexthdr=4)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/netbios.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/netbios.py
new file mode 100644
index 00000000..f06e9307
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/netbios.py
@@ -0,0 +1,222 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+NetBIOS over TCP/IP
+
+[RFC 1001/1002]
+"""
+
+import struct
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP,TCP
+from scapy.layers.l2 import SourceMACField
+
+class NetBIOS_DS(Packet):
+ name = "NetBIOS datagram service"
+ fields_desc = [
+ ByteEnumField("type",17, {17:"direct_group"}),
+ ByteField("flags",0),
+ XShortField("id",0),
+ IPField("src","127.0.0.1"),
+ ShortField("sport",138),
+ ShortField("len",None),
+ ShortField("ofs",0),
+ NetBIOSNameField("srcname",""),
+ NetBIOSNameField("dstname",""),
+ ]
+ def post_build(self, p, pay):
+ p += pay
+ if self.len is None:
+ l = len(p)-14
+ p = p[:10]+struct.pack("!H", l)+p[12:]
+ return p
+
+# ShortField("length",0),
+# ShortField("Delimitor",0),
+# ByteField("command",0),
+# ByteField("data1",0),
+# ShortField("data2",0),
+# ShortField("XMIt",0),
+# ShortField("RSPCor",0),
+# StrFixedLenField("dest","",16),
+# StrFixedLenField("source","",16),
+#
+# ]
+#
+
+#NetBIOS
+
+
+# Name Query Request
+# Node Status Request
+class NBNSQueryRequest(Packet):
+ name="NBNS query request"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0x0110),
+ ShortField("QDCOUNT",1),
+ ShortField("ANCOUNT",0),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",0),
+ NetBIOSNameField("QUESTION_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"})]
+
+# Name Registration Request
+# Name Refresh Request
+# Name Release Request or Demand
+class NBNSRequest(Packet):
+ name="NBNS request"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0x2910),
+ ShortField("QDCOUNT",1),
+ ShortField("ANCOUNT",0),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",1),
+ NetBIOSNameField("QUESTION_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
+ ShortEnumField("RR_NAME",0xC00C,{0xC00C:"Label String Pointer to QUESTION_NAME"}),
+ ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
+ IntField("TTL", 0),
+ ShortField("RDLENGTH", 6),
+ BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
+ BitEnumField("OWNER_NODE_TYPE",00,2,{0:"B node",1:"P node",2:"M node",3:"H node"}),
+ BitEnumField("UNUSED",0,13,{0:"Unused"}),
+ IPField("NB_ADDRESS", "127.0.0.1")]
+
+# Name Query Response
+# Name Registration Response
+class NBNSQueryResponse(Packet):
+ name="NBNS query response"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0x8500),
+ ShortField("QDCOUNT",0),
+ ShortField("ANCOUNT",1),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",0),
+ NetBIOSNameField("RR_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
+ IntField("TTL", 0x493e0),
+ ShortField("RDLENGTH", 6),
+ ShortField("NB_FLAGS", 0),
+ IPField("NB_ADDRESS", "127.0.0.1")]
+
+# Name Query Response (negative)
+# Name Release Response
+class NBNSQueryResponseNegative(Packet):
+ name="NBNS query response (negative)"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0x8506),
+ ShortField("QDCOUNT",0),
+ ShortField("ANCOUNT",1),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",0),
+ NetBIOSNameField("RR_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
+ IntField("TTL",0),
+ ShortField("RDLENGTH",6),
+ BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
+ BitEnumField("OWNER_NODE_TYPE",00,2,{0:"B node",1:"P node",2:"M node",3:"H node"}),
+ BitEnumField("UNUSED",0,13,{0:"Unused"}),
+ IPField("NB_ADDRESS", "127.0.0.1")]
+
+# Node Status Response
+class NBNSNodeStatusResponse(Packet):
+ name="NBNS Node Status Response"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0x8500),
+ ShortField("QDCOUNT",0),
+ ShortField("ANCOUNT",1),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",0),
+ NetBIOSNameField("RR_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("RR_TYPE",0x21, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
+ IntField("TTL",0),
+ ShortField("RDLENGTH",83),
+ ByteField("NUM_NAMES",1)]
+
+# Service for Node Status Response
+class NBNSNodeStatusResponseService(Packet):
+ name="NBNS Node Status Response Service"
+ fields_desc = [StrFixedLenField("NETBIOS_NAME","WINDOWS ",15),
+ ByteEnumField("SUFFIX",0,{0:"workstation",0x03:"messenger service",0x20:"file server service",0x1b:"domain master browser",0x1c:"domain controller", 0x1e:"browser election service"}),
+ ByteField("NAME_FLAGS",0x4),
+ ByteEnumField("UNUSED",0,{0:"unused"})]
+
+# End of Node Status Response packet
+class NBNSNodeStatusResponseEnd(Packet):
+ name="NBNS Node Status Response"
+ fields_desc = [SourceMACField("MAC_ADDRESS"),
+ BitField("STATISTICS",0,57*8)]
+
+# Wait for Acknowledgement Response
+class NBNSWackResponse(Packet):
+ name="NBNS Wait for Acknowledgement Response"
+ fields_desc = [ShortField("NAME_TRN_ID",0),
+ ShortField("FLAGS", 0xBC07),
+ ShortField("QDCOUNT",0),
+ ShortField("ANCOUNT",1),
+ ShortField("NSCOUNT",0),
+ ShortField("ARCOUNT",0),
+ NetBIOSNameField("RR_NAME","windows"),
+ ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
+ ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
+ IntField("TTL", 2),
+ ShortField("RDLENGTH",2),
+ BitField("RDATA",10512,16)] #10512=0010100100010000
+
+class NBTDatagram(Packet):
+ name="NBT Datagram Packet"
+ fields_desc= [ByteField("Type", 0x10),
+ ByteField("Flags", 0x02),
+ ShortField("ID", 0),
+ IPField("SourceIP", "127.0.0.1"),
+ ShortField("SourcePort", 138),
+ ShortField("Length", 272),
+ ShortField("Offset", 0),
+ NetBIOSNameField("SourceName",b"windows"),
+ ShortEnumField("SUFFIX1",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0),
+ NetBIOSNameField("DestinationName",b"windows"),
+ ShortEnumField("SUFFIX2",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
+ ByteField("NULL",0)]
+
+
+class NBTSession(Packet):
+ name="NBT Session Packet"
+ fields_desc= [ByteEnumField("TYPE",0,{0x00:"Session Message",0x81:"Session Request",0x82:"Positive Session Response",0x83:"Negative Session Response",0x84:"Retarget Session Response",0x85:"Session Keepalive"}),
+ BitField("RESERVED",0x00,7),
+ BitField("LENGTH",0,17)]
+
+bind_layers( UDP, NBNSQueryRequest, dport=137)
+bind_layers( UDP, NBNSRequest, dport=137)
+bind_layers( UDP, NBNSQueryResponse, sport=137)
+bind_layers( UDP, NBNSQueryResponseNegative, sport=137)
+bind_layers( UDP, NBNSNodeStatusResponse, sport=137)
+bind_layers( NBNSNodeStatusResponse, NBNSNodeStatusResponseService, )
+bind_layers( NBNSNodeStatusResponse, NBNSNodeStatusResponseService, )
+bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseService, )
+bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseEnd, )
+bind_layers( UDP, NBNSWackResponse, sport=137)
+bind_layers( UDP, NBTDatagram, dport=138)
+bind_layers( TCP, NBTSession, dport=139)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/netflow.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/netflow.py
new file mode 100644
index 00000000..44567737
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/netflow.py
@@ -0,0 +1,48 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Cisco NetFlow protocol v1
+"""
+
+
+from scapy.fields import *
+from scapy.packet import *
+
+# Cisco Netflow Protocol version 1
+class NetflowHeader(Packet):
+ name = "Netflow Header"
+ fields_desc = [ ShortField("version", 1) ]
+
+class NetflowHeaderV1(Packet):
+ name = "Netflow Header V1"
+ fields_desc = [ ShortField("count", 0),
+ IntField("sysUptime", 0),
+ IntField("unixSecs", 0),
+ IntField("unixNanoSeconds", 0) ]
+
+
+class NetflowRecordV1(Packet):
+ name = "Netflow Record"
+ fields_desc = [ IPField("ipsrc", "0.0.0.0"),
+ IPField("ipdst", "0.0.0.0"),
+ IPField("nexthop", "0.0.0.0"),
+ ShortField("inputIfIndex", 0),
+ ShortField("outpuIfIndex", 0),
+ IntField("dpkts", 0),
+ IntField("dbytes", 0),
+ IntField("starttime", 0),
+ IntField("endtime", 0),
+ ShortField("srcport", 0),
+ ShortField("dstport", 0),
+ ShortField("padding", 0),
+ ByteField("proto", 0),
+ ByteField("tos", 0),
+ IntField("padding1", 0),
+ IntField("padding2", 0) ]
+
+
+bind_layers( NetflowHeader, NetflowHeaderV1, version=1)
+bind_layers( NetflowHeaderV1, NetflowRecordV1, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/ntp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ntp.py
new file mode 100644
index 00000000..6d11966c
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ntp.py
@@ -0,0 +1,77 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+NTP (Network Time Protocol).
+"""
+
+import time
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+
+
+# seconds between 01-01-1900 and 01-01-1970
+_NTP_BASETIME = 2208988800
+
+class TimeStampField(FixedPointField):
+ def __init__(self, name, default):
+ FixedPointField.__init__(self, name, default, 64, 32)
+
+ def i2repr(self, pkt, val):
+ if val is None:
+ return "--"
+ val = self.i2h(pkt,val)
+ if val < _NTP_BASETIME:
+ return val
+ return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(val-_NTP_BASETIME))
+
+ def any2i(self, pkt, val):
+ if type(val) is str:
+ return int(time.mktime(time.strptime(val))) + _NTP_BASETIME + 3600 # XXX
+ return FixedPointField.any2i(self,pkt,val)
+
+ def i2m(self, pkt, val):
+ if val is None:
+ val = FixedPointField.any2i(self, pkt, time.time()+_NTP_BASETIME)
+ return FixedPointField.i2m(self, pkt, val)
+
+
+
+class NTP(Packet):
+ # RFC 1769
+ name = "NTP"
+ fields_desc = [
+ BitEnumField('leap', 0, 2,
+ { 0: 'nowarning',
+ 1: 'longminute',
+ 2: 'shortminute',
+ 3: 'notsync'}),
+ BitField('version', 3, 3),
+ BitEnumField('mode', 3, 3,
+ { 0: 'reserved',
+ 1: 'sym_active',
+ 2: 'sym_passive',
+ 3: 'client',
+ 4: 'server',
+ 5: 'broadcast',
+ 6: 'control',
+ 7: 'private'}),
+ BitField('stratum', 2, 8),
+ BitField('poll', 0xa, 8), ### XXX : it's a signed int
+ BitField('precision', 0, 8), ### XXX : it's a signed int
+ FixedPointField('delay', 0, size=32, frac_bits=16),
+ FixedPointField('dispersion', 0, size=32, frac_bits=16),
+ IPField('id', "127.0.0.1"),
+ TimeStampField('ref', 0),
+ TimeStampField('orig', None), # None means current time
+ TimeStampField('recv', 0),
+ TimeStampField('sent', None)
+ ]
+ def mysummary(self):
+ return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%")
+
+
+bind_layers( UDP, NTP, dport=123, sport=123)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/pflog.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/pflog.py
new file mode 100644
index 00000000..a8fc9fe0
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/pflog.py
@@ -0,0 +1,59 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+PFLog: OpenBSD PF packet filter logging.
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP
+if conf.ipv6_enabled:
+ from scapy.layers.inet6 import IPv6
+from scapy.config import conf
+
+class PFLog(Packet):
+ name = "PFLog"
+ # from OpenBSD src/sys/net/pfvar.h and src/sys/net/if_pflog.h
+ fields_desc = [ ByteField("hdrlen", 0),
+ ByteEnumField("addrfamily", 2, {socket.AF_INET: "IPv4",
+ socket.AF_INET6: "IPv6"}),
+ ByteEnumField("action", 1, {0: "pass", 1: "drop",
+ 2: "scrub", 3: "no-scrub",
+ 4: "nat", 5: "no-nat",
+ 6: "binat", 7: "no-binat",
+ 8: "rdr", 9: "no-rdr",
+ 10: "syn-proxy-drop" }),
+ ByteEnumField("reason", 0, {0: "match", 1: "bad-offset",
+ 2: "fragment", 3: "short",
+ 4: "normalize", 5: "memory",
+ 6: "bad-timestamp",
+ 7: "congestion",
+ 8: "ip-options",
+ 9: "proto-cksum",
+ 10: "state-mismatch",
+ 11: "state-insert",
+ 12: "state-limit",
+ 13: "src-limit",
+ 14: "syn-proxy" }),
+ StrFixedLenField("iface", "", 16),
+ StrFixedLenField("ruleset", "", 16),
+ SignedIntField("rulenumber", 0),
+ SignedIntField("subrulenumber", 0),
+ SignedIntField("uid", 0),
+ IntField("pid", 0),
+ SignedIntField("ruleuid", 0),
+ IntField("rulepid", 0),
+ ByteEnumField("direction", 255, {0: "inout", 1: "in",
+ 2:"out", 255: "unknown"}),
+ StrFixedLenField("pad", "\x00\x00\x00", 3 ) ]
+ def mysummary(self):
+ return self.sprintf("%PFLog.addrfamily% %PFLog.action% on %PFLog.iface% by rule %PFLog.rulenumber%")
+
+bind_layers(PFLog, IP, addrfamily=socket.AF_INET)
+if conf.ipv6_enabled:
+ bind_layers(PFLog, IPv6, addrfamily=socket.AF_INET6)
+
+conf.l2types.register(117, PFLog)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/ppp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ppp.py
new file mode 100644
index 00000000..08cf62cd
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/ppp.py
@@ -0,0 +1,349 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+PPP (Point to Point Protocol)
+
+[RFC 1661]
+"""
+
+import struct
+from scapy.packet import *
+from scapy.layers.l2 import *
+from scapy.layers.inet import *
+from scapy.fields import *
+
+class PPPoE(Packet):
+ name = "PPP over Ethernet"
+ fields_desc = [ BitField("version", 1, 4),
+ BitField("type", 1, 4),
+ ByteEnumField("code", 0, {0:"Session"}),
+ XShortField("sessionid", 0x0),
+ ShortField("len", None) ]
+
+ def post_build(self, p, pay):
+ p += pay
+ if self.len is None:
+ l = len(p)-6
+ p = p[:4]+struct.pack("!H", l)+p[6:]
+ return p
+
+class PPPoED(PPPoE):
+ name = "PPP over Ethernet Discovery"
+ fields_desc = [ BitField("version", 1, 4),
+ BitField("type", 1, 4),
+ ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}),
+ XShortField("sessionid", 0x0),
+ ShortField("len", None) ]
+
+
+_PPP_proto = { 0x0001: "Padding Protocol",
+ 0x0003: "ROHC small-CID [RFC3095]",
+ 0x0005: "ROHC large-CID [RFC3095]",
+ 0x0021: "Internet Protocol version 4",
+ 0x0023: "OSI Network Layer",
+ 0x0025: "Xerox NS IDP",
+ 0x0027: "DECnet Phase IV",
+ 0x0029: "Appletalk",
+ 0x002b: "Novell IPX",
+ 0x002d: "Van Jacobson Compressed TCP/IP",
+ 0x002f: "Van Jacobson Uncompressed TCP/IP",
+ 0x0031: "Bridging PDU",
+ 0x0033: "Stream Protocol (ST-II)",
+ 0x0035: "Banyan Vines",
+ 0x0037: "reserved (until 1993) [Typo in RFC1172]",
+ 0x0039: "AppleTalk EDDP",
+ 0x003b: "AppleTalk SmartBuffered",
+ 0x003d: "Multi-Link [RFC1717]",
+ 0x003f: "NETBIOS Framing",
+ 0x0041: "Cisco Systems",
+ 0x0043: "Ascom Timeplex",
+ 0x0045: "Fujitsu Link Backup and Load Balancing (LBLB)",
+ 0x0047: "DCA Remote Lan",
+ 0x0049: "Serial Data Transport Protocol (PPP-SDTP)",
+ 0x004b: "SNA over 802.2",
+ 0x004d: "SNA",
+ 0x004f: "IPv6 Header Compression",
+ 0x0051: "KNX Bridging Data [ianp]",
+ 0x0053: "Encryption [Meyer]",
+ 0x0055: "Individual Link Encryption [Meyer]",
+ 0x0057: "Internet Protocol version 6 [Hinden]",
+ 0x0059: "PPP Muxing [RFC3153]",
+ 0x005b: "Vendor-Specific Network Protocol (VSNP) [RFC3772]",
+ 0x0061: "RTP IPHC Full Header [RFC3544]",
+ 0x0063: "RTP IPHC Compressed TCP [RFC3544]",
+ 0x0065: "RTP IPHC Compressed Non TCP [RFC3544]",
+ 0x0067: "RTP IPHC Compressed UDP 8 [RFC3544]",
+ 0x0069: "RTP IPHC Compressed RTP 8 [RFC3544]",
+ 0x006f: "Stampede Bridging",
+ 0x0071: "Reserved [Fox]",
+ 0x0073: "MP+ Protocol [Smith]",
+ 0x007d: "reserved (Control Escape) [RFC1661]",
+ 0x007f: "reserved (compression inefficient [RFC1662]",
+ 0x0081: "Reserved Until 20-Oct-2000 [IANA]",
+ 0x0083: "Reserved Until 20-Oct-2000 [IANA]",
+ 0x00c1: "NTCITS IPI [Ungar]",
+ 0x00cf: "reserved (PPP NLID)",
+ 0x00fb: "single link compression in multilink [RFC1962]",
+ 0x00fd: "compressed datagram [RFC1962]",
+ 0x00ff: "reserved (compression inefficient)",
+ 0x0201: "802.1d Hello Packets",
+ 0x0203: "IBM Source Routing BPDU",
+ 0x0205: "DEC LANBridge100 Spanning Tree",
+ 0x0207: "Cisco Discovery Protocol [Sastry]",
+ 0x0209: "Netcs Twin Routing [Korfmacher]",
+ 0x020b: "STP - Scheduled Transfer Protocol [Segal]",
+ 0x020d: "EDP - Extreme Discovery Protocol [Grosser]",
+ 0x0211: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
+ 0x0213: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
+ 0x0231: "Luxcom",
+ 0x0233: "Sigma Network Systems",
+ 0x0235: "Apple Client Server Protocol [Ridenour]",
+ 0x0281: "MPLS Unicast [RFC3032] ",
+ 0x0283: "MPLS Multicast [RFC3032]",
+ 0x0285: "IEEE p1284.4 standard - data packets [Batchelder]",
+ 0x0287: "ETSI TETRA Network Protocol Type 1 [Nieminen]",
+ 0x0289: "Multichannel Flow Treatment Protocol [McCann]",
+ 0x2063: "RTP IPHC Compressed TCP No Delta [RFC3544]",
+ 0x2065: "RTP IPHC Context State [RFC3544]",
+ 0x2067: "RTP IPHC Compressed UDP 16 [RFC3544]",
+ 0x2069: "RTP IPHC Compressed RTP 16 [RFC3544]",
+ 0x4001: "Cray Communications Control Protocol [Stage]",
+ 0x4003: "CDPD Mobile Network Registration Protocol [Quick]",
+ 0x4005: "Expand accelerator protocol [Rachmani]",
+ 0x4007: "ODSICP NCP [Arvind]",
+ 0x4009: "DOCSIS DLL [Gaedtke]",
+ 0x400B: "Cetacean Network Detection Protocol [Siller]",
+ 0x4021: "Stacker LZS [Simpson]",
+ 0x4023: "RefTek Protocol [Banfill]",
+ 0x4025: "Fibre Channel [Rajagopal]",
+ 0x4027: "EMIT Protocols [Eastham]",
+ 0x405b: "Vendor-Specific Protocol (VSP) [RFC3772]",
+ 0x8021: "Internet Protocol Control Protocol",
+ 0x8023: "OSI Network Layer Control Protocol",
+ 0x8025: "Xerox NS IDP Control Protocol",
+ 0x8027: "DECnet Phase IV Control Protocol",
+ 0x8029: "Appletalk Control Protocol",
+ 0x802b: "Novell IPX Control Protocol",
+ 0x802d: "reserved",
+ 0x802f: "reserved",
+ 0x8031: "Bridging NCP",
+ 0x8033: "Stream Protocol Control Protocol",
+ 0x8035: "Banyan Vines Control Protocol",
+ 0x8037: "reserved (until 1993)",
+ 0x8039: "reserved",
+ 0x803b: "reserved",
+ 0x803d: "Multi-Link Control Protocol",
+ 0x803f: "NETBIOS Framing Control Protocol",
+ 0x8041: "Cisco Systems Control Protocol",
+ 0x8043: "Ascom Timeplex",
+ 0x8045: "Fujitsu LBLB Control Protocol",
+ 0x8047: "DCA Remote Lan Network Control Protocol (RLNCP)",
+ 0x8049: "Serial Data Control Protocol (PPP-SDCP)",
+ 0x804b: "SNA over 802.2 Control Protocol",
+ 0x804d: "SNA Control Protocol",
+ 0x804f: "IP6 Header Compression Control Protocol",
+ 0x8051: "KNX Bridging Control Protocol [ianp]",
+ 0x8053: "Encryption Control Protocol [Meyer]",
+ 0x8055: "Individual Link Encryption Control Protocol [Meyer]",
+ 0x8057: "IPv6 Control Protovol [Hinden]",
+ 0x8059: "PPP Muxing Control Protocol [RFC3153]",
+ 0x805b: "Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]",
+ 0x806f: "Stampede Bridging Control Protocol",
+ 0x8073: "MP+ Control Protocol [Smith]",
+ 0x8071: "Reserved [Fox]",
+ 0x807d: "Not Used - reserved [RFC1661]",
+ 0x8081: "Reserved Until 20-Oct-2000 [IANA]",
+ 0x8083: "Reserved Until 20-Oct-2000 [IANA]",
+ 0x80c1: "NTCITS IPI Control Protocol [Ungar]",
+ 0x80cf: "Not Used - reserved [RFC1661]",
+ 0x80fb: "single link compression in multilink control [RFC1962]",
+ 0x80fd: "Compression Control Protocol [RFC1962]",
+ 0x80ff: "Not Used - reserved [RFC1661]",
+ 0x8207: "Cisco Discovery Protocol Control [Sastry]",
+ 0x8209: "Netcs Twin Routing [Korfmacher]",
+ 0x820b: "STP - Control Protocol [Segal]",
+ 0x820d: "EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]",
+ 0x8235: "Apple Client Server Protocol Control [Ridenour]",
+ 0x8281: "MPLSCP [RFC3032]",
+ 0x8285: "IEEE p1284.4 standard - Protocol Control [Batchelder]",
+ 0x8287: "ETSI TETRA TNP1 Control Protocol [Nieminen]",
+ 0x8289: "Multichannel Flow Treatment Protocol [McCann]",
+ 0xc021: "Link Control Protocol",
+ 0xc023: "Password Authentication Protocol",
+ 0xc025: "Link Quality Report",
+ 0xc027: "Shiva Password Authentication Protocol",
+ 0xc029: "CallBack Control Protocol (CBCP)",
+ 0xc02b: "BACP Bandwidth Allocation Control Protocol [RFC2125]",
+ 0xc02d: "BAP [RFC2125]",
+ 0xc05b: "Vendor-Specific Authentication Protocol (VSAP) [RFC3772]",
+ 0xc081: "Container Control Protocol [KEN]",
+ 0xc223: "Challenge Handshake Authentication Protocol",
+ 0xc225: "RSA Authentication Protocol [Narayana]",
+ 0xc227: "Extensible Authentication Protocol [RFC2284]",
+ 0xc229: "Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]",
+ 0xc26f: "Stampede Bridging Authorization Protocol",
+ 0xc281: "Proprietary Authentication Protocol [KEN]",
+ 0xc283: "Proprietary Authentication Protocol [Tackabury]",
+ 0xc481: "Proprietary Node ID Authentication Protocol [KEN]"}
+
+
+class HDLC(Packet):
+ fields_desc = [ XByteField("address",0xff),
+ XByteField("control",0x03) ]
+
+class PPP(Packet):
+ name = "PPP Link Layer"
+ fields_desc = [ ShortEnumField("proto", 0x0021, _PPP_proto) ]
+ @classmethod
+ def dispatch_hook(cls, _pkt=None, *args, **kargs):
+ if _pkt and _pkt[0] == 0xff:
+ cls = HDLC
+ return cls
+
+_PPP_conftypes = { 1:"Configure-Request",
+ 2:"Configure-Ack",
+ 3:"Configure-Nak",
+ 4:"Configure-Reject",
+ 5:"Terminate-Request",
+ 6:"Terminate-Ack",
+ 7:"Code-Reject",
+ 8:"Protocol-Reject",
+ 9:"Echo-Request",
+ 10:"Echo-Reply",
+ 11:"Discard-Request",
+ 14:"Reset-Request",
+ 15:"Reset-Ack",
+ }
+
+
+### PPP IPCP stuff (RFC 1332)
+
+# All IPCP options are defined below (names and associated classes)
+_PPP_ipcpopttypes = { 1:"IP-Addresses (Deprecated)",
+ 2:"IP-Compression-Protocol",
+ 3:"IP-Address",
+ 4:"Mobile-IPv4", # not implemented, present for completeness
+ 129:"Primary-DNS-Address",
+ 130:"Primary-NBNS-Address",
+ 131:"Secondary-DNS-Address",
+ 132:"Secondary-NBNS-Address"}
+
+
+class PPP_IPCP_Option(Packet):
+ name = "PPP IPCP Option"
+ fields_desc = [ ByteEnumField("type" , None , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ StrLenField("data", b"", length_from=lambda p:max(0,p.len-2)) ]
+ def extract_padding(self, pay):
+ return b"",pay
+
+ registered_options = {}
+ @classmethod
+ def register_variant(cls):
+ cls.registered_options[cls.type.default] = cls
+ @classmethod
+ def dispatch_hook(cls, _pkt=None, *args, **kargs):
+ if _pkt:
+ #o = ord(_pkt[0])
+ o = (_pkt[0])
+ return cls.registered_options.get(o, cls)
+ return cls
+
+
+class PPP_IPCP_Option_IPAddress(PPP_IPCP_Option):
+ name = "PPP IPCP Option: IP Address"
+ fields_desc = [ ByteEnumField("type" , 3 , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ IPField("data","0.0.0.0"),
+ ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
+
+class PPP_IPCP_Option_DNS1(PPP_IPCP_Option):
+ name = "PPP IPCP Option: DNS1 Address"
+ fields_desc = [ ByteEnumField("type" , 129 , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ IPField("data","0.0.0.0"),
+ ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
+
+class PPP_IPCP_Option_DNS2(PPP_IPCP_Option):
+ name = "PPP IPCP Option: DNS2 Address"
+ fields_desc = [ ByteEnumField("type" , 131 , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ IPField("data","0.0.0.0"),
+ ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
+
+class PPP_IPCP_Option_NBNS1(PPP_IPCP_Option):
+ name = "PPP IPCP Option: NBNS1 Address"
+ fields_desc = [ ByteEnumField("type" , 130 , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ IPField("data","0.0.0.0"),
+ ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
+
+class PPP_IPCP_Option_NBNS2(PPP_IPCP_Option):
+ name = "PPP IPCP Option: NBNS2 Address"
+ fields_desc = [ ByteEnumField("type" , 132 , _PPP_ipcpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ IPField("data","0.0.0.0"),
+ ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
+
+
+class PPP_IPCP(Packet):
+ fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
+ XByteField("id", 0 ),
+ FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
+ PacketListField("options", [], PPP_IPCP_Option, length_from=lambda p:p.len-4,) ]
+
+
+### ECP
+
+_PPP_ecpopttypes = { 0:"OUI",
+ 1:"DESE", }
+
+class PPP_ECP_Option(Packet):
+ name = "PPP ECP Option"
+ fields_desc = [ ByteEnumField("type" , None , _PPP_ecpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
+ StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
+ def extract_padding(self, pay):
+ return b"",pay
+
+ registered_options = {}
+ @classmethod
+ def register_variant(cls):
+ cls.registered_options[cls.type.default] = cls
+ @classmethod
+ def dispatch_hook(cls, _pkt=None, *args, **kargs):
+ if _pkt:
+ #o = ord(_pkt[0])
+ o = (_pkt[0])
+ return cls.registered_options.get(o, cls)
+ return cls
+
+class PPP_ECP_Option_OUI(PPP_ECP_Option):
+ fields_desc = [ ByteEnumField("type" , 0 , _PPP_ecpopttypes),
+ FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
+ StrFixedLenField("oui","",3),
+ ByteField("subtype",0),
+ StrLenField("data", "", length_from=lambda p:p.len-6) ]
+
+
+
+class PPP_ECP(Packet):
+ fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
+ XByteField("id", 0 ),
+ FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
+ PacketListField("options", [], PPP_ECP_Option, length_from=lambda p:p.len-4,) ]
+
+bind_layers( Ether, PPPoED, type=0x8863)
+bind_layers( Ether, PPPoE, type=0x8864)
+bind_layers( CookedLinux, PPPoED, proto=0x8863)
+bind_layers( CookedLinux, PPPoE, proto=0x8864)
+bind_layers( PPPoE, PPP, code=0)
+bind_layers( HDLC, PPP, )
+bind_layers( PPP, IP, proto=33)
+bind_layers( PPP, PPP_IPCP, proto=0x8021)
+bind_layers( PPP, PPP_ECP, proto=0x8053)
+bind_layers( Ether, PPP_IPCP, type=0x8021)
+bind_layers( Ether, PPP_ECP, type=0x8053)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/radius.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/radius.py
new file mode 100644
index 00000000..13239603
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/radius.py
@@ -0,0 +1,65 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+RADIUS (Remote Authentication Dial In User Service)
+"""
+
+import struct
+from scapy.packet import *
+from scapy.fields import *
+
+class Radius(Packet):
+ name = "Radius"
+ fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request",
+ 2: "Access-Accept",
+ 3: "Access-Reject",
+ 4: "Accounting-Request",
+ 5: "Accounting-Accept",
+ 6: "Accounting-Status",
+ 7: "Password-Request",
+ 8: "Password-Ack",
+ 9: "Password-Reject",
+ 10: "Accounting-Message",
+ 11: "Access-Challenge",
+ 12: "Status-Server",
+ 13: "Status-Client",
+ 21: "Resource-Free-Request",
+ 22: "Resource-Free-Response",
+ 23: "Resource-Query-Request",
+ 24: "Resource-Query-Response",
+ 25: "Alternate-Resource-Reclaim-Request",
+ 26: "NAS-Reboot-Request",
+ 27: "NAS-Reboot-Response",
+ 29: "Next-Passcode",
+ 30: "New-Pin",
+ 31: "Terminate-Session",
+ 32: "Password-Expired",
+ 33: "Event-Request",
+ 34: "Event-Response",
+ 40: "Disconnect-Request",
+ 41: "Disconnect-ACK",
+ 42: "Disconnect-NAK",
+ 43: "CoA-Request",
+ 44: "CoA-ACK",
+ 45: "CoA-NAK",
+ 50: "IP-Address-Allocate",
+ 51: "IP-Address-Release",
+ 253: "Experimental-use",
+ 254: "Reserved",
+ 255: "Reserved"} ),
+ ByteField("id", 0),
+ ShortField("len", None),
+ StrFixedLenField("authenticator","",16) ]
+ def post_build(self, p, pay):
+ p += pay
+ l = self.len
+ if l is None:
+ l = len(p)
+ p = p[:2]+struct.pack("!H",l)+p[4:]
+ return p
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/rip.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/rip.py
new file mode 100644
index 00000000..1507fe5c
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/rip.py
@@ -0,0 +1,74 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+RIP (Routing Information Protocol).
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import UDP
+
+class RIP(Packet):
+ name = "RIP header"
+ fields_desc = [
+ ByteEnumField("cmd", 1, {1:"req", 2:"resp", 3:"traceOn", 4:"traceOff",
+ 5:"sun", 6:"trigReq", 7:"trigResp", 8:"trigAck",
+ 9:"updateReq", 10:"updateResp", 11:"updateAck"}),
+ ByteField("version", 1),
+ ShortField("null", 0),
+ ]
+
+ def guess_payload_class(self, payload):
+ if payload[:2] == "\xff\xff":
+ return RIPAuth
+ else:
+ return Packet.guess_payload_class(self, payload)
+
+class RIPEntry(RIP):
+ name = "RIP entry"
+ fields_desc = [
+ ShortEnumField("AF", 2, {2:"IP"}),
+ ShortField("RouteTag", 0),
+ IPField("addr", "0.0.0.0"),
+ IPField("mask", "0.0.0.0"),
+ IPField("nextHop", "0.0.0.0"),
+ IntEnumField("metric", 1, {16:"Unreach"}),
+ ]
+
+class RIPAuth(Packet):
+ name = "RIP authentication"
+ fields_desc = [
+ ShortEnumField("AF", 0xffff, {0xffff:"Auth"}),
+ ShortEnumField("authtype", 2, {1:"md5authdata", 2:"simple", 3:"md5"}),
+ ConditionalField(StrFixedLenField("password", None, 16),
+ lambda pkt: pkt.authtype == 2),
+ ConditionalField(ShortField("digestoffset", 0),
+ lambda pkt: pkt.authtype == 3),
+ ConditionalField(ByteField("keyid", 0),
+ lambda pkt: pkt.authtype == 3),
+ ConditionalField(ByteField("authdatalen", 0),
+ lambda pkt: pkt.authtype == 3),
+ ConditionalField(IntField("seqnum", 0),
+ lambda pkt: pkt.authtype == 3),
+ ConditionalField(StrFixedLenField("zeropad", None, 8),
+ lambda pkt: pkt.authtype == 3),
+ ConditionalField(StrLenField("authdata", None,
+ length_from=lambda pkt: pkt.md5datalen),
+ lambda pkt: pkt.authtype == 1)
+ ]
+
+ def pre_dissect(self, s):
+ if s[2:4] == "\x00\x01":
+ self.md5datalen = len(s) - 4
+
+ return s
+
+
+bind_layers( UDP, RIP, sport=520)
+bind_layers( UDP, RIP, dport=520)
+bind_layers( RIP, RIPEntry, )
+bind_layers( RIPEntry, RIPEntry, )
+bind_layers( RIPAuth, RIPEntry, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/rtp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/rtp.py
new file mode 100644
index 00000000..629dccdd
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/rtp.py
@@ -0,0 +1,40 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+RTP (Real-time Transport Protocol).
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+
+_rtp_payload_types = {
+ # http://www.iana.org/assignments/rtp-parameters
+ 0: 'G.711 PCMU', 3: 'GSM',
+ 4: 'G723', 5: 'DVI4',
+ 6: 'DVI4', 7: 'LPC',
+ 8: 'PCMA', 9: 'G722',
+ 10: 'L16', 11: 'L16',
+ 12: 'QCELP', 13: 'CN',
+ 14: 'MPA', 15: 'G728',
+ 16: 'DVI4', 17: 'DVI4',
+ 18: 'G729', 25: 'CelB',
+ 26: 'JPEG', 28: 'nv',
+ 31: 'H261', 32: 'MPV',
+ 33: 'MP2T', 34: 'H263' }
+
+class RTP(Packet):
+ name="RTP"
+ fields_desc = [ BitField('version', 2, 2),
+ BitField('padding', 0, 1),
+ BitField('extension', 0, 1),
+ BitFieldLenField('numsync', None, 4, count_of='sync'),
+ BitField('marker', 0, 1),
+ BitEnumField('payload', 0, 7, _rtp_payload_types),
+ ShortField('sequence', 0),
+ IntField('timestamp', 0),
+ IntField('sourcesync', 0),
+ FieldListField('sync', [], IntField("id",0), count_from=lambda pkt:pkt.numsync) ]
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/sctp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/sctp.py
new file mode 100644
index 00000000..57712112
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/sctp.py
@@ -0,0 +1,439 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Copyright (C) 6WIND <olivier.matz@6wind.com>
+## This program is published under a GPLv2 license
+
+"""
+SCTP (Stream Control Transmission Protocol).
+"""
+
+import struct
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP
+from scapy.layers.inet6 import IP6Field
+
+IPPROTO_SCTP=132
+
+# crc32-c (Castagnoli) (crc32c_poly=0x1EDC6F41)
+crc32c_table = [
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
+ ]
+
+def crc32c(buf):
+ crc = 0xffffffff
+ for c in buf:
+ #crc = (crc>>8) ^ crc32c_table[(crc^(ord(c))) & 0xFF]
+ crc = (crc>>8) ^ crc32c_table[(crc^(c)) & 0xFF]
+ crc = (~crc) & 0xffffffff
+ # reverse endianness
+ return struct.unpack(">I",struct.pack("<I", crc))[0]
+
+# old checksum (RFC2960)
+"""
+BASE = 65521 # largest prime smaller than 65536
+def update_adler32(adler, buf):
+ s1 = adler & 0xffff
+ s2 = (adler >> 16) & 0xffff
+ print(s1,s2)
+
+ for c in buf:
+ print(ord(c))
+ s1 = (s1 + ord(c)) % BASE
+ s2 = (s2 + s1) % BASE
+ print(s1,s2)
+ return (s2 << 16) + s1
+
+def sctp_checksum(buf):
+ return update_adler32(1, buf)
+"""
+
+sctpchunktypescls = {
+ 0 : "SCTPChunkData",
+ 1 : "SCTPChunkInit",
+ 2 : "SCTPChunkInitAck",
+ 3 : "SCTPChunkSACK",
+ 4 : "SCTPChunkHeartbeatReq",
+ 5 : "SCTPChunkHeartbeatAck",
+ 6 : "SCTPChunkAbort",
+ 7 : "SCTPChunkShutdown",
+ 8 : "SCTPChunkShutdownAck",
+ 9 : "SCTPChunkError",
+ 10 : "SCTPChunkCookieEcho",
+ 11 : "SCTPChunkCookieAck",
+ 14 : "SCTPChunkShutdownComplete",
+ }
+
+sctpchunktypes = {
+ 0 : "data",
+ 1 : "init",
+ 2 : "init-ack",
+ 3 : "sack",
+ 4 : "heartbeat-req",
+ 5 : "heartbeat-ack",
+ 6 : "abort",
+ 7 : "shutdown",
+ 8 : "shutdown-ack",
+ 9 : "error",
+ 10 : "cookie-echo",
+ 11 : "cookie-ack",
+ 14 : "shutdown-complete",
+ }
+
+sctpchunkparamtypescls = {
+ 1 : "SCTPChunkParamHearbeatInfo",
+ 5 : "SCTPChunkParamIPv4Addr",
+ 6 : "SCTPChunkParamIPv6Addr",
+ 7 : "SCTPChunkParamStateCookie",
+ 8 : "SCTPChunkParamUnrocognizedParam",
+ 9 : "SCTPChunkParamCookiePreservative",
+ 11 : "SCTPChunkParamHostname",
+ 12 : "SCTPChunkParamSupportedAddrTypes",
+ 32768 : "SCTPChunkParamECNCapable",
+ 49152 : "SCTPChunkParamFwdTSN",
+ 49158 : "SCTPChunkParamAdaptationLayer",
+ }
+
+sctpchunkparamtypes = {
+ 1 : "heartbeat-info",
+ 5 : "IPv4",
+ 6 : "IPv6",
+ 7 : "state-cookie",
+ 8 : "unrecognized-param",
+ 9 : "cookie-preservative",
+ 11 : "hostname",
+ 12 : "addrtypes",
+ 32768 : "ecn-capable",
+ 49152 : "fwd-tsn-supported",
+ 49158 : "adaptation-layer",
+ }
+
+############## SCTP header
+
+# Dummy class to guess payload type (variable parameters)
+class _SCTPChunkGuessPayload:
+ def default_payload_class(self,p):
+ if len(p) < 4:
+ return conf.padding_layer
+ else:
+ t = p[0]
+ return globals().get(sctpchunktypescls.get(t, "Raw"), conf.raw_layer)
+
+
+class SCTP(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ShortField("sport", None),
+ ShortField("dport", None),
+ XIntField("tag", None),
+ XIntField("chksum", None), ]
+ def answers(self, other):
+ if not isinstance(other, SCTP):
+ return 0
+ if conf.checkIPsrc:
+ if not ((self.sport == other.dport) and
+ (self.dport == other.sport)):
+ return 0
+ return 1
+ def post_build(self, p, pay):
+ p += pay
+ if self.chksum is None:
+ crc = crc32c(str(p))
+ p = p[:8]+struct.pack(">I", crc)+p[12:]
+ return p
+
+############## SCTP Chunk variable params
+
+class ChunkParamField(PacketListField):
+ islist = 1
+ holds_packets=1
+ def __init__(self, name, default, count_from=None, length_from=None):
+ PacketListField.__init__(self, name, default, conf.raw_layer, count_from=count_from, length_from=length_from)
+ def m2i(self, p, m):
+ cls = conf.raw_layer
+ if len(m) >= 4:
+ #t = ord(m[0]) * 256 + ord(m[1])
+ t = (m[0]) * 256 + (m[1])
+ cls = globals().get(sctpchunkparamtypescls.get(t, "Raw"), conf.raw_layer)
+ return cls(m)
+
+# dummy class to avoid Raw() after Chunk params
+class _SCTPChunkParam:
+ def extract_padding(self, s):
+ return b"",s[:]
+
+class SCTPChunkParamHearbeatInfo(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 1, sctpchunkparamtypes),
+ FieldLenField("len", None, length_of="data",
+ adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("data", b"",
+ length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),]
+
+class SCTPChunkParamIPv4Addr(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 5, sctpchunkparamtypes),
+ ShortField("len", 8),
+ IPField("addr","127.0.0.1"), ]
+
+class SCTPChunkParamIPv6Addr(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 6, sctpchunkparamtypes),
+ ShortField("len", 20),
+ IP6Field("addr","::1"), ]
+
+class SCTPChunkParamStateCookie(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 7, sctpchunkparamtypes),
+ FieldLenField("len", None, length_of="cookie",
+ adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("cookie", b"",
+ length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),]
+
+class SCTPChunkParamUnrocognizedParam(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 8, sctpchunkparamtypes),
+ FieldLenField("len", None, length_of="param",
+ adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("param", b"",
+ length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),]
+
+class SCTPChunkParamCookiePreservative(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 9, sctpchunkparamtypes),
+ ShortField("len", 8),
+ XIntField("sug_cookie_inc", None), ]
+
+class SCTPChunkParamHostname(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 11, sctpchunkparamtypes),
+ FieldLenField("len", None, length_of="hostname",
+ adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("hostname", b"",
+ length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"), ]
+
+class SCTPChunkParamSupportedAddrTypes(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 12, sctpchunkparamtypes),
+ FieldLenField("len", None, length_of="addr_type_list",
+ adjust = lambda pkt,x:x+4),
+ PadField(FieldListField("addr_type_list", [ "IPv4" ],
+ ShortEnumField("addr_type", 5, sctpchunkparamtypes),
+ length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"), ]
+
+class SCTPChunkParamECNCapable(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 32768, sctpchunkparamtypes),
+ ShortField("len", 4), ]
+
+class SCTPChunkParamFwdTSN(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 49152, sctpchunkparamtypes),
+ ShortField("len", 4), ]
+
+class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet):
+ fields_desc = [ ShortEnumField("type", 49158, sctpchunkparamtypes),
+ ShortField("len", 8),
+ XIntField("indication", None), ]
+
+############## SCTP Chunks
+
+class SCTPChunkData(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 0, sctpchunktypes),
+ BitField("reserved", None, 4),
+ BitField("delay_sack", 0, 1),
+ BitField("unordered", 0, 1),
+ BitField("beginning", 0, 1),
+ BitField("ending", 0, 1),
+ FieldLenField("len", None, length_of="data", adjust = lambda pkt,x:x+16),
+ XIntField("tsn", None),
+ XShortField("stream_id", None),
+ XShortField("stream_seq", None),
+ XIntField("proto_id", None),
+ PadField(StrLenField("data", None, length_from=lambda pkt: pkt.len-16),
+ 4, padwith=b"\x00"),
+ ]
+
+class SCTPChunkInit(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 1, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="params", adjust = lambda pkt,x:x+20),
+ XIntField("init_tag", None),
+ IntField("a_rwnd", None),
+ ShortField("n_out_streams", None),
+ ShortField("n_in_streams", None),
+ XIntField("init_tsn", None),
+ ChunkParamField("params", None, length_from=lambda pkt:pkt.len-20),
+ ]
+
+class SCTPChunkInitAck(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 2, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="params", adjust = lambda pkt,x:x+20),
+ XIntField("init_tag", None),
+ IntField("a_rwnd", None),
+ ShortField("n_out_streams", None),
+ ShortField("n_in_streams", None),
+ XIntField("init_tsn", None),
+ ChunkParamField("params", None, length_from=lambda pkt:pkt.len-20),
+ ]
+
+class GapAckField(Field):
+ def __init__(self, name, default):
+ Field.__init__(self, name, default, "4s")
+ def i2m(self, pkt, x):
+ if x is None:
+ return "\0\0\0\0"
+ sta, end = map(int, x.split(":"))
+ args = tuple([">HH", sta, end])
+ return struct.pack(*args)
+ def m2i(self, pkt, x):
+ return "%d:%d"%(struct.unpack(">HH", x))
+ def any2i(self, pkt, x):
+ if type(x) is tuple and len(x) == 2:
+ return "%d:%d"%(x)
+ return x
+
+class SCTPChunkSACK(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 3, sctpchunktypes),
+ XByteField("flags", None),
+ ShortField("len", None),
+ XIntField("cumul_tsn_ack", None),
+ IntField("a_rwnd", None),
+ FieldLenField("n_gap_ack", None, count_of="gap_ack_list"),
+ FieldLenField("n_dup_tsn", None, count_of="dup_tsn_list"),
+ FieldListField("gap_ack_list", [ ], GapAckField("gap_ack", None), count_from=lambda pkt:pkt.n_gap_ack),
+ FieldListField("dup_tsn_list", [ ], XIntField("dup_tsn", None), count_from=lambda pkt:pkt.n_dup_tsn),
+ ]
+
+ def post_build(self, p, pay):
+ if self.len is None:
+ p = p[:2] + struct.pack(">H", len(p)) + p[4:]
+ return p+pay
+
+
+class SCTPChunkHeartbeatReq(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 4, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="params", adjust = lambda pkt,x:x+4),
+ ChunkParamField("params", None, length_from=lambda pkt:pkt.len-4),
+ ]
+
+class SCTPChunkHeartbeatAck(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 5, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="params", adjust = lambda pkt,x:x+4),
+ ChunkParamField("params", None, length_from=lambda pkt:pkt.len-4),
+ ]
+
+class SCTPChunkAbort(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 6, sctpchunktypes),
+ BitField("reserved", None, 7),
+ BitField("TCB", 0, 1),
+ FieldLenField("len", None, length_of="error_causes", adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("error_causes", b"", length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),
+ ]
+
+class SCTPChunkShutdown(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 7, sctpchunktypes),
+ XByteField("flags", None),
+ ShortField("len", 8),
+ XIntField("cumul_tsn_ack", None),
+ ]
+
+class SCTPChunkShutdownAck(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 8, sctpchunktypes),
+ XByteField("flags", None),
+ ShortField("len", 4),
+ ]
+
+class SCTPChunkError(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 9, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="error_causes", adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("error_causes", b"", length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),
+ ]
+
+class SCTPChunkCookieEcho(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 10, sctpchunktypes),
+ XByteField("flags", None),
+ FieldLenField("len", None, length_of="cookie", adjust = lambda pkt,x:x+4),
+ PadField(StrLenField("cookie", b"", length_from=lambda pkt: pkt.len-4),
+ 4, padwith=b"\x00"),
+ ]
+
+class SCTPChunkCookieAck(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 11, sctpchunktypes),
+ XByteField("flags", None),
+ ShortField("len", 4),
+ ]
+
+class SCTPChunkShutdownComplete(_SCTPChunkGuessPayload, Packet):
+ fields_desc = [ ByteEnumField("type", 12, sctpchunktypes),
+ BitField("reserved", None, 7),
+ BitField("TCB", 0, 1),
+ ShortField("len", 4),
+ ]
+
+bind_layers( IP, SCTP, proto=IPPROTO_SCTP)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/sebek.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/sebek.py
new file mode 100644
index 00000000..c54e6728
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/sebek.py
@@ -0,0 +1,109 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Sebek: Linux kernel module for data collection on honeypots.
+"""
+
+from scapy.fields import *
+from scapy.packet import *
+from scapy.layers.inet import UDP
+
+
+### SEBEK
+
+
+class SebekHead(Packet):
+ name = "Sebek header"
+ fields_desc = [ XIntField("magic", 0xd0d0d0),
+ ShortField("version", 1),
+ ShortEnumField("type", 0, {"read":0, "write":1,
+ "socket":2, "open":3}),
+ IntField("counter", 0),
+ IntField("time_sec", 0),
+ IntField("time_usec", 0) ]
+ def mysummary(self):
+ return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%")
+
+# we need this because Sebek headers differ between v1 and v3, and
+# between v3 type socket and v3 others
+
+class SebekV1(Packet):
+ name = "Sebek v1"
+ fields_desc = [ IntField("pid", 0),
+ IntField("uid", 0),
+ IntField("fd", 0),
+ StrFixedLenField("command", "", 12),
+ FieldLenField("data_length", None, "data",fmt="I"),
+ StrLenField("data", "", length_from=lambda x:x.data_length) ]
+ def mysummary(self):
+ if isinstance(self.underlayer, SebekHead):
+ return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.command%)")
+ else:
+ return self.sprintf("Sebek v1 (%SebekV1.command%)")
+
+class SebekV3(Packet):
+ name = "Sebek v3"
+ fields_desc = [ IntField("parent_pid", 0),
+ IntField("pid", 0),
+ IntField("uid", 0),
+ IntField("fd", 0),
+ IntField("inode", 0),
+ StrFixedLenField("command", "", 12),
+ FieldLenField("data_length", None, "data",fmt="I"),
+ StrLenField("data", "", length_from=lambda x:x.data_length) ]
+ def mysummary(self):
+ if isinstance(self.underlayer, SebekHead):
+ return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.command%)")
+ else:
+ return self.sprintf("Sebek v3 (%SebekV3.command%)")
+
+class SebekV2(SebekV3):
+ def mysummary(self):
+ if isinstance(self.underlayer, SebekHead):
+ return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.command%)")
+ else:
+ return self.sprintf("Sebek v2 (%SebekV2.command%)")
+
+class SebekV3Sock(Packet):
+ name = "Sebek v2 socket"
+ fields_desc = [ IntField("parent_pid", 0),
+ IntField("pid", 0),
+ IntField("uid", 0),
+ IntField("fd", 0),
+ IntField("inode", 0),
+ StrFixedLenField("command", "", 12),
+ IntField("data_length", 15),
+ IPField("dip", "127.0.0.1"),
+ ShortField("dport", 0),
+ IPField("sip", "127.0.0.1"),
+ ShortField("sport", 0),
+ ShortEnumField("call", 0, { "bind":2,
+ "connect":3, "listen":4,
+ "accept":5, "sendmsg":16,
+ "recvmsg":17, "sendto":11,
+ "recvfrom":12}),
+ ByteEnumField("proto", 0, IP_PROTOS) ]
+ def mysummary(self):
+ if isinstance(self.underlayer, SebekHead):
+ return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.command%)")
+ else:
+ return self.sprintf("Sebek v3 socket (%SebekV3Sock.command%)")
+
+class SebekV2Sock(SebekV3Sock):
+ def mysummary(self):
+ if isinstance(self.underlayer, SebekHead):
+ return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.command%)")
+ else:
+ return self.sprintf("Sebek v2 socket (%SebekV2Sock.command%)")
+
+bind_layers( UDP, SebekHead, sport=1101)
+bind_layers( UDP, SebekHead, dport=1101)
+bind_layers( UDP, SebekHead, dport=1101, sport=1101)
+bind_layers( SebekHead, SebekV1, version=1)
+bind_layers( SebekHead, SebekV2Sock, version=2, type=2)
+bind_layers( SebekHead, SebekV2, version=2)
+bind_layers( SebekHead, SebekV3Sock, version=3, type=2)
+bind_layers( SebekHead, SebekV3, version=3)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/skinny.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/skinny.py
new file mode 100644
index 00000000..9fb6ac06
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/skinny.py
@@ -0,0 +1,161 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Cisco Skinny protocol.
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import TCP
+
+# shamelessly ripped from Ethereal dissector
+skinny_messages = {
+# Station -> Callmanager
+ 0x0000: "KeepAliveMessage",
+ 0x0001: "RegisterMessage",
+ 0x0002: "IpPortMessage",
+ 0x0003: "KeypadButtonMessage",
+ 0x0004: "EnblocCallMessage",
+ 0x0005: "StimulusMessage",
+ 0x0006: "OffHookMessage",
+ 0x0007: "OnHookMessage",
+ 0x0008: "HookFlashMessage",
+ 0x0009: "ForwardStatReqMessage",
+ 0x000A: "SpeedDialStatReqMessage",
+ 0x000B: "LineStatReqMessage",
+ 0x000C: "ConfigStatReqMessage",
+ 0x000D: "TimeDateReqMessage",
+ 0x000E: "ButtonTemplateReqMessage",
+ 0x000F: "VersionReqMessage",
+ 0x0010: "CapabilitiesResMessage",
+ 0x0011: "MediaPortListMessage",
+ 0x0012: "ServerReqMessage",
+ 0x0020: "AlarmMessage",
+ 0x0021: "MulticastMediaReceptionAck",
+ 0x0022: "OpenReceiveChannelAck",
+ 0x0023: "ConnectionStatisticsRes",
+ 0x0024: "OffHookWithCgpnMessage",
+ 0x0025: "SoftKeySetReqMessage",
+ 0x0026: "SoftKeyEventMessage",
+ 0x0027: "UnregisterMessage",
+ 0x0028: "SoftKeyTemplateReqMessage",
+ 0x0029: "RegisterTokenReq",
+ 0x002A: "MediaTransmissionFailure",
+ 0x002B: "HeadsetStatusMessage",
+ 0x002C: "MediaResourceNotification",
+ 0x002D: "RegisterAvailableLinesMessage",
+ 0x002E: "DeviceToUserDataMessage",
+ 0x002F: "DeviceToUserDataResponseMessage",
+ 0x0030: "UpdateCapabilitiesMessage",
+ 0x0031: "OpenMultiMediaReceiveChannelAckMessage",
+ 0x0032: "ClearConferenceMessage",
+ 0x0033: "ServiceURLStatReqMessage",
+ 0x0034: "FeatureStatReqMessage",
+ 0x0035: "CreateConferenceResMessage",
+ 0x0036: "DeleteConferenceResMessage",
+ 0x0037: "ModifyConferenceResMessage",
+ 0x0038: "AddParticipantResMessage",
+ 0x0039: "AuditConferenceResMessage",
+ 0x0040: "AuditParticipantResMessage",
+ 0x0041: "DeviceToUserDataVersion1Message",
+# Callmanager -> Station */
+ 0x0081: "RegisterAckMessage",
+ 0x0082: "StartToneMessage",
+ 0x0083: "StopToneMessage",
+ 0x0085: "SetRingerMessage",
+ 0x0086: "SetLampMessage",
+ 0x0087: "SetHkFDetectMessage",
+ 0x0088: "SetSpeakerModeMessage",
+ 0x0089: "SetMicroModeMessage",
+ 0x008A: "StartMediaTransmission",
+ 0x008B: "StopMediaTransmission",
+ 0x008C: "StartMediaReception",
+ 0x008D: "StopMediaReception",
+ 0x008F: "CallInfoMessage",
+ 0x0090: "ForwardStatMessage",
+ 0x0091: "SpeedDialStatMessage",
+ 0x0092: "LineStatMessage",
+ 0x0093: "ConfigStatMessage",
+ 0x0094: "DefineTimeDate",
+ 0x0095: "StartSessionTransmission",
+ 0x0096: "StopSessionTransmission",
+ 0x0097: "ButtonTemplateMessage",
+ 0x0098: "VersionMessage",
+ 0x0099: "DisplayTextMessage",
+ 0x009A: "ClearDisplay",
+ 0x009B: "CapabilitiesReqMessage",
+ 0x009C: "EnunciatorCommandMessage",
+ 0x009D: "RegisterRejectMessage",
+ 0x009E: "ServerResMessage",
+ 0x009F: "Reset",
+ 0x0100: "KeepAliveAckMessage",
+ 0x0101: "StartMulticastMediaReception",
+ 0x0102: "StartMulticastMediaTransmission",
+ 0x0103: "StopMulticastMediaReception",
+ 0x0104: "StopMulticastMediaTransmission",
+ 0x0105: "OpenReceiveChannel",
+ 0x0106: "CloseReceiveChannel",
+ 0x0107: "ConnectionStatisticsReq",
+ 0x0108: "SoftKeyTemplateResMessage",
+ 0x0109: "SoftKeySetResMessage",
+ 0x0110: "SelectSoftKeysMessage",
+ 0x0111: "CallStateMessage",
+ 0x0112: "DisplayPromptStatusMessage",
+ 0x0113: "ClearPromptStatusMessage",
+ 0x0114: "DisplayNotifyMessage",
+ 0x0115: "ClearNotifyMessage",
+ 0x0116: "ActivateCallPlaneMessage",
+ 0x0117: "DeactivateCallPlaneMessage",
+ 0x0118: "UnregisterAckMessage",
+ 0x0119: "BackSpaceReqMessage",
+ 0x011A: "RegisterTokenAck",
+ 0x011B: "RegisterTokenReject",
+ 0x0042: "DeviceToUserDataResponseVersion1Message",
+ 0x011C: "StartMediaFailureDetection",
+ 0x011D: "DialedNumberMessage",
+ 0x011E: "UserToDeviceDataMessage",
+ 0x011F: "FeatureStatMessage",
+ 0x0120: "DisplayPriNotifyMessage",
+ 0x0121: "ClearPriNotifyMessage",
+ 0x0122: "StartAnnouncementMessage",
+ 0x0123: "StopAnnouncementMessage",
+ 0x0124: "AnnouncementFinishMessage",
+ 0x0127: "NotifyDtmfToneMessage",
+ 0x0128: "SendDtmfToneMessage",
+ 0x0129: "SubscribeDtmfPayloadReqMessage",
+ 0x012A: "SubscribeDtmfPayloadResMessage",
+ 0x012B: "SubscribeDtmfPayloadErrMessage",
+ 0x012C: "UnSubscribeDtmfPayloadReqMessage",
+ 0x012D: "UnSubscribeDtmfPayloadResMessage",
+ 0x012E: "UnSubscribeDtmfPayloadErrMessage",
+ 0x012F: "ServiceURLStatMessage",
+ 0x0130: "CallSelectStatMessage",
+ 0x0131: "OpenMultiMediaChannelMessage",
+ 0x0132: "StartMultiMediaTransmission",
+ 0x0133: "StopMultiMediaTransmission",
+ 0x0134: "MiscellaneousCommandMessage",
+ 0x0135: "FlowControlCommandMessage",
+ 0x0136: "CloseMultiMediaReceiveChannel",
+ 0x0137: "CreateConferenceReqMessage",
+ 0x0138: "DeleteConferenceReqMessage",
+ 0x0139: "ModifyConferenceReqMessage",
+ 0x013A: "AddParticipantReqMessage",
+ 0x013B: "DropParticipantReqMessage",
+ 0x013C: "AuditConferenceReqMessage",
+ 0x013D: "AuditParticipantReqMessage",
+ 0x013F: "UserToDeviceDataVersion1Message",
+ }
+
+
+
+class Skinny(Packet):
+ name="Skinny"
+ fields_desc = [ LEIntField("len",0),
+ LEIntField("res",0),
+ LEIntEnumField("msg",0,skinny_messages) ]
+
+bind_layers( TCP, Skinny, dport=2000)
+bind_layers( TCP, Skinny, sport=2000)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/smb.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/smb.py
new file mode 100644
index 00000000..f8e0da7a
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/smb.py
@@ -0,0 +1,354 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+SMB (Server Message Block), also known as CIFS.
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.netbios import NBTSession
+
+
+# SMB NetLogon Response Header
+class SMBNetlogon_Protocol_Response_Header(Packet):
+ name="SMBNetlogon Protocol Response Header"
+ fields_desc = [StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x25,{0x25:"Trans"}),
+ ByteField("Error_Class",0x02),
+ ByteField("Reserved",0),
+ LEShortField("Error_code",4),
+ ByteField("Flags",0),
+ LEShortField("Flags2",0x0000),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",0),
+ LEShortField("UID",0),
+ LEShortField("MID",0),
+ ByteField("WordCount",17),
+ LEShortField("TotalParamCount",0),
+ LEShortField("TotalDataCount",112),
+ LEShortField("MaxParamCount",0),
+ LEShortField("MaxDataCount",0),
+ ByteField("MaxSetupCount",0),
+ ByteField("unused2",0),
+ LEShortField("Flags3",0),
+ ByteField("TimeOut1",0xe8),
+ ByteField("TimeOut2",0x03),
+ LEShortField("unused3",0),
+ LEShortField("unused4",0),
+ LEShortField("ParamCount2",0),
+ LEShortField("ParamOffset",0),
+ LEShortField("DataCount",112),
+ LEShortField("DataOffset",92),
+ ByteField("SetupCount", 3),
+ ByteField("unused5", 0)]
+
+# SMB MailSlot Protocol
+class SMBMailSlot(Packet):
+ name = "SMB Mail Slot Protocol"
+ fields_desc = [LEShortField("opcode", 1),
+ LEShortField("priority", 1),
+ LEShortField("class", 2),
+ LEShortField("size", 135),
+ StrNullField("name","\\MAILSLOT\\NET\\GETDC660")]
+
+# SMB NetLogon Protocol Response Tail SAM
+class SMBNetlogon_Protocol_Response_Tail_SAM(Packet):
+ name = "SMB Netlogon Protocol Response Tail SAM"
+ fields_desc = [ByteEnumField("Command", 0x17, {0x12:"SAM logon request", 0x17:"SAM Active directory Response"}),
+ ByteField("unused", 0),
+ ShortField("Data1", 0),
+ ShortField("Data2", 0xfd01),
+ ShortField("Data3", 0),
+ ShortField("Data4", 0xacde),
+ ShortField("Data5", 0x0fe5),
+ ShortField("Data6", 0xd10a),
+ ShortField("Data7", 0x374c),
+ ShortField("Data8", 0x83e2),
+ ShortField("Data9", 0x7dd9),
+ ShortField("Data10", 0x3a16),
+ ShortField("Data11", 0x73ff),
+ ByteField("Data12", 0x04),
+ StrFixedLenField("Data13", "rmff", 4),
+ ByteField("Data14", 0x0),
+ ShortField("Data16", 0xc018),
+ ByteField("Data18", 0x0a),
+ StrFixedLenField("Data20", "rmff-win2k", 10),
+ ByteField("Data21", 0xc0),
+ ShortField("Data22", 0x18c0),
+ ShortField("Data23", 0x180a),
+ StrFixedLenField("Data24", "RMFF-WIN2K", 10),
+ ShortField("Data25", 0),
+ ByteField("Data26", 0x17),
+ StrFixedLenField("Data27", "Default-First-Site-Name", 23),
+ ShortField("Data28", 0x00c0),
+ ShortField("Data29", 0x3c10),
+ ShortField("Data30", 0x00c0),
+ ShortField("Data31", 0x0200),
+ ShortField("Data32", 0x0),
+ ShortField("Data33", 0xac14),
+ ShortField("Data34", 0x0064),
+ ShortField("Data35", 0x0),
+ ShortField("Data36", 0x0),
+ ShortField("Data37", 0x0),
+ ShortField("Data38", 0x0),
+ ShortField("Data39", 0x0d00),
+ ShortField("Data40", 0x0),
+ ShortField("Data41", 0xffff)]
+
+# SMB NetLogon Protocol Response Tail LM2.0
+class SMBNetlogon_Protocol_Response_Tail_LM20(Packet):
+ name = "SMB Netlogon Protocol Response Tail LM20"
+ fields_desc = [ByteEnumField("Command",0x06,{0x06:"LM 2.0 Response to logon request"}),
+ ByteField("unused", 0),
+ StrFixedLenField("DblSlash", "\\\\", 2),
+ StrNullField("ServerName","WIN"),
+ LEShortField("LM20Token", 0xffff)]
+
+# SMBNegociate Protocol Request Header
+class SMBNegociate_Protocol_Request_Header(Packet):
+ name="SMBNegociate Protocol Request Header"
+ fields_desc = [StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_code",0),
+ ByteField("Flags",0x18),
+ LEShortField("Flags2",0x0000),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",0),
+ LEShortField("ByteCount",12)]
+
+# SMB Negociate Protocol Request Tail
+class SMBNegociate_Protocol_Request_Tail(Packet):
+ name="SMB Negociate Protocol Request Tail"
+ fields_desc=[ByteField("BufferFormat",0x02),
+ StrNullField("BufferData","NT LM 0.12")]
+
+# SMBNegociate Protocol Response Advanced Security
+class SMBNegociate_Protocol_Response_Advanced_Security(Packet):
+ name="SMBNegociate Protocol Response Advanced Security"
+ fields_desc = [StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_Code",0),
+ ByteField("Flags",0x98),
+ LEShortField("Flags2",0x0000),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",17),
+ LEShortField("DialectIndex",7),
+ ByteField("SecurityMode",0x03),
+ LEShortField("MaxMpxCount",50),
+ LEShortField("MaxNumberVC",1),
+ LEIntField("MaxBufferSize",16144),
+ LEIntField("MaxRawSize",65536),
+ LEIntField("SessionKey",0x0000),
+ LEShortField("ServerCapabilities",0xf3f9),
+ BitField("UnixExtensions",0,1),
+ BitField("Reserved2",0,7),
+ BitField("ExtendedSecurity",1,1),
+ BitField("CompBulk",0,2),
+ BitField("Reserved3",0,5),
+# There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
+ LEIntField("ServerTimeHigh",0xD6228000),
+ LEIntField("ServerTimeLow",0x1C4EF94),
+ LEShortField("ServerTimeZone",0x3c),
+ ByteField("EncryptionKeyLength",0),
+ LEFieldLenField("ByteCount", None, "SecurityBlob", adjust=lambda pkt,x:x-16),
+ BitField("GUID",0,128),
+ StrLenField("SecurityBlob", "", length_from=lambda x:x.ByteCount+16)]
+
+# SMBNegociate Protocol Response No Security
+# When using no security, with EncryptionKeyLength=8, you must have an EncryptionKey before the DomainName
+class SMBNegociate_Protocol_Response_No_Security(Packet):
+ name="SMBNegociate Protocol Response No Security"
+ fields_desc = [StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_Code",0),
+ ByteField("Flags",0x98),
+ LEShortField("Flags2",0x0000),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",17),
+ LEShortField("DialectIndex",7),
+ ByteField("SecurityMode",0x03),
+ LEShortField("MaxMpxCount",50),
+ LEShortField("MaxNumberVC",1),
+ LEIntField("MaxBufferSize",16144),
+ LEIntField("MaxRawSize",65536),
+ LEIntField("SessionKey",0x0000),
+ LEShortField("ServerCapabilities",0xf3f9),
+ BitField("UnixExtensions",0,1),
+ BitField("Reserved2",0,7),
+ BitField("ExtendedSecurity",0,1),
+ FlagsField("CompBulk",0,2,"CB"),
+ BitField("Reserved3",0,5),
+ # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
+ LEIntField("ServerTimeHigh",0xD6228000),
+ LEIntField("ServerTimeLow",0x1C4EF94),
+ LEShortField("ServerTimeZone",0x3c),
+ ByteField("EncryptionKeyLength",8),
+ LEShortField("ByteCount",24),
+ BitField("EncryptionKey",0,64),
+ StrNullField("DomainName","WORKGROUP"),
+ StrNullField("ServerName","RMFF1")]
+
+# SMBNegociate Protocol Response No Security No Key
+class SMBNegociate_Protocol_Response_No_Security_No_Key(Packet):
+ namez="SMBNegociate Protocol Response No Security No Key"
+ fields_desc = [StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_Code",0),
+ ByteField("Flags",0x98),
+ LEShortField("Flags2",0x0000),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",17),
+ LEShortField("DialectIndex",7),
+ ByteField("SecurityMode",0x03),
+ LEShortField("MaxMpxCount",50),
+ LEShortField("MaxNumberVC",1),
+ LEIntField("MaxBufferSize",16144),
+ LEIntField("MaxRawSize",65536),
+ LEIntField("SessionKey",0x0000),
+ LEShortField("ServerCapabilities",0xf3f9),
+ BitField("UnixExtensions",0,1),
+ BitField("Reserved2",0,7),
+ BitField("ExtendedSecurity",0,1),
+ FlagsField("CompBulk",0,2,"CB"),
+ BitField("Reserved3",0,5),
+ # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
+ LEIntField("ServerTimeHigh",0xD6228000),
+ LEIntField("ServerTimeLow",0x1C4EF94),
+ LEShortField("ServerTimeZone",0x3c),
+ ByteField("EncryptionKeyLength",0),
+ LEShortField("ByteCount",16),
+ StrNullField("DomainName","WORKGROUP"),
+ StrNullField("ServerName","RMFF1")]
+
+# Session Setup AndX Request
+class SMBSession_Setup_AndX_Request(Packet):
+ name="Session Setup AndX Request"
+ fields_desc=[StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_Code",0),
+ ByteField("Flags",0x18),
+ LEShortField("Flags2",0x0001),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",13),
+ ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
+ ByteField("Reserved2",0),
+ LEShortField("AndXOffset",96),
+ LEShortField("MaxBufferS",2920),
+ LEShortField("MaxMPXCount",50),
+ LEShortField("VCNumber",0),
+ LEIntField("SessionKey",0),
+ LEFieldLenField("ANSIPasswordLength",None,"ANSIPassword"),
+ LEShortField("UnicodePasswordLength",0),
+ LEIntField("Reserved3",0),
+ LEShortField("ServerCapabilities",0x05),
+ BitField("UnixExtensions",0,1),
+ BitField("Reserved4",0,7),
+ BitField("ExtendedSecurity",0,1),
+ BitField("CompBulk",0,2),
+ BitField("Reserved5",0,5),
+ LEShortField("ByteCount",35),
+ StrLenField("ANSIPassword", "Pass",length_from=lambda x:x.ANSIPasswordLength),
+ StrNullField("Account","GUEST"),
+ StrNullField("PrimaryDomain", ""),
+ StrNullField("NativeOS","Windows 4.0"),
+ StrNullField("NativeLanManager","Windows 4.0"),
+ ByteField("WordCount2",4),
+ ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
+ ByteField("Reserved6",0),
+ LEShortField("AndXOffset2",0),
+ LEShortField("Flags3",0x2),
+ LEShortField("PasswordLength",0x1),
+ LEShortField("ByteCount2",18),
+ ByteField("Password",0),
+ StrNullField("Path","\\\\WIN2K\\IPC$"),
+ StrNullField("Service","IPC")]
+
+# Session Setup AndX Response
+class SMBSession_Setup_AndX_Response(Packet):
+ name="Session Setup AndX Response"
+ fields_desc=[StrFixedLenField("Start","\xffSMB",4),
+ ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
+ ByteField("Error_Class",0),
+ ByteField("Reserved",0),
+ LEShortField("Error_Code",0),
+ ByteField("Flags",0x90),
+ LEShortField("Flags2",0x1001),
+ LEShortField("PIDHigh",0x0000),
+ LELongField("Signature",0x0),
+ LEShortField("Unused",0x0),
+ LEShortField("TID",0),
+ LEShortField("PID",1),
+ LEShortField("UID",0),
+ LEShortField("MID",2),
+ ByteField("WordCount",3),
+ ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
+ ByteField("Reserved2",0),
+ LEShortField("AndXOffset",66),
+ LEShortField("Action",0),
+ LEShortField("ByteCount",25),
+ StrNullField("NativeOS","Windows 4.0"),
+ StrNullField("NativeLanManager","Windows 4.0"),
+ StrNullField("PrimaryDomain",""),
+ ByteField("WordCount2",3),
+ ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
+ ByteField("Reserved3",0),
+ LEShortField("AndXOffset2",80),
+ LEShortField("OptionalSupport",0x01),
+ LEShortField("ByteCount2",5),
+ StrNullField("Service","IPC"),
+ StrNullField("NativeFileSystem","")]
+
+bind_layers( NBTSession, SMBNegociate_Protocol_Request_Header, )
+bind_layers( NBTSession, SMBNegociate_Protocol_Response_Advanced_Security, ExtendedSecurity=1)
+bind_layers( NBTSession, SMBNegociate_Protocol_Response_No_Security, ExtendedSecurity=0, EncryptionKeyLength=8)
+bind_layers( NBTSession, SMBNegociate_Protocol_Response_No_Security_No_Key, ExtendedSecurity=0, EncryptionKeyLength=0)
+bind_layers( NBTSession, SMBSession_Setup_AndX_Request, )
+bind_layers( NBTSession, SMBSession_Setup_AndX_Response, )
+bind_layers( SMBNegociate_Protocol_Request_Header, SMBNegociate_Protocol_Request_Tail, )
+bind_layers( SMBNegociate_Protocol_Request_Tail, SMBNegociate_Protocol_Request_Tail, )
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/snmp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/snmp.py
new file mode 100644
index 00000000..dddd4e27
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/snmp.py
@@ -0,0 +1,255 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+SNMP (Simple Network Management Protocol).
+"""
+
+from scapy.asn1packet import *
+from scapy.asn1fields import *
+from scapy.layers.inet import UDP
+
+##########
+## SNMP ##
+##########
+
+######[ ASN1 class ]######
+
+class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):
+ name="SNMP"
+ PDU_GET = 0xa0
+ PDU_NEXT = 0xa1
+ PDU_RESPONSE = 0xa2
+ PDU_SET = 0xa3
+ PDU_TRAPv1 = 0xa4
+ PDU_BULK = 0xa5
+ PDU_INFORM = 0xa6
+ PDU_TRAPv2 = 0xa7
+
+
+class ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_GET
+
+class ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_NEXT
+
+class ASN1_SNMP_PDU_RESPONSE(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_RESPONSE
+
+class ASN1_SNMP_PDU_SET(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_SET
+
+class ASN1_SNMP_PDU_TRAPv1(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_TRAPv1
+
+class ASN1_SNMP_PDU_BULK(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_BULK
+
+class ASN1_SNMP_PDU_INFORM(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_INFORM
+
+class ASN1_SNMP_PDU_TRAPv2(ASN1_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_TRAPv2
+
+
+######[ BER codecs ]#######
+
+class BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_GET
+
+class BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_NEXT
+
+class BERcodec_SNMP_PDU_RESPONSE(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_RESPONSE
+
+class BERcodec_SNMP_PDU_SET(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_SET
+
+class BERcodec_SNMP_PDU_TRAPv1(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_TRAPv1
+
+class BERcodec_SNMP_PDU_BULK(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_BULK
+
+class BERcodec_SNMP_PDU_INFORM(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_INFORM
+
+class BERcodec_SNMP_PDU_TRAPv2(BERcodec_SEQUENCE):
+ tag = ASN1_Class_SNMP.PDU_TRAPv2
+
+
+
+######[ ASN1 fields ]######
+
+class ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_GET
+
+class ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_NEXT
+
+class ASN1F_SNMP_PDU_RESPONSE(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_RESPONSE
+
+class ASN1F_SNMP_PDU_SET(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_SET
+
+class ASN1F_SNMP_PDU_TRAPv1(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv1
+
+class ASN1F_SNMP_PDU_BULK(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_BULK
+
+class ASN1F_SNMP_PDU_INFORM(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_INFORM
+
+class ASN1F_SNMP_PDU_TRAPv2(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv2
+
+
+
+######[ SNMP Packet ]######
+
+SNMP_error = { 0: "no_error",
+ 1: "too_big",
+ 2: "no_such_name",
+ 3: "bad_value",
+ 4: "read_only",
+ 5: "generic_error",
+ 6: "no_access",
+ 7: "wrong_type",
+ 8: "wrong_length",
+ 9: "wrong_encoding",
+ 10: "wrong_value",
+ 11: "no_creation",
+ 12: "inconsistent_value",
+ 13: "ressource_unavailable",
+ 14: "commit_failed",
+ 15: "undo_failed",
+ 16: "authorization_error",
+ 17: "not_writable",
+ 18: "inconsistent_name",
+ }
+
+SNMP_trap_types = { 0: "cold_start",
+ 1: "warm_start",
+ 2: "link_down",
+ 3: "link_up",
+ 4: "auth_failure",
+ 5: "egp_neigh_loss",
+ 6: "enterprise_specific",
+ }
+
+class SNMPvarbind(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SEQUENCE( ASN1F_OID("oid","1.3"),
+ ASN1F_field("value",ASN1_NULL(0))
+ )
+
+
+class SNMPget(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_GET( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPnext(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_NEXT( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPresponse(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_RESPONSE( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPset(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_SET( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPtrapv1(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_OID("enterprise", "1.3"),
+ ASN1F_IPADDRESS("agent_addr","0.0.0.0"),
+ ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types),
+ ASN1F_INTEGER("specific_trap", 0),
+ ASN1F_TIME_TICKS("time_stamp", IntAutoTime()),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPbulk(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_BULK( ASN1F_INTEGER("id",0),
+ ASN1F_INTEGER("non_repeaters",0),
+ ASN1F_INTEGER("max_repetitions",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPinform(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_INFORM( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+class SNMPtrapv2(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SNMP_PDU_TRAPv2( ASN1F_INTEGER("id",0),
+ ASN1F_enum_INTEGER("error",0, SNMP_error),
+ ASN1F_INTEGER("error_index",0),
+ ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
+ )
+
+
+class SNMP(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SEQUENCE(
+ ASN1F_enum_INTEGER("version", 1, {0:"v1", 1:"v2c", 2:"v2", 3:"v3"}),
+ ASN1F_STRING("community",b"public"),
+ ASN1F_CHOICE("PDU", SNMPget(),
+ SNMPget, SNMPnext, SNMPresponse, SNMPset,
+ SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)
+ )
+ def answers(self, other):
+ return ( isinstance(self.PDU, SNMPresponse) and
+ ( isinstance(other.PDU, SNMPget) or
+ isinstance(other.PDU, SNMPnext) or
+ isinstance(other.PDU, SNMPset) ) and
+ self.PDU.id == other.PDU.id )
+
+bind_layers( UDP, SNMP, sport=161)
+bind_layers( UDP, SNMP, dport=161)
+bind_layers( UDP, SNMP, sport=162)
+bind_layers( UDP, SNMP, dport=162)
+
+def snmpwalk(dst, oid="1", community=b"public"):
+ try:
+ while 1:
+ r = sr1(IP(dst=dst)/UDP(sport=RandShort())/SNMP(community=community, PDU=SNMPnext(varbindlist=[SNMPvarbind(oid=oid)])),timeout=2, chainCC=1, verbose=0, retry=2)
+ if ICMP in r:
+ print(repr(r))
+ break
+ if r is None:
+ print("No answers")
+ break
+ print("%-40s: %r" % (r[SNMPvarbind].oid.val,r[SNMPvarbind].value))
+ oid = r[SNMPvarbind].oid
+
+ except KeyboardInterrupt:
+ pass
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/tftp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/tftp.py
new file mode 100644
index 00000000..1535e99c
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/tftp.py
@@ -0,0 +1,477 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+TFTP (Trivial File Transfer Protocol).
+"""
+
+import os,random
+from scapy.packet import *
+from scapy.fields import *
+from scapy.automaton import *
+from scapy.layers.inet import UDP
+
+
+
+TFTP_operations = { 1:"RRQ",2:"WRQ",3:"DATA",4:"ACK",5:"ERROR",6:"OACK" }
+
+
+class TFTP(Packet):
+ name = "TFTP opcode"
+ fields_desc = [ ShortEnumField("op", 1, TFTP_operations), ]
+
+
+
+class TFTP_RRQ(Packet):
+ name = "TFTP Read Request"
+ fields_desc = [ StrNullField("filename", ""),
+ StrNullField("mode", "octet") ]
+ def answers(self, other):
+ return 0
+ def mysummary(self):
+ return self.sprintf("RRQ %filename%"),[UDP]
+
+
+class TFTP_WRQ(Packet):
+ name = "TFTP Write Request"
+ fields_desc = [ StrNullField("filename", ""),
+ StrNullField("mode", "octet") ]
+ def answers(self, other):
+ return 0
+ def mysummary(self):
+ return self.sprintf("WRQ %filename%"),[UDP]
+
+class TFTP_DATA(Packet):
+ name = "TFTP Data"
+ fields_desc = [ ShortField("block", 0) ]
+ def answers(self, other):
+ return self.block == 1 and isinstance(other, TFTP_RRQ)
+ def mysummary(self):
+ return self.sprintf("DATA %block%"),[UDP]
+
+class TFTP_Option(Packet):
+ fields_desc = [ StrNullField("oname",""),
+ StrNullField("value","") ]
+ def extract_padding(self, pkt):
+ return "",pkt
+
+class TFTP_Options(Packet):
+ fields_desc = [ PacketListField("options", [], TFTP_Option, length_from=lambda x:None) ]
+
+
+class TFTP_ACK(Packet):
+ name = "TFTP Ack"
+ fields_desc = [ ShortField("block", 0) ]
+ def answers(self, other):
+ if isinstance(other, TFTP_DATA):
+ return self.block == other.block
+ elif isinstance(other, TFTP_RRQ) or isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_OACK):
+ return self.block == 0
+ return 0
+ def mysummary(self):
+ return self.sprintf("ACK %block%"),[UDP]
+
+TFTP_Error_Codes = { 0: "Not defined",
+ 1: "File not found",
+ 2: "Access violation",
+ 3: "Disk full or allocation exceeded",
+ 4: "Illegal TFTP operation",
+ 5: "Unknown transfer ID",
+ 6: "File already exists",
+ 7: "No such user",
+ 8: "Terminate transfer due to option negotiation",
+ }
+
+class TFTP_ERROR(Packet):
+ name = "TFTP Error"
+ fields_desc = [ ShortEnumField("errorcode", 0, TFTP_Error_Codes),
+ StrNullField("errormsg", "")]
+ def answers(self, other):
+ return (isinstance(other, TFTP_DATA) or
+ isinstance(other, TFTP_RRQ) or
+ isinstance(other, TFTP_WRQ) or
+ isinstance(other, TFTP_ACK))
+ def mysummary(self):
+ return self.sprintf("ERROR %errorcode%: %errormsg%"),[UDP]
+
+
+class TFTP_OACK(Packet):
+ name = "TFTP Option Ack"
+ fields_desc = [ ]
+ def answers(self, other):
+ return isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_RRQ)
+
+
+bind_layers(UDP, TFTP, dport=69)
+bind_layers(TFTP, TFTP_RRQ, op=1)
+bind_layers(TFTP, TFTP_WRQ, op=2)
+bind_layers(TFTP, TFTP_DATA, op=3)
+bind_layers(TFTP, TFTP_ACK, op=4)
+bind_layers(TFTP, TFTP_ERROR, op=5)
+bind_layers(TFTP, TFTP_OACK, op=6)
+bind_layers(TFTP_RRQ, TFTP_Options)
+bind_layers(TFTP_WRQ, TFTP_Options)
+bind_layers(TFTP_OACK, TFTP_Options)
+
+
+class TFTP_read(Automaton):
+ def parse_args(self, filename, server, sport = None, port=69, **kargs):
+ Automaton.parse_args(self, **kargs)
+ self.filename = filename
+ self.server = server
+ self.port = port
+ self.sport = sport
+
+
+ def master_filter(self, pkt):
+ return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
+ and pkt[UDP].dport == self.my_tid
+ and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
+
+ # BEGIN
+ @ATMT.state(initial=1)
+ def BEGIN(self):
+ self.blocksize=512
+ self.my_tid = self.sport or RandShort()._fix()
+ bind_bottom_up(UDP, TFTP, dport=self.my_tid)
+ self.server_tid = None
+ self.res = ""
+
+ self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
+ self.last_packet = self.l3/TFTP_RRQ(filename=self.filename, mode="octet")
+ self.send(self.last_packet)
+ self.awaiting=1
+
+ raise self.WAITING()
+
+ # WAITING
+ @ATMT.state()
+ def WAITING(self):
+ pass
+
+
+ @ATMT.receive_condition(WAITING)
+ def receive_data(self, pkt):
+ if TFTP_DATA in pkt and pkt[TFTP_DATA].block == self.awaiting:
+ if self.server_tid is None:
+ self.server_tid = pkt[UDP].sport
+ self.l3[UDP].dport = self.server_tid
+ raise self.RECEIVING(pkt)
+
+ @ATMT.receive_condition(WAITING, prio=1)
+ def receive_error(self, pkt):
+ if TFTP_ERROR in pkt:
+ raise self.ERROR(pkt)
+
+
+ @ATMT.timeout(WAITING, 3)
+ def timeout_waiting(self):
+ raise self.WAITING()
+ @ATMT.action(timeout_waiting)
+ def retransmit_last_packet(self):
+ self.send(self.last_packet)
+
+ @ATMT.action(receive_data)
+# @ATMT.action(receive_error)
+ def send_ack(self):
+ self.last_packet = self.l3 / TFTP_ACK(block = self.awaiting)
+ self.send(self.last_packet)
+
+
+ # RECEIVED
+ @ATMT.state()
+ def RECEIVING(self, pkt):
+ if conf.raw_layer in pkt:
+ recvd = pkt[conf.raw_layer].load
+ else:
+ recvd = ""
+ self.res += recvd
+ self.awaiting += 1
+ if len(recvd) == self.blocksize:
+ raise self.WAITING()
+ raise self.END()
+
+ # ERROR
+ @ATMT.state(error=1)
+ def ERROR(self,pkt):
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+ return pkt[TFTP_ERROR].summary()
+
+ #END
+ @ATMT.state(final=1)
+ def END(self):
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+ return self.res
+
+
+
+
+class TFTP_write(Automaton):
+ def parse_args(self, filename, data, server, sport=None, port=69,**kargs):
+ Automaton.parse_args(self, **kargs)
+ self.filename = filename
+ self.server = server
+ self.port = port
+ self.sport = sport
+ self.blocksize = 512
+ self.origdata = data
+
+ def master_filter(self, pkt):
+ return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
+ and pkt[UDP].dport == self.my_tid
+ and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
+
+
+ # BEGIN
+ @ATMT.state(initial=1)
+ def BEGIN(self):
+ self.data = [ self.origdata[i*self.blocksize:(i+1)*self.blocksize]
+ for i in range( len(self.origdata)/self.blocksize+1) ]
+ self.my_tid = self.sport or RandShort()._fix()
+ bind_bottom_up(UDP, TFTP, dport=self.my_tid)
+ self.server_tid = None
+
+ self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
+ self.last_packet = self.l3/TFTP_WRQ(filename=self.filename, mode="octet")
+ self.send(self.last_packet)
+ self.res = ""
+ self.awaiting=0
+
+ raise self.WAITING_ACK()
+
+ # WAITING_ACK
+ @ATMT.state()
+ def WAITING_ACK(self):
+ pass
+
+ @ATMT.receive_condition(WAITING_ACK)
+ def received_ack(self,pkt):
+ if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.awaiting:
+ if self.server_tid is None:
+ self.server_tid = pkt[UDP].sport
+ self.l3[UDP].dport = self.server_tid
+ raise self.SEND_DATA()
+
+ @ATMT.receive_condition(WAITING_ACK)
+ def received_error(self, pkt):
+ if TFTP_ERROR in pkt:
+ raise self.ERROR(pkt)
+
+ @ATMT.timeout(WAITING_ACK, 3)
+ def timeout_waiting(self):
+ raise self.WAITING_ACK()
+ @ATMT.action(timeout_waiting)
+ def retransmit_last_packet(self):
+ self.send(self.last_packet)
+
+ # SEND_DATA
+ @ATMT.state()
+ def SEND_DATA(self):
+ self.awaiting += 1
+ self.last_packet = self.l3/TFTP_DATA(block=self.awaiting)/self.data.pop(0)
+ self.send(self.last_packet)
+ if self.data:
+ raise self.WAITING_ACK()
+ raise self.END()
+
+
+ # ERROR
+ @ATMT.state(error=1)
+ def ERROR(self,pkt):
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+ return pkt[TFTP_ERROR].summary()
+
+ # END
+ @ATMT.state(final=1)
+ def END(self):
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+
+
+class TFTP_WRQ_server(Automaton):
+
+ def parse_args(self, ip=None, sport=None, *args, **kargs):
+ Automaton.parse_args(self, *args, **kargs)
+ self.ip = ip
+ self.sport = sport
+
+ def master_filter(self, pkt):
+ return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
+
+ @ATMT.state(initial=1)
+ def BEGIN(self):
+ self.blksize=512
+ self.blk=1
+ self.filedata=""
+ self.my_tid = self.sport or random.randint(10000,65500)
+ bind_bottom_up(UDP, TFTP, dport=self.my_tid)
+
+ @ATMT.receive_condition(BEGIN)
+ def receive_WRQ(self,pkt):
+ if TFTP_WRQ in pkt:
+ raise self.WAIT_DATA().action_parameters(pkt)
+
+ @ATMT.action(receive_WRQ)
+ def ack_WRQ(self, pkt):
+ ip = pkt[IP]
+ self.ip = ip.dst
+ self.dst = ip.src
+ self.filename = pkt[TFTP_WRQ].filename
+ options = pkt[TFTP_Options]
+ self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=pkt.sport)/TFTP()
+ if options is None:
+ self.last_packet = self.l3/TFTP_ACK(block=0)
+ self.send(self.last_packet)
+ else:
+ opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
+ if opt:
+ self.blksize = int(opt[0].value)
+ self.debug(2,"Negotiated new blksize at %i" % self.blksize)
+ self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
+ self.send(self.last_packet)
+
+ @ATMT.state()
+ def WAIT_DATA(self):
+ pass
+
+ @ATMT.timeout(WAIT_DATA, 1)
+ def resend_ack(self):
+ self.send(self.last_packet)
+ raise self.WAIT_DATA()
+
+ @ATMT.receive_condition(WAIT_DATA)
+ def receive_data(self, pkt):
+ if TFTP_DATA in pkt:
+ data = pkt[TFTP_DATA]
+ if data.block == self.blk:
+ raise self.DATA(data)
+
+ @ATMT.action(receive_data)
+ def ack_data(self):
+ self.last_packet = self.l3/TFTP_ACK(block = self.blk)
+ self.send(self.last_packet)
+
+ @ATMT.state()
+ def DATA(self, data):
+ self.filedata += data.load
+ if len(data.load) < self.blksize:
+ raise self.END()
+ self.blk += 1
+ raise self.WAIT_DATA()
+
+ @ATMT.state(final=1)
+ def END(self):
+ return self.filename,self.filedata
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+
+
+class TFTP_RRQ_server(Automaton):
+ def parse_args(self, store=None, joker=None, dir=None, ip=None, sport=None, serve_one=False, **kargs):
+ Automaton.parse_args(self,**kargs)
+ if store is None:
+ store = {}
+ if dir is not None:
+ self.dir = os.path.join(os.path.abspath(dir),"")
+ else:
+ self.dir = None
+ self.store = store
+ self.joker = joker
+ self.ip = ip
+ self.sport = sport
+ self.serve_one = serve_one
+ self.my_tid = self.sport or random.randint(10000,65500)
+ bind_bottom_up(UDP, TFTP, dport=self.my_tid)
+
+ def master_filter(self, pkt):
+ return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
+
+ @ATMT.state(initial=1)
+ def WAIT_RRQ(self):
+ self.blksize=512
+ self.blk=0
+
+ @ATMT.receive_condition(WAIT_RRQ)
+ def receive_rrq(self, pkt):
+ if TFTP_RRQ in pkt:
+ raise self.RECEIVED_RRQ(pkt)
+
+
+ @ATMT.state()
+ def RECEIVED_RRQ(self, pkt):
+ ip = pkt[IP]
+ options = pkt[TFTP_Options]
+ self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=ip.sport)/TFTP()
+ self.filename = pkt[TFTP_RRQ].filename
+ self.blk=1
+ self.data = None
+ if self.filename in self.store:
+ self.data = self.store[self.filename]
+ elif self.dir is not None:
+ fn = os.path.abspath(os.path.join(self.dir, self.filename))
+ if fn.startswith(self.dir): # Check we're still in the server's directory
+ try:
+ self.data=open(fn).read()
+ except IOError:
+ pass
+ if self.data is None:
+ self.data = self.joker
+
+ if options:
+ opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
+ if opt:
+ self.blksize = int(opt[0].value)
+ self.debug(2,"Negotiated new blksize at %i" % self.blksize)
+ self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
+ self.send(self.last_packet)
+
+
+
+
+ @ATMT.condition(RECEIVED_RRQ)
+ def file_in_store(self):
+ if self.data is not None:
+ self.blknb = len(self.data)/self.blksize+1
+ raise self.SEND_FILE()
+
+ @ATMT.condition(RECEIVED_RRQ)
+ def file_not_found(self):
+ if self.data is None:
+ raise self.WAIT_RRQ()
+ @ATMT.action(file_not_found)
+ def send_error(self):
+ self.send(self.l3/TFTP_ERROR(errorcode=1, errormsg=TFTP_Error_Codes[1]))
+
+ @ATMT.state()
+ def SEND_FILE(self):
+ self.send(self.l3/TFTP_DATA(block=self.blk)/self.data[(self.blk-1)*self.blksize:self.blk*self.blksize])
+
+ @ATMT.timeout(SEND_FILE, 3)
+ def timeout_waiting_ack(self):
+ raise self.SEND_FILE()
+
+ @ATMT.receive_condition(SEND_FILE)
+ def received_ack(self, pkt):
+ if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.blk:
+ raise self.RECEIVED_ACK()
+ @ATMT.state()
+ def RECEIVED_ACK(self):
+ self.blk += 1
+
+ @ATMT.condition(RECEIVED_ACK)
+ def no_more_data(self):
+ if self.blk > self.blknb:
+ if self.serve_one:
+ raise self.END()
+ raise self.WAIT_RRQ()
+ @ATMT.condition(RECEIVED_ACK, prio=2)
+ def data_remaining(self):
+ raise self.SEND_FILE()
+
+ @ATMT.state(final=1)
+ def END(self):
+ split_bottom_up(UDP, TFTP, dport=self.my_tid)
+
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/vrrp.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/vrrp.py
new file mode 100644
index 00000000..e2818381
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/vrrp.py
@@ -0,0 +1,39 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Copyright (C) 6WIND <olivier.matz@6wind.com>
+## This program is published under a GPLv2 license
+
+"""
+VRRP (Virtual Router Redundancy Protocol).
+"""
+
+from scapy.packet import *
+from scapy.fields import *
+from scapy.layers.inet import IP
+
+IPPROTO_VRRP=112
+
+# RFC 3768 - Virtual Router Redundancy Protocol (VRRP)
+class VRRP(Packet):
+ fields_desc = [
+ BitField("version" , 2, 4),
+ BitField("type" , 1, 4),
+ ByteField("vrid", 1),
+ ByteField("priority", 100),
+ FieldLenField("ipcount", None, count_of="addrlist", fmt="B"),
+ ByteField("authtype", 0),
+ ByteField("adv", 1),
+ XShortField("chksum", None),
+ FieldListField("addrlist", [], IPField("", "0.0.0.0"),
+ count_from = lambda pkt: pkt.ipcount),
+ IntField("auth1", 0),
+ IntField("auth2", 0) ]
+
+ def post_build(self, p, pay):
+ if self.chksum is None:
+ ck = checksum(p)
+ p = p[:6]+bytes([(ck>>8),(ck&0xff)])+p[8:]
+ return p
+
+bind_layers( IP, VRRP, proto=IPPROTO_VRRP)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/x509.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/x509.py
new file mode 100644
index 00000000..18aaa5e3
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/layers/x509.py
@@ -0,0 +1,108 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+X.509 certificates.
+"""
+
+from scapy.asn1packet import *
+from scapy.asn1fields import *
+
+##########
+## X509 ##
+##########
+
+######[ ASN1 class ]######
+
+class ASN1_Class_X509(ASN1_Class_UNIVERSAL):
+ name="X509"
+ CONT0 = 0xa0
+ CONT1 = 0xa1
+ CONT2 = 0xa2
+ CONT3 = 0xa3
+
+class ASN1_X509_CONT0(ASN1_SEQUENCE):
+ tag = ASN1_Class_X509.CONT0
+
+class ASN1_X509_CONT1(ASN1_SEQUENCE):
+ tag = ASN1_Class_X509.CONT1
+
+class ASN1_X509_CONT2(ASN1_SEQUENCE):
+ tag = ASN1_Class_X509.CONT2
+
+class ASN1_X509_CONT3(ASN1_SEQUENCE):
+ tag = ASN1_Class_X509.CONT3
+
+######[ BER codecs ]#######
+
+class BERcodec_X509_CONT0(BERcodec_SEQUENCE):
+ tag = ASN1_Class_X509.CONT0
+
+class BERcodec_X509_CONT1(BERcodec_SEQUENCE):
+ tag = ASN1_Class_X509.CONT1
+
+class BERcodec_X509_CONT2(BERcodec_SEQUENCE):
+ tag = ASN1_Class_X509.CONT2
+
+class BERcodec_X509_CONT3(BERcodec_SEQUENCE):
+ tag = ASN1_Class_X509.CONT3
+
+######[ ASN1 fields ]######
+
+class ASN1F_X509_CONT0(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_X509.CONT0
+
+class ASN1F_X509_CONT1(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_X509.CONT1
+
+class ASN1F_X509_CONT2(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_X509.CONT2
+
+class ASN1F_X509_CONT3(ASN1F_SEQUENCE):
+ ASN1_tag = ASN1_Class_X509.CONT3
+
+######[ X509 packets ]######
+
+class X509RDN(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SET(
+ ASN1F_SEQUENCE( ASN1F_OID("oid","2.5.4.6"),
+ ASN1F_PRINTABLE_STRING("value","")
+ )
+ )
+
+class X509v3Ext(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_field("val",ASN1_NULL(0))
+
+
+class X509Cert(ASN1_Packet):
+ ASN1_codec = ASN1_Codecs.BER
+ ASN1_root = ASN1F_SEQUENCE(
+ ASN1F_SEQUENCE(
+ ASN1F_optionnal(ASN1F_X509_CONT0(ASN1F_INTEGER("version",3))),
+ ASN1F_INTEGER("sn",1),
+ ASN1F_SEQUENCE(ASN1F_OID("sign_algo","1.2.840.113549.1.1.5"),
+ ASN1F_field("sa_value",ASN1_NULL(0))),
+ ASN1F_SEQUENCE_OF("issuer",[],X509RDN),
+ ASN1F_SEQUENCE(ASN1F_UTC_TIME("not_before",ZuluTime(-600)), # ten minutes ago
+ ASN1F_UTC_TIME("not_after",ZuluTime(+86400))), # for 24h
+ ASN1F_SEQUENCE_OF("subject",[],X509RDN),
+ ASN1F_SEQUENCE(
+ ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"),
+ ASN1F_field("pk_value",ASN1_NULL(0))),
+ ASN1F_BIT_STRING("pubkey","")
+ ),
+ ASN1F_optionnal(ASN1F_X509_CONT3(ASN1F_SEQUENCE_OF("x509v3ext",[],X509v3Ext))),
+
+ ),
+ ASN1F_SEQUENCE(ASN1F_OID("sign_algo2","1.2.840.113549.1.1.5"),
+ ASN1F_field("sa2_value",ASN1_NULL(0))),
+ ASN1F_BIT_STRING("signature","")
+ )
+
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/main.py b/scripts/external_libs/scapy-python3-0.18/scapy/main.py
new file mode 100644
index 00000000..47805443
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/main.py
@@ -0,0 +1,380 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Main module for interactive startup.
+"""
+
+import os,sys,socket
+import glob
+import builtins
+import types
+import gzip
+from .error import *
+from . import utils
+
+
+def _probe_config_file(cf):
+ cf_path = os.path.join(os.path.expanduser("~"), cf)
+ try:
+ os.stat(cf_path)
+ except OSError:
+ return None
+ else:
+ return cf_path
+
+def _read_config_file(cf):
+ log_loading.debug("Loading config file [%s]" % cf)
+ try:
+ exec(open(cf).read())
+ except IOError as e:
+ log_loading.warning("Cannot read config file [%s] [%s]" % (cf,e))
+ except Exception as e:
+ log_loading.exception("Error during evaluation of config file [%s]" % cf)
+
+
+DEFAULT_PRESTART_FILE = _probe_config_file(".scapy_prestart.py")
+DEFAULT_STARTUP_FILE = _probe_config_file(".scapy_startup.py")
+
+def _usage():
+ print("""Usage: scapy.py [-s sessionfile] [-c new_startup_file] [-p new_prestart_file] [-C] [-P]
+ -C: do not read startup file
+ -P: do not read pre-startup file""")
+ sys.exit(0)
+
+
+from .config import conf
+from .themes import DefaultTheme
+
+
+######################
+## Extension system ##
+######################
+
+
+def _load(module):
+ try:
+ mod = __import__(module,globals(),locals(),".")
+ builtins.__dict__.update(mod.__dict__)
+ except Exception as e:
+ log_interactive.error(e)
+
+def load_module(name):
+ _load("scapy.modules."+name)
+
+def load_layer(name):
+ _load("scapy.layers."+name)
+
+def load_contrib(name):
+ _load("scapy.contrib."+name)
+
+def list_contrib(name=None):
+ if name is None:
+ name="*.py"
+ elif "*" not in name and "?" not in name and not name.endswith(".py"):
+ name += ".py"
+ name = os.path.join(os.path.dirname(__file__), "contrib", name)
+ for f in glob.glob(name):
+ mod = os.path.basename(f)
+ if mod.startswith("__"):
+ continue
+ if mod.endswith(".py"):
+ mod = mod[:-3]
+ desc = { "description":"-", "status":"?", "name":mod }
+ for l in open(f):
+ p = l.find("scapy.contrib.")
+ if p >= 0:
+ p += 14
+ q = l.find("=", p)
+ key = l[p:q].strip()
+ value = l[q+1:].strip()
+ desc[key] = value
+ print("%(name)-20s: %(description)-40s status=%(status)s" % desc)
+
+
+
+
+
+
+##############################
+## Session saving/restoring ##
+##############################
+
+
+def save_session(fname=None, session=None, pickleProto=4):
+ import dill as pickle
+
+ if fname is None:
+ fname = conf.session
+ if not fname:
+ conf.session = fname = utils.get_temp_file(keep=True)
+ log_interactive.info("Use [%s] as session file" % fname)
+ if session is None:
+ session = builtins.__dict__["scapy_session"]
+
+ to_be_saved = session.copy()
+
+ for k in list(to_be_saved.keys()):
+ if k in ["__builtins__", "In", "Out", "conf"] or k.startswith("_") or \
+ (hasattr(to_be_saved[k], "__module__") and str(to_be_saved[k].__module__).startswith('IPython')):
+ del(to_be_saved[k])
+ continue
+ if type(to_be_saved[k]) in [type, types.ModuleType, types.MethodType]:
+ log_interactive.info("[%s] (%s) can't be saved." % (k, type(to_be_saved[k])))
+ del(to_be_saved[k])
+
+ try:
+ os.rename(fname, fname+".bak")
+ except OSError:
+ pass
+ f=gzip.open(fname,"wb")
+ for i in to_be_saved.keys():
+ #d = {i: to_be_saved[i]}
+ #pickle.dump(d, f, pickleProto)
+ pickle.dump(to_be_saved, f, pickleProto)
+ f.close()
+
+def load_session(fname=None):
+ if conf.interactive_shell.lower() == "ipython":
+ log_interactive.error("There are issues with load_session in ipython. Use python for interactive shell, or use -s parameter to load session")
+ return
+
+ import dill as pickle
+
+ if fname is None:
+ fname = conf.session
+ try:
+ s = pickle.load(gzip.open(fname,"rb"))
+ except IOError:
+ s = pickle.load(open(fname,"rb"))
+ scapy_session = builtins.__dict__["scapy_session"]
+ scapy_session.clear()
+ scapy_session.update(s)
+
+def update_session(fname=None):
+ import dill as pickle
+ if fname is None:
+ fname = conf.session
+ try:
+ s = pickle.load(gzip.open(fname,"rb"))
+ except IOError:
+ s = pickle.load(open(fname,"rb"))
+ scapy_session = builtins.__dict__["scapy_session"]
+ scapy_session.update(s)
+
+
+################
+##### Main #####
+################
+
+def scapy_delete_temp_files():
+ for f in conf.temp_files:
+ try:
+ os.unlink(f)
+ except:
+ pass
+
+def scapy_write_history_file(readline):
+ if conf.histfile:
+ try:
+ readline.write_history_file(conf.histfile)
+ except IOError as e:
+ try:
+ warning("Could not write history to [%s]\n\t (%s)" % (conf.histfile,e))
+ tmp = utils.get_temp_file(keep=True)
+ readline.write_history_file(tmp)
+ warning("Wrote history to [%s]" % tmp)
+ except:
+ warning("Cound not write history to [%s]. Discarded" % tmp)
+
+
+def interact(mydict=None,argv=None,mybanner=None,loglevel=20):
+ global session
+ import code,sys,pickle,os,getopt,re
+ from .config import conf
+ conf.interactive = True
+ if loglevel is not None:
+ conf.logLevel=loglevel
+
+ the_banner = "Welcome to Scapy (%s)"
+ if mybanner is not None:
+ the_banner += "\n"
+ the_banner += mybanner
+
+ if argv is None:
+ argv = sys.argv
+
+ import atexit
+ try:
+ import rlcompleter,readline
+ except ImportError:
+ log_loading.info("Can't load Python libreadline or completer")
+ READLINE=0
+ else:
+ READLINE=1
+ class ScapyCompleter(rlcompleter.Completer):
+ def global_matches(self, text):
+ matches = []
+ n = len(text)
+ for lst in [dir(builtins), session.keys()]:
+ for word in lst:
+ if word[:n] == text and word != "__builtins__":
+ matches.append(word)
+ return matches
+
+
+ def attr_matches(self, text):
+ m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+ if not m:
+ return
+ expr, attr = m.group(1, 3)
+ try:
+ object = eval(expr)
+ except:
+ object = eval(expr, session)
+ if isinstance(object, Packet) or isinstance(object, Packet_metaclass):
+ #words = filter(lambda x: x[0]!="_",dir(object))
+ words = [ x for x in dir(object) if x[0]!="_" ]
+ words += [x.name for x in object.fields_desc]
+ else:
+ words = dir(object)
+ if hasattr( object,"__class__" ):
+ words = words + rlcompleter.get_class_members(object.__class__)
+ matches = []
+ n = len(attr)
+ for word in words:
+ if word[:n] == attr and word != "__builtins__":
+ matches.append("%s.%s" % (expr, word))
+ return matches
+
+ readline.set_completer(ScapyCompleter().complete)
+ readline.parse_and_bind("C-o: operate-and-get-next")
+ readline.parse_and_bind("tab: complete")
+
+
+ session=None
+ session_name=""
+ STARTUP_FILE = DEFAULT_STARTUP_FILE
+ PRESTART_FILE = DEFAULT_PRESTART_FILE
+
+
+ iface = None
+ try:
+ opts=getopt.getopt(argv[1:], "hs:Cc:Pp:d")
+ for opt, parm in opts[0]:
+ if opt == "-h":
+ _usage()
+ elif opt == "-s":
+ session_name = parm
+ elif opt == "-c":
+ STARTUP_FILE = parm
+ elif opt == "-C":
+ STARTUP_FILE = None
+ elif opt == "-p":
+ PRESTART_FILE = parm
+ elif opt == "-P":
+ PRESTART_FILE = None
+ elif opt == "-d":
+ conf.logLevel = max(1,conf.logLevel-10)
+
+ if len(opts[1]) > 0:
+ raise getopt.GetoptError("Too many parameters : [%s]" % " ".join(opts[1]))
+
+
+ except getopt.GetoptError as msg:
+ log_loading.error(msg)
+ sys.exit(1)
+
+ if PRESTART_FILE:
+ _read_config_file(PRESTART_FILE)
+
+ scapy_builtins = __import__("scapy.all",globals(),locals(),".").__dict__
+ builtins.__dict__.update(scapy_builtins)
+ globkeys = list(scapy_builtins.keys())
+ globkeys.append("scapy_session")
+ scapy_builtins=None # XXX replace with "with" statement
+ if mydict is not None:
+ builtins.__dict__.update(mydict)
+ globkeys += mydict.keys()
+
+
+ conf.color_theme = DefaultTheme()
+ if STARTUP_FILE:
+ _read_config_file(STARTUP_FILE)
+
+ if session_name:
+ try:
+ os.stat(session_name)
+ except OSError:
+ log_loading.info("New session [%s]" % session_name)
+ else:
+ try:
+ try:
+ session = pickle.load(gzip.open(session_name,"rb"))
+ except IOError:
+ session = pickle.load(open(session_name,"rb"))
+ log_loading.info("Using session [%s]" % session_name)
+ except EOFError:
+ log_loading.error("Error opening session [%s]" % session_name)
+ except AttributeError:
+ log_loading.error("Error opening session [%s]. Attribute missing" % session_name)
+
+ if session:
+ if "conf" in session:
+ conf.configure(session["conf"])
+ session["conf"] = conf
+ else:
+ conf.session = session_name
+ session={"conf":conf}
+
+ else:
+ session={"conf": conf}
+
+ builtins.__dict__["scapy_session"] = session
+
+
+ if READLINE:
+ if conf.histfile:
+ try:
+ readline.read_history_file(conf.histfile)
+ except IOError:
+ pass
+ atexit.register(scapy_write_history_file,readline)
+
+ atexit.register(scapy_delete_temp_files)
+
+ IPYTHON=False
+ if conf.interactive_shell.lower() == "ipython":
+ try:
+ import IPython
+ IPYTHON=True
+ except ImportError as e:
+ log_loading.warning("IPython not available. Using standard Python shell instead.")
+ IPYTHON=False
+
+ if IPYTHON:
+ banner = the_banner % (conf.version) + " using IPython %s" % IPython.__version__
+
+ if conf.ipython_embedded:
+ IPython.embed(user_ns=session, banner2=banner)
+ else:
+ IPython.start_ipython(argv=[], user_ns=session)
+
+ else:
+ code.interact(banner = the_banner % (conf.version),
+ local=session, readfunc=conf.readfunc)
+
+ if conf.session:
+ save_session(conf.session, session)
+
+
+ for k in globkeys:
+ try:
+ del(builtins.__dict__[k])
+ except:
+ pass
+
+if __name__ == "__main__":
+ interact()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/__init__.py
new file mode 100644
index 00000000..6303dad0
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/__init__.py
@@ -0,0 +1,8 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Package of extension modules that have to be loaded explicitly.
+"""
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/geoip.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/geoip.py
new file mode 100644
index 00000000..7396fe96
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/geoip.py
@@ -0,0 +1,77 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+GeoIP: find out the geographical location of IP addresses
+"""
+
+from scapy.data import KnowledgeBase
+from scapy.config import conf
+
+conf.IPCountry_base = "GeoIPCountry4Scapy.gz"
+conf.countryLoc_base = "countryLoc.csv"
+
+##########################
+## IP location database ##
+##########################
+
+class IPCountryKnowledgeBase(KnowledgeBase):
+ """
+How to generate the base :
+db = []
+for l in open("GeoIPCountryWhois.csv").readlines():
+ s,e,c = l.split(",")[2:5]
+ db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1]))
+cPickle.dump(gzip.open("xxx","w"),db)
+"""
+ def lazy_init(self):
+ self.base = load_object(self.filename)
+
+
+class CountryLocKnowledgeBase(KnowledgeBase):
+ def lazy_init(self):
+ f=open(self.filename)
+ self.base = {}
+ while 1:
+ l = f.readline()
+ if not l:
+ break
+ l = l.strip().split(",")
+ if len(l) != 3:
+ continue
+ c,lat,long = l
+
+ self.base[c] = (float(long),float(lat))
+ f.close()
+
+
+
+@conf.commands.register
+def locate_ip(ip):
+ """Get geographic coordinates from IP using geoip database"""
+ ip=map(int,ip.split("."))
+ ip = ip[3]+(ip[2]<<8)+(ip[1]<<16)+(ip[0]<<24)
+
+ cloc = country_loc_kdb.get_base()
+ db = IP_country_kdb.get_base()
+
+ d=0
+ f=len(db)-1
+ while (f-d) > 1:
+ guess = (d+f)/2
+ if ip > db[guess][0]:
+ d = guess
+ else:
+ f = guess
+ s,e,c = db[guess]
+ if s <= ip and ip <= e:
+ return cloc.get(c,None)
+
+
+
+
+
+conf.IP_country_kdb = IPCountryKnowledgeBase(conf.IPCountry_base)
+conf.country_loc_kdb = CountryLocKnowledgeBase(conf.countryLoc_base)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/nmap.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/nmap.py
new file mode 100644
index 00000000..07ec7a93
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/nmap.py
@@ -0,0 +1,215 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Clone of Nmap's first generation OS fingerprinting.
+"""
+
+import os
+
+from scapy.data import KnowledgeBase
+from scapy.config import conf
+from scapy.arch import WINDOWS
+
+
+if WINDOWS:
+ conf.nmap_base=os.environ["ProgramFiles"] + "\\nmap\\nmap-os-fingerprints"
+else:
+ conf.nmap_base ="/usr/share/nmap/nmap-os-fingerprints"
+
+
+######################
+## nmap OS fp stuff ##
+######################
+
+
+class NmapKnowledgeBase(KnowledgeBase):
+ def lazy_init(self):
+ try:
+ f=open(self.filename)
+ except IOError:
+ return
+
+ self.base = []
+ name = None
+ try:
+ for l in f:
+ l = l.strip()
+ if not l or l[0] == "#":
+ continue
+ if l[:12] == "Fingerprint ":
+ if name is not None:
+ self.base.append((name,sig))
+ name = l[12:].strip()
+ sig={}
+ p = self.base
+ continue
+ elif l[:6] == "Class ":
+ continue
+ op = l.find("(")
+ cl = l.find(")")
+ if op < 0 or cl < 0:
+ warning("error reading nmap os fp base file")
+ continue
+ test = l[:op]
+ s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
+ si = {}
+ for n,v in s:
+ si[n] = v
+ sig[test]=si
+ if name is not None:
+ self.base.append((name,sig))
+ except:
+ self.base = None
+ warning("Can't read nmap database [%s](new nmap version ?)" % self.filename)
+ f.close()
+
+nmap_kdb = NmapKnowledgeBase(conf.nmap_base)
+
+def TCPflags2str(f):
+ fl="FSRPAUEC"
+ s=""
+ for i in range(len(fl)):
+ if f & 1:
+ s = fl[i]+s
+ f >>= 1
+ return s
+
+def nmap_tcppacket_sig(pkt):
+ r = {}
+ if pkt is not None:
+# r["Resp"] = "Y"
+ r["DF"] = (pkt.flags & 2) and "Y" or "N"
+ r["W"] = "%X" % pkt.window
+ r["ACK"] = pkt.ack==2 and "S++" or pkt.ack==1 and "S" or "O"
+ r["Flags"] = TCPflags2str(pkt.payload.flags)
+ r["Ops"] = "".join(map(lambda x: x[0][0],pkt.payload.options))
+ else:
+ r["Resp"] = "N"
+ return r
+
+
+def nmap_udppacket_sig(S,T):
+ r={}
+ if T is None:
+ r["Resp"] = "N"
+ else:
+ r["DF"] = (T.flags & 2) and "Y" or "N"
+ r["TOS"] = "%X" % T.tos
+ r["IPLEN"] = "%X" % T.len
+ r["RIPTL"] = "%X" % T.payload.payload.len
+ r["RID"] = S.id == T.payload.payload.id and "E" or "F"
+ r["RIPCK"] = S.chksum == T.getlayer(IPerror).chksum and "E" or T.getlayer(IPerror).chksum == 0 and "0" or "F"
+ r["UCK"] = S.payload.chksum == T.getlayer(UDPerror).chksum and "E" or T.getlayer(UDPerror).chksum ==0 and "0" or "F"
+ r["ULEN"] = "%X" % T.getlayer(UDPerror).len
+ r["DAT"] = T.getlayer(conf.raw_layer) is None and "E" or S.getlayer(conf.raw_layer).load == T.getlayer(conf.raw_layer).load and "E" or "F"
+ return r
+
+
+
+def nmap_match_one_sig(seen, ref):
+ c = 0
+ for k in seen.keys():
+ if k in ref:
+ if seen[k] in ref[k].split("|"):
+ c += 1
+ if c == 0 and seen.get("Resp") == "N":
+ return 0.7
+ else:
+ return 1.0*c/len(seen.keys())
+
+
+def nmap_sig(target, oport=80, cport=81, ucport=1):
+ res = {}
+
+ tcpopt = [ ("WScale", 10),
+ ("NOP",None),
+ ("MSS", 256),
+ ("Timestamp",(123,0)) ]
+ tests = [ IP(dst=target, id=1)/TCP(seq=1, sport=5001, dport=oport, options=tcpopt, flags="CS"),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5002, dport=oport, options=tcpopt, flags=0),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5003, dport=oport, options=tcpopt, flags="SFUP"),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5004, dport=oport, options=tcpopt, flags="A"),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5005, dport=cport, options=tcpopt, flags="S"),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5006, dport=cport, options=tcpopt, flags="A"),
+ IP(dst=target, id=1)/TCP(seq=1, sport=5007, dport=cport, options=tcpopt, flags="FPU"),
+ IP(str(IP(dst=target)/UDP(sport=5008,dport=ucport)/(300*"i"))) ]
+
+ ans, unans = sr(tests, timeout=2)
+ ans += map(lambda x: (x,None), unans)
+
+ for S,T in ans:
+ if S.sport == 5008:
+ res["PU"] = nmap_udppacket_sig(S,T)
+ else:
+ t = "T%i" % (S.sport-5000)
+ if T is not None and T.haslayer(ICMP):
+ warning("Test %s answered by an ICMP" % t)
+ T=None
+ res[t] = nmap_tcppacket_sig(T)
+
+ return res
+
+def nmap_probes2sig(tests):
+ tests=tests.copy()
+ res = {}
+ if "PU" in tests:
+ res["PU"] = nmap_udppacket_sig(*tests["PU"])
+ del(tests["PU"])
+ for k in tests:
+ res[k] = nmap_tcppacket_sig(tests[k])
+ return res
+
+
+def nmap_search(sigs):
+ guess = 0,[]
+ for os,fp in nmap_kdb.get_base():
+ c = 0.0
+ for t in sigs.keys():
+ if t in fp:
+ c += nmap_match_one_sig(sigs[t], fp[t])
+ c /= len(sigs.keys())
+ if c > guess[0]:
+ guess = c,[ os ]
+ elif c == guess[0]:
+ guess[1].append(os)
+ return guess
+
+
+@conf.commands.register
+def nmap_fp(target, oport=80, cport=81):
+ """nmap fingerprinting
+nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
+"""
+ sigs = nmap_sig(target, oport, cport)
+ return nmap_search(sigs)
+
+
+@conf.commands.register
+def nmap_sig2txt(sig):
+ torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"]
+ korder = ["Class", "gcd", "SI", "IPID", "TS",
+ "Resp", "DF", "W", "ACK", "Flags", "Ops",
+ "TOS", "IPLEN", "RIPTL", "RID", "RIPCK", "UCK", "ULEN", "DAT" ]
+ txt=[]
+ for i in sig.keys():
+ if i not in torder:
+ torder.append(i)
+ for t in torder:
+ sl = sig.get(t)
+ if sl is None:
+ continue
+ s = []
+ for k in korder:
+ v = sl.get(k)
+ if v is None:
+ continue
+ s.append("%s=%s"%(k,v))
+ txt.append("%s(%s)" % (t, "%".join(s)))
+ return "\n".join(txt)
+
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/p0f.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/p0f.py
new file mode 100644
index 00000000..289ef531
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/p0f.py
@@ -0,0 +1,549 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Clone of p0f passive OS fingerprinting
+"""
+
+from scapy.data import KnowledgeBase
+from scapy.config import conf
+from scapy.error import warning
+from scapy.layers.inet import IP, TCP, TCPOptions
+from scapy.packet import NoPayload
+
+conf.p0f_base ="/etc/p0f/p0f.fp"
+conf.p0fa_base ="/etc/p0f/p0fa.fp"
+conf.p0fr_base ="/etc/p0f/p0fr.fp"
+#conf.p0fo_base ="/etc/p0f/p0fo.fp"
+
+
+###############
+## p0f stuff ##
+###############
+
+# File format (according to p0f.fp) :
+#
+# wwww:ttt:D:ss:OOO...:QQ:OS:Details
+#
+# wwww - window size
+# ttt - initial TTL
+# D - don't fragment bit (0=unset, 1=set)
+# ss - overall SYN packet size
+# OOO - option value and order specification
+# QQ - quirks list
+# OS - OS genre
+# details - OS description
+
+class p0fKnowledgeBase(KnowledgeBase):
+ def __init__(self, filename):
+ KnowledgeBase.__init__(self, filename)
+ #self.ttl_range=[255]
+ def lazy_init(self):
+ try:
+ f=open(self.filename)
+ except IOError:
+ warning("Can't open base %s" % self.filename)
+ return
+ try:
+ self.base = []
+ for l in f:
+ if l[0] in ["#","\n"]:
+ continue
+ l = tuple(l.split(":"))
+ if len(l) < 8:
+ continue
+ def a2i(x):
+ if x.isdigit():
+ return int(x)
+ return x
+ li = [ a2i(i) for i in l[1:4] ]
+ #if li[0] not in self.ttl_range:
+ # self.ttl_range.append(li[0])
+ # self.ttl_range.sort()
+ self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
+ except:
+ warning("Can't parse p0f database (new p0f version ?)")
+ self.base = None
+ f.close()
+
+p0f_kdb = p0fKnowledgeBase(conf.p0f_base)
+p0fa_kdb = p0fKnowledgeBase(conf.p0fa_base)
+p0fr_kdb = p0fKnowledgeBase(conf.p0fr_base)
+#p0fo_kdb = p0fKnowledgeBase(conf.p0fo_base)
+
+def p0f_selectdb(flags):
+ # tested flags: S, R, A
+ if flags & 0x16 == 0x2:
+ # SYN
+ return p0f_kdb
+ elif flags & 0x16 == 0x12:
+ # SYN/ACK
+ return p0fa_kdb
+ elif flags & 0x16 in [ 0x4, 0x14 ]:
+ # RST RST/ACK
+ return p0fr_kdb
+# elif flags & 0x16 == 0x10:
+ # ACK
+# return p0fo_kdb
+ else:
+ return None
+
+def packet2p0f(pkt):
+ pkt = pkt.copy()
+ pkt = pkt.__class__(bytes(pkt))
+ while pkt.haslayer(IP) and pkt.haslayer(TCP):
+ pkt = pkt.getlayer(IP)
+ if isinstance(pkt.payload, TCP):
+ break
+ pkt = pkt.payload
+
+ if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
+ raise TypeError("Not a TCP/IP packet")
+ #if pkt.payload.flags & 0x7 != 0x02: #S,!F,!R
+ # raise TypeError("Not a SYN or SYN/ACK packet")
+
+ db = p0f_selectdb(pkt.payload.flags)
+
+ #t = p0f_kdb.ttl_range[:]
+ #t += [pkt.ttl]
+ #t.sort()
+ #ttl=t[t.index(pkt.ttl)+1]
+ ttl = pkt.ttl
+
+ df = (pkt.flags & 2) / 2
+ ss = len(pkt)
+ # from p0f/config.h : PACKET_BIG = 100
+ if ss > 100:
+ if db == p0fr_kdb:
+ # p0fr.fp: "Packet size may be wildcarded. The meaning of
+ # wildcard is, however, hardcoded as 'size >
+ # PACKET_BIG'"
+ ss = '*'
+ else:
+ ss = 0
+# if db == p0fo_kdb:
+ # p0fo.fp: "Packet size MUST be wildcarded."
+# ss = '*'
+
+ ooo = ""
+ mss = -1
+ qqT = False
+ qqP = False
+ #qqBroken = False
+ ilen = (pkt.payload.dataofs << 2) - 20 # from p0f.c
+ for option in pkt.payload.options:
+ ilen -= 1
+ if option[0] == "MSS":
+ ooo += "M" + str(option[1]) + ","
+ mss = option[1]
+ # FIXME: qqBroken
+ ilen -= 3
+ elif option[0] == "WScale":
+ ooo += "W" + str(option[1]) + ","
+ # FIXME: qqBroken
+ ilen -= 2
+ elif option[0] == "Timestamp":
+ if option[1][0] == 0:
+ ooo += "T0,"
+ else:
+ ooo += "T,"
+ if option[1][1] != 0:
+ qqT = True
+ ilen -= 9
+ elif option[0] == "SAckOK":
+ ooo += "S,"
+ ilen -= 1
+ elif option[0] == "NOP":
+ ooo += "N,"
+ elif option[0] == "EOL":
+ ooo += "E,"
+ if ilen > 0:
+ qqP = True
+ else:
+ if type(option[0]) is str:
+ ooo += "?%i," % TCPOptions[1][option[0]]
+ else:
+ ooo += "?%i," % option[0]
+ # FIXME: ilen
+ ooo = ooo[:-1]
+ if ooo == "": ooo = "."
+
+ win = pkt.payload.window
+ if mss != -1:
+ if mss != 0 and win % mss == 0:
+ win = "S" + str(win/mss)
+ elif win % (mss + 40) == 0:
+ win = "T" + str(win/(mss+40))
+ win = str(win)
+
+ qq = ""
+
+ if db == p0fr_kdb:
+ if pkt.payload.flags & 0x10 == 0x10:
+ # p0fr.fp: "A new quirk, 'K', is introduced to denote
+ # RST+ACK packets"
+ qq += "K"
+ # The two next cases should also be only for p0f*r*, but although
+ # it's not documented (or I have not noticed), p0f seems to
+ # support the '0' and 'Q' quirks on any databases (or at the least
+ # "classical" p0f.fp).
+ if pkt.payload.seq == pkt.payload.ack:
+ # p0fr.fp: "A new quirk, 'Q', is used to denote SEQ number
+ # equal to ACK number."
+ qq += "Q"
+ if pkt.payload.seq == 0:
+ # p0fr.fp: "A new quirk, '0', is used to denote packets
+ # with SEQ number set to 0."
+ qq += "0"
+ if qqP:
+ qq += "P"
+ if pkt.id == 0:
+ qq += "Z"
+ if pkt.options != []:
+ qq += "I"
+ if pkt.payload.urgptr != 0:
+ qq += "U"
+ if pkt.payload.reserved != 0:
+ qq += "X"
+ if pkt.payload.ack != 0:
+ qq += "A"
+ if qqT:
+ qq += "T"
+# if db == p0fo_kdb:
+# if pkt.payload.flags & 0x20 != 0:
+ # U
+ # p0fo.fp: "PUSH flag is excluded from 'F' quirk checks"
+# qq += "F"
+# else:
+# if pkt.payload.flags & 0x28 != 0:
+ # U or P
+ qq += "F"
+ #if db != p0fo_kdb and not isinstance(pkt.payload.payload, NoPayload):
+ if not isinstance(pkt.payload.payload, NoPayload):
+ # p0fo.fp: "'D' quirk is not checked for."
+ qq += "D"
+ # FIXME : "!" - broken options segment: not handled yet
+
+ if qq == "":
+ qq = "."
+
+ return (db, (win, ttl, df, ss, ooo, qq))
+
+def p0f_correl(x,y):
+ d = 0
+ # wwww can be "*" or "%nn". "Tnn" and "Snn" should work fine with
+ # the x[0] == y[0] test.
+ d += (x[0] == y[0] or y[0] == "*" or (y[0][0] == "%" and x[0].isdigit() and (int(x[0]) % int(y[0][1:])) == 0))
+ # ttl
+ d += (y[1] >= x[1] and y[1] - x[1] < 32)
+ for i in [2, 5]:
+ d += (x[i] == y[i] or y[i] == '*')
+ # '*' has a special meaning for ss
+ d += x[3] == y[3]
+ xopt = x[4].split(",")
+ yopt = y[4].split(",")
+ if len(xopt) == len(yopt):
+ same = True
+ for i in range(len(xopt)):
+ if not (xopt[i] == yopt[i] or
+ (len(yopt[i]) == 2 and len(xopt[i]) > 1 and
+ yopt[i][1] == "*" and xopt[i][0] == yopt[i][0]) or
+ (len(yopt[i]) > 2 and len(xopt[i]) > 1 and
+ yopt[i][1] == "%" and xopt[i][0] == yopt[i][0] and
+ int(xopt[i][1:]) % int(yopt[i][2:]) == 0)):
+ same = False
+ break
+ if same:
+ d += len(xopt)
+ return d
+
+
+@conf.commands.register
+def p0f(pkt):
+ """Passive OS fingerprinting: which OS emitted this TCP packet ?
+p0f(packet) -> accuracy, [list of guesses]
+"""
+ db, sig = packet2p0f(pkt)
+ if db:
+ pb = db.get_base()
+ else:
+ pb = []
+ if not pb:
+ warning("p0f base empty.")
+ return []
+ #s = len(pb[0][0])
+ r = []
+ max = len(sig[4].split(",")) + 5
+ for b in pb:
+ d = p0f_correl(sig,b)
+ if d == max:
+ r.append((b[6], b[7], b[1] - pkt[IP].ttl))
+ return r
+
+def prnp0f(pkt):
+ # we should print which DB we use
+ try:
+ r = p0f(pkt)
+ except:
+ return
+ if r == []:
+ r = ("UNKNOWN", "[" + ":".join([ str(i) for i in packet2p0f(pkt)[1]]) + ":?:?]", None)
+ else:
+ r = r[0]
+ uptime = None
+ try:
+ uptime = pkt2uptime(pkt)
+ except:
+ pass
+ if uptime == 0:
+ uptime = None
+ res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1])
+ if uptime is not None:
+ res += pkt.sprintf(" (up: " + str(uptime//3600) + " hrs)\n -> %IP.dst%:%TCP.dport% (%TCP.flags%)")
+ else:
+ res += pkt.sprintf("\n -> %IP.dst%:%TCP.dport% (%TCP.flags%)")
+ if r[2] is not None:
+ res += " (distance " + str(r[2]) + ")"
+ print(res)
+
+@conf.commands.register
+def pkt2uptime(pkt, HZ=100):
+ """Calculate the date the machine which emitted the packet booted using TCP timestamp
+pkt2uptime(pkt, [HZ=100])"""
+ if not isinstance(pkt, Packet):
+ raise TypeError("Not a TCP packet")
+ if isinstance(pkt,NoPayload):
+ raise TypeError("Not a TCP packet")
+ if not isinstance(pkt, TCP):
+ return pkt2uptime(pkt.payload)
+ for opt in pkt.options:
+ if opt[0] == "Timestamp":
+ #t = pkt.time - opt[1][0] * 1.0/HZ
+ #return time.ctime(t)
+ t = opt[1][0] / HZ
+ return t
+ raise TypeError("No timestamp option")
+
+def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
+ extrahops=0, mtu=1500, uptime=None):
+ """Modifies pkt so that p0f will think it has been sent by a
+specific OS. If osdetails is None, then we randomly pick up a
+personality matching osgenre. If osgenre and signature are also None,
+we use a local signature (using p0f_getlocalsigs). If signature is
+specified (as a tuple), we use the signature.
+
+For now, only TCP Syn packets are supported.
+Some specifications of the p0f.fp file are not (yet) implemented."""
+ pkt = pkt.copy()
+ #pkt = pkt.__class__(str(pkt))
+ while pkt.haslayer(IP) and pkt.haslayer(TCP):
+ pkt = pkt.getlayer(IP)
+ if isinstance(pkt.payload, TCP):
+ break
+ pkt = pkt.payload
+
+ if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
+ raise TypeError("Not a TCP/IP packet")
+
+ if uptime is None:
+ uptime = random.randint(120,100*60*60*24*365)
+
+ db = p0f_selectdb(pkt.payload.flags)
+ if osgenre:
+ pb = db.get_base()
+ if pb is None:
+ pb = []
+ #pb = filter(lambda x: x[6] == osgenre, pb)
+ pb = [ x for x in pb if x[6] == osgenre ]
+ if osdetails:
+ #pb = filter(lambda x: x[7] == osdetails, pb)
+ pb = [ x for x in pb if x[7] == osdetails ]
+ elif signature:
+ pb = [signature]
+ else:
+ pb = p0f_getlocalsigs()[db]
+ if db == p0fr_kdb:
+ # 'K' quirk <=> RST+ACK
+ if pkt.payload.flags & 0x4 == 0x4:
+ #pb = filter(lambda x: 'K' in x[5], pb)
+ pb = [ x for x in pb if 'K' in x[5] ]
+ else:
+ #pb = filter(lambda x: 'K' not in x[5], pb)
+ pb = [ x for x in pb if 'K' not in x[5] ]
+ if not pb:
+ raise Scapy_Exception("No match in the p0f database")
+ pers = pb[random.randint(0, len(pb) - 1)]
+
+ # options (we start with options because of MSS)
+ ## TODO: let the options already set if they are valid
+ options = []
+ if pers[4] != '.':
+ for opt in pers[4].split(','):
+ if opt[0] == 'M':
+ # MSS might have a maximum size because of window size
+ # specification
+ if pers[0][0] == 'S':
+ maxmss = (2**16-1) / int(pers[0][1:])
+ else:
+ maxmss = (2**16-1)
+ # If we have to randomly pick up a value, we cannot use
+ # scapy RandXXX() functions, because the value has to be
+ # set in case we need it for the window size value. That's
+ # why we use random.randint()
+ if opt[1:] == '*':
+ options.append(('MSS', random.randint(1,maxmss)))
+ elif opt[1] == '%':
+ coef = int(opt[2:])
+ options.append(('MSS', coef*random.randint(1,maxmss/coef)))
+ else:
+ options.append(('MSS', int(opt[1:])))
+ elif opt[0] == 'W':
+ if opt[1:] == '*':
+ options.append(('WScale', RandByte()))
+ elif opt[1] == '%':
+ coef = int(opt[2:])
+ options.append(('WScale', coef*RandNum(min=1,
+ max=(2**8-1)/coef)))
+ else:
+ options.append(('WScale', int(opt[1:])))
+ elif opt == 'T0':
+ options.append(('Timestamp', (0, 0)))
+ elif opt == 'T':
+ if 'T' in pers[5]:
+ # FIXME: RandInt() here does not work (bug (?) in
+ # TCPOptionsField.m2i often raises "OverflowError:
+ # long int too large to convert to int" in:
+ # oval = struct.pack(ofmt, *oval)"
+ # Actually, this is enough to often raise the error:
+ # struct.pack('I', RandInt())
+ options.append(('Timestamp', (uptime, random.randint(1,2**32-1))))
+ else:
+ options.append(('Timestamp', (uptime, 0)))
+ elif opt == 'S':
+ options.append(('SAckOK', ''))
+ elif opt == 'N':
+ options.append(('NOP', None))
+ elif opt == 'E':
+ options.append(('EOL', None))
+ elif opt[0] == '?':
+ if int(opt[1:]) in TCPOptions[0]:
+ optname = TCPOptions[0][int(opt[1:])][0]
+ optstruct = TCPOptions[0][int(opt[1:])][1]
+ options.append((optname,
+ struct.unpack(optstruct,
+ RandString(struct.calcsize(optstruct))._fix())))
+ else:
+ options.append((int(opt[1:]), ''))
+ ## FIXME: qqP not handled
+ else:
+ warning("unhandled TCP option " + opt)
+ pkt.payload.options = options
+
+ # window size
+ if pers[0] == '*':
+ pkt.payload.window = RandShort()
+ elif pers[0].isdigit():
+ pkt.payload.window = int(pers[0])
+ elif pers[0][0] == '%':
+ coef = int(pers[0][1:])
+ pkt.payload.window = coef * RandNum(min=1,max=(2**16-1)/coef)
+ elif pers[0][0] == 'T':
+ pkt.payload.window = mtu * int(pers[0][1:])
+ elif pers[0][0] == 'S':
+ ## needs MSS set
+ #MSS = filter(lambda x: x[0] == 'MSS', options)
+ MSS = [ x for x in options if x[0] == 'MSS' ]
+ if not MSS:
+ raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")
+ pkt.payload.window = MSS[0][1] * int(pers[0][1:])
+ else:
+ raise Scapy_Exception('Unhandled window size specification')
+
+ # ttl
+ pkt.ttl = pers[1]-extrahops
+ # DF flag
+ pkt.flags |= (2 * pers[2])
+ ## FIXME: ss (packet size) not handled (how ? may be with D quirk
+ ## if present)
+ # Quirks
+ if pers[5] != '.':
+ for qq in pers[5]:
+ ## FIXME: not handled: P, I, X, !
+ # T handled with the Timestamp option
+ if qq == 'Z': pkt.id = 0
+ elif qq == 'U': pkt.payload.urgptr = RandShort()
+ elif qq == 'A': pkt.payload.ack = RandInt()
+ elif qq == 'F':
+ #if db == p0fo_kdb:
+ # pkt.payload.flags |= 0x20 # U
+ #else:
+ pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU
+ elif qq == 'D' and db != p0fo_kdb:
+ pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
+ elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
+ #elif qq == '0': pkt.payload.seq = 0
+ #if db == p0fr_kdb:
+ # '0' quirk is actually not only for p0fr.fp (see
+ # packet2p0f())
+ if '0' in pers[5]:
+ pkt.payload.seq = 0
+ elif pkt.payload.seq == 0:
+ pkt.payload.seq = RandInt()
+
+ while pkt.underlayer:
+ pkt = pkt.underlayer
+ return pkt
+
+def p0f_getlocalsigs():
+ """This function returns a dictionary of signatures indexed by p0f
+db (e.g., p0f_kdb, p0fa_kdb, ...) for the local TCP/IP stack.
+
+You need to have your firewall at least accepting the TCP packets
+from/to a high port (30000 <= x <= 40000) on your loopback interface.
+
+Please note that the generated signatures come from the loopback
+interface and may (are likely to) be different than those generated on
+"normal" interfaces."""
+ pid = os.fork()
+ port = random.randint(30000, 40000)
+ if pid > 0:
+ # parent: sniff
+ result = {}
+ def addresult(res):
+ # TODO: wildcard window size in some cases? and maybe some
+ # other values?
+ if res[0] not in result:
+ result[res[0]] = [res[1]]
+ else:
+ if res[1] not in result[res[0]]:
+ result[res[0]].append(res[1])
+ # XXX could we try with a "normal" interface using other hosts
+ iface = conf.route.route('127.0.0.1')[0]
+ # each packet is seen twice: S + RA, S + SA + A + FA + A
+ # XXX are the packets also seen twice on non Linux systems ?
+ count=14
+ pl = sniff(iface=iface, filter='tcp and port ' + str(port), count = count, timeout=3)
+ map(addresult, map(packet2p0f, pl))
+ os.waitpid(pid,0)
+ elif pid < 0:
+ log_runtime.error("fork error")
+ else:
+ # child: send
+ # XXX erk
+ time.sleep(1)
+ s1 = socket.socket(socket.AF_INET, type = socket.SOCK_STREAM)
+ # S & RA
+ try:
+ s1.connect(('127.0.0.1', port))
+ except socket.error:
+ pass
+ # S, SA, A, FA, A
+ s1.bind(('127.0.0.1', port))
+ s1.connect(('127.0.0.1', port))
+ # howto: get an RST w/o ACK packet
+ s1.close()
+ os._exit(0)
+ return result
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/queso.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/queso.py
new file mode 100644
index 00000000..fbc7d06b
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/queso.py
@@ -0,0 +1,113 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Clone of queso OS fingerprinting
+"""
+
+from scapy.data import KnowledgeBase
+from scapy.config import conf
+from scapy.layers.inet import IP,TCP
+#from
+
+conf.queso_base ="/etc/queso.conf"
+
+
+#################
+## Queso stuff ##
+#################
+
+
+def quesoTCPflags(flags):
+ if flags == "-":
+ return "-"
+ flv = "FSRPAUXY"
+ v = 0
+ for i in flags:
+ v |= 2**flv.index(i)
+ return "%x" % v
+
+class QuesoKnowledgeBase(KnowledgeBase):
+ def lazy_init(self):
+ try:
+ f = open(self.filename)
+ except IOError:
+ return
+ self.base = {}
+ p = None
+ try:
+ for l in f:
+ l = l.strip()
+ if not l or l[0] == ';':
+ continue
+ if l[0] == '*':
+ if p is not None:
+ p[""] = name
+ name = l[1:].strip()
+ p = self.base
+ continue
+ if l[0] not in list("0123456"):
+ continue
+ res = l[2:].split()
+ res[-1] = quesoTCPflags(res[-1])
+ res = " ".join(res)
+ if not res in p:
+ p[res] = {}
+ p = p[res]
+ if p is not None:
+ p[""] = name
+ except:
+ self.base = None
+ warning("Can't load queso base [%s]", self.filename)
+ f.close()
+
+
+queso_kdb = QuesoKnowledgeBase(conf.queso_base)
+
+
+def queso_sig(target, dport=80, timeout=3):
+ p = queso_kdb.get_base()
+ ret = []
+ for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
+ ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
+ timeout=timeout, verbose=0)
+ if len(ans) == 0:
+ rs = "- - - -"
+ else:
+ s,r = ans[0]
+ rs = "%i" % (r.seq != 0)
+ if not r.ack:
+ r += " 0"
+ elif r.ack-s.seq > 666:
+ rs += " R" % 0
+ else:
+ rs += " +%i" % (r.ack-s.seq)
+ rs += " %X" % r.window
+ rs += " %x" % r.payload.flags
+ ret.append(rs)
+ return ret
+
+def queso_search(sig):
+ p = queso_kdb.get_base()
+ sig.reverse()
+ ret = []
+ try:
+ while sig:
+ s = sig.pop()
+ p = p[s]
+ if "" in p:
+ ret.append(p[""])
+ except KeyError:
+ pass
+ return ret
+
+
+@conf.commands.register
+def queso(*args,**kargs):
+ """Queso OS fingerprinting
+queso(target, dport=80, timeout=3)"""
+ return queso_search(queso_sig(*args, **kargs))
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/modules/voip.py b/scripts/external_libs/scapy-python3-0.18/scapy/modules/voip.py
new file mode 100644
index 00000000..70000a54
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/modules/voip.py
@@ -0,0 +1,149 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+VoIP (Voice over IP) related functions
+"""
+
+import os
+###################
+## Testing stuff ##
+###################
+
+from fcntl import fcntl
+from scapy.sendrecv import sniff
+from scapy.layers.inet import IP,UDP
+from scapy.layers.rtp import RTP
+from scapy.utils import get_temp_file
+
+
+def merge(x,y,sample_size=2):
+ if len(x) > len(y):
+ y += "\x00"*(len(x)-len(y))
+ elif len(x) < len(y):
+ x += "\x00"*(len(y)-len(x))
+ m = ""
+ ss=sample_size
+ for i in range(len(x)/ss):
+ m += x[ss*i:ss*(i+1)]+y[ss*i:ss*(i+1)]
+ return m
+# return "".join(map(str.__add__, x, y))
+
+
+def voip_play(s1,list=None,**kargs):
+ FIFO=get_temp_file()
+ FIFO1=FIFO % 1
+ FIFO2=FIFO % 2
+
+ os.mkfifo(FIFO1)
+ os.mkfifo(FIFO2)
+ try:
+ os.system("soxmix -t .ul %s -t .ul %s -t ossdsp /dev/dsp &" % (FIFO1,FIFO2))
+
+ c1=open(FIFO1,"w", 4096)
+ c2=open(FIFO2,"w", 4096)
+ fcntl.fcntl(c1.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
+ fcntl.fcntl(c2.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
+
+ # dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
+ def play(pkt,last=[]):
+ if not pkt:
+ return
+ if not pkt.haslayer(UDP):
+ return
+ ip=pkt.getlayer(IP)
+ if s1 in [ip.src, ip.dst]:
+ if not last:
+ last.append(pkt)
+ return
+ load=last.pop()
+ # x1 = load.load[12:]
+ c1.write(load.load[12:])
+ if load.getlayer(IP).src == ip.src:
+ # x2 = ""
+ c2.write("\x00"*len(load.load[12:]))
+ last.append(pkt)
+ else:
+ # x2 = pkt.load[:12]
+ c2.write(pkt.load[12:])
+ # dsp.write(merge(x1,x2))
+
+ if list is None:
+ sniff(store=0, prn=play, **kargs)
+ else:
+ for p in list:
+ play(p)
+ finally:
+ os.unlink(FIFO1)
+ os.unlink(FIFO2)
+
+
+
+def voip_play1(s1,list=None,**kargs):
+
+
+ dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
+ def play(pkt):
+ if not pkt:
+ return
+ if not pkt.haslayer(UDP):
+ return
+ ip=pkt.getlayer(IP)
+ if s1 in [ip.src, ip.dst]:
+ dsp.write(pkt.getlayer(conf.raw_layer).load[12:])
+ try:
+ if list is None:
+ sniff(store=0, prn=play, **kargs)
+ else:
+ for p in list:
+ play(p)
+ finally:
+ dsp.close()
+ rd.close()
+
+def voip_play2(s1,**kargs):
+ dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
+ def play(pkt,last=[]):
+ if not pkt:
+ return
+ if not pkt.haslayer(UDP):
+ return
+ ip=pkt.getlayer(IP)
+ if s1 in [ip.src, ip.dst]:
+ if not last:
+ last.append(pkt)
+ return
+ load=last.pop()
+ x1 = load.load[12:]
+# c1.write(load.load[12:])
+ if load.getlayer(IP).src == ip.src:
+ x2 = ""
+# c2.write("\x00"*len(load.load[12:]))
+ last.append(pkt)
+ else:
+ x2 = pkt.load[:12]
+# c2.write(pkt.load[12:])
+ dsp.write(merge(x1,x2))
+
+ sniff(store=0, prn=play, **kargs)
+
+def voip_play3(lst=None,**kargs):
+ dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
+ try:
+ def play(pkt, dsp=dsp):
+ if pkt and pkt.haslayer(UDP) and pkt.haslayer(conf.raw_layer):
+ dsp.write(pkt.getlayer(RTP).load)
+ if lst is None:
+ sniff(store=0, prn=play, **kargs)
+ else:
+ for p in lst:
+ play(p)
+ finally:
+ try:
+ dsp.close()
+ rd.close()
+ except:
+ pass
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/packet.py b/scripts/external_libs/scapy-python3-0.18/scapy/packet.py
new file mode 100644
index 00000000..c92a27b1
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/packet.py
@@ -0,0 +1,1360 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Packet class. Binding mechanism. fuzz() method.
+"""
+
+import time,itertools,os
+import sys,traceback
+import copy
+from .fields import StrField,ConditionalField,Emph,PacketListField
+from .config import conf
+from .base_classes import BasePacket,Gen,SetGen,Packet_metaclass,NewDefaultValues
+from .volatile import VolatileValue
+from .utils import import_hexcap,tex_escape,colgen,get_temp_file
+from .error import Scapy_Exception,log_runtime, warning
+import subprocess
+import pprint
+
+class CGlobal:
+ ONCE =False
+
+try:
+ import pyx
+except ImportError:
+ pass
+
+
+class RawVal:
+ def __init__(self, val=b""):
+ assert type(val) == bytes
+ self.val = val
+ def __str__(self):
+ return str(self.val)
+ def __repr__(self):
+ return "<RawVal [%r]>" % self.val
+ def bytes(self):
+ return self.val
+
+
+class CPacketRes:
+ pass;
+
+class Packet(BasePacket, metaclass = Packet_metaclass):
+ name=None
+
+ fields_desc = []
+
+ aliastypes = []
+ overload_fields = {}
+
+ underlayer = None
+
+ sent_time = None
+ payload_guess = []
+ initialized = 0
+ show_indent=1
+ explicit = 0
+ raw_packet_cache = None
+
+ @classmethod
+ def from_hexcap(cls):
+ return cls(import_hexcap())
+
+ @classmethod
+ def upper_bonds(self):
+ for fval,upper in self.payload_guess:
+ print("%-20s %s" % (upper.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.items())))
+
+ @classmethod
+ def lower_bonds(self):
+ for lower,fval in self.overload_fields.items():
+ print("%-20s %s" % (lower.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.items())))
+
+ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, **fields):
+ self.time = time.time()
+ self.sent_time = 0
+ if self.name is None:
+ self.name = self.__class__.__name__
+ self.aliastypes = [ self.__class__ ] + self.aliastypes
+ self.default_fields = {}
+ self.offset=0; # offset of the object
+ self.offset_fields = {} # ofsset of each field
+ self.overloaded_fields = {}
+ self.fields={}
+ self.fieldtype={}
+ self.packetfields=[]
+ self.__dict__["payload"] = NoPayload()
+ self.init_fields()
+ self.underlayer = _underlayer
+ self.initialized = 1
+ self.original = _pkt
+ if _pkt:
+ self.dissect(_pkt)
+ if not _internal:
+ self.dissection_done(self)
+ for f in fields.keys():
+ self.fields[f] = self.get_field(f).any2i(self,fields[f])
+ if type(post_transform) is list:
+ self.post_transforms = post_transform
+ elif post_transform is None:
+ self.post_transforms = []
+ else:
+ self.post_transforms = [post_transform]
+
+ def init_fields(self):
+ self.do_init_fields(self.fields_desc)
+
+ def do_init_fields(self, flist):
+ for f in flist:
+ self.default_fields[f.name] = copy.deepcopy(f.default)
+ self.fieldtype[f.name] = f
+ if f.holds_packets:
+ self.packetfields.append(f)
+
+ def dissection_done(self,pkt):
+ """DEV: will be called after a dissection is completed"""
+ self.post_dissection(pkt)
+ self.payload.dissection_done(pkt)
+
+ def post_dissection(self, pkt):
+ """DEV: is called after the dissection of the whole packet"""
+ pass
+
+ def get_field(self, fld):
+ """DEV: returns the field instance from the name of the field"""
+ return self.fieldtype[fld]
+
+ def add_payload(self, payload):
+ if payload is None:
+ return
+ elif not isinstance(self.payload, NoPayload):
+ self.payload.add_payload(payload)
+ else:
+ if isinstance(payload, Packet):
+ self.__dict__["payload"] = payload
+ payload.add_underlayer(self)
+ for t in self.aliastypes:
+ if t in payload.overload_fields:
+ self.overloaded_fields = payload.overload_fields[t]
+ break
+ #elif type(payload) is str:
+ elif type(payload) is bytes:
+ self.__dict__["payload"] = conf.raw_layer(load=payload)
+ else:
+ raise TypeError("payload must be either 'Packet' or 'bytes', not [%s]" % repr(payload))
+ def remove_payload(self):
+ self.payload.remove_underlayer(self)
+ self.__dict__["payload"] = NoPayload()
+ self.overloaded_fields = {}
+ def add_underlayer(self, underlayer):
+ self.underlayer = underlayer
+ def remove_underlayer(self,other):
+ self.underlayer = None
+ def copy(self):
+ """Returns a deep copy of the instance."""
+ clone = self.__class__()
+ clone.fields = self.fields.copy()
+ for k in clone.fields:
+ clone.fields[k] = self.get_field(k).do_copy(clone.fields[k])
+ clone.default_fields = self.default_fields.copy()
+ clone.overloaded_fields = self.overloaded_fields.copy()
+ clone.overload_fields = self.overload_fields.copy()
+ clone.offset=self.offset
+ clone.underlayer = self.underlayer
+ clone.explicit = self.explicit
+ clone.raw_packet_cache = self.raw_packet_cache
+ clone.post_transforms = self.post_transforms[:]
+ clone.__dict__["payload"] = self.payload.copy()
+ clone.payload.add_underlayer(clone)
+ return clone
+
+ def dump_offsets (self):
+ print ("obj-id {0} {1} {2}".format(id(self),self.name ,self.offset))
+ if self.payload:
+ self.payload.dump_offsets()
+
+ def getfieldval(self, attr):
+ if attr in self.fields:
+ return self.fields[attr]
+ if attr in self.overloaded_fields:
+ return self.overloaded_fields[attr]
+ if attr in self.default_fields:
+ return self.default_fields[attr]
+ return self.payload.getfieldval(attr)
+
+ def getbyteval(self, attr):
+ fld,v = self.getfield_and_val(attr)
+ return fld.i2b(self, v)
+
+ def getstrval(self, attr):
+ fld,v = self.getfield_and_val(attr)
+ return fld.i2repr(self, v)
+
+ def getfield_and_val(self, attr):
+ if attr in self.fields:
+ return self.get_field(attr),self.fields[attr]
+ if attr in self.overloaded_fields:
+ return self.get_field(attr),self.overloaded_fields[attr]
+ if attr in self.default_fields:
+ return self.get_field(attr),self.default_fields[attr]
+ return self.payload.getfield_and_val(attr)
+
+ def __getattr__(self, attr):
+ if self.initialized:
+ fld,v = self.getfield_and_val(attr)
+ if fld is not None:
+ return fld.i2h(self, v)
+ return v
+ raise AttributeError(attr)
+
+ def setfieldval(self, attr, val):
+ if attr in self.default_fields:
+ fld = self.get_field(attr)
+ if fld is None:
+ any2i = lambda x,y: y
+ else:
+ any2i = fld.any2i
+ self.fields[attr] = any2i(self, val)
+ self.explicit = 0
+ self.raw_packet_cache = None
+ elif attr == "payload":
+ self.remove_payload()
+ self.add_payload(val)
+ else:
+ self.payload.setfieldval(attr,val)
+
+ def __setattr__(self, attr, val):
+ if self.initialized:
+ try:
+ self.setfieldval(attr,val)
+ except AttributeError:
+ pass
+ else:
+ return
+ self.__dict__[attr] = val
+
+ def delfieldval(self, attr):
+ if attr in self.fields:
+ del(self.fields[attr])
+ self.explicit = 0 # in case a default value must be explicited
+ self.raw_packet_cache = None
+ elif attr in self.default_fields:
+ pass
+ elif attr == "payload":
+ self.remove_payload()
+ else:
+ self.payload.delfieldval(attr)
+
+ def __delattr__(self, attr):
+ if self.initialized:
+ try:
+ self.delfieldval(attr)
+ except AttributeError:
+ pass
+ else:
+ return
+ if attr in self.__dict__:
+ del(self.__dict__[attr])
+ else:
+ raise AttributeError(attr)
+
+ def __repr__(self):
+ s = ""
+ ct = conf.color_theme
+ for f in self.fields_desc:
+ if isinstance(f, ConditionalField) and not f._evalcond(self):
+ continue
+ if f.name in self.fields:
+ val = f.i2repr(self, self.fields[f.name])
+ elif f.name in self.overloaded_fields:
+ val = f.i2repr(self, self.overloaded_fields[f.name])
+ else:
+ continue
+ if isinstance(f, Emph) or f in conf.emph:
+ ncol = ct.emph_field_name
+ vcol = ct.emph_field_value
+ else:
+ ncol = ct.field_name
+ vcol = ct.field_value
+
+
+ s += " %s%s%s" % (ncol(f.name),
+ ct.punct("="),
+ vcol(val))
+ return "%s%s %s %s%s%s"% (ct.punct("<"),
+ ct.layer_name(self.__class__.__name__),
+ s,
+ ct.punct("|"),
+ repr(self.payload),
+ ct.punct(">"))
+ #def __str__(self):
+ #TODO3 FIX
+ def __str__(self):
+ warning("Unless called manually, this could indicate deprecated use. Should be changed to bytes(self)")
+ return repr(bytes(self))
+ def __bytes__(self):
+ return self.build()
+ def __div__(self, other):
+ if isinstance(other, Packet):
+ cloneA = self.copy()
+ cloneB = other.copy()
+ cloneA.add_payload(cloneB)
+ return cloneA
+ elif type(other) is str:
+ return self/conf.raw_layer(load=other.encode('ascii'))
+ elif type(other) is bytes:
+ return self/conf.raw_layer(load=other)
+ else:
+ return other.__rdiv__(self)
+ __truediv__ = __div__
+ def __rdiv__(self, other):
+ if type(other) is str:
+ return conf.raw_layer(load=other.encode('ascii'))/self
+ if type(other) is bytes:
+ return conf.raw_layer(load=other)/self
+ else:
+ raise TypeError
+ __rtruediv__ = __rdiv__
+ def __mul__(self, other):
+ if type(other) is int:
+ return [self]*other
+ else:
+ raise TypeError
+ def __rmul__(self,other):
+ return self.__mul__(other)
+
+ def __nonzero__(self):
+ return True
+
+ def __len__(self):
+ return len(bytes(self))
+
+ def dump_fields_offsets (self):
+ for f in self.fields_desc:
+ print ("field %-40s %02d %02d" % (f.name, f.offset,f.get_size_bytes () ) );
+
+ def self_build(self, field_pos_list=None):
+ if self.raw_packet_cache is not None:
+ return self.raw_packet_cache
+ p=b""
+ for f in self.fields_desc:
+ #print(f.name)
+ if type(p) is tuple :
+ f.offset=len(p[0])
+ else:
+ assert(type(p)==bytes)
+ f.offset=len(p)
+
+ val = self.getfieldval(f.name)
+ if isinstance(val, RawVal):
+ #sval = str(val)
+ sval = bytes(val)
+ p += sval
+ if field_pos_list is not None:
+ field_pos_list.append( (f.name, sval.encode("string_escape"), len(p), len(sval) ) )
+ f.offset= val
+ else:
+ p = f.addfield(self, p, val)
+ return p
+
+ def do_build_payload(self):
+ return self.payload.do_build(None)
+
+ def do_update_payload_offset(self,pkt):
+ #print "obj-id ",id(self)
+ #print "current offset ",self.name," ",self.offset
+ #print "current header size ",len(pkt)
+ self.payload.offset = self.offset + len(pkt)
+
+ def dump_layers_offset (self):
+ p=self;
+ while True:
+ print (p.name, "offset :",p.offset)
+ p=p.payload
+ if p ==None or isinstance(p,NoPayload):
+ break;
+
+
+ def do_build(self,result):
+ if not self.explicit:
+ self = next(self.__iter__())
+ pkt = self.self_build()
+ for t in self.post_transforms:
+ pkt = t(pkt)
+ self.do_update_payload_offset(pkt)
+ pay = self.do_build_payload()
+ p = self.post_build(pkt,pay)
+ if result != None:
+ result.pkt = self;
+ return p
+
+ def build_padding(self):
+ return self.payload.build_padding()
+
+ def update_build_info (self,other):
+ p=self;
+ o=other;
+ while True:
+ assert(p.aliastypes==o.aliastypes)
+ assert(type(p) == type(o) )
+
+ #copy
+ p.offset=o.offset
+
+ #next
+ p=p.payload
+ o=o.payload
+ if p ==None or isinstance(p,NoPayload):
+ break;
+
+ def build(self):
+ result = CPacketRes;
+ p = self.do_build(result)
+ p += self.build_padding()
+ p = self.build_done(p)
+ self.update_build_info (result.pkt)
+ return p
+
+ def post_build(self, pkt, pay):
+ """DEV: called right after the current layer is build."""
+ return pkt+pay
+
+ def build_done(self, p):
+ return self.payload.build_done(p)
+
+ def do_build_ps(self):
+ p=b""
+ pl = []
+ q=b""
+ for f in self.fields_desc:
+ if isinstance(f, ConditionalField) and not f._evalcond(self):
+ continue
+ p = f.addfield(self, p, self.getfieldval(f.name) )
+ if type(p) is bytes:
+ r = p[len(q):]
+ q = p
+ else:
+ r = b""
+ pl.append( (f, f.i2repr(self,self.getfieldval(f.name)), r) )
+
+ pkt,lst = self.payload.build_ps(internal=1)
+ p += pkt
+ lst.append( (self, pl) )
+
+ return p,lst
+
+ def build_ps(self,internal=0):
+ p,lst = self.do_build_ps()
+# if not internal:
+# pkt = self
+# while pkt.haslayer(conf.padding_layer):
+# pkt = pkt.getlayer(conf.padding_layer)
+# lst.append( (pkt, [ ("loakjkjd", pkt.load, pkt.load) ] ) )
+# p += pkt.load
+# pkt = pkt.payload
+ return p,lst
+
+
+ def psdump(self, filename=None, **kargs):
+ """psdump(filename=None, layer_shift=0, rebuild=1)
+Creates an EPS file describing a packet. If filename is not provided a temporary file is created and gs is called."""
+ canvas = self.canvas_dump(**kargs)
+ if filename is None:
+ fname = get_temp_file(autoext=".eps")
+ canvas.writeEPSfile(fname)
+ subprocess.Popen([conf.prog.psreader, fname+".eps"])
+ else:
+ canvas.writeEPSfile(filename)
+
+ def pdfdump(self, filename=None, **kargs):
+ """pdfdump(filename=None, layer_shift=0, rebuild=1)
+ Creates a PDF file describing a packet. If filename is not provided a temporary file is created and xpdf is called."""
+ canvas = self.canvas_dump(**kargs)
+ if filename is None:
+ fname = get_temp_file(autoext=".pdf")
+ canvas.writePDFfile(fname)
+ subprocess.Popen([conf.prog.pdfreader, fname+".pdf"])
+ else:
+ canvas.writePDFfile(filename)
+
+
+ def canvas_dump(self, layer_shift=0, rebuild=1):
+ canvas = pyx.canvas.canvas()
+ if rebuild:
+ p,t = self.__class__(bytes(self)).build_ps()
+ else:
+ p,t = self.build_ps()
+ YTXT=len(t)
+ for n,l in t:
+ YTXT += len(l)
+ YTXT = float(YTXT)
+ YDUMP=YTXT
+
+ XSTART = 1
+ XDSTART = 10
+ y = 0.0
+ yd = 0.0
+ xd = 0
+ XMUL= 0.55
+ YMUL = 0.4
+
+ backcolor=colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)
+ forecolor=colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)
+# backcolor=makecol(0.376, 0.729, 0.525, 1.0)
+
+
+ def hexstr(x):
+ s = []
+ for c in x:
+ s.append("%02x" % c)
+ return " ".join(s)
+
+
+ def make_dump_txt(x,y,txt):
+ return pyx.text.text(XDSTART+x*XMUL, (YDUMP-y)*YMUL, r"\tt{%s}"%hexstr(txt), [pyx.text.size.Large])
+
+ def make_box(o):
+ return pyx.box.rect(o.left(), o.bottom(), o.width(), o.height(), relcenter=(0.5,0.5))
+
+ def make_frame(lst):
+ if len(lst) == 1:
+ b = lst[0].bbox()
+ b.enlarge(pyx.unit.u_pt)
+ return b.path()
+ else:
+ fb = lst[0].bbox()
+ fb.enlarge(pyx.unit.u_pt)
+ lb = lst[-1].bbox()
+ lb.enlarge(pyx.unit.u_pt)
+ if len(lst) == 2 and fb.left() > lb.right():
+ return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),
+ pyx.path.lineto(fb.left(), fb.top()),
+ pyx.path.lineto(fb.left(), fb.bottom()),
+ pyx.path.lineto(fb.right(), fb.bottom()),
+ pyx.path.moveto(lb.left(), lb.top()),
+ pyx.path.lineto(lb.right(), lb.top()),
+ pyx.path.lineto(lb.right(), lb.bottom()),
+ pyx.path.lineto(lb.left(), lb.bottom()))
+ else:
+ # XXX
+ gb = lst[1].bbox()
+ if gb != lb:
+ gb.enlarge(pyx.unit.u_pt)
+ kb = lst[-2].bbox()
+ if kb != gb and kb != lb:
+ kb.enlarge(pyx.unit.u_pt)
+ return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),
+ pyx.path.lineto(fb.right(), fb.top()),
+ pyx.path.lineto(fb.right(), kb.bottom()),
+ pyx.path.lineto(lb.right(), kb.bottom()),
+ pyx.path.lineto(lb.right(), lb.bottom()),
+ pyx.path.lineto(lb.left(), lb.bottom()),
+ pyx.path.lineto(lb.left(), gb.top()),
+ pyx.path.lineto(fb.left(), gb.top()),
+ pyx.path.closepath(),)
+
+
+ def make_dump(s, shift=0, y=0, col=None, bkcol=None, larg=16):
+ c = pyx.canvas.canvas()
+ tlist = []
+ while s:
+ dmp,s = s[:larg-shift],s[larg-shift:]
+ txt = make_dump_txt(shift, y, dmp)
+ tlist.append(txt)
+ shift += len(dmp)
+ if shift >= 16:
+ shift = 0
+ y += 1
+ if col is None:
+ col = pyx.color.rgb.red
+ if bkcol is None:
+ col = pyx.color.rgb.white
+ c.stroke(make_frame(tlist),[col,pyx.deco.filled([bkcol]),pyx.style.linewidth.Thick])
+ for txt in tlist:
+ c.insert(txt)
+ return c, tlist[-1].bbox(), shift, y
+
+
+ last_shift,last_y=0,0.0
+ while t:
+ bkcol = next(backcolor)
+ proto,fields = t.pop()
+ y += 0.5
+ pt = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % proto.name, [ pyx.text.size.Large])
+ y += 1
+ ptbb=pt.bbox()
+ ptbb.enlarge(pyx.unit.u_pt*2)
+ canvas.stroke(ptbb.path(),[pyx.color.rgb.black, pyx.deco.filled([bkcol])])
+ canvas.insert(pt)
+ for fname, fval, fdump in fields:
+ col = next(forecolor)
+ ft = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fname.name))
+ if isinstance(fval, str):
+ if len(fval) > 18:
+ fval = fval[:18]+"[...]"
+ else:
+ fval=""
+ vt = pyx.text.text(XSTART+3, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fval))
+ y += 1.0
+ if fdump:
+ dt,target,last_shift,last_y = make_dump(fdump, last_shift, last_y, col, bkcol)
+
+ dtb = dt.bbox()
+ dtb=target
+ vtb = vt.bbox()
+ bxvt = make_box(vtb)
+ bxdt = make_box(dtb)
+ dtb.enlarge(pyx.unit.u_pt)
+ try:
+ if yd < 0:
+ cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=-90)
+ else:
+ cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=90)
+ except:
+ pass
+ else:
+ canvas.stroke(cnx,[pyx.style.linewidth.thin,pyx.deco.earrow.small,col])
+
+ canvas.insert(dt)
+
+ canvas.insert(ft)
+ canvas.insert(vt)
+ last_y += layer_shift
+
+ return canvas
+
+
+
+ def extract_padding(self, s):
+ """DEV: to be overloaded to extract current layer's padding. Return a couple of strings (actual layer, padding)"""
+ return s,None
+
+ def post_dissect(self, s):
+ """DEV: is called right after the current layer has been dissected"""
+ return s
+
+ def pre_dissect(self, s):
+ """DEV: is called right before the current layer is dissected"""
+ return s
+
+ def do_dissect(self, s):
+ flist = self.fields_desc[:]
+ flist.reverse()
+ raw = s
+ while s and flist:
+ f = flist.pop()
+ #print(f, end = " = ")
+ s,fval = f.getfield(self, s)
+ #print('fval')
+ self.fields[f.name] = fval
+ assert(raw.endswith(s))
+ if s:
+ self.raw_packet_cache = raw[:-len(s)]
+ else:
+ self.raw_packet_cache = raw
+ self.explicit = 1
+ return s
+
+ def do_dissect_payload(self, s):
+ if s:
+ cls = self.guess_payload_class(s)
+ try:
+ p = cls(s, _internal=1, _underlayer=self)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ if isinstance(cls,type) and issubclass(cls,Packet):
+ log_runtime.error("%s dissector failed" % cls.name)
+ else:
+ log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
+ if cls is not None:
+ raise
+ p = conf.raw_layer(s, _internal=1, _underlayer=self)
+ self.add_payload(p)
+
+ def dissect(self, s):
+ s = self.pre_dissect(s)
+
+ s = self.do_dissect(s)
+
+ s = self.post_dissect(s)
+
+ payl,pad = self.extract_padding(s)
+ self.do_dissect_payload(payl)
+ if pad and conf.padding:
+ self.add_payload(conf.padding_layer(pad))
+
+
+ def guess_payload_class(self, payload):
+ """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism."""
+ for t in self.aliastypes:
+ for fval, cls in t.payload_guess:
+ ok = 1
+ for k in fval.keys():
+ if not hasattr(self, k) or fval[k] != self.getfieldval(k):
+ ok = 0
+ break
+ if ok:
+ return cls
+ return self.default_payload_class(payload)
+
+ def default_payload_class(self, payload):
+ """DEV: Returns the default payload class if nothing has been found by the guess_payload_class() method."""
+ return conf.raw_layer
+
+ def hide_defaults(self):
+ """Removes fields' values that are the same as default values."""
+ for k in list(self.fields.keys()):
+ if k in self.default_fields:
+ if self.default_fields[k] == self.fields[k]:
+ del(self.fields[k])
+ self.payload.hide_defaults()
+
+ def clone_with(self, payload=None, **kargs):
+ pkt = self.__class__()
+ pkt.explicit = 1
+ pkt.fields = kargs
+ pkt.offset=self.offset
+ pkt.time = self.time
+ pkt.underlayer = self.underlayer
+ pkt.overload_fields = self.overload_fields.copy()
+ pkt.post_transforms = self.post_transforms
+ if payload is not None:
+ pkt.add_payload(payload)
+ return pkt
+
+
+ def __iter__(self):
+ def loop(todo, done, self=self):
+ if todo:
+ eltname = todo.pop()
+ elt = self.getfieldval(eltname)
+ if not isinstance(elt, Gen):
+ if self.get_field(eltname).islist:
+ elt = SetGen([elt])
+ else:
+ elt = SetGen(elt)
+ for e in elt:
+ done[eltname]=e
+ for x in loop(todo[:], done):
+ yield x
+ else:
+ if isinstance(self.payload,NoPayload):
+ payloads = [None]
+ else:
+ payloads = self.payload
+ for payl in payloads:
+ done2=done.copy()
+ for k in done2:
+ if isinstance(done2[k], VolatileValue):
+ done2[k] = done2[k]._fix()
+ pkt = self.clone_with(payload=payl, **done2)
+ yield pkt
+
+ if self.explicit:
+ todo = []
+ done = self.fields
+ else:
+ todo = [ k for (k,v) in itertools.chain(self.default_fields.items(),
+ self.overloaded_fields.items())
+ if isinstance(v, VolatileValue) ] + list(self.fields.keys())
+ done = {}
+ return loop(todo, done)
+
+ def __gt__(self, other):
+ """True if other is an answer from self (self ==> other)."""
+ if isinstance(other, Packet):
+ return other < self
+ elif type(other) is str:
+ return 1
+ else:
+ raise TypeError((self, other))
+ def __lt__(self, other):
+ """True if self is an answer from other (other ==> self)."""
+ if isinstance(other, Packet):
+ return self.answers(other)
+ elif type(other) is str:
+ return 1
+ else:
+ raise TypeError((self, other))
+
+ def __eq__(self, other):
+ if not isinstance(other, self.__class__):
+ return False
+ for f in self.fields_desc:
+ if f not in other.fields_desc:
+ return False
+ if self.getfieldval(f.name) != other.getfieldval(f.name):
+ return False
+ return self.payload == other.payload
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def hashret(self):
+ """DEV: returns a string that has the same value for a request and its answer."""
+ return self.payload.hashret()
+ def answers(self, other):
+ """DEV: true if self is an answer from other"""
+ if other.__class__ == self.__class__:
+ return self.payload.answers(other.payload)
+ return 0
+
+ def haslayer(self, cls):
+ """true if self has a layer that is an instance of cls. Superseded by "cls in self" syntax."""
+ if self.__class__ == cls or self.__class__.__name__ == cls:
+ return 1
+ for f in self.packetfields:
+ fvalue_gen = self.getfieldval(f.name)
+ if fvalue_gen is None:
+ continue
+ if not f.islist:
+ fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
+ for fvalue in fvalue_gen:
+ if isinstance(fvalue, Packet):
+ ret = fvalue.haslayer(cls)
+ if ret:
+ return ret
+ return self.payload.haslayer(cls)
+ def getlayer(self, cls, nb=1, _track=None):
+ """Return the nb^th layer that is an instance of cls."""
+ if type(cls) is int:
+ nb = cls+1
+ cls = None
+ if type(cls) is str and "." in cls:
+ ccls,fld = cls.split(".",1)
+ else:
+ ccls,fld = cls,None
+ if cls is None or self.__class__ == cls or self.__class__.name == ccls:
+ if nb == 1:
+ if fld is None:
+ return self
+ else:
+ return self.getfieldval(fld)
+ else:
+ nb -=1
+ for f in self.packetfields:
+ fvalue_gen = self.getfieldval(f.name)
+ if fvalue_gen is None:
+ continue
+ if not f.islist:
+ fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
+ for fvalue in fvalue_gen:
+ if isinstance(fvalue, Packet):
+ track=[]
+ ret = fvalue.getlayer(cls, nb, _track=track)
+ if ret is not None:
+ return ret
+ nb = track[0]
+ return self.payload.getlayer(cls,nb,_track=_track)
+
+ def firstlayer(self):
+ q = self
+ while q.underlayer is not None:
+ q = q.underlayer
+ return q
+
+ def __getitem__(self, cls):
+ if type(cls) is slice:
+ lname = cls.start
+ if cls.stop:
+ ret = self.getlayer(cls.start, cls.stop)
+ else:
+ ret = self.getlayer(cls.start)
+ if ret is None and cls.step is not None:
+ ret = cls.step
+ else:
+ lname=cls
+ ret = self.getlayer(cls)
+ if ret is None:
+ if type(lname) is Packet_metaclass:
+ lname = lname.__name__
+ elif type(lname) is not str:
+ lname = repr(lname)
+ raise IndexError("Layer [%s] not found" % lname)
+ return ret
+
+ def __delitem__(self, cls):
+ del(self[cls].underlayer.payload)
+
+ def __setitem__(self, cls, val):
+ self[cls].underlayer.payload = val
+
+ def __contains__(self, cls):
+ """"cls in self" returns true if self has a layer which is an instance of cls."""
+ return self.haslayer(cls)
+
+ def route(self):
+ return (None,None,None)
+
+ def fragment(self, *args, **kargs):
+ return self.payload.fragment(*args, **kargs)
+
+
+ def display(self,*args,**kargs): # Deprecated. Use show()
+ """Deprecated. Use show() method."""
+ self.show(*args,**kargs)
+ def show(self, indent=3, lvl="", label_lvl=""):
+ """Prints a hierarchical view of the packet. "indent" gives the size of indentation for each layer."""
+ ct = conf.color_theme
+ print("%s%s %s %s" % (label_lvl,
+ ct.punct("###["),
+ ct.layer_name(self.name),
+ ct.punct("]###")))
+ for f in self.fields_desc:
+ if isinstance(f, ConditionalField) and not f._evalcond(self):
+ continue
+ if isinstance(f, Emph) or f in conf.emph:
+ ncol = ct.emph_field_name
+ vcol = ct.emph_field_value
+ else:
+ ncol = ct.field_name
+ vcol = ct.field_value
+ fvalue = self.getfieldval(f.name)
+ if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and type(fvalue) is list):
+ print("%s \\%-10s\\" % (label_lvl+lvl, ncol(f.name)))
+ fvalue_gen = SetGen(fvalue,_iterpacket=0)
+ for fvalue in fvalue_gen:
+ fvalue.show(indent=indent, label_lvl=label_lvl+lvl+" |")
+ else:
+ begn = "%s %-10s%s " % (label_lvl+lvl,
+ ncol(f.name),
+ ct.punct("="),)
+ reprval = f.i2repr(self,fvalue)
+ if type(reprval) is str:
+ reprval = reprval.replace("\n", "\n"+" "*(len(label_lvl)
+ +len(lvl)
+ +len(f.name)
+ +4))
+ print("%s%s" % (begn,vcol(reprval)))
+ self.payload.show(indent=indent, lvl=lvl+(" "*indent*self.show_indent), label_lvl=label_lvl)
+ def show2(self):
+ """Prints a hierarchical view of an assembled version of the packet, so that automatic fields are calculated (checksums, etc.)"""
+ self.__class__(bytes(self)).show()
+
+ def sprintf(self, fmt, relax=1):
+ """sprintf(format, [relax=1]) -> str
+where format is a string that can include directives. A directive begins and
+ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
+
+fmt is a classic printf directive, "r" can be appended for raw substitution
+(ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
+(ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
+Special case : "%.time%" is the creation time.
+Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
+ "%03xr,IP.proto% %r,TCP.flags%")
+
+Moreover, the format string can include conditionnal statements. A conditionnal
+statement looks like : {layer:string} where layer is a layer name, and string
+is the string to insert in place of the condition if it is true, i.e. if layer
+is present. If layer is preceded by a "!", the result si inverted. Conditions
+can be imbricated. A valid statement can be :
+ p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
+ p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")
+
+A side effect is that, to obtain "{" and "}" characters, you must use
+"%(" and "%)".
+"""
+
+ escape = { "%": "%",
+ "(": "{",
+ ")": "}" }
+
+
+ # Evaluate conditions
+ while "{" in fmt:
+ i = fmt.rindex("{")
+ j = fmt[i+1:].index("}")
+ cond = fmt[i+1:i+j+1]
+ k = cond.find(":")
+ if k < 0:
+ raise Scapy_Exception("Bad condition in format string: [%s] (read sprintf doc!)"%cond)
+ cond,format = cond[:k],cond[k+1:]
+ res = False
+ if cond[0] == "!":
+ res = True
+ cond = cond[1:]
+ if self.haslayer(cond):
+ res = not res
+ if not res:
+ format = ""
+ fmt = fmt[:i]+format+fmt[i+j+2:]
+
+ # Evaluate directives
+ s = ""
+ while "%" in fmt:
+ i = fmt.index("%")
+ s += fmt[:i]
+ fmt = fmt[i+1:]
+ if fmt and fmt[0] in escape:
+ s += escape[fmt[0]]
+ fmt = fmt[1:]
+ continue
+ try:
+ i = fmt.index("%")
+ sfclsfld = fmt[:i]
+ fclsfld = sfclsfld.split(",")
+ if len(fclsfld) == 1:
+ f = "s"
+ clsfld = fclsfld[0]
+ elif len(fclsfld) == 2:
+ f,clsfld = fclsfld
+ else:
+ raise Scapy_Exception
+ if "." in clsfld:
+ cls,fld = clsfld.split(".")
+ else:
+ cls = self.__class__.__name__
+ fld = clsfld
+ num = 1
+ if ":" in cls:
+ cls,num = cls.split(":")
+ num = int(num)
+ fmt = fmt[i+1:]
+ except:
+ raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))
+ else:
+ if fld == "time":
+ val = time.strftime("%H:%M:%S.%%06i", time.localtime(self.time)) % int((self.time-int(self.time))*1000000)
+ elif cls == self.__class__.__name__ and hasattr(self, fld):
+ if num > 1:
+ val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f,cls,num-1,fld), relax)
+ f = "s"
+ elif f[-1] == "r": # Raw field value
+ val = getattr(self,fld)
+ f = f[:-1]
+ if not f:
+ f = "s"
+ else:
+ val = getattr(self,fld)
+ if fld in self.fieldtype:
+ val = self.fieldtype[fld].i2repr(self,val)
+ else:
+ val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
+ f = "s"
+ s += ("%"+f) % val
+
+ s += fmt
+ return s
+
+ def mysummary(self):
+ """DEV: can be overloaded to return a string that summarizes the layer.
+ Only one mysummary() is used in a whole packet summary: the one of the upper layer,
+ except if a mysummary() also returns (as a couple) a list of layers whose
+ mysummary() must be called if they are present."""
+ return ""
+
+ def _do_summary(self):
+ found,s,needed = self.payload._do_summary()
+ if s:
+ s = " / "+s
+ ret = ""
+ if not found or self.__class__ in needed:
+ ret = self.mysummary()
+ if type(ret) is tuple:
+ ret,n = ret
+ needed += n
+ if ret or needed:
+ found = 1
+ if not ret:
+ ret = self.__class__.__name__
+ if self.__class__ in conf.emph:
+ impf = []
+ for f in self.fields_desc:
+ if f in conf.emph:
+ impf.append("%s=%s" % (f.name, f.i2repr(self, self.getfieldval(f.name))))
+ ret = "%s [%s]" % (ret," ".join(impf))
+ ret = "%s%s" % (ret,s)
+ return found,ret,needed
+
+ def summary(self, intern=0):
+ """Prints a one line summary of a packet."""
+ found,s,needed = self._do_summary()
+ return s
+
+
+ def lastlayer(self,layer=None):
+ """Returns the uppest layer of the packet"""
+ return self.payload.lastlayer(self)
+
+ def decode_payload_as(self,cls):
+ """Reassembles the payload and decode it using another packet class"""
+ s = bytes(self.payload)
+ self.payload = cls(s, _internal=1, _underlayer=self)
+ pp = self
+ while pp.underlayer is not None:
+ pp = pp.underlayer
+ self.payload.dissection_done(pp)
+
+ def libnet(self):
+ """Not ready yet. Should give the necessary C code that interfaces with libnet to recreate the packet"""
+ print("libnet_build_%s(" % self.__class__.name.lower())
+ det = self.__class__(str(self))
+ for f in self.fields_desc:
+ val = det.getfieldval(f.name)
+ if val is None:
+ val = 0
+ elif type(val) is int:
+ val = str(val)
+ else:
+ val = '"%s"' % str(val)
+ print("\t%s, \t\t/* %s */" % (val,f.name))
+ print(");")
+ def command(self):
+ """Returns a string representing the command you have to type to obtain the same packet"""
+ f = []
+ for fn,fv in self.fields.items():
+ fld = self.get_field(fn)
+ if isinstance(fv, Packet):
+ fv = fv.command()
+ elif fld.islist and fld.holds_packets and type(fv) is list:
+ #fv = "[%s]" % ",".join( map(Packet.command, fv))
+ fv = "[%s]" % ",".join([ Packet.command(i) for i in fv ])
+ else:
+ fv = repr(fv)
+ f.append("%s=%s" % (fn, fv))
+ c = "%s(%s)" % (self.__class__.__name__, ", ".join(f))
+ pc = self.payload.command()
+ if pc:
+ c += "/"+pc
+ return c
+
+class NoPayload(Packet):
+ def __new__(cls, *args, **kargs):
+ singl = cls.__dict__.get("__singl__")
+ if singl is None:
+ cls.__singl__ = singl = Packet.__new__(cls)
+ Packet.__init__(singl)
+ return singl
+ def __init__(self, *args, **kargs):
+ pass
+ def dissection_done(self,pkt):
+ return
+ def add_payload(self, payload):
+ raise Scapy_Exception("Can't add payload to NoPayload instance")
+ def remove_payload(self):
+ pass
+ def add_underlayer(self,underlayer):
+ pass
+ def remove_underlayer(self,other):
+ pass
+ def copy(self):
+ return self
+ def __repr__(self):
+ return ""
+ def __str__(self):
+ return ""
+ def __nonzero__(self):
+ return False
+ def do_build(self,result):
+ return b""
+ def build(self):
+ return b""
+ def build_padding(self):
+ return b""
+ def build_done(self, p):
+ return p
+ def build_ps(self, internal=0):
+ return b"",[]
+ def getfieldval(self, attr):
+ raise AttributeError(attr)
+ def getfield_and_val(self, attr):
+ raise AttributeError(attr)
+ def setfieldval(self, attr, val):
+ raise AttributeError(attr)
+ def delfieldval(self, attr):
+ raise AttributeError(attr)
+ def __getattr__(self, attr):
+ if attr in self.__dict__:
+ return self.__dict__[attr]
+ elif attr in self.__class__.__dict__:
+ return self.__class__.__dict__[attr]
+ else:
+ raise AttributeError(attr)
+ def hide_defaults(self):
+ pass
+ def __iter__(self):
+ return iter([])
+ def __eq__(self, other):
+ if isinstance(other, NoPayload):
+ return True
+ return False
+ def hashret(self):
+ return b""
+ def answers(self, other):
+ return isinstance(other, NoPayload) or isinstance(other, conf.padding_layer)
+ def haslayer(self, cls):
+ return 0
+ def getlayer(self, cls, nb=1, _track=None):
+ if _track is not None:
+ _track.append(nb)
+ return None
+ def fragment(self, *args, **kargs):
+ raise Scapy_Exception("cannot fragment this packet")
+ def show(self, indent=3, lvl="", label_lvl=""):
+ pass
+ def sprintf(self, fmt, relax):
+ if relax:
+ return "??"
+ else:
+ raise Scapy_Exception("Format not found [%s]"%fmt)
+ def _do_summary(self):
+ return 0,"",[]
+ def lastlayer(self,layer):
+ return layer
+ def command(self):
+ return ""
+
+####################
+## packet classes ##
+####################
+
+
+class Raw(Packet):
+ name = "Raw"
+ fields_desc = [ StrField("load", b"") ]
+ def answers(self, other):
+ return 1
+# s = str(other)
+# t = self.load
+# l = min(len(s), len(t))
+# return s[:l] == t[:l]
+ def mysummary(self):
+ cs = conf.raw_summary
+ if cs:
+ if callable(cs):
+ return "Raw %s" % cs(self.load)
+ else:
+ return "Raw %r" % self.load
+ return Packet.mysummary(self)
+
+class Padding(Raw):
+ name = "Padding"
+ def self_build(self):
+ return b""
+ def build_padding(self):
+ return (self.getbyteval("load") if self.raw_packet_cache is None
+ else self.raw_packet_cache) + self.payload.build_padding()
+
+conf.raw_layer = Raw
+conf.padding_layer = Padding
+if conf.default_l2 is None:
+ conf.default_l2 = Raw
+
+#################
+## Bind layers ##
+#################
+
+
+def bind_bottom_up(lower, upper, __fval=None, **fval):
+ if __fval is not None:
+ fval.update(__fval)
+ lower.payload_guess = lower.payload_guess[:]
+ lower.payload_guess.append((fval, upper))
+
+
+def bind_top_down(lower, upper, __fval=None, **fval):
+ if __fval is not None:
+ fval.update(__fval)
+ upper.overload_fields = upper.overload_fields.copy()
+ upper.overload_fields[lower] = fval
+
+@conf.commands.register
+def bind_layers(lower, upper, __fval=None, **fval):
+ """Bind 2 layers on some specific fields' values"""
+ if __fval is not None:
+ fval.update(__fval)
+ bind_top_down(lower, upper, **fval)
+ bind_bottom_up(lower, upper, **fval)
+
+def split_bottom_up(lower, upper, __fval=None, **fval):
+ if __fval is not None:
+ fval.update(__fval)
+ #def do_filter((f,u),upper=upper,fval=fval):
+ def do_filter(s,upper=upper,fval=fval):
+ if s[1] != upper:
+ return True
+ for k in fval:
+ if k not in s[0] or s[0][k] != fval[k]:
+ return True
+ return False
+ lower.payload_guess = list(filter(do_filter, lower.payload_guess))
+
+def split_top_down(lower, upper, __fval=None, **fval):
+ if __fval is not None:
+ fval.update(__fval)
+ if lower in upper.overload_fields:
+ ofval = upper.overload_fields[lower]
+ for k in fval:
+ if k not in ofval or ofval[k] != fval[k]:
+ return
+ upper.overload_fields = upper.overload_fields.copy()
+ del(upper.overload_fields[lower])
+
+@conf.commands.register
+def split_layers(lower, upper, __fval=None, **fval):
+ """Split 2 layers previously bound"""
+ if __fval is not None:
+ fval.update(__fval)
+ split_bottom_up(lower, upper, **fval)
+ split_top_down(lower, upper, **fval)
+
+
+@conf.commands.register
+def ls(obj=None):
+ """List available layers, or infos on a given layer"""
+ if obj is None:
+
+ import builtins
+ all = builtins.__dict__.copy()
+ all.update(globals())
+ objlst = sorted(conf.layers, key=lambda x:x.__name__)
+ for o in objlst:
+ print("%-10s : %s" %(o.__name__,o.name))
+ else:
+ if isinstance(obj, type) and issubclass(obj, Packet):
+ for f in obj.fields_desc:
+ print("%-10s : %-20s = (%s)" % (f.name, f.__class__.__name__, repr(f.default)))
+ elif isinstance(obj, Packet):
+ for f in obj.fields_desc:
+ print("%-10s : %-20s = %-15s (%s)" % (f.name, f.__class__.__name__, repr(getattr(obj,f.name)), repr(f.default)))
+ if not isinstance(obj.payload, NoPayload):
+ print("--")
+ ls(obj.payload)
+
+
+ else:
+ print("Not a packet class. Type 'ls()' to list packet classes.")
+
+
+
+#############
+## Fuzzing ##
+#############
+
+@conf.commands.register
+def fuzz(p, _inplace=0):
+ """Transform a layer into a fuzzy layer by replacing some default values by random objects"""
+ if not _inplace:
+ p = p.copy()
+ q = p
+ while not isinstance(q, NoPayload):
+ for f in q.fields_desc:
+ if isinstance(f, PacketListField):
+ for r in getattr(q, f.name):
+ print("fuzzing", repr(r))
+ fuzz(r, _inplace=1)
+ elif f.default is not None:
+ rnd = f.randval()
+ if rnd is not None:
+ q.default_fields[f.name] = rnd
+ q = q.payload
+ return p
+
+
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/pipetool.py b/scripts/external_libs/scapy-python3-0.18/scapy/pipetool.py
new file mode 100644
index 00000000..2dc28cb5
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/pipetool.py
@@ -0,0 +1,566 @@
+#! /usr/bin/env python
+
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+from __future__ import with_statement
+
+import scapy.utils
+from scapy.config import conf
+import os,_thread,select
+import subprocess
+import itertools
+import collections
+import time
+from scapy.error import log_interactive,warning
+import queue
+
+class PipeEngine:
+ pipes = {}
+ @classmethod
+ def list_pipes(cls):
+ for pn,pc in sorted(cls.pipes.items()):
+ doc = pc.__doc__ or ""
+ if doc:
+ doc = doc.splitlines()[0]
+ print("%20s: %s" % (pn, doc))
+ @classmethod
+ def list_pipes_detailed(cls):
+ for pn,pc in sorted(cls.pipes.items()):
+ if pc.__doc__:
+ print("###### %s\n %s" % (pn ,pc.__doc__))
+ else:
+ print("###### %s" % pn)
+
+ def __init__(self, *pipes):
+ self.active_pipes = set()
+ self.active_sources = set()
+ self.active_drains = set()
+ self.active_sinks = set()
+ self._add_pipes(*pipes)
+ self.thread_lock = _thread.allocate_lock()
+ self.command_lock = _thread.allocate_lock()
+ self.__fdr,self.__fdw = os.pipe()
+ self.threadid = None
+ def __getattr__(self, attr):
+ if attr.startswith("spawn_"):
+ dname = attr[6:]
+ if dname in self.pipes:
+ def f(*args, **kargs):
+ k = self.pipes[dname]
+ p = k(*args, **kargs)
+ self.add(p)
+ return p
+ return f
+ raise AttributeError(attr)
+
+ def add_one_pipe(self, pipe):
+ self.active_pipes.add(pipe)
+ if isinstance(pipe, Source):
+ self.active_sources.add(pipe)
+ if isinstance(pipe, Drain):
+ self.active_drains.add(pipe)
+ if isinstance(pipe, Sink):
+ self.active_sinks.add(pipe)
+
+ def get_pipe_list(self, pipe):
+ def flatten(p, l):
+ l.add(p)
+ for q in p.sources|p.sinks|p.high_sources|p.high_sinks:
+ if q not in l:
+ flatten(q, l)
+ pl = set()
+ flatten(pipe, pl)
+ return pl
+
+ def _add_pipes(self, *pipes):
+ pl = set()
+ for p in pipes:
+ pl |= self.get_pipe_list(p)
+ pl -= self.active_pipes
+ for q in pl:
+ self.add_one_pipe(q)
+ return pl
+
+
+ def run(self):
+ log_interactive.info("Pipe engine thread started.")
+ try:
+ for p in self.active_pipes:
+ p.start()
+ sources = self.active_sources
+ sources.add(self.__fdr)
+ exhausted = set([])
+ RUN=True
+ STOP_IF_EXHAUSTED = False
+ while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
+ fds,fdo,fde=select.select(sources,[],[])
+ for fd in fds:
+ if fd is self.__fdr:
+ cmd = os.read(self.__fdr,1)
+ if cmd == "X":
+ RUN=False
+ break
+ elif cmd == "B":
+ STOP_IF_EXHAUSTED = True
+ elif cmd == "A":
+ sources = self.active_sources-exhausted
+ sources.add(self.__fdr)
+ else:
+ warning("Unknown internal pipe engine command: %r. Ignoring." % cmd)
+ elif fd in sources:
+ try:
+ fd.deliver()
+ except Exception as e:
+ log_interactive.exception("piping from %s failed: %s" % (fd.name, e))
+ else:
+ if fd.exhausted():
+ exhausted.add(fd)
+ sources.remove(fd)
+ except KeyboardInterrupt:
+ pass
+ finally:
+ try:
+ for p in self.active_pipes:
+ p.stop()
+ finally:
+ self.thread_lock.release()
+ log_interactive.info("Pipe engine thread stopped.")
+
+ def start(self):
+ if self.thread_lock.acquire(0):
+ self.threadid = _thread.start_new_thread(self.run,())
+ else:
+ warning("Pipe engine already running")
+ def wait_and_stop(self):
+ self.stop(_cmd="B")
+ def stop(self, _cmd="X"):
+ try:
+ with self.command_lock:
+ if self.threadid is not None:
+ os.write(self.__fdw, _cmd)
+ while not self.thread_lock.acquire(0):
+ time.sleep(0.01) # interruptible wait for thread to terminate
+ self.thread_lock.release() # (not using .join() because it needs 'threading' module)
+ else:
+ warning("Pipe engine thread not running")
+ except KeyboardInterrupt:
+ print("Interrupted by user.")
+
+ def add(self, *pipes):
+ pipes = self._add_pipes(*pipes)
+ with self.command_lock:
+ if self.threadid is not None:
+ for p in pipes:
+ p.start()
+ os.write(self.__fdw, "A")
+
+ def graph(self,**kargs):
+ g=['digraph "pipe" {',"\tnode [shape=rectangle];",]
+ for p in self.active_pipes:
+ g.append('\t"%i" [label="%s"];' % (id(p), p.name))
+ g.append("")
+ g.append("\tedge [color=blue, arrowhead=vee];")
+ for p in self.active_pipes:
+ for q in p.sinks:
+ g.append('\t"%i" -> "%i";' % (id(p), id(q)))
+ g.append("")
+ g.append("\tedge [color=red, arrowhead=veevee];")
+ for p in self.active_pipes:
+ for q in p.high_sinks:
+ g.append('\t"%i" -> "%i" [color="red"];' % (id(p), id(q)))
+ g.append('}')
+ graph = "\n".join(g)
+ scapy.utils.do_graph(graph, **kargs)
+
+
+class _ConnectorLogic(object):
+ def __init__(self):
+ self.sources = set()
+ self.sinks = set()
+ self.high_sources = set()
+ self.high_sinks = set()
+
+ def __lt__(self, other):
+ other.sinks.add(self)
+ self.sources.add(other)
+ return other
+ def __gt__(self, other):
+ self.sinks.add(other)
+ other.sources.add(self)
+ return other
+ def __eq__(self, other):
+ self > other
+ other > self
+ return other
+
+ def __lshift__(self, other):
+ self.high_sources.add(other)
+ other.high_sinks.add(self)
+ return other
+ def __rshift__(self, other):
+ self.high_sinks.add(other)
+ other.high_sources.add(self)
+ return other
+ def __floordiv__(self, other):
+ self >> other
+ other >> self
+ return other
+
+
+class Pipe(_ConnectorLogic):
+ #TODO3 Move to new metaclass syntax
+ class __metaclass__(type):
+ def __new__(cls, name, bases, dct):
+ c = type.__new__(cls, name, bases, dct)
+ PipeEngine.pipes[name] = c
+ return c
+ def __init__(self, name=None):
+ _ConnectorLogic.__init__(self)
+ if name is None:
+ name = "%s" % (self.__class__.__name__)
+ self.name = name
+ def _send(self, msg):
+ for s in self.sinks:
+ s.push(msg)
+ def _high_send(self, msg):
+ for s in self.high_sinks:
+ s.high_push(msg)
+
+ def __repr__(self):
+ ct = conf.color_theme
+ s = "%s%s" % (ct.punct("<"), ct.layer_name(self.name))
+ if self.sources or self.sinks:
+ s+= " %s" % ct.punct("[")
+ if self.sources:
+ s+="%s%s" % (ct.punct(",").join(ct.field_name(s.name) for s in self.sources),
+ ct.field_value(">"))
+ s += ct.layer_name("#")
+ if self.sinks:
+ s+="%s%s" % (ct.field_value(">"),
+ ct.punct(",").join(ct.field_name(s.name) for s in self.sinks))
+ s += ct.punct("]")
+
+ if self.high_sources or self.high_sinks:
+ s+= " %s" % ct.punct("[")
+ if self.high_sources:
+ s+="%s%s" % (ct.punct(",").join(ct.field_name(s.name) for s in self.high_sources),
+ ct.field_value(">>"))
+ s += ct.layer_name("#")
+ if self.high_sinks:
+ s+="%s%s" % (ct.field_value(">>"),
+ ct.punct(",").join(ct.field_name(s.name) for s in self.high_sinks))
+ s += ct.punct("]")
+
+
+ s += ct.punct(">")
+ return s
+
+class Source(Pipe):
+ def __init__(self, name=None):
+ Pipe.__init__(self, name=name)
+ self.is_exhausted = False
+ def _read_message(self):
+ return Message()
+ def deliver(self):
+ msg = self._read_message
+ self._send(msg)
+ def fileno(self):
+ return None
+ def exhausted(self):
+ return self.is_exhausted
+ def start(self):
+ pass
+ def stop(self):
+ pass
+
+class Drain(Pipe):
+ """Repeat messages from low/high entries to (resp.) low/high exits
+ +-------+
+ >>-|-------|->>
+ | |
+ >-|-------|->
+ +-------+
+"""
+ def push(self, msg):
+ self._send(msg)
+ def high_push(self, msg):
+ self._high_send(msg)
+ def start(self):
+ pass
+ def stop(self):
+ pass
+
+class Sink(Pipe):
+ def push(self, msg):
+ pass
+ def high_push(self, msg):
+ pass
+ def start(self):
+ pass
+ def stop(self):
+ pass
+
+
+class AutoSource(Source):
+ def __init__(self, name=None):
+ Source.__init__(self, name=name)
+ self.__fdr,self.__fdw = os.pipe()
+ self._queue = collections.deque()
+ def fileno(self):
+ return self.__fdr
+ def _gen_data(self, msg):
+ self._queue.append((msg,False))
+ self._wake_up()
+ def _gen_high_data(self, msg):
+ self._queue.append((msg,True))
+ self._wake_up()
+ def _wake_up(self):
+ os.write(self.__fdw,"x")
+ def deliver(self):
+ os.read(self.__fdr,1)
+ try:
+ msg,high = self._queue.popleft()
+ except IndexError: #empty queue. Exhausted source
+ pass
+ else:
+ if high:
+ self._high_send(msg)
+ else:
+ self._send(msg)
+
+class ThreadGenSource(AutoSource):
+ def __init__(self, name=None):
+ AutoSource.__init__(self, name=name)
+ self.RUN = False
+ def generate(self):
+ pass
+ def start(self):
+ self.RUN = True
+ _thread.start_new_thread(self.generate,())
+ def stop(self):
+ self.RUN = False
+
+
+
+class ConsoleSink(Sink):
+ """Print messages on low and high entries
+ +-------+
+ >>-|--. |->>
+ | print |
+ >-|--' |->
+ +-------+
+"""
+ def push(self, msg):
+ print(">%r" % msg)
+ def high_push(self, msg):
+ print(">>%r" % msg)
+
+class RawConsoleSink(Sink):
+ """Print messages on low and high entries
+ +-------+
+ >>-|--. |->>
+ | write |
+ >-|--' |->
+ +-------+
+"""
+ def __init__(self, name=None, newlines=True):
+ Sink.__init__(self, name=name)
+ self.newlines = newlines
+ def push(self, msg):
+ if self.newlines:
+ msg += "\n"
+ os.write(1, str(msg))
+ def high_push(self, msg):
+ if self.newlines:
+ msg += "\n"
+ os.write(1, str(msg))
+
+class CLIFeeder(AutoSource):
+ """Send messages from python command line
+ +--------+
+ >>-| |->>
+ | send() |
+ >-| `----|->
+ +--------+
+"""
+ def send(self, msg):
+ self._gen_data(msg)
+ def close(self):
+ self.is_exhausted = True
+
+class CLIHighFeeder(CLIFeeder):
+ """Send messages from python command line to high output
+ +--------+
+ >>-| .----|->>
+ | send() |
+ >-| |->
+ +--------+
+"""
+ def send(self, msg):
+ self._gen_high_data(msg)
+
+
+class PeriodicSource(ThreadGenSource):
+ """Generage messages periodically on low exit
+ +-------+
+ >>-| |->>
+ | msg,T |
+ >-| `----|->
+ +-------+
+"""
+ def __init__(self, msg, period, period2=0, name=None):
+ ThreadGenSource.__init__(self,name=name)
+ if not hasattr(msg, "__iter__"):
+ msg=[msg]
+ self.msg = msg
+ self.period = period
+ self.period2 = period2
+ def generate(self):
+ while self.RUN:
+ empty_gen = True
+ for m in self.msg:
+ empty_gen = False
+ self._gen_data(m)
+ time.sleep(self.period)
+ if empty_gen:
+ self.is_exhausted = True
+ self._wake_up()
+ time.sleep(self.period2)
+
+class TermSink(Sink):
+ """Print messages on low and high entries on a separate terminal
+ +-------+
+ >>-|--. |->>
+ | print |
+ >-|--' |->
+ +-------+
+"""
+ def __init__(self, name=None, keepterm=True, newlines=True, openearly=True):
+ Sink.__init__(self, name=name)
+ self.keepterm = keepterm
+ self.newlines = newlines
+ self.openearly = openearly
+ self.opened = False
+ if self.openearly:
+ self.start()
+
+ def start(self):
+ if not self.opened:
+ self.opened = True
+ self.__r,self.__w = os.pipe()
+ cmd = ["xterm"]
+ if self.name is not None:
+ cmd.extend(["-title",self.name])
+ if self.keepterm:
+ cmd.append("-hold")
+ cmd.extend(["-e", "cat 0<&%i" % self.__r])
+ self.__p = subprocess.Popen(cmd)
+ os.close(self.__r)
+ def stop(self):
+ if not self.keepterm:
+ self.opened = False
+ os.close(self.__w)
+ self.__p.kill()
+ self.__p.wait()
+ def _print(self, s):
+ if self.newlines:
+ s+="\n"
+ os.write(self.__w, s)
+
+ def push(self, msg):
+ self._print(str(msg))
+ def high_push(self, msg):
+ self._print(str(msg))
+
+
+class QueueSink(Sink):
+ """Collect messages from high and low entries and queue them. Messages are unqueued with the .recv() method.
+ +-------+
+ >>-|--. |->>
+ | queue |
+ >-|--' |->
+ +-------+
+"""
+ def __init__(self, name=None):
+ Sink.__init__(self, name=name)
+ self.q = queue.Queue()
+ def push(self, msg):
+ self.q.put(msg)
+ def high_push(self, msg):
+ self.q.put(msg)
+ def recv(self):
+ while True:
+ try:
+ return self.q.get(True, timeout=0.1)
+ except queue.Empty:
+ pass
+
+
+class TransformDrain(Drain):
+ """Apply a function to messages on low and high entry
+ +-------+
+ >>-|--[f]--|->>
+ | |
+ >-|--[f]--|->
+ +-------+
+"""
+ def __init__(self, f, name=None):
+ Drain.__init__(self, name=name)
+ self.f = f
+ def push(self, msg):
+ self._send(self.f(msg))
+ def high_push(self, msg):
+ self._high_send(self.f(msg))
+
+class UpDrain(Drain):
+ """Repeat messages from low entry to high exit
+ +-------+
+ >>-| ,--|->>
+ | / |
+ >-|--' |->
+ +-------+
+"""
+ def push(self, msg):
+ self._high_send(msg)
+ def high_push(self, msg):
+ pass
+
+class DownDrain(Drain):
+ """Repeat messages from high entry to low exit
+ +-------+
+ >>-|--. |->>
+ | \ |
+ >-| `--|->
+ +-------+
+"""
+ def push(self, msg):
+ pass
+ def high_push(self, msg):
+ self._send(msg)
+
+
+def _testmain():
+ s = PeriodicSource("hello", 1, name="src")
+ d1 = Drain(name="d1")
+ c = ConsoleSink(name="c")
+ tf = TransformDrain(lambda x:"Got %r" % x)
+ t = TermSink(name="t", keepterm=False)
+
+ s > d1 > c
+ d1 > tf > t
+
+ p = PipeEngine(s)
+
+ p.graph(type="png",target="> /tmp/pipe.png")
+
+ p.start()
+ print(p.threadid)
+ time.sleep(5)
+ p.stop()
+
+
+if __name__ == "__main__":
+ _testmain()
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/plist.py b/scripts/external_libs/scapy-python3-0.18/scapy/plist.py
new file mode 100644
index 00000000..bdf0b757
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/plist.py
@@ -0,0 +1,517 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+PacketList: holds several packets and allows to do operations on them.
+"""
+
+
+import os,subprocess
+from .config import conf
+from .base_classes import BasePacket,BasePacketList
+from collections import defaultdict
+
+from .utils import do_graph,hexdump,make_table,make_lined_table,make_tex_table,get_temp_file
+
+from scapy.arch import NETWORKX
+if NETWORKX:
+ import networkx as nx
+
+
+#############
+## Results ##
+#############
+
+class PacketList(BasePacketList):
+ res = []
+ def __init__(self, res=None, name="PacketList", stats=None, vector_index = None):
+ """create a packet list from a list of packets
+ res: the list of packets
+ stats: a list of classes that will appear in the stats (defaults to [TCP,UDP,ICMP])"""
+ if stats is None:
+ stats = conf.stats_classic_protocols
+ self.stats = stats
+ if res is None:
+ res = []
+ if isinstance(res, PacketList):
+ res = res.res
+ self.res = res
+ self.listname = name
+ self.vector_index = vector_index
+ def __len__(self):
+ return len(self.res)
+ def _elt2pkt(self, elt):
+ if self.vector_index == None:
+ return elt
+ else:
+ return elt[self.vector_index]
+ def _elt2sum(self, elt):
+ if self.vector_index == None:
+ return elt.summary()
+ else:
+ return "%s ==> %s" % (elt[0].summary(),elt[1].summary())
+
+ def _elt2show(self, elt):
+ return self._elt2sum(elt)
+ def __repr__(self):
+ stats=dict.fromkeys(self.stats,0)
+ other = 0
+ for r in self.res:
+ f = 0
+ for p in stats:
+ if self._elt2pkt(r).haslayer(p):
+ stats[p] += 1
+ f = 1
+ break
+ if not f:
+ other += 1
+ s = ""
+ ct = conf.color_theme
+ for p in self.stats:
+ s += " %s%s%s" % (ct.packetlist_proto(p.name),
+ ct.punct(":"),
+ ct.packetlist_value(stats[p]))
+ s += " %s%s%s" % (ct.packetlist_proto("Other"),
+ ct.punct(":"),
+ ct.packetlist_value(other))
+ return "%s%s%s%s%s" % (ct.punct("<"),
+ ct.packetlist_name(self.listname),
+ ct.punct(":"),
+ s,
+ ct.punct(">"))
+ def __getattr__(self, attr):
+ return getattr(self.res, attr)
+ def __getitem__(self, item):
+ if isinstance(item,type) and issubclass(item,BasePacket):
+ #return self.__class__(filter(lambda x: item in self._elt2pkt(x),self.res),
+ return self.__class__([ x for x in self.res if item in self._elt2pkt(x) ],
+ name="%s from %s"%(item.__name__,self.listname))
+ if type(item) is slice:
+ return self.__class__(self.res.__getitem__(item),
+ name = "mod %s" % self.listname)
+ return self.res.__getitem__(item)
+ def __getslice__(self, *args, **kargs):
+ return self.__class__(self.res.__getslice__(*args, **kargs),
+ name="mod %s"%self.listname)
+ def __add__(self, other):
+ return self.__class__(self.res+other.res,
+ name="%s+%s"%(self.listname,other.listname))
+ def summary(self, prn=None, lfilter=None):
+ """prints a summary of each packet
+prn: function to apply to each packet instead of lambda x:x.summary()
+lfilter: truth function to apply to each packet to decide whether it will be displayed"""
+ for r in self.res:
+ if lfilter is not None:
+ if not lfilter(r):
+ continue
+ if prn is None:
+ print(self._elt2sum(r))
+ else:
+ print(prn(r))
+ def nsummary(self,prn=None, lfilter=None):
+ """prints a summary of each packet with the packet's number
+prn: function to apply to each packet instead of lambda x:x.summary()
+lfilter: truth function to apply to each packet to decide whether it will be displayed"""
+ for i, p in enumerate(self.res):
+ if lfilter is not None:
+ if not lfilter(p):
+ continue
+ print(conf.color_theme.id(i,fmt="%04i"), end = " ")
+ if prn is None:
+ print(self._elt2sum(p))
+ else:
+ print(prn(p))
+ def display(self): # Deprecated. Use show()
+ """deprecated. is show()"""
+ self.show()
+ def show(self, *args, **kargs):
+ """Best way to display the packet list. Defaults to nsummary() method"""
+ return self.nsummary(*args, **kargs)
+
+ def filter(self, func):
+ """Returns a packet list filtered by a truth function"""
+ return self.__class__(list(filter(func,self.res)),
+ name="filtered %s"%self.listname)
+
+ def plot(self, f, lfilter=None,**kargs):
+ """Applies a function to each packet to get a value that will be plotted with matplotlib. A matplotlib object is returned
+ lfilter: a truth function that decides whether a packet must be ploted"""
+
+ return plt.plot([ f(i) for i in self.res if not lfilter or lfilter(i) ], **kargs)
+
+ def diffplot(self, f, delay=1, lfilter=None, **kargs):
+ """diffplot(f, delay=1, lfilter=None)
+ Applies a function to couples (l[i],l[i+delay])"""
+
+ return plt.plot([ f(i, j) for i in self.res[:-delay] for j in self.res[delay:] if not lfilter or (lfilter(i) and lfilter(j))],
+ **kargs)
+
+ def multiplot(self, f, lfilter=None, **kargs):
+ """Uses a function that returns a label and a value for this label, then plots all the values label by label"""
+
+ d = defaultdict(list)
+ for i in self.res:
+ if lfilter and not lfilter(i):
+ continue
+ k, v = f(i)
+ d[k].append(v)
+
+ figure = plt.figure()
+ ax = figure.add_axes(plt.axes())
+ for i in d:
+ ax.plot(d[i], **kargs)
+ return figure
+
+
+ def rawhexdump(self):
+ """Prints an hexadecimal dump of each packet in the list"""
+ for p in self:
+ hexdump(self._elt2pkt(p))
+
+ def hexraw(self, lfilter=None):
+ """Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped
+ lfilter: a truth function that decides whether a packet must be displayed"""
+ for i,p in enumerate(self.res):
+ p1 = self._elt2pkt(p)
+ if lfilter is not None and not lfilter(p1):
+ continue
+ print("%s %s %s" % (conf.color_theme.id(i,fmt="%04i"),
+ p1.sprintf("%.time%"),
+ self._elt2sum(p)))
+ if p1.haslayer(conf.raw_layer):
+ hexdump(p1.getlayer(conf.raw_layer).load)
+
+ def hexdump(self, lfilter=None):
+ """Same as nsummary(), except that packets are also hexdumped
+ lfilter: a truth function that decides whether a packet must be displayed"""
+ for i,p in enumerate(self.res):
+ p1 = self._elt2pkt(p)
+ if lfilter is not None and not lfilter(p1):
+ continue
+ print("%s %s %s" % (conf.color_theme.id(i,fmt="%04i"),
+ p1.sprintf("%.time%"),
+ self._elt2sum(p)))
+ hexdump(p1)
+
+ def padding(self, lfilter=None):
+ """Same as hexraw(), for Padding layer"""
+ for i,p in enumerate(self.res):
+ p1 = self._elt2pkt(p)
+ if p1.haslayer(conf.padding_layer):
+ if lfilter is None or lfilter(p1):
+ print("%s %s %s" % (conf.color_theme.id(i,fmt="%04i"),
+ p1.sprintf("%.time%"),
+ self._elt2sum(p)))
+ hexdump(p1.getlayer(conf.padding_layer).load)
+
+ def nzpadding(self, lfilter=None):
+ """Same as padding() but only non null padding"""
+ for i,p in enumerate(self.res):
+ p1 = self._elt2pkt(p)
+ if p1.haslayer(conf.padding_layer):
+ pad = p1.getlayer(conf.padding_layer).load
+ if pad == pad[0]*len(pad):
+ continue
+ if lfilter is None or lfilter(p1):
+ print("%s %s %s" % (conf.color_theme.id(i,fmt="%04i"),
+ p1.sprintf("%.time%"),
+ self._elt2sum(p)))
+ hexdump(p1.getlayer(conf.padding_layer).load)
+
+
+ def conversations(self, getsrcdst=None, draw = True, **kargs):
+ """Graphes a conversations between sources and destinations and display it
+ (using graphviz)
+ getsrcdst: a function that takes an element of the list and return the source and dest
+ by defaults, return source and destination IP
+ if networkx library is available returns a DiGraph, or draws it if draw = True otherwise graphviz is used
+ format: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
+ target: output filename. If None, matplotlib is used to display
+ prog: which graphviz program to use"""
+ if getsrcdst is None:
+ getsrcdst = lambda x:(x['IP'].src, x['IP'].dst)
+ conv = {}
+ for p in self.res:
+ p = self._elt2pkt(p)
+ try:
+ c = getsrcdst(p)
+ except:
+ #XXX warning()
+ continue
+ conv[c] = conv.get(c,0)+1
+
+ if NETWORKX: # networkx is available
+ gr = nx.DiGraph()
+ for s,d in conv:
+ if s not in gr:
+ gr.add_node(s)
+ if d not in gr:
+ gr.add_node(d)
+ gr.add_edge(s, d)
+ if draw:
+ return do_graph(gr, **kargs)
+ else:
+ return gr
+ else:
+ gr = 'digraph "conv" {\n'
+ for s,d in conv:
+ gr += '\t "%s" -> "%s"\n' % (s,d)
+ gr += "}\n"
+ return do_graph(gr, **kargs)
+
+ def afterglow(self, src=None, event=None, dst=None, **kargs):
+ """Experimental clone attempt of http://sourceforge.net/projects/afterglow
+ each datum is reduced as src -> event -> dst and the data are graphed.
+ by default we have IP.src -> IP.dport -> IP.dst"""
+ if src is None:
+ src = lambda x: x['IP'].src
+ if event is None:
+ event = lambda x: x['IP'].dport
+ if dst is None:
+ dst = lambda x: x['IP'].dst
+ sl = {}
+ el = {}
+ dl = {}
+ for i in self.res:
+ try:
+ s,e,d = src(i),event(i),dst(i)
+ if s in sl:
+ n,l = sl[s]
+ n += 1
+ if e not in l:
+ l.append(e)
+ sl[s] = (n,l)
+ else:
+ sl[s] = (1,[e])
+ if e in el:
+ n,l = el[e]
+ n+=1
+ if d not in l:
+ l.append(d)
+ el[e] = (n,l)
+ else:
+ el[e] = (1,[d])
+ dl[d] = dl.get(d,0)+1
+ except:
+ continue
+
+ import math
+ def normalize(n):
+ return 2+math.log(n)/4.0
+
+ def minmax(x):
+ m,M = min(x),max(x)
+ if m == M:
+ m = 0
+ if M == 0:
+ M = 1
+ return m,M
+
+ #mins,maxs = minmax(map(lambda (x,y): x, sl.values()))
+ mins,maxs = minmax([ a[0] for a in sl.values()])
+ #mine,maxe = minmax(map(lambda (x,y): x, el.values()))
+ mine,maxe = minmax([ a[0] for a in el.values()])
+ mind,maxd = minmax(dl.values())
+
+ gr = 'digraph "afterglow" {\n\tedge [len=2.5];\n'
+
+ gr += "# src nodes\n"
+ for s in sl:
+ n,l = sl[s]; n = 1+(n-mins)/(maxs-mins)
+ gr += '"src.%s" [label = "%s", shape=box, fillcolor="#FF0000", style=filled, fixedsize=1, height=%.2f,width=%.2f];\n' % (repr(s),repr(s),n,n)
+ gr += "# event nodes\n"
+ for e in el:
+ n,l = el[e]; n = n = 1+(n-mine)/(maxe-mine)
+ gr += '"evt.%s" [label = "%s", shape=circle, fillcolor="#00FFFF", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (repr(e),repr(e),n,n)
+ for d in dl:
+ n = dl[d]; n = n = 1+(n-mind)/(maxd-mind)
+ gr += '"dst.%s" [label = "%s", shape=triangle, fillcolor="#0000ff", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (repr(d),repr(d),n,n)
+
+ gr += "###\n"
+ for s in sl:
+ n,l = sl[s]
+ for e in l:
+ gr += ' "src.%s" -> "evt.%s";\n' % (repr(s),repr(e))
+ for e in el:
+ n,l = el[e]
+ for d in l:
+ gr += ' "evt.%s" -> "dst.%s";\n' % (repr(e),repr(d))
+
+ gr += "}"
+ return do_graph(gr, **kargs)
+
+
+ def _dump_document(self, **kargs):
+ import pyx
+ d = pyx.document.document()
+ l = len(self.res)
+ for i in range(len(self.res)):
+ elt = self.res[i]
+ c = self._elt2pkt(elt).canvas_dump(**kargs)
+ cbb = c.bbox()
+ c.text(cbb.left(),cbb.top()+1,r"\font\cmssfont=cmss12\cmssfont{Frame %i/%i}" % (i,l),[pyx.text.size.LARGE])
+ if conf.verb >= 2:
+ os.write(1,b".")
+ d.append(pyx.document.page(c, paperformat=pyx.document.paperformat.A4,
+ margin=1*pyx.unit.t_cm,
+ fittosize=1))
+ return d
+
+
+
+ def psdump(self, filename = None, **kargs):
+ """Creates a multipage poscript file with a psdump of every packet
+ filename: name of the file to write to. If empty, a temporary file is used and
+ conf.prog.psreader is called"""
+ d = self._dump_document(**kargs)
+ if filename is None:
+ filename = get_temp_file(autoext=".ps")
+ d.writePSfile(filename)
+ subprocess.Popen([conf.prog.psreader, filename+".ps"])
+ else:
+ d.writePSfile(filename)
+ print
+
+ def pdfdump(self, filename = None, **kargs):
+ """Creates a PDF file with a psdump of every packet
+ filename: name of the file to write to. If empty, a temporary file is used and
+ conf.prog.pdfreader is called"""
+ d = self._dump_document(**kargs)
+ if filename is None:
+ filename = get_temp_file(autoext=".pdf")
+ d.writePDFfile(filename)
+ subprocess.Popen([conf.prog.pdfreader, filename+".pdf"])
+ else:
+ d.writePDFfile(filename)
+ print
+
+ def sr(self,multi=0):
+ """sr([multi=1]) -> (SndRcvList, PacketList)
+ Matches packets in the list and return ( (matched couples), (unmatched packets) )"""
+ remain = self.res[:]
+ sr = []
+ i = 0
+ while i < len(remain):
+ s = remain[i]
+ j = i
+ while j < len(remain)-1:
+ j += 1
+ r = remain[j]
+ if r.answers(s):
+ sr.append((s,r))
+ if multi:
+ remain[i]._answered=1
+ remain[j]._answered=2
+ continue
+ del(remain[j])
+ del(remain[i])
+ i -= 1
+ break
+ i += 1
+ if multi:
+ remain = filter(lambda x:not hasattr(x,"_answered"), remain)
+ return SndRcvList(sr),PacketList(remain)
+
+ def sessions(self, session_extractor=None):
+ if session_extractor is None:
+ def session_extractor(p):
+ sess = "Other"
+ if 'Ether' in p:
+ if 'IP' in p:
+ if 'TCP' in p:
+ sess = p.sprintf("TCP %IP.src%:%r,TCP.sport% > %IP.dst%:%r,TCP.dport%")
+ elif 'UDP' in p:
+ sess = p.sprintf("UDP %IP.src%:%r,UDP.sport% > %IP.dst%:%r,UDP.dport%")
+ elif 'ICMP' in p:
+ sess = p.sprintf("ICMP %IP.src% > %IP.dst% type=%r,ICMP.type% code=%r,ICMP.code% id=%ICMP.id%")
+ else:
+ sess = p.sprintf("IP %IP.src% > %IP.dst% proto=%IP.proto%")
+ elif 'ARP' in p:
+ sess = p.sprintf("ARP %ARP.psrc% > %ARP.pdst%")
+ else:
+ sess = p.sprintf("Ethernet type=%04xr,Ether.type%")
+ return sess
+ sessions = defaultdict(self.__class__)
+ for p in self.res:
+ sess = session_extractor(self._elt2pkt(p))
+ sessions[sess].append(p)
+ return dict(sessions)
+
+ def replace(self, *args, **kargs):
+ """
+ lst.replace(<field>,[<oldvalue>,]<newvalue>)
+ lst.replace( (fld,[ov],nv),(fld,[ov,]nv),...)
+ if ov is None, all values are replaced
+ ex:
+ lst.replace( IP.src, "192.168.1.1", "10.0.0.1" )
+ lst.replace( IP.ttl, 64 )
+ lst.replace( (IP.ttl, 64), (TCP.sport, 666, 777), )
+ """
+ delete_checksums = kargs.get("delete_checksums",False)
+ x=PacketList(name="Replaced %s" % self.listname)
+ if type(args[0]) is not tuple:
+ args = (args,)
+ for p in self.res:
+ p = self._elt2pkt(p)
+ copied = False
+ for scheme in args:
+ fld = scheme[0]
+ old = scheme[1] # not used if len(scheme) == 2
+ new = scheme[-1]
+ for o in fld.owners:
+ if o in p:
+ if len(scheme) == 2 or p[o].getfieldval(fld.name) == old:
+ if not copied:
+ p = p.copy()
+ if delete_checksums:
+ p.delete_checksums()
+ copied = True
+ setattr(p[o], fld.name, new)
+ x.append(p)
+ return x
+
+
+class SndRcvList(PacketList):
+ def __init__(self, res=None, name="Results", stats=None):
+ PacketList.__init__(self, res, name, stats, vector_index = 1)
+ def summary(self, prn=None, lfilter=None):
+ """prints a summary of each SndRcv packet pair
+prn: function to apply to each packet pair instead of lambda s, r: "%s ==> %s" % (s.summary(),r.summary())
+lfilter: truth function to apply to each packet pair to decide whether it will be displayed"""
+ for s, r in self.res:
+ if lfilter is not None:
+ if not lfilter(s, r):
+ continue
+ if prn is None:
+ print(self._elt2sum((s, r)))
+ else:
+ print(prn(s, r))
+ def nsummary(self,prn=None, lfilter=None):
+ """prints a summary of each SndRcv packet pair with the pair's number
+prn: function to apply to each packet pair instead of lambda s, r: "%s ==> %s" % (s.summary(),r.summary())
+lfilter: truth function to apply to each packet pair to decide whether it will be displayed"""
+ for i, (s, r) in enumerate(self.res):
+ if lfilter is not None:
+ if not lfilter(s, r):
+ continue
+ print(conf.color_theme.id(i,fmt="%04i"), end = " ")
+ if prn is None:
+ print(self._elt2sum((s, r)))
+ else:
+ print(prn(s, r))
+ def filter(self, func):
+ """Returns a SndRcv list filtered by a truth function"""
+ return self.__class__( [ i for i in self.res if func(*i) ], name='filtered %s'%self.listname)
+
+ def make_table(self, *args, **kargs):
+ """Prints a table using a function that returs for each packet its head column value, head row value and displayed value
+ ex: p.make_table(lambda s, r:(s[IP].dst, r[TCP].sport, s[TCP].sprintf("%flags%")) """
+ return make_table(self.res, *args, **kargs)
+ def make_lined_table(self, *args, **kargs):
+ """Same as make_table, but print a table with lines"""
+ return make_lined_table(self.res, *args, **kargs)
+ def make_tex_table(self, *args, **kargs):
+ """Same as make_table, but print a table with LaTeX syntax"""
+ return make_tex_table(self.res, *args, **kargs)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/pton_ntop.py b/scripts/external_libs/scapy-python3-0.18/scapy/pton_ntop.py
new file mode 100644
index 00000000..1629edee
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/pton_ntop.py
@@ -0,0 +1,90 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Convert IPv6 addresses between textual representation and binary.
+
+These functions are missing when python is compiled
+without IPv6 support, on Windows for instance.
+"""
+
+import socket,struct
+
+def inet_pton(af, addr):
+ """Convert an IP address from text representation into binary form"""
+ print('hello')
+ if af == socket.AF_INET:
+ return inet_aton(addr)
+ elif af == socket.AF_INET6:
+ # IPv6: The use of "::" indicates one or more groups of 16 bits of zeros.
+ # We deal with this form of wildcard using a special marker.
+ JOKER = b"*"
+ while b"::" in addr:
+ addr = addr.replace(b"::", b":" + JOKER + b":")
+ joker_pos = None
+
+ # The last part of an IPv6 address can be an IPv4 address
+ ipv4_addr = None
+ if b"." in addr:
+ ipv4_addr = addr.split(b":")[-1]
+
+ result = b""
+ parts = addr.split(b":")
+ for part in parts:
+ if part == JOKER:
+ # Wildcard is only allowed once
+ if joker_pos is None:
+ joker_pos = len(result)
+ else:
+ raise Exception("Illegal syntax for IP address")
+ elif part == ipv4_addr: # FIXME: Make sure IPv4 can only be last part
+ # FIXME: inet_aton allows IPv4 addresses with less than 4 octets
+ result += socket.inet_aton(ipv4_addr)
+ else:
+ # Each part must be 16bit. Add missing zeroes before decoding.
+ try:
+ result += part.rjust(4, b"0").decode("hex")
+ except TypeError:
+ raise Exception("Illegal syntax for IP address")
+
+ # If there's a wildcard, fill up with zeros to reach 128bit (16 bytes)
+ if JOKER in addr:
+ result = (result[:joker_pos] + b"\x00" * (16 - len(result))
+ + result[joker_pos:])
+
+ if len(result) != 16:
+ raise Exception("Illegal syntax for IP address")
+ return result
+ else:
+ raise Exception("Address family not supported")
+
+
+def inet_ntop(af, addr):
+ """Convert an IP address from binary form into text represenation"""
+ if af == socket.AF_INET:
+ return inet_ntoa(addr)
+ elif af == socket.AF_INET6:
+ # IPv6 addresses have 128bits (16 bytes)
+ if len(addr) != 16:
+ raise Exception("Illegal syntax for IP address")
+ parts = []
+ for left in [0, 2, 4, 6, 8, 10, 12, 14]:
+ try:
+ value = struct.unpack("!H", addr[left:left+2])[0]
+ hexstr = hex(value)[2:]
+ except TypeError:
+ raise Exception("Illegal syntax for IP address")
+ parts.append(hexstr.lstrip("0").lower())
+ result = b":".join(parts)
+ while b":::" in result:
+ result = result.replace(b":::", b"::")
+ # Leaving out leading and trailing zeros is only allowed with ::
+ if result.endswith(b":") and not result.endswith(b"::"):
+ result = result + b"0"
+ if result.startswith(b":") and not result.startswith(b"::"):
+ result = b"0" + result
+ return result
+ else:
+ raise Exception("Address family not supported yet")
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/route.py b/scripts/external_libs/scapy-python3-0.18/scapy/route.py
new file mode 100644
index 00000000..bccc43a2
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/route.py
@@ -0,0 +1,175 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Routing and handling of network interfaces.
+"""
+
+import socket
+from scapy.arch import read_routes,get_if_addr,LOOPBACK_NAME
+from scapy.utils import atol,ltoa,itom
+from scapy.config import conf
+from scapy.error import Scapy_Exception,warning
+
+##############################
+## Routing/Interfaces stuff ##
+##############################
+
+class Route:
+ def __init__(self):
+ self.resync()
+ self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self.cache = {}
+
+ def invalidate_cache(self):
+ self.cache = {}
+
+ def resync(self):
+ self.invalidate_cache()
+ self.routes = read_routes()
+
+ def __repr__(self):
+ rt = "Network Netmask Gateway Iface Output IP\n"
+ for net,msk,gw,iface,addr in self.routes:
+ rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
+ ltoa(msk),
+ gw,
+ iface,
+ addr)
+ return rt
+
+ def make_route(self, host=None, net=None, gw=None, dev=None):
+ if host is not None:
+ thenet,msk = host,32
+ elif net is not None:
+ thenet,msk = net.split("/")
+ msk = int(msk)
+ else:
+ raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net")
+ if gw is None:
+ gw="0.0.0.0"
+ if dev is None:
+ if gw:
+ nhop = gw
+ else:
+ nhop = thenet
+ dev,ifaddr,x = self.route(nhop)
+ else:
+ ifaddr = get_if_addr(dev)
+ return (atol(thenet), itom(msk), gw, dev, ifaddr)
+
+ def add(self, *args, **kargs):
+ """Ex:
+ add(net="192.168.1.0/24",gw="1.2.3.4")
+ """
+ self.invalidate_cache()
+ self.routes.append(self.make_route(*args,**kargs))
+
+
+ def delt(self, *args, **kargs):
+ """delt(host|net, gw|dev)"""
+ self.invalidate_cache()
+ route = self.make_route(*args,**kargs)
+ try:
+ i=self.routes.index(route)
+ del(self.routes[i])
+ except ValueError:
+ warning("no matching route found")
+
+ def ifchange(self, iff, addr):
+ self.invalidate_cache()
+ the_addr,the_msk = (addr.split("/")+["32"])[:2]
+ the_msk = itom(int(the_msk))
+ the_rawaddr = atol(the_addr)
+ the_net = the_rawaddr & the_msk
+
+
+ for i in range(len(self.routes)):
+ net,msk,gw,iface,addr = self.routes[i]
+ if iface != iff:
+ continue
+ if gw == '0.0.0.0':
+ self.routes[i] = (the_net,the_msk,gw,iface,the_addr)
+ else:
+ self.routes[i] = (net,msk,gw,iface,the_addr)
+ conf.netcache.flush()
+
+
+
+ def ifdel(self, iff):
+ self.invalidate_cache()
+ new_routes=[]
+ for rt in self.routes:
+ if rt[3] != iff:
+ new_routes.append(rt)
+ self.routes=new_routes
+
+ def ifadd(self, iff, addr):
+ self.invalidate_cache()
+ the_addr,the_msk = (addr.split("/")+["32"])[:2]
+ the_msk = itom(int(the_msk))
+ the_rawaddr = atol(the_addr)
+ the_net = the_rawaddr & the_msk
+ self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr))
+
+
+ def route(self,dest,verbose=None):
+ if type(dest) is list and dest:
+ dest = dest[0]
+ if dest in self.cache:
+ return self.cache[dest]
+ if verbose is None:
+ verbose=conf.verb
+ # Transform "192.168.*.1-5" to one IP of the set
+ dst = dest.split("/")[0]
+ dst = dst.replace("*","0")
+ while True:
+ l = dst.find("-")
+ if l < 0:
+ break
+ m = (dst[l:]+".").find(".")
+ dst = dst[:l]+dst[l+m:]
+
+
+ dst = atol(dst)
+ pathes=[]
+ for d,m,gw,i,a in self.routes:
+ aa = atol(a)
+ #Commented out after issue with virtual network with local address 0.0.0.0
+ #if aa == dst:
+ # pathes.append((0xffffffff,(LOOPBACK_NAME,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_NAME,"0.0.0.0","0.0.0.0" #XXX linux specific!
+ # Choose the more specific route (greatest netmask).
+ # XXX: we don't care about metrics
+ pathes.sort()
+ ret = pathes[-1][1]
+ self.cache[dest] = ret
+ return ret
+
+ def get_if_bcast(self, iff):
+ for net, msk, gw, iface, addr in self.routes:
+ if (iff == iface and net != 0):
+ bcast = atol(addr)|(~msk&0xffffffff); # FIXME: check error in atol()
+ return ltoa(bcast);
+ warning("No broadcast address found for iface %s\n" % iff);
+
+#conf.route=Route()
+
+conf.route=None;
+_betteriface = None
+
+
+
+#XXX use "with"
+#_betteriface = conf.route.route("0.0.0.0", verbose=0)[0]
+
+if _betteriface != LOOPBACK_NAME:
+ conf.iface = _betteriface
+del(_betteriface)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/route6.py b/scripts/external_libs/scapy-python3-0.18/scapy/route6.py
new file mode 100644
index 00000000..44a66735
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/route6.py
@@ -0,0 +1,288 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp>
+## Arnaud Ebalard <arnaud.ebalard@eads.net>
+
+"""
+Routing and network interface handling for IPv6.
+"""
+
+#############################################################################
+#############################################################################
+### Routing/Interfaces stuff ###
+#############################################################################
+#############################################################################
+
+import socket
+from .config import conf
+from .utils6 import *
+from .arch import *
+
+
+class Route6:
+
+ def __init__(self):
+ self.invalidate_cache()
+ self.resync()
+
+ def invalidate_cache(self):
+ self.cache = {}
+
+ def flush(self):
+ self.invalidate_cache()
+ self.routes = []
+
+ def resync(self):
+ # TODO : At the moment, resync will drop existing Teredo routes
+ # if any. Change that ...
+ self.invalidate_cache()
+ self.routes = read_routes6()
+ if self.routes == []:
+ log_loading.info("No IPv6 support in kernel")
+
+ def __repr__(self):
+ rtlst = [('Destination', 'Next Hop', "iface", "src candidates")]
+
+ for net,msk,gw,iface,cset in self.routes:
+ rtlst.append(('%s/%i'% (net,msk), gw, iface, ", ".join(cset)))
+
+ #colwidth = map(lambda x: max(map(lambda y: len(y), x)), apply(zip, rtlst))
+ rtlst = zip(rtlst)
+ colwidth = [ max([len(y) for y in x]) for x in rtlst]
+ fmt = " ".join(map(lambda x: "%%-%ds"%x, colwidth))
+ rt = "\n".join([ fmt % x for x in rtlst])
+
+ return rt
+
+
+ # Unlike Scapy's Route.make_route() function, we do not have 'host' and 'net'
+ # parameters. We only have a 'dst' parameter that accepts 'prefix' and
+ # 'prefix/prefixlen' values.
+ # WARNING: Providing a specific device will at the moment not work correctly.
+ def make_route(self, dst, gw=None, dev=None):
+ """Internal function : create a route for 'dst' via 'gw'.
+ """
+ prefix, plen = (dst.split("/")+["128"])[:2]
+ plen = int(plen)
+
+ if gw is None:
+ gw = "::"
+ if dev is None:
+ dev, ifaddr, x = self.route(gw)
+ else:
+ # TODO: do better than that
+ # replace that unique address by the list of all addresses
+ lifaddr = in6_getifaddr()
+ #filter(lambda x: x[2] == dev, lifaddr)
+ devaddrs = [ i for i in lifaddr if i[2] == dev]
+ ifaddr = construct_source_candidate_set(prefix, plen, devaddrs, LOOPBACK_NAME)
+
+ return (prefix, plen, gw, dev, ifaddr)
+
+
+ def add(self, *args, **kargs):
+ """Ex:
+ add(dst="2001:db8:cafe:f000::/56")
+ add(dst="2001:db8:cafe:f000::/56", gw="2001:db8:cafe::1")
+ add(dst="2001:db8:cafe:f000::/64", gw="2001:db8:cafe::1", dev="eth0")
+ """
+ self.invalidate_cache()
+ self.routes.append(self.make_route(*args, **kargs))
+
+
+ def delt(self, dst, gw=None):
+ """ Ex:
+ delt(dst="::/0")
+ delt(dst="2001:db8:cafe:f000::/56")
+ delt(dst="2001:db8:cafe:f000::/56", gw="2001:db8:deca::1")
+ """
+ tmp = dst+b"/128"
+ dst, plen = tmp.split(b'/')[:2]
+ dst = in6_ptop(dst)
+ plen = int(plen)
+ #l = filter(lambda x: in6_ptop(x[0]) == dst and x[1] == plen, self.routes)
+ l = [ x for x in self.routes if in6_ptop(x[0]) == dst and x[1] == plen ]
+ if gw:
+ gw = in6_ptop(gw)
+ #l = filter(lambda x: in6_ptop(x[0]) == gw, self.routes)
+ l = [ x for x in self.routes if in6_ptop(x[0]) == gw ]
+ if len(l) == 0:
+ warning("No matching route found")
+ elif len(l) > 1:
+ warning("Found more than one match. Aborting.")
+ else:
+ i=self.routes.index(l[0])
+ self.invalidate_cache()
+ del(self.routes[i])
+
+ def ifchange(self, iff, addr):
+ the_addr, the_plen = (addr.split("/")+["128"])[:2]
+ the_plen = int(the_plen)
+
+ naddr = inet_pton(socket.AF_INET6, the_addr)
+ nmask = in6_cidr2mask(the_plen)
+ the_net = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))
+
+ for i in range(len(self.routes)):
+ net,plen,gw,iface,addr = self.routes[i]
+ if iface != iff:
+ continue
+ if gw == '::':
+ self.routes[i] = (the_net,the_plen,gw,iface,the_addr)
+ else:
+ self.routes[i] = (net,the_plen,gw,iface,the_addr)
+ self.invalidate_cache()
+ ip6_neigh_cache.flush()
+
+ def ifdel(self, iff):
+ """ removes all route entries that uses 'iff' interface. """
+ new_routes=[]
+ for rt in self.routes:
+ if rt[3] != iff:
+ new_routes.append(rt)
+ self.invalidate_cache()
+ self.routes = new_routes
+
+
+ def ifadd(self, iff, addr):
+ """
+ Add an interface 'iff' with provided address into routing table.
+
+ Ex: ifadd('eth0', '2001:bd8:cafe:1::1/64') will add following entry into
+ Scapy6 internal routing table:
+
+ Destination Next Hop iface Def src @
+ 2001:bd8:cafe:1::/64 :: eth0 2001:bd8:cafe:1::1
+
+ prefix length value can be omitted. In that case, a value of 128
+ will be used.
+ """
+ addr, plen = (addr.split(b"/")+[b"128"])[:2]
+ addr = in6_ptop(addr)
+ plen = int(plen)
+ naddr = inet_pton(socket.AF_INET6, addr)
+ nmask = in6_cidr2mask(plen)
+ prefix = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))
+ self.invalidate_cache()
+ self.routes.append((prefix,plen,'::',iff,[addr]))
+
+ def route(self, dst, dev=None):
+ """
+ Provide best route to IPv6 destination address, based on Scapy6
+ 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.
+ """
+ # 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")
+ l = dst.find("-")
+ while l >= 0:
+ m = (dst[l:]+":").find(":")
+ dst = dst[:l]+dst[l+m:]
+ l = 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
+
+ # Deal with dev-specific request for cache search
+ k = dst
+ if dev is not None:
+ k = dst + "%%" + dev
+ if k in self.cache:
+ return self.cache[k]
+
+ pathes = []
+
+ # 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 in self.routes:
+ if dev is not None and iface != dev:
+ continue
+ if in6_isincluded(dst, p, plen):
+ pathes.append((plen, (iface, cset, gw)))
+ elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):
+ pathes.append((plen, (iface, cset, gw)))
+
+ if not pathes:
+ warning("No route found for IPv6 destination %s (no default route?). This affects only IPv6" % dst)
+ return (LOOPBACK_NAME, "::", "::") # XXX Linux specific
+
+ # Sort with longest prefix first
+ pathes.sort(reverse=True)
+
+ best_plen = pathes[0][0]
+ pathes = filter(lambda x: x[0] == best_plen, pathes)
+
+ res = []
+ for p in pathes: # Here we select best source address for every route
+ tmp = p[1]
+ srcaddr = get_source_addr_from_candidate_set(dst, p[1][1])
+ if srcaddr is not None:
+ res.append((p[0], (tmp[0], srcaddr, tmp[2])))
+
+ if res == []:
+ warning("Found a route for IPv6 destination '%s', but no possible source address. This affects only IPv6" % dst)
+ return (LOOPBACK_NAME, b"::", b"::") # XXX Linux specific
+
+ # 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
+ # XXX TODO : in a _near_ future, include metric in the game
+
+ 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 = filter(lambda x: in6_isaddr6to4(x[1][1]), res)
+ tmp = [ x for x in res if in6_isaddr6to4(x[1][1]) ]
+ elif in6_ismaddr(dst) or in6_islladdr(dst):
+ # TODO : I'm sure we are not covering all addresses. Check that
+ #tmp = filter(lambda x: x[1][0] == conf.iface6, res)
+ tmp = [ x for x in res if x[1][0] == conf.iface6 ]
+
+ if tmp:
+ res = tmp
+
+ # Fill the cache (including dev-specific request)
+ k = dst
+ if dev is not None:
+ k = dst + "%%" + dev
+ self.cache[k] = res[0][1]
+
+ return res[0][1]
+
+conf.route6 = Route6()
+
+#TBD-hhaim no need for that
+#_res = conf.route6.route("::/0")
+_res = None;
+
+if _res:
+ iff, gw, addr = _res
+ conf.iface6 = iff
+del(_res)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/scapypipes.py b/scripts/external_libs/scapy-python3-0.18/scapy/scapypipes.py
new file mode 100644
index 00000000..aa67277e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/scapypipes.py
@@ -0,0 +1,123 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+from .pipetool import Source,Drain,Sink
+from .config import conf
+
+
+class SniffSource(Source):
+ """Read packets from an interface and send them to low exit.
+ +-----------+
+ >>-| |->>
+ | |
+ >-| [iface]--|->
+ +-----------+
+"""
+ def __init__(self, iface=None, filter=None, name=None):
+ Source.__init__(self, name=name)
+ self.iface = iface
+ self.filter = filter
+ def start(self):
+ self.s = conf.L2listen(iface=self.iface, filter=self.filter)
+ def stop(self):
+ self.s.close()
+ def fileno(self):
+ return self.s.fileno()
+ def deliver(self):
+ self._send(self.s.recv())
+
+class RdpcapSource(Source):
+ """Read packets from a PCAP file send them to low exit.
+ +----------+
+ >>-| |->>
+ | |
+ >-| [pcap]--|->
+ +----------+
+"""
+ def __init__(self, fname, name=None):
+ Source.__init__(self, name=name)
+ self.fname = fname
+ self.f = PcapReader(self.fname)
+ def start(self):
+ print("start")
+ self.f = PcapReader(self.fname)
+ self.is_exhausted = False
+ def stop(self):
+ print("stop")
+ self.f.close()
+ def fileno(self):
+ return self.f.fileno()
+ def deliver(self):
+ p = self.f.recv()
+ print("deliver %r" % p)
+ if p is None:
+ self.is_exhausted = True
+ else:
+ self._send(p)
+
+
+class InjectSink(Sink):
+ """Packets received on low input are injected to an interface
+ +-----------+
+ >>-| |->>
+ | |
+ >-|--[iface] |->
+ +-----------+
+"""
+ def __init__(self, iface=None, name=None):
+ Sink.__init__(self, name=name)
+ if iface == None:
+ iface = conf.iface
+ self.iface = iface
+ def start(self):
+ self.s = conf.L2socket(iface=self.iface)
+ def stop(self):
+ self.s.close()
+ def push(self, msg):
+ self.s.send(msg)
+
+class Inject3Sink(InjectSink):
+ def start(self):
+ self.s = conf.L3socket(iface=self.iface)
+
+
+class WrpcapSink(Sink):
+ """Packets received on low input are written to PCA file
+ +----------+
+ >>-| |->>
+ | |
+ >-|--[pcap] |->
+ +----------+
+"""
+ def __init__(self, fname, name=None):
+ Sink.__init__(self, name=name)
+ self.f = PcapWriter(fname)
+ def stop(self):
+ self.f.flush()
+ def push(self, msg):
+ self.f.write(msg)
+
+
+class UDPDrain(Drain):
+ """Apply a function to messages on low and high entry
+ +-------------+
+ >>-|--[payload]--|->>
+ | X |
+ >-|----[UDP]----|->
+ +-------------+
+"""
+ def __init__(self, ip="127.0.0.1", port=1234):
+ Drain.__init__(self)
+ self.ip = ip
+ self.port = port
+
+ def push(self, msg):
+ if IP in msg and msg[IP].proto == 17 and UDP in msg:
+ payload = msg[UDP].payload
+ self._high_send(str(payload))
+ def high_push(self, msg):
+ p = IP(dst=self.ip)/UDP(sport=1234,dport=self.port)/msg
+ self._send(p)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/sendrecv.py b/scripts/external_libs/scapy-python3-0.18/scapy/sendrecv.py
new file mode 100644
index 00000000..8649c14d
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/sendrecv.py
@@ -0,0 +1,678 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Functions to send and receive packets.
+"""
+
+import pickle,os,sys,time,subprocess,itertools
+from select import select
+from .data import *
+import scapy.arch
+from .config import conf
+from .packet import Gen
+from .utils import warning,get_temp_file,PcapReader,wrpcap
+from . import plist
+from .error import log_runtime,log_interactive
+from .base_classes import SetGen
+
+#################
+## Debug class ##
+#################
+
+class debug:
+ recv=[]
+ sent=[]
+ match=[]
+
+
+####################
+## Send / Receive ##
+####################
+
+
+
+
+def sndrcv(pks, pkt, timeout = None, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
+ if not isinstance(pkt, Gen):
+ pkt = SetGen(pkt)
+
+ if verbose is None:
+ verbose = conf.verb
+ debug.recv = plist.PacketList([],"Unanswered")
+ debug.sent = plist.PacketList([],"Sent")
+ debug.match = plist.SndRcvList([])
+ nbrecv=0
+ ans = []
+ # do it here to fix random fields, so that parent and child have the same
+ all_stimuli = tobesent = [p for p in pkt]
+ notans = len(tobesent)
+
+ hsent={}
+ for i in tobesent:
+ h = i.hashret()
+ if h in hsent:
+ hsent[h].append(i)
+ else:
+ hsent[h] = [i]
+ if retry < 0:
+ retry = -retry
+ autostop=retry
+ else:
+ autostop=0
+
+
+ while retry >= 0:
+ found=0
+
+ if timeout < 0:
+ timeout = None
+
+ rdpipe,wrpipe = os.pipe()
+ rdpipe=os.fdopen(rdpipe, "rb")
+ wrpipe=os.fdopen(wrpipe,"wb")
+
+ pid=1
+ try:
+ pid = os.fork()
+ if pid == 0:
+ try:
+ sys.stdin.close()
+ rdpipe.close()
+ try:
+ i = 0
+ if verbose:
+ print("Begin emission:")
+ for p in tobesent:
+ pks.send(p)
+ i += 1
+ time.sleep(inter)
+ if verbose:
+ print("Finished to send %i packets." % i)
+ except SystemExit:
+ pass
+ except KeyboardInterrupt:
+ pass
+ except:
+ log_runtime.exception("--- Error in child %i" % os.getpid())
+ log_runtime.info("--- Error in child %i" % os.getpid())
+ finally:
+ try:
+ os.setpgrp() # Chance process group to avoid ctrl-C
+ sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
+ pickle.dump( (conf.netcache,sent_times), wrpipe )
+ wrpipe.close()
+ except:
+ pass
+ elif pid < 0:
+ log_runtime.error("fork error")
+ else:
+ wrpipe.close()
+ stoptime = 0
+ remaintime = None
+ inmask = [rdpipe,pks]
+ try:
+ try:
+ while 1:
+ if stoptime:
+ remaintime = stoptime-time.time()
+ if remaintime <= 0:
+ break
+ r = None
+ if scapy.arch.FREEBSD or scapy.arch.DARWIN:
+ inp, out, err = select(inmask,[],[], 0.05)
+ if len(inp) == 0 or pks in inp:
+ r = pks.nonblock_recv()
+ else:
+ inp, out, err = select(inmask,[],[], remaintime)
+ if len(inp) == 0:
+ break
+ if pks in inp:
+ r = pks.recv(MTU)
+ if rdpipe in inp:
+ if timeout:
+ stoptime = time.time()+timeout
+ del(inmask[inmask.index(rdpipe)])
+ if r is None:
+ continue
+ ok = 0
+ h = r.hashret()
+ if h in hsent:
+ hlst = hsent[h]
+ for i in range(len(hlst)):
+ if r.answers(hlst[i]):
+ ans.append((hlst[i],r))
+ if verbose > 1:
+ os.write(1, b"*")
+ ok = 1
+ if not multi:
+ del(hlst[i])
+ notans -= 1;
+ else:
+ if not hasattr(hlst[i], '_answered'):
+ notans -= 1;
+ hlst[i]._answered = 1;
+ break
+ if notans == 0 and not multi:
+ break
+ if not ok:
+ if verbose > 1:
+ os.write(1, b".")
+ nbrecv += 1
+ if conf.debug_match:
+ debug.recv.append(r)
+ except KeyboardInterrupt:
+ if chainCC:
+ raise
+ finally:
+ try:
+ nc,sent_times = pickle.load(rdpipe)
+ except EOFError:
+ warning("Child died unexpectedly. Packets may have not been sent %i"%os.getpid())
+ else:
+ conf.netcache.update(nc)
+ for p,t in zip(all_stimuli, sent_times):
+ p.sent_time = t
+ os.waitpid(pid,0)
+ finally:
+ if pid == 0:
+ os._exit(0)
+
+ #remain = reduce(list.__add__, hsent.values(), [])
+ remain = list(itertools.chain(*[ i for i in hsent.values() ]))
+ if multi:
+ #remain = filter(lambda p: not hasattr(p, '_answered'), remain);
+ remain = [ p for p in remain if not hasattr(p, '_answered')]
+
+ if autostop and len(remain) > 0 and len(remain) != len(tobesent):
+ retry = autostop
+
+ tobesent = remain
+ if len(tobesent) == 0:
+ break
+ retry -= 1
+
+ if conf.debug_match:
+ debug.sent=plist.PacketList(remain[:],"Sent")
+ debug.match=plist.SndRcvList(ans[:])
+
+ #clean the ans list to delete the field _answered
+ if (multi):
+ for s,r in ans:
+ if hasattr(s, '_answered'):
+ del(s._answered)
+
+ if verbose:
+ print("\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans))
+ return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
+
+
+def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, realtime=None, *args, **kargs):
+ if type(x) is bytes:
+ x = conf.raw_layer(load=x)
+ if type(x) is str:
+ x = conf.raw_layer(load=x.encode('ascii'))
+ if not isinstance(x, Gen):
+ x = SetGen(x)
+ if verbose is None:
+ verbose = conf.verb
+ n = 0
+ if count is not None:
+ loop = -count
+ elif not loop:
+ loop=-1
+ try:
+ while loop:
+ dt0 = None
+ for p in x:
+ if realtime:
+ ct = time.time()
+ if dt0:
+ st = dt0+p.time-ct
+ if st > 0:
+ time.sleep(st)
+ else:
+ dt0 = ct-p.time
+ s.send(p)
+ n += 1
+ if verbose:
+ os.write(1,b".")
+ time.sleep(inter)
+ if loop < 0:
+ loop += 1
+ except KeyboardInterrupt:
+ pass
+ s.close()
+ if verbose:
+ print("\nSent %i packets." % n)
+
+@conf.commands.register
+def send(x, inter=0, loop=0, count=None, verbose=None, realtime=None, *args, **kargs):
+ """Send packets at layer 3
+send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
+ __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose, realtime=realtime)
+
+@conf.commands.register
+def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, realtime=None, *args, **kargs):
+ """Send packets at layer 2
+sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
+ if iface is None and iface_hint is not None:
+ iface = conf.route.route(iface_hint)[0]
+ __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose, realtime=realtime)
+
+@conf.commands.register
+def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, verbose=True):
+ """Send packets at layer 2 using tcpreplay for performance
+ pps: packets per second
+ mpbs: MBits per second
+ realtime: use packet's timestamp, bending time with realtime value
+ loop: number of times to process the packet list
+ file_cache: cache packets in RAM instead of reading from disk at each iteration
+ iface: output interface
+ verbose: if False, discard tcpreplay output """
+ if iface is None:
+ iface = conf.iface
+ argv = [conf.prog.tcpreplay, "--intf1=%s" % iface ]
+ if pps is not None:
+ argv.append("--pps=%i" % pps)
+ elif mbps is not None:
+ argv.append("--mbps=%f" % mbps)
+ elif realtime is not None:
+ argv.append("--multiplier=%i" % realtime)
+ else:
+ argv.append("--topspeed")
+ if not verbose:
+ argv.append("-q")
+ if loop:
+ argv.append("--loop=%i" % loop)
+ if file_cache:
+ argv.append("--enable-file-cache")
+
+ f = get_temp_file()
+ argv.append(f)
+ wrpcap(f, x)
+ with open(os.devnull, "wb") as null:
+ proc_output = null if not verbose else None
+ try:
+ subprocess.check_call(argv,
+ stdout=proc_output,
+ stderr=proc_output)
+ except KeyboardInterrupt:
+ log_interactive.info("Interrupted by user")
+ except Exception as e:
+ log_interactive.error("while trying to exec [%s]: %s" % (argv[0],e))
+ finally:
+ os.unlink(f)
+
+
+
+
+
+@conf.commands.register
+def sr(x,filter=None, iface=None, nofilter=0, *args,**kargs):
+ """Send and receive packets at layer 3
+nofilter: put 1 to avoid use of bpf filters
+retry: if positive, how many times to resend unanswered packets
+ if negative, how many times to retry when no more packets are answered
+timeout: how much time to wait after the last packet has been sent
+verbose: set verbosity level
+multi: whether to accept multiple answers for the same stimulus
+filter: provide a BPF filter
+iface: listen answers only on the given interface"""
+ if not "timeout" in kargs:
+ kargs["timeout"] = -1
+ s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
+ a,b=sndrcv(s,x,*args,**kargs)
+ s.close()
+ return a,b
+
+@conf.commands.register
+def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
+ """Send packets at layer 3 and return only the first answer
+nofilter: put 1 to avoid use of bpf filters
+retry: if positive, how many times to resend unanswered packets
+ if negative, how many times to retry when no more packets are answered
+timeout: how much time to wait after the last packet has been sent
+verbose: set verbosity level
+multi: whether to accept multiple answers for the same stimulus
+filter: provide a BPF filter
+iface: listen answers only on the given interface"""
+ if not "timeout" in kargs:
+ kargs["timeout"] = -1
+ s=conf.L3socket(filter=filter, nofilter=nofilter, iface=iface)
+ a,b=sndrcv(s,x,*args,**kargs)
+ s.close()
+ if len(a) > 0:
+ return a[0][1]
+ else:
+ return None
+
+@conf.commands.register
+def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
+ """Send and receive packets at layer 2
+nofilter: put 1 to avoid use of bpf filters
+retry: if positive, how many times to resend unanswered packets
+ if negative, how many times to retry when no more packets are answered
+timeout: how much time to wait after the last packet has been sent
+verbose: set verbosity level
+multi: whether to accept multiple answers for the same stimulus
+filter: provide a BPF filter
+iface: work only on the given interface"""
+ if not "timeout" in kargs:
+ kargs["timeout"] = -1
+ if iface is None and iface_hint is not None:
+ iface = conf.route.route(iface_hint)[0]
+ s = conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type)
+ a,b=sndrcv(s ,x,*args,**kargs)
+ s.close()
+ return a,b
+
+@conf.commands.register
+def srp1(*args,**kargs):
+ """Send and receive packets at layer 2 and return only the first answer
+nofilter: put 1 to avoid use of bpf filters
+retry: if positive, how many times to resend unanswered packets
+ if negative, how many times to retry when no more packets are answered
+timeout: how much time to wait after the last packet has been sent
+verbose: set verbosity level
+multi: whether to accept multiple answers for the same stimulus
+filter: provide a BPF filter
+iface: work only on the given interface"""
+ if not "timeout" in kargs:
+ kargs["timeout"] = -1
+ a,b=srp(*args,**kargs)
+ if len(a) > 0:
+ return a[0][1]
+ else:
+ return None
+
+def __sr_loop(srfunc, pkts, prn=lambda x:x[1].summary(), prnfail=lambda x:x.summary(), inter=1, timeout=None, count=None, verbose=None, store=1, *args, **kargs):
+ n = 0
+ r = 0
+ ct = conf.color_theme
+ if verbose is None:
+ verbose = conf.verb
+ parity = 0
+ ans=[]
+ unans=[]
+ if timeout is None:
+ timeout = min(2*inter, 5)
+ try:
+ while 1:
+ parity ^= 1
+ col = [ct.even,ct.odd][parity]
+ if count is not None:
+ if count == 0:
+ break
+ count -= 1
+ start = time.time()
+ print("\rsend...\r", end = " ")
+ res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=1, *args, **kargs)
+ n += len(res[0])+len(res[1])
+ r += len(res[0])
+ if verbose > 1 and prn and len(res[0]) > 0:
+ msg = "RECV %i:" % len(res[0])
+ print( "\r"+ct.success(msg), end = " ")
+ for p in res[0]:
+ print(col(prn(p)))
+ print(" "*len(msg), end = " ")
+ if verbose > 1 and prnfail and len(res[1]) > 0:
+ msg = "fail %i:" % len(res[1])
+ print("\r"+ct.fail(msg), end = " ")
+ for p in res[1]:
+ print(col(prnfail(p)))
+ print(" "*len(msg), end = " ")
+ if verbose > 1 and not (prn or prnfail):
+ print("recv:%i fail:%i" % tuple(map(len, res[:2])))
+ if store:
+ ans += res[0]
+ unans += res[1]
+ end=time.time()
+ if end-start < inter:
+ time.sleep(inter+start-end)
+ except KeyboardInterrupt:
+ pass
+
+ if verbose and n>0:
+ print(ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n,r,100.0*r/n)))
+ return plist.SndRcvList(ans),plist.PacketList(unans)
+
+@conf.commands.register
+def srloop(pkts, *args, **kargs):
+ """Send a packet at layer 3 in loop and print the answer each time
+srloop(pkts, [prn], [inter], [count], ...) --> None"""
+ return __sr_loop(sr, pkts, *args, **kargs)
+
+@conf.commands.register
+def srploop(pkts, *args, **kargs):
+ """Send a packet at layer 2 in loop and print the answer each time
+srloop(pkts, [prn], [inter], [count], ...) --> None"""
+ return __sr_loop(srp, pkts, *args, **kargs)
+
+
+#def sndrcvflood(pks, pkt, prn=lambda (s,r):r.summary(), chainCC=0, store=1, unique=0):
+def sndrcvflood(pks, pkt, prn=lambda a:a[1].summary(), chainCC=0, store=1, unique=0):
+ if not isinstance(pkt, Gen):
+ pkt = SetGen(pkt)
+ tobesent = [p for p in pkt]
+ received = plist.SndRcvList()
+ seen = {}
+
+ hsent={}
+ for i in tobesent:
+ h = i.hashret()
+ if h in hsent:
+ hsent[h].append(i)
+ else:
+ hsent[h] = [i]
+
+ def send_in_loop(tobesent):
+ while 1:
+ for p in tobesent:
+ yield p
+
+ packets_to_send = send_in_loop(tobesent)
+
+ ssock = rsock = pks.fileno()
+
+ try:
+ while 1:
+ readyr,readys,_ = select([rsock],[ssock],[])
+ if ssock in readys:
+ pks.send(next(packets_to_send))
+
+ if rsock in readyr:
+ p = pks.recv(MTU)
+ if p is None:
+ continue
+ h = p.hashret()
+ if h in hsent:
+ hlst = hsent[h]
+ for i in hlst:
+ if p.answers(i):
+ res = prn((i,p))
+ if unique:
+ if res in seen:
+ continue
+ seen[res] = None
+ if res is not None:
+ print(res)
+ if store:
+ received.append((i,p))
+ except KeyboardInterrupt:
+ if chainCC:
+ raise
+ return received
+
+@conf.commands.register
+def srflood(x,filter=None, iface=None, nofilter=None, *args,**kargs):
+ """Flood and receive packets at layer 3
+prn: function applied to packets received. Ret val is printed if not None
+store: if 1 (default), store answers and return them
+unique: only consider packets whose print
+nofilter: put 1 to avoid use of bpf filters
+filter: provide a BPF filter
+iface: listen answers only on the given interface"""
+ s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
+ r=sndrcvflood(s,x,*args,**kargs)
+ s.close()
+ return r
+
+@conf.commands.register
+def srpflood(x,filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
+ """Flood and receive packets at layer 2
+prn: function applied to packets received. Ret val is printed if not None
+store: if 1 (default), store answers and return them
+unique: only consider packets whose print
+nofilter: put 1 to avoid use of bpf filters
+filter: provide a BPF filter
+iface: listen answers only on the given interface"""
+ if iface is None and iface_hint is not None:
+ iface = conf.route.route(iface_hint)[0]
+ s = conf.L2socket(filter=filter, iface=iface, nofilter=nofilter)
+ r=sndrcvflood(s,x,*args,**kargs)
+ s.close()
+ return r
+
+
+
+
+@conf.commands.register
+def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None,
+ opened_socket=None, stop_filter=None, *arg, **karg):
+ """Sniff packets
+sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
+
+ count: number of packets to capture. 0 means infinity
+ store: wether to store sniffed packets or discard them
+ prn: function to apply to each packet. If something is returned,
+ it is displayed. Ex:
+ ex: prn = lambda x: x.summary()
+lfilter: python function applied to each packet to determine
+ if further action may be done
+ ex: lfilter = lambda x: x.haslayer(Padding)
+offline: pcap file to read packets from, instead of sniffing them
+timeout: stop sniffing after a given time (default: None)
+L2socket: use the provided L2socket
+opened_socket: provide an object ready to use .recv() on
+stop_filter: python function applied to each packet to determine
+ if we have to stop the capture after this packet
+ ex: stop_filter = lambda x: x.haslayer(TCP)
+ """
+ c = 0
+
+ if opened_socket is not None:
+ s = opened_socket
+ else:
+ if offline is None:
+ if L2socket is None:
+ L2socket = conf.L2listen
+ s = L2socket(type=ETH_P_ALL, *arg, **karg)
+ else:
+ s = PcapReader(offline)
+
+ lst = []
+ if timeout is not None:
+ stoptime = time.time()+timeout
+ remain = None
+ try:
+ while 1:
+ if timeout is not None:
+ remain = stoptime-time.time()
+ if remain <= 0:
+ break
+ sel = select([s],[],[],remain)
+ if s in sel[0]:
+ p = s.recv(MTU)
+ if p is None:
+ break
+ if lfilter and not lfilter(p):
+ continue
+ if store:
+ lst.append(p)
+ c += 1
+ if prn:
+ r = prn(p)
+ if r is not None:
+ print(r)
+ if stop_filter and stop_filter(p):
+ break
+ if count > 0 and c >= count:
+ break
+ except KeyboardInterrupt:
+ pass
+ if opened_socket is None:
+ s.close()
+ return plist.PacketList(lst,"Sniffed")
+
+
+@conf.commands.register
+def bridge_and_sniff(if1, if2, count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None,
+ stop_filter=None, *args, **kargs):
+ """Forward traffic between two interfaces and sniff packets exchanged
+bridge_and_sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2Socket args) -> list of packets
+
+ count: number of packets to capture. 0 means infinity
+ store: wether to store sniffed packets or discard them
+ prn: function to apply to each packet. If something is returned,
+ it is displayed. Ex:
+ ex: prn = lambda x: x.summary()
+lfilter: python function applied to each packet to determine
+ if further action may be done
+ ex: lfilter = lambda x: x.haslayer(Padding)
+timeout: stop sniffing after a given time (default: None)
+L2socket: use the provided L2socket
+stop_filter: python function applied to each packet to determine
+ if we have to stop the capture after this packet
+ ex: stop_filter = lambda x: x.haslayer(TCP)
+ """
+ c = 0
+ if L2socket is None:
+ L2socket = conf.L2socket
+ s1 = L2socket(iface=if1)
+ s2 = L2socket(iface=if2)
+ peerof={s1:s2,s2:s1}
+ label={s1:if1, s2:if2}
+
+ lst = []
+ if timeout is not None:
+ stoptime = time.time()+timeout
+ remain = None
+ try:
+ while True:
+ if timeout is not None:
+ remain = stoptime-time.time()
+ if remain <= 0:
+ break
+ ins,outs,errs = select([s1,s2],[],[], remain)
+ for s in ins:
+ p = s.recv()
+ if p is not None:
+ peerof[s].send(p.original)
+ if lfilter and not lfilter(p):
+ continue
+ if store:
+ p.sniffed_on = label[s]
+ lst.append(p)
+ c += 1
+ if prn:
+ r = prn(p)
+ if r is not None:
+ print("%s: %s" % (label[s],r))
+ if stop_filter and stop_filter(p):
+ break
+ if count > 0 and c >= count:
+ break
+ except KeyboardInterrupt:
+ pass
+ finally:
+ return plist.PacketList(lst,"Sniffed")
+
+
+@conf.commands.register
+def tshark(*args,**kargs):
+ """Sniff packets and print them calling pkt.show(), a bit like text wireshark"""
+ sniff(prn=lambda x: x.display(),*args,**kargs)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/supersocket.py b/scripts/external_libs/scapy-python3-0.18/scapy/supersocket.py
new file mode 100644
index 00000000..b87f9c16
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/supersocket.py
@@ -0,0 +1,141 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+SuperSocket.
+"""
+
+import socket,time
+from .config import conf
+from .data import *
+from scapy.error import warning, log_runtime
+
+class _SuperSocket_metaclass(type):
+ def __repr__(self):
+ if self.desc is not None:
+ return "<%s: %s>" % (self.__name__,self.desc)
+ else:
+ return "<%s>" % self.__name__
+
+
+class SuperSocket(metaclass = _SuperSocket_metaclass):
+ desc = None
+ closed=0
+ def __init__(self, family=socket.AF_INET,type=socket.SOCK_STREAM, proto=0):
+ self.ins = socket.socket(family, type, proto)
+ self.outs = self.ins
+ self.promisc=None
+ def send(self, x):
+ sx = bytes(x)
+ if hasattr(x, "sent_time"):
+ x.sent_time = time.time()
+ return self.outs.send(sx)
+ def recv(self, x=MTU):
+ return conf.raw_layer(self.ins.recv(x))
+ def fileno(self):
+ return self.ins.fileno()
+ def close(self):
+ if self.closed:
+ return
+ self.closed=1
+ if self.ins != self.outs:
+ if self.outs and self.outs.fileno() != -1:
+ self.outs.close()
+ if self.ins and self.ins.fileno() != -1:
+ self.ins.close()
+ def sr(self, *args, **kargs):
+ return sendrecv.sndrcv(self, *args, **kargs)
+ def sr1(self, *args, **kargs):
+ a,b = sendrecv.sndrcv(self, *args, **kargs)
+ if len(a) > 0:
+ return a[0][1]
+ else:
+ return None
+ def sniff(self, *args, **kargs):
+ return sendrecv.sniff(opened_socket=self, *args, **kargs)
+
+class L3RawSocket(SuperSocket):
+ desc = "Layer 3 using Raw sockets (PF_INET/SOCK_RAW)"
+ def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
+ self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
+ self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
+ self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
+ if iface is not None:
+ self.ins.bind((iface, type))
+ def recv(self, x=MTU):
+ pkt, sa_ll = self.ins.recvfrom(x)
+ if sa_ll[2] == socket.PACKET_OUTGOING:
+ return None
+ if sa_ll[3] in conf.l2types:
+ cls = conf.l2types[sa_ll[3]]
+ lvl = 2
+ elif sa_ll[1] in conf.l3types:
+ cls = conf.l3types[sa_ll[1]]
+ lvl = 3
+ else:
+ cls = conf.default_l2
+ warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
+ lvl = 3
+
+ try:
+ pkt = cls(pkt)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ pkt = conf.raw_layer(pkt)
+ if lvl == 2:
+ pkt = pkt.payload
+
+ if pkt is not None:
+ from arch import get_last_packet_timestamp
+ pkt.time = get_last_packet_timestamp(self.ins)
+ return pkt
+ def send(self, x):
+ try:
+ #sx = str(x)
+ sx = x
+ x.sent_time = time.time()
+ self.outs.sendto(sx,(x.dst,0))
+ except socket.error as msg:
+ log_runtime.error(msg)
+
+class SimpleSocket(SuperSocket):
+ desc = "wrapper arround a classic socket"
+ def __init__(self, sock):
+ self.ins = sock
+ self.outs = sock
+
+
+class StreamSocket(SimpleSocket):
+ desc = "transforms a stream socket into a layer 2"
+ def __init__(self, sock, basecls=None):
+ if basecls is None:
+ basecls = conf.raw_layer
+ SimpleSocket.__init__(self, sock)
+ self.basecls = basecls
+
+ def recv(self, x=MTU):
+ pkt = self.ins.recv(x, socket.MSG_PEEK)
+ x = len(pkt)
+ if x == 0:
+ raise socket.error((100,"Underlying stream socket tore down"))
+ pkt = self.basecls(pkt)
+ pad = pkt.getlayer(conf.padding_layer)
+ if pad is not None and pad.underlayer is not None:
+ del(pad.underlayer.payload)
+ while pad is not None and not isinstance(pad, NoPayload):
+ x -= len(pad.load)
+ pad = pad.payload
+ self.ins.recv(x)
+ return pkt
+
+
+
+if conf.L3socket is None:
+ conf.L3socket = L3RawSocket
+
+import scapy.sendrecv
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/themes.py b/scripts/external_libs/scapy-python3-0.18/scapy/themes.py
new file mode 100644
index 00000000..f519ad7e
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/themes.py
@@ -0,0 +1,277 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Color themes for the interactive console.
+"""
+
+##################
+## Color themes ##
+##################
+
+class Color:
+ normal = "\033[0m"
+ black = "\033[30m"
+ red = "\033[31m"
+ green = "\033[32m"
+ yellow = "\033[33m"
+ blue = "\033[34m"
+ purple = "\033[35m"
+ cyan = "\033[36m"
+ grey = "\033[37m"
+
+ bold = "\033[1m"
+ uline = "\033[4m"
+ blink = "\033[5m"
+ invert = "\033[7m"
+
+
+def create_styler(fmt=None, before="", after="", fmt2="%s"):
+ def do_style(val, fmt=fmt, before=before, after=after, fmt2=fmt2):
+ if fmt is None:
+ if type(val) is not str:
+ val = str(val)
+ else:
+ val = fmt % val
+ return fmt2 % (before+val+after)
+ return do_style
+
+class ColorTheme:
+ def __repr__(self):
+ return "<%s>" % self.__class__.__name__
+ def __getattr__(self, attr):
+ return create_styler()
+
+
+class NoTheme(ColorTheme):
+ pass
+
+
+class AnsiColorTheme(ColorTheme):
+ def __getattr__(self, attr):
+ if attr.startswith("__"):
+ raise AttributeError(attr)
+ s = "style_%s" % attr
+ if s in self.__class__.__dict__:
+ before = getattr(self, s)
+ after = self.style_normal
+ else:
+ before = after = ""
+
+ return create_styler(before=before, after=after)
+
+
+ style_normal = ""
+ style_prompt = ""
+ style_punct = ""
+ style_id = ""
+ style_not_printable = ""
+ style_layer_name = ""
+ style_field_name = ""
+ style_field_value = ""
+ style_emph_field_name = ""
+ style_emph_field_value = ""
+ style_packetlist_name = ""
+ style_packetlist_proto = ""
+ style_packetlist_value = ""
+ style_fail = ""
+ style_success = ""
+ style_odd = ""
+ style_even = ""
+ style_opening = ""
+ style_active = ""
+ style_closed = ""
+ style_left = ""
+ style_right = ""
+
+class BlackAndWhite(AnsiColorTheme):
+ pass
+
+class DefaultTheme(AnsiColorTheme):
+ style_normal = Color.normal
+ style_prompt = Color.blue+Color.bold
+ style_punct = Color.normal
+ style_id = Color.blue+Color.bold
+ style_not_printable = Color.grey
+ style_layer_name = Color.red+Color.bold
+ style_field_name = Color.blue
+ style_field_value = Color.purple
+ style_emph_field_name = Color.blue+Color.uline+Color.bold
+ style_emph_field_value = Color.purple+Color.uline+Color.bold
+ style_packetlist_name = Color.red+Color.bold
+ style_packetlist_proto = Color.blue
+ style_packetlist_value = Color.purple
+ style_fail = Color.red+Color.bold
+ style_success = Color.blue+Color.bold
+ style_even = Color.black+Color.bold
+ style_odd = Color.black
+ style_opening = Color.yellow
+ style_active = Color.black
+ style_closed = Color.grey
+ style_left = Color.blue+Color.invert
+ style_right = Color.red+Color.invert
+
+class BrightTheme(AnsiColorTheme):
+ style_normal = Color.normal
+ style_punct = Color.normal
+ style_id = Color.yellow+Color.bold
+ style_layer_name = Color.red+Color.bold
+ style_field_name = Color.yellow+Color.bold
+ style_field_value = Color.purple+Color.bold
+ style_emph_field_name = Color.yellow+Color.bold
+ style_emph_field_value = Color.green+Color.bold
+ style_packetlist_name = Color.red+Color.bold
+ style_packetlist_proto = Color.yellow+Color.bold
+ style_packetlist_value = Color.purple+Color.bold
+ style_fail = Color.red+Color.bold
+ style_success = Color.blue+Color.bold
+ style_even = Color.black+Color.bold
+ style_odd = Color.black
+ style_left = Color.cyan+Color.invert
+ style_right = Color.purple+Color.invert
+
+
+class RastaTheme(AnsiColorTheme):
+ style_normal = Color.normal+Color.green+Color.bold
+ style_prompt = Color.yellow+Color.bold
+ style_punct = Color.red
+ style_id = Color.green+Color.bold
+ style_not_printable = Color.green
+ style_layer_name = Color.red+Color.bold
+ style_field_name = Color.yellow+Color.bold
+ style_field_value = Color.green+Color.bold
+ style_emph_field_name = Color.green
+ style_emph_field_value = Color.green
+ style_packetlist_name = Color.red+Color.bold
+ style_packetlist_proto = Color.yellow+Color.bold
+ style_packetlist_value = Color.green+Color.bold
+ style_fail = Color.red
+ style_success = Color.red+Color.bold
+ style_even = Color.yellow
+ style_odd = Color.green
+ style_left = Color.yellow+Color.invert
+ style_right = Color.red+Color.invert
+
+class ColorOnBlackTheme(AnsiColorTheme):
+ """Color theme for black backgrounds"""
+ style_normal = Color.normal
+ style_prompt = Color.green+Color.bold
+ style_punct = Color.normal
+ style_id = Color.green
+ style_not_printable = Color.black+Color.bold
+ style_layer_name = Color.yellow+Color.bold
+ style_field_name = Color.cyan
+ style_field_value = Color.purple+Color.bold
+ style_emph_field_name = Color.cyan+Color.bold
+ style_emph_field_value = Color.red+Color.bold
+ style_packetlist_name = Color.black+Color.bold
+ style_packetlist_proto = Color.yellow+Color.bold
+ style_packetlist_value = Color.purple+Color.bold
+ style_fail = Color.red+Color.bold
+ style_success = Color.green
+ style_even = Color.black+Color.bold
+ style_odd = Color.grey
+ style_opening = Color.yellow
+ style_active = Color.grey+Color.bold
+ style_closed = Color.black+Color.bold
+ style_left = Color.cyan+Color.bold
+ style_right = Color.red+Color.bold
+
+
+class FormatTheme(ColorTheme):
+ def __getattr__(self, attr):
+ if attr.startswith("__"):
+ raise AttributeError(attr)
+ colfmt = self.__class__.__dict__.get("style_%s" % attr, "%s")
+ return create_styler(fmt2 = colfmt)
+
+class LatexTheme(FormatTheme):
+ style_prompt = r"\textcolor{blue}{%s}"
+ style_not_printable = r"\textcolor{gray}{%s}"
+ style_layer_name = r"\textcolor{red}{\bf %s}"
+ style_field_name = r"\textcolor{blue}{%s}"
+ style_field_value = r"\textcolor{purple}{%s}"
+ style_emph_field_name = r"\textcolor{blue}{\underline{%s}}" #ul
+ style_emph_field_value = r"\textcolor{purple}{\underline{%s}}" #ul
+ style_packetlist_name = r"\textcolor{red}{\bf %s}"
+ style_packetlist_proto = r"\textcolor{blue}{%s}"
+ style_packetlist_value = r"\textcolor{purple}{%s}"
+ style_fail = r"\textcolor{red}{\bf %s}"
+ style_success = r"\textcolor{blue}{\bf %s}"
+ style_left = r"\textcolor{blue}{%s}"
+ style_right = r"\textcolor{red}{%s}"
+# style_even = r"}{\bf "
+# style_odd = ""
+
+class LatexTheme2(FormatTheme):
+ style_prompt = r"@`@textcolor@[@blue@]@@[@%s@]@"
+ style_not_printable = r"@`@textcolor@[@gray@]@@[@%s@]@"
+ style_layer_name = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
+ style_field_name = r"@`@textcolor@[@blue@]@@[@%s@]@"
+ style_field_value = r"@`@textcolor@[@purple@]@@[@%s@]@"
+ style_emph_field_name = r"@`@textcolor@[@blue@]@@[@@`@underline@[@%s@]@@]@"
+ style_emph_field_value = r"@`@textcolor@[@purple@]@@[@@`@underline@[@%s@]@@]@"
+ style_packetlist_name = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
+ style_packetlist_proto = r"@`@textcolor@[@blue@]@@[@%s@]@"
+ style_packetlist_value = r"@`@textcolor@[@purple@]@@[@%s@]@"
+ style_fail = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
+ style_success = r"@`@textcolor@[@blue@]@@[@@`@bfserices@[@@]@%s@]@"
+ style_even = r"@`@textcolor@[@gray@]@@[@@`@bfseries@[@@]@%s@]@"
+# style_odd = r"@`@textcolor@[@black@]@@[@@`@bfseries@[@@]@%s@]@"
+ style_left = r"@`@textcolor@[@blue@]@@[@%s@]@"
+ style_right = r"@`@textcolor@[@red@]@@[@%s@]@"
+
+class HTMLTheme(FormatTheme):
+ style_prompt = "<span class=prompt>%s</span>"
+ style_not_printable = "<span class=not_printable>%s</span>"
+ style_layer_name = "<span class=layer_name>%s</span>"
+ style_field_name = "<span class=field_name>%s</span>"
+ style_field_value = "<span class=field_value>%s</span>"
+ style_emph_field_name = "<span class=emph_field_name>%s</span>"
+ style_emph_field_value = "<span class=emph_field_value>%s</span>"
+ style_packetlist_name = "<span class=packetlist_name>%s</span>"
+ style_packetlist_proto = "<span class=packetlist_proto>%s</span>"
+ style_packetlist_value = "<span class=packetlist_value>%s</span>"
+ style_fail = "<span class=fail>%s</span>"
+ style_success = "<span class=success>%s</span>"
+ style_even = "<span class=even>%s</span>"
+ style_odd = "<span class=odd>%s</span>"
+ style_left = "<span class=left>%s</span>"
+ style_right = "<span class=right>%s</span>"
+
+class HTMLTheme2(HTMLTheme):
+ style_prompt = "#[#span class=prompt#]#%s#[#/span#]#"
+ style_not_printable = "#[#span class=not_printable#]#%s#[#/span#]#"
+ style_layer_name = "#[#span class=layer_name#]#%s#[#/span#]#"
+ style_field_name = "#[#span class=field_name#]#%s#[#/span#]#"
+ style_field_value = "#[#span class=field_value#]#%s#[#/span#]#"
+ style_emph_field_name = "#[#span class=emph_field_name#]#%s#[#/span#]#"
+ style_emph_field_value = "#[#span class=emph_field_value#]#%s#[#/span#]#"
+ style_packetlist_name = "#[#span class=packetlist_name#]#%s#[#/span#]#"
+ style_packetlist_proto = "#[#span class=packetlist_proto#]#%s#[#/span#]#"
+ style_packetlist_value = "#[#span class=packetlist_value#]#%s#[#/span#]#"
+ style_fail = "#[#span class=fail#]#%s#[#/span#]#"
+ style_success = "#[#span class=success#]#%s#[#/span#]#"
+ style_even = "#[#span class=even#]#%s#[#/span#]#"
+ style_odd = "#[#span class=odd#]#%s#[#/span#]#"
+ style_left = "#[#span class=left#]#%s#[#/span#]#"
+ style_right = "#[#span class=right#]#%s#[#/span#]#"
+
+
+class ColorPrompt:
+ __prompt = ">>> "
+ def __str__(self):
+ try:
+ ct = scapy.config.conf.color_theme
+ if isinstance(ct, AnsiColorTheme):
+ ## ^A and ^B delimit invisible caracters for readline to count right
+ return "\001%s\002" % ct.prompt("\002"+scapy.config.conf.prompt+"\001")
+ else:
+ return ct.prompt(scapy.config.conf.prompt)
+ except:
+ return self.__prompt
+
+
+import scapy.config
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/tools/UTscapy.py b/scripts/external_libs/scapy-python3-0.18/scapy/tools/UTscapy.py
new file mode 100644
index 00000000..212aa123
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/tools/UTscapy.py
@@ -0,0 +1,677 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Unit testing infrastructure for Scapy
+"""
+
+import sys,getopt,imp
+import bz2, base64, os.path, time, traceback, zlib, hashlib
+
+
+#### Import tool ####
+
+def import_module(name):
+ name = os.path.realpath(name)
+ thepath = os.path.dirname(name)
+ name = os.path.basename(name)
+ if name.endswith(".py"):
+ name = name[:-3]
+ f,path,desc = imp.find_module(name,[thepath])
+
+ try:
+ return imp.load_module(name, f, path, desc)
+ finally:
+ if f:
+ f.close()
+
+
+#### INTERNAL/EXTERNAL FILE EMBEDDING ####
+
+class File:
+ def __init__(self, name, URL, local):
+ self.name = name
+ self.local = local
+ self.URL = URL
+ def get_local(self):
+ return bz2.decompress(base64.decodestring(self.local))
+ def get_URL(self):
+ return URL
+ def write(self, dir):
+ if dir:
+ dir += "/"
+ open(dir+self.name,"w").write(self.get_local())
+
+
+# Embed a base64 encoded bziped version of js and css files
+# to work if you can't reach Internet.
+class External_Files:
+ UTscapy_js = File("UTscapy.js", "http://www.secdev.org/projects/UTscapy/UTscapy.js",
+"""QlpoOTFBWSZTWWVijKQAAXxfgERUYOvAChIhBAC/79+qQAH8AFA0poANAMjQAAAG
+ABo0NGEZNBo00BhgAaNDRhGTQaNNAYFURJinplGaKbRkJiekzSenqmpA0Gm1LFMp
+RUklVQlK9WUTZYpNFI1IiEWEFT09Sfj5uO+qO6S5DQwKIxM92+Zku94wL6V/1KTK
+an2c66Ug6SmVKy1ZIrgauxMVLF5xLH0lJRQuKlqLF10iatlTzqvw7S9eS3+h4lu3
+GZyMgoOude3NJ1pQy8eo+X96IYZw+ynehsiPj73m0rnvQ3QXZ9BJQiZQYQ5/uNcl
+2WOlC5vyQqV/BWsnr2NZYLYXQLDs/Bffk4ZfR4/SH6GfA5Xlek4xHNHqbSsRbREO
+gueXo3kcYi94K6hSO3ldD2O/qJXOFqJ8o3TE2aQahxtQpCVUKQMvODHwu2YkaORY
+ZC6gihEallcHDIAtRPScBACAJnUggYhLDX6DEko7nC9GvAw5OcEkiyDUbLdiGCzD
+aXWMC2DuQ2Y6sGf6NcRuON7QSbhHsPc4KKmZ/xdyRThQkGVijKQ=""")
+ UTscapy_css = File("UTscapy.css","http://www.secdev.org/projects/UTscapy/UTscapy.css",
+"""QlpoOTFBWSZTWTbBCNEAAE7fgHxwSB//+Cpj2QC//9/6UAR+63dxbNzO3ccmtGEk
+pM0m1I9E/Qp6g9Q09TNQ9QDR6gMgAkiBFG9U9TEGRkGgABoABoBmpJkRAaAxD1AN
+Gh6gNADQBzAATJgATCYJhDAEYAEiQkwIyJk0n6qenpqeoaMUeo9RgIxp6pX78kfx
+Jx4MUhDHKEb2pJAYAelG1cybiZBBDipH8ocxNyHDAqTUxiQmIAEDE3ApIBUUECAT
+7Lvlf4xA/sVK0QHkSlYtT0JmErdOjx1v5NONPYSjrIhQnbl1MbG5m+InMYmVAWJp
+uklD9cNdmQv2YigxbEtgUrsY2pDDV/qMT2SHnHsViu2rrp2LA01YJIHZqjYCGIQN
+sGNobFxAYHLqqMOj9TI2Y4GRpRCUGu82PnMnXUBgDSkTY4EfmygaqvUwbGMbPwyE
+220Q4G+sDvw7+6in3CAOS634pcOEAdREUW+QqMjvWvECrGISo1piv3vqubTGOL1c
+ssrFnnSfU4T6KSCbPs98HJ2yjWN4i8Bk5WrM/JmELLNeZ4vgMkA4JVQInNnWTUTe
+gmMSlJd/b7JuRwiM5RUzXOBTa0e3spO/rsNJiylu0rCxygdRo2koXdSJzmUVjJUm
+BOFIkUKq8LrE+oT9h2qUqqUQ25fGV7e7OFkpmZopqUi0WeIBzlXdYY0Zz+WUJUTC
+RC+CIPFIYh1RkopswMAop6ZjuZKRqR0WNuV+rfuF5aCXPpxAm0F14tPyhf42zFMT
+GJUMxxowJnoauRq4xGQk+2lYFxbQ0FiC43WZSyYLHMuo5NTJ92QLAgs4FgOyZQqQ
+xpsGKMA0cIisNeiootpnlWQvkPzNGUTPg8jqkwTvqQLguZLKJudha1hqfBib1IfO
+LNChcU6OqF+3wyPKg5Y5oSbSJPAMcRDANwmS2i9oZm6vsD1pLkWtFGbAkEjjCuEU
+W1ev1IsF2UVmWYFtJkqLT708ApUBK/ig3rbJWSq7RGQd3sSrOKu3lyKzTBdkXK2a
+BGLV5dS1XURdKxaRkMplLLQxsimBYZEAa8KQkYyI+4EagMqycRR7RgwtZFxJSu0T
+1q5wS2JG82iETHplbNj8DYo9IkmKzNAiw4FxK8bRfIYvwrbshbEagL11AQJFsqeZ
+WeXDoWEx2FMyyZRAB5QyCFnwYtwtWAQmmITY8aIM2SZyRnHH9Wi8+Sr2qyCscFYo
+vzM985aHXOHAxQN2UQZbQkUv3D4Vc+lyvalAffv3Tyg4ks3a22kPXiyeCGweviNX
+0K8TKasyOhGsVamTUAZBXfQVw1zmdS4rHDnbHgtIjX3DcCt6UIr0BHTYjdV0JbPj
+r1APYgXihjQwM2M83AKIhwQQJv/F3JFOFCQNsEI0QA==""")
+ def get_local_dict(cls):
+ #return dict(map(lambda (x,y): (x, y.name), filter(lambda (x,y): isinstance(y, File), cls.__dict__.items())))
+ return dict(map(lambda a: (a[0], a[1].name), filter(lambda a: isinstance(a[1], File), cls.__dict__.items())))
+ get_local_dict = classmethod(get_local_dict)
+ def get_URL_dict(cls):
+ #return dict(map(lambda (x,y): (x, y.URL), filter(lambda (x,y): isinstance(y, File), cls.__dict__.items())))
+ return dict(map(lambda a: (a[0], a[1].URL), filter(lambda a: isinstance(a[1], File), cls.__dict__.items())))
+ get_URL_dict = classmethod(get_URL_dict)
+
+
+#### HELPER CLASSES FOR PARAMETRING OUTPUT FORMAT ####
+
+class EnumClass:
+ def from_string(cls,x):
+ return cls.__dict__[x.upper()]
+ from_string = classmethod(from_string)
+
+class Format(EnumClass):
+ TEXT = 1
+ ANSI = 2
+ HTML = 3
+ LATEX = 4
+ XUNIT = 5
+
+
+#### TEST CLASSES ####
+
+class TestClass:
+ def __getitem__(self, item):
+ return getattr(self, item)
+ def add_keywords(self, kw):
+ if kw is str:
+ self.keywords.append(kw)
+ else:
+ self.keywords += kw
+
+class TestCampaign(TestClass):
+ def __init__(self, title):
+ self.title = title
+ self.filename = None
+ self.headcomments = ""
+ self.campaign = []
+ self.keywords = []
+ self.crc = None
+ self.sha = None
+ self.preexec = None
+ self.preexec_output = None
+ def add_testset(self, testset):
+ self.campaign.append(testset)
+ def __iter__(self):
+ return self.campaign.__iter__()
+ def all_tests(self):
+ for ts in self:
+ for t in ts:
+ yield t
+
+class TestSet(TestClass):
+ def __init__(self, name):
+ self.name = name
+ self.set = []
+ self.comments = ""
+ self.keywords = []
+ self.crc = None
+ self.expand = 1
+ def add_test(self, test):
+ self.set.append(test)
+ def __iter__(self):
+ return self.set.__iter__()
+
+class UnitTest(TestClass):
+ def __init__(self, name):
+ self.name = name
+ self.test = ""
+ self.comments = ""
+ self.result = ""
+ self.res = True # must be True at init to have a different truth value than None
+ self.output = ""
+ self.num = -1
+ self.keywords = []
+ self.crc = None
+ self.expand = 1
+ def __nonzero__(self):
+ return self.res
+
+
+#### PARSE CAMPAIGN ####
+
+def parse_campaign_file(campaign_file):
+ test_campaign = TestCampaign("Test campaign")
+ test_campaign.filename= campaign_file.name
+ testset = None
+ test = None
+ testnb = 0
+
+ for l in campaign_file.readlines():
+ if l[0] == '#':
+ continue
+ if l[0] == "~":
+ (test or testset or campaign_file).add_keywords(l[1:].split())
+ elif l[0] == "%":
+ test_campaign.title = l[1:].strip()
+ elif l[0] == "+":
+ testset = TestSet(l[1:].strip())
+ test_campaign.add_testset(testset)
+ test = None
+ elif l[0] == "=":
+ test = UnitTest(l[1:].strip())
+ test.num = testnb
+ testnb += 1
+ testset.add_test(test)
+ elif l[0] == "*":
+ if test is not None:
+
+ test.comments += l[1:]
+ elif testset is not None:
+ testset.comments += l[1:]
+ else:
+ test_campaign.headcomments += l[1:]
+ else:
+ if test is None:
+ if l.strip():
+ print("Unknown content [%s]" % l.strip(), file = sys.stderr)
+ else:
+ test.test += l
+ return test_campaign
+
+def dump_campaign(test_campaign):
+ print("#"*(len(test_campaign.title)+6))
+ print("## %(title)s ##" % test_campaign)
+ print("#"*(len(test_campaign.title)+6))
+ if test_campaign.sha and test_campaign.crc:
+ print("CRC=[%(crc)s] SHA=[%(sha)s]" % test_campaign)
+ print("from file %(filename)s" % test_campaign)
+ print()
+ for ts in test_campaign:
+ if ts.crc:
+ print("+--[%s]%s(%s)--" % (ts.name,"-"*max(2,80-len(ts.name)-18),ts.crc))
+ else:
+ print("+--[%s]%s" % (ts.name,"-"*max(2,80-len(ts.name)-6)))
+ if ts.keywords:
+ print(" kw=%s" % ",".join(ts.keywords))
+ for t in ts:
+ print("%(num)03i %(name)s" % t)
+ c = k = ""
+ if t.keywords:
+ k = "kw=%s" % ",".join(t.keywords)
+ if t.crc:
+ c = "[%(crc)s] " % t
+ if c or k:
+ print(" %s%s" % (c,k) )
+
+#### COMPUTE CAMPAIGN DIGESTS ####
+
+def crc32(x):
+ return "%08X" % (0xffffffff & zlib.crc32(x))
+
+def sha1(x):
+ return hashlib.sha1(x).hexdigest().upper()
+
+def compute_campaign_digests(test_campaign):
+ dc = b""
+ for ts in test_campaign:
+ dts = b""
+ for t in ts:
+ dt = t.test.strip().encode('ascii')
+ t.crc = crc32(dt)
+ dts += b"\0"+dt
+ ts.crc = crc32(dts)
+ dc += b"\0\x01"+dts
+ test_campaign.crc = crc32(dc)
+ if type(test_campaign.filename) is str and test_campaign.filename != '<stdin>':
+ test = open(test_campaign.filename, 'rb').read()
+ elif test_campaign.filename == '<stdin>':
+ test = sys.stdin.read().encode('ascii')
+ else:
+ raise Exception("Unknown test source %s" % test_campaign.filename)
+ test_campaign.sha = sha1(test)
+
+
+#### FILTER CAMPAIGN #####
+
+def filter_tests_on_numbers(test_campaign, num):
+ if num:
+ for ts in test_campaign:
+ #ts.set = filter(lambda t: t.num in num, ts.set)
+ ts.set = [ t for t in ts.set if t.num in num ]
+ #test_campaign.campaign = filter(lambda ts: len(ts.set) > 0, test_campaign.campaign)
+ test_campaign.campaign = [ ts for ts in test_campaign.campaign if len(ts.set) > 0 ]
+
+def filter_tests_keep_on_keywords(test_campaign, kw):
+ def kw_match(lst, kw):
+ for k in lst:
+ if k in kw:
+ return True
+ return False
+
+ if kw:
+ for ts in test_campaign:
+ #ts.set = filter(lambda t: kw_match(t.keywords, kw), ts.set)
+ ts.set = [ t for t in ts.set if kw_match(t.keywords, kw) ]
+
+def filter_tests_remove_on_keywords(test_campaign, kw):
+ def kw_match(lst, kw):
+ for k in kw:
+ if k not in lst:
+ return False
+ return True
+
+ if kw:
+ for ts in test_campaign:
+ #ts.set = filter(lambda t: not kw_match(t.keywords, kw), ts.set)
+ ts.set = [ t for t in ts.set if not kw_match(t.keywords, kw) ]
+
+
+def remove_empty_testsets(test_campaign):
+ #test_campaign.campaign = filter(lambda ts: len(ts.set) > 0, test_campaign.campaign)
+ test_campaign.campaign = [ ts for ts in test_campaign.campaign if len(ts.set) > 0 ]
+
+
+#### RUN CAMPAIGN #####
+
+def run_campaign(test_campaign, get_interactive_session, verb=2):
+ passed=failed=0
+ if test_campaign.preexec:
+ test_campaign.preexec_output = get_interactive_session(test_campaign.preexec.strip())[0]
+ for testset in test_campaign:
+ for t in testset:
+ t.output,res = get_interactive_session(t.test.strip())
+ the_res = False
+ try:
+ if res is None or res:
+ the_res= True
+ except Exception as msg:
+ t.output+="UTscapy: Error during result interpretation:\n"
+ t.output+="".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback,))
+ if the_res:
+ t.res = True
+ res = "passed"
+ passed += 1
+ else:
+ t.res = False
+ res = "failed"
+ failed += 1
+ t.result = res
+ if verb > 1:
+ print("%(result)6s %(crc)s %(name)s" % t, file = sys.stderr)
+ test_campaign.passed = passed
+ test_campaign.failed = failed
+ if verb:
+ print("Campaign CRC=%(crc)s SHA=%(sha)s" % test_campaign, file = sys.stderr)
+ print("PASSED=%i FAILED=%i" % (passed, failed), file = sys.stderr)
+
+
+#### INFO LINES ####
+
+def info_line(test_campaign):
+ filename = test_campaign.filename
+ if filename is None:
+ return "Run %s by UTscapy" % time.ctime()
+ else:
+ return "Run %s from [%s] by UTscapy" % (time.ctime(), filename)
+
+def html_info_line(test_campaign):
+ filename = test_campaign.filename
+ if filename is None:
+ return """Run %s by <a href="http://www.secdev.org/projects/UTscapy/">UTscapy</a><br>""" % time.ctime()
+ else:
+ return """Run %s from [%s] by <a href="http://www.secdev.org/projects/UTscapy/">UTscapy</a><br>""" % (time.ctime(), filename)
+
+
+#### CAMPAIGN TO something ####
+
+def campaign_to_TEXT(test_campaign):
+ output="%(title)s\n" % test_campaign
+ output += "-- "+info_line(test_campaign)+"\n\n"
+ output += "Passed=%(passed)i\nFailed=%(failed)i\n\n%(headcomments)s\n" % test_campaign
+
+ for testset in test_campaign:
+ output += "######\n## %(name)s\n######\n%(comments)s\n\n" % testset
+ for t in testset:
+ if t.expand:
+ output += "###(%(num)03i)=[%(result)s] %(name)s\n%(comments)s\n%(output)s\n\n" % t
+
+ return output
+
+def campaign_to_ANSI(test_campaign):
+ output="%(title)s\n" % test_campaign
+ output += "-- "+info_line(test_campaign)+"\n\n"
+ output += "Passed=%(passed)i\nFailed=%(failed)i\n\n%(headcomments)s\n" % test_campaign
+
+ for testset in test_campaign:
+ output += "######\n## %(name)s\n######\n%(comments)s\n\n" % testset
+ for t in testset:
+ if t.expand:
+ output += "###(%(num)03i)=[%(result)s] %(name)s\n%(comments)s\n%(output)s\n\n" % t
+
+ return output
+
+def campaign_to_xUNIT(test_campaign):
+ output='<?xml version="1.0" encoding="UTF-8" ?>\n<testsuite>\n'
+ for testset in test_campaign:
+ for t in testset:
+ output += ' <testcase classname="%s"\n' % testset.name.encode("string_escape").replace('"',' ')
+ output += ' name="%s"\n' % t.name.encode("string_escape").replace('"',' ')
+ output += ' duration="0">\n' % t
+ if not t.res:
+ output += '<error><![CDATA[%(output)s]]></error>\n' % t
+ output += "</testcase>\n"
+ output += '</testsuite>'
+ return output
+
+
+def campaign_to_HTML(test_campaign, local=0):
+ output = """<html>
+<head>
+<title>%(title)s</title>
+<link rel="stylesheet" href="%%(UTscapy_css)s" type="text/css">
+<script language="JavaScript" src="%%(UTscapy_js)s" type="text/javascript"></script>
+</head>
+<body>
+
+<h1>%(title)s</h1>
+
+<span class=button onClick="hide_all('tst')">Shrink All</span>
+<span class=button onClick="show_all('tst')">Expand All</span>
+<span class=button onClick="show_passed('tst')">Expand Passed</span>
+<span class=button onClick="show_failed('tst')">Expand Failed</span>
+<p>
+""" % test_campaign
+
+ if local:
+ External_Files.UTscapy_js.write(os.path.dirname(test_campaign.output_file.name))
+ External_Files.UTscapy_css.write(os.path.dirname(test_campaign.output_file.name))
+ output %= External_Files.get_local_dict()
+ else:
+ output %= External_Files.get_URL_dict()
+
+ if test_campaign.crc is not None and test_campaign.sha is not None:
+ output += "CRC=<span class=crc>%(crc)s</span> SHA=<span class=crc>%(sha)s</span><br>" % test_campaign
+ output += "<small><em>"+html_info_line(test_campaign)+"</em></small>"
+ output += test_campaign.headcomments + "\n<p>PASSED=%(passed)i FAILED=%(failed)i<p>\n\n" % test_campaign
+ for ts in test_campaign:
+ for t in ts:
+ output += """<span class=button%(result)s onClick="goto_id('tst%(num)il')">%(num)03i</span>\n""" % t
+ output += "\n\n"
+
+ for testset in test_campaign:
+ output += "<h2>" % testset
+ if testset.crc is not None:
+ output += "<span class=crc>%(crc)s</span> " % testset
+ output += "%(name)s</h2>\n%(comments)s\n<ul>\n" % testset
+ for t in testset:
+ output += """<li class=%(result)s id="tst%(num)il">\n""" % t
+ if t.expand == 2:
+ output +="""
+<span id="tst%(num)i+" class="button%(result)s" onClick="show('tst%(num)i')" style="POSITION: absolute; VISIBILITY: hidden;">+%(num)03i+</span>
+<span id="tst%(num)i-" class="button%(result)s" onClick="hide('tst%(num)i')">-%(num)03i-</span>
+""" % t
+ else:
+ output += """
+<span id="tst%(num)i+" class="button%(result)s" onClick="show('tst%(num)i')">+%(num)03i+</span>
+<span id="tst%(num)i-" class="button%(result)s" onClick="hide('tst%(num)i')" style="POSITION: absolute; VISIBILITY: hidden;">-%(num)03i-</span>
+""" % t
+ if t.crc is not None:
+ output += "<span class=crc>%(crc)s</span>\n" % t
+ output += """%(name)s\n<span class="comment %(result)s" id="tst%(num)i" """ % t
+ if t.expand < 2:
+ output += """ style="POSITION: absolute; VISIBILITY: hidden;" """
+ output += """><br>%(comments)s
+<pre>
+%(output)s</pre></span>
+""" % t
+ output += "\n</ul>\n\n"
+
+ output += "</body></html>"
+ return output
+
+def campaign_to_LATEX(test_campaign):
+ output = r"""\documentclass{report}
+\usepackage{alltt}
+\usepackage{xcolor}
+\usepackage{a4wide}
+\usepackage{hyperref}
+
+\title{%(title)s}
+\date{%%s}
+
+\begin{document}
+\maketitle
+\tableofcontents
+
+\begin{description}
+\item[Passed:] %(passed)i
+\item[Failed:] %(failed)i
+\end{description}
+
+%(headcomments)s
+
+""" % test_campaign
+ output %= info_line(test_campaign)
+
+ for testset in test_campaign:
+ output += "\\chapter{%(name)s}\n\n%(comments)s\n\n" % testset
+ for t in testset:
+ if t.expand:
+ output += r"""\section{%(name)s}
+
+[%(num)03i] [%(result)s]
+
+%(comments)s
+\begin{alltt}
+%(output)s
+\end{alltt}
+
+""" % t
+
+ output += "\\end{document}\n"
+ return output
+
+
+
+#### USAGE ####
+
+def usage():
+ print("""Usage: UTscapy [-m module] [-f {text|ansi|HTML|LaTeX}] [-o output_file]
+ [-t testfile] [-k keywords [-k ...]] [-K keywords [-K ...]]
+ [-l] [-d|-D] [-F] [-q[q]] [-P preexecute_python_code]
+ [-s /path/to/scpay]
+-l\t\t: generate local files
+-F\t\t: expand only failed tests
+-d\t\t: dump campaign
+-D\t\t: dump campaign and stop
+-C\t\t: don't calculate CRC and SHA
+-s\t\t: path to scapy.py
+-q\t\t: quiet mode
+-qq\t\t: [silent mode]
+-n <testnum>\t: only tests whose numbers are given (eg. 1,3-7,12)
+-m <module>\t: additional module to put in the namespace
+-k <kw1>,<kw2>,...\t: include only tests with one of those keywords (can be used many times)
+-K <kw1>,<kw2>,...\t: remove tests with one of those keywords (can be used many times)
+-P <preexecute_python_code>
+""", file = sys.stderr)
+ raise SystemExit
+
+
+#### MAIN ####
+
+def main(argv):
+ import builtins
+
+ # Parse arguments
+
+ FORMAT = Format.ANSI
+ TESTFILE = sys.stdin
+ OUTPUTFILE = sys.stdout
+ LOCAL = 0
+ NUM=None
+ KW_OK = []
+ KW_KO = []
+ DUMP = 0
+ CRC = 1
+ ONLYFAILED = 0
+ VERB=2
+ PREEXEC=""
+ SCAPY="scapy"
+ MODULES = []
+ try:
+ opts = getopt.getopt(argv, "o:t:f:hln:m:k:K:DdCFqP:s:")
+ for opt,optarg in opts[0]:
+ if opt == "-h":
+ usage()
+ elif opt == "-F":
+ ONLYFAILED = 1
+ elif opt == "-q":
+ VERB -= 1
+ elif opt == "-D":
+ DUMP = 2
+ elif opt == "-d":
+ DUMP = 1
+ elif opt == "-C":
+ CRC = 0
+ elif opt == "-s":
+ SCAPY = optarg
+ elif opt == "-P":
+ PREEXEC += "\n"+optarg
+ elif opt == "-f":
+ try:
+ FORMAT = Format.from_string(optarg)
+ except KeyError as msg:
+ raise getopt.GetoptError("Unknown output format %s" % msg)
+ elif opt == "-t":
+ TESTFILE = open(optarg)
+ elif opt == "-o":
+ OUTPUTFILE = open(optarg, "w")
+ elif opt == "-l":
+ LOCAL = 1
+ elif opt == "-n":
+ NUM = []
+ for v in map( lambda x: x.strip(), optarg.split(",") ):
+ try:
+ NUM.append(int(v))
+ except ValueError:
+ v1,v2 = map(int, v.split("-"))
+ for vv in range(v1,v2+1):
+ NUM.append(vv)
+ elif opt == "-m":
+ MODULES.append(optarg)
+ elif opt == "-k":
+ KW_OK.append(optarg.split(","))
+ elif opt == "-K":
+ KW_KO.append(optarg.split(","))
+
+
+ try:
+ from scapy import all as scapy
+ except ImportError as e:
+ raise getopt.GetoptError("cannot import [%s]: %s" % (SCAPY,e))
+
+ for m in MODULES:
+ try:
+ mod = import_module(m)
+ builtins.__dict__.update(mod.__dict__)
+ except ImportError as e:
+ raise getopt.GetoptError("cannot import [%s]: %s" % (m,e))
+
+ except getopt.GetoptError as msg:
+ print("ERROR:",msg, file = sys.stderr)
+ raise SystemExit
+
+ autorun_func = {
+ Format.TEXT: scapy.autorun_get_text_interactive_session,
+ Format.ANSI: scapy.autorun_get_ansi_interactive_session,
+ Format.HTML: scapy.autorun_get_html_interactive_session,
+ Format.LATEX: scapy.autorun_get_latex_interactive_session,
+ Format.XUNIT: scapy.autorun_get_text_interactive_session,
+ }
+
+ # Parse test file
+ test_campaign = parse_campaign_file(TESTFILE)
+
+ # Report parameters
+ if PREEXEC:
+ test_campaign.preexec = PREEXEC
+
+
+ # Compute campaign CRC and SHA
+ if CRC:
+ compute_campaign_digests(test_campaign)
+
+ # Filter out unwanted tests
+ filter_tests_on_numbers(test_campaign, NUM)
+ for k in KW_OK:
+ filter_tests_keep_on_keywords(test_campaign, k)
+ for k in KW_KO:
+ filter_tests_remove_on_keywords(test_campaign, k)
+
+ remove_empty_testsets(test_campaign)
+
+
+ # Dump campaign
+ if DUMP:
+ dump_campaign(test_campaign)
+ if DUMP > 1:
+ sys.exit()
+
+ # Run tests
+ test_campaign.output_file = OUTPUTFILE
+ run_campaign(test_campaign, autorun_func[FORMAT], verb=VERB)
+
+ # Shrink passed
+ if ONLYFAILED:
+ for t in test_campaign.all_tests():
+ if t:
+ t.expand = 0
+ else:
+ t.expand = 2
+
+ # Generate report
+ if FORMAT == Format.TEXT:
+ output = campaign_to_TEXT(test_campaign)
+ elif FORMAT == Format.ANSI:
+ output = campaign_to_ANSI(test_campaign)
+ elif FORMAT == Format.HTML:
+ output = campaign_to_HTML(test_campaign, local=LOCAL)
+ elif FORMAT == Format.LATEX:
+ output = campaign_to_LATEX(test_campaign)
+ elif FORMAT == Format.XUNIT:
+ output = campaign_to_xUNIT(test_campaign)
+
+ OUTPUTFILE.write(output)
+ OUTPUTFILE.close()
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/tools/__init__.py b/scripts/external_libs/scapy-python3-0.18/scapy/tools/__init__.py
new file mode 100644
index 00000000..af6eec74
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/tools/__init__.py
@@ -0,0 +1,8 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Additional tools to be run separately
+"""
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/tools/check_asdis.py b/scripts/external_libs/scapy-python3-0.18/scapy/tools/check_asdis.py
new file mode 100644
index 00000000..3e45007f
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/tools/check_asdis.py
@@ -0,0 +1,103 @@
+#! /usr/bin/env python
+
+import getopt
+
+def usage():
+ print("""Usage: check_asdis -i <pcap_file> [-o <wrong_packets.pcap>]
+ -v increase verbosity
+ -d hexdiff packets that differ
+ -z compress output pcap
+ -a open pcap file in append mode""", file = sys.stderr)
+
+def main(argv):
+ PCAP_IN = None
+ PCAP_OUT = None
+ COMPRESS=False
+ APPEND=False
+ DIFF=False
+ VERBOSE=0
+ try:
+ opts=getopt.getopt(argv, "hi:o:azdv")
+ for opt, parm in opts[0]:
+ if opt == "-h":
+ usage()
+ raise SystemExit
+ elif opt == "-i":
+ PCAP_IN = parm
+ elif opt == "-o":
+ PCAP_OUT = parm
+ elif opt == "-v":
+ VERBOSE += 1
+ elif opt == "-d":
+ DIFF = True
+ elif opt == "-a":
+ APPEND = True
+ elif opt == "-z":
+ COMPRESS = True
+
+
+ if PCAP_IN is None:
+ raise getopt.GetoptError("Missing pcap file (-i)")
+
+ except getopt.GetoptError as e:
+ print("ERROR: %s" % e, file = sys.stderr)
+ raise SystemExit
+
+
+
+ from scapy.config import conf
+ from scapy.utils import RawPcapReader,RawPcapWriter,hexdiff
+ from scapy.layers import all
+
+
+ pcap = RawPcapReader(PCAP_IN)
+ pcap_out = None
+ if PCAP_OUT:
+ pcap_out = RawPcapWriter(PCAP_OUT, append=APPEND, gz=COMPRESS, linktype=pcap.linktype)
+ pcap_out._write_header(None)
+
+ LLcls = conf.l2types.get(pcap.linktype)
+ if LLcls is None:
+ print(" Unknown link type [%i]. Can't test anything!" % pcap.linktype, file = sys.stderr)
+ raise SystemExit
+
+
+ i=-1
+ differ=0
+ failed=0
+ for p1,meta in pcap:
+ i += 1
+ try:
+ p2d = LLcls(p1)
+ p2 = str(p2d)
+ except KeyboardInterrupt:
+ raise
+ except Exception as e:
+ print("Dissection error on packet %i" % i)
+ failed += 1
+ else:
+ if p1 == p2:
+ if VERBOSE >= 2:
+ print("Packet %i ok" % i)
+ continue
+ else:
+ print("Packet %i differs" % i)
+ differ += 1
+ if VERBOSE >= 1:
+ print(repr(p2d))
+ if DIFF:
+ hexdiff(p1,p2)
+ if pcap_out is not None:
+ pcap_out.write(p1)
+ i+=1
+ correct = i-differ-failed
+ print("%i total packets. %i ok, %i differed, %i failed. %.2f%% correct." % (i, correct, differ,
+ failed, i and 100.0*(correct)/i))
+
+
+if __name__ == "__main__":
+ import sys
+ try:
+ main(sys.argv[1:])
+ except KeyboardInterrupt:
+ print("Interrupted by user.", file = sys.stderr)
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/utils.py b/scripts/external_libs/scapy-python3-0.18/scapy/utils.py
new file mode 100644
index 00000000..252109bb
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/utils.py
@@ -0,0 +1,1054 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+General utility functions.
+"""
+
+import os,sys,socket,types
+import random,time
+import gzip,zlib
+import re,struct,array,stat
+import subprocess
+
+import warnings
+warnings.filterwarnings("ignore","tempnam",RuntimeWarning, __name__)
+
+from .config import conf
+from .data import MTU
+from .error import log_runtime,log_loading,log_interactive, Scapy_Exception
+from .base_classes import BasePacketList,BasePacket
+
+
+WINDOWS=sys.platform.startswith("win32")
+
+###########
+## Tools ##
+###########
+
+def get_temp_file(keep=False, autoext=""):
+ import tempfile
+ fd, fname = tempfile.mkstemp(suffix = ".scapy" + autoext)
+ os.close(fd)
+ if not keep:
+ conf.temp_files.append(fname)
+ return fname
+
+def str2bytes(x):
+ """Convert input argument to bytes"""
+ if type(x) is bytes:
+ return x
+ elif type(x) is str:
+ return bytes([ ord(i) for i in x ])
+ else:
+ return str2bytes(str(x))
+
+def chb(x):
+ if type(x) is str:
+ return x
+ else:
+ return chr(x)
+
+def orb(x):
+ if type(x) is str:
+ return ord(x)
+ else:
+ return x
+
+def any2b(x):
+ if type(x) is not str and type(x) is not bytes:
+ try:
+ x=bytes(x)
+ except:
+ x = str(x)
+ if type(x) is str:
+ x = bytes([ ord(i) for i in x ])
+ return x
+
+def sane_color(x):
+ r=""
+ for i in x:
+ j = orb(i)
+ if (j < 32) or (j >= 127):
+ r=r+conf.color_theme.not_printable(".")
+ else:
+ r=r+chb(i)
+ return r
+
+def sane(x):
+ r=""
+ for i in x:
+ if type(x) is str:
+ j = ord(i)
+ else:
+ j = i
+ if (j < 32) or (j >= 127):
+ r=r+"."
+ else:
+ r=r+chb(i)
+ return r
+
+def lhex(x):
+ if type(x) is int:
+ return hex(x)
+ elif type(x) is tuple:
+ return "(%s)" % ", ".join(map(lhex, x))
+ elif type(x) is list:
+ return "[%s]" % ", ".join(map(lhex, x))
+ else:
+ return x
+
+@conf.commands.register
+def hexdump(x):
+ if type(x) is not str and type(x) is not bytes:
+ try:
+ x=bytes(x)
+ except:
+ x = str(x)
+ l = len(x)
+ i = 0
+ while i < l:
+ print("%04x " % i,end = " ")
+ for j in range(16):
+ if i+j < l:
+ print("%02X" % orb(x[i+j]), end = " ")
+ else:
+ print(" ", end = " ")
+ if j%16 == 7:
+ print("", end = " ")
+ print(" ", end = " ")
+ print(sane_color(x[i:i+16]))
+ i += 16
+
+@conf.commands.register
+def linehexdump(x, onlyasc=0, onlyhex=0):
+ if type(x) is not str and type(x) is not bytes:
+ try:
+ x=bytes(x)
+ except:
+ x = str(x)
+ l = len(x)
+ if not onlyasc:
+ for i in range(l):
+ print("%02X" % orb(x[i]), end = " ")
+ print("", end = " ")
+ if not onlyhex:
+ print(sane_color(x))
+
+def chexdump(x):
+ if type(x) is not str and type(x) is not bytes:
+ try:
+ x=bytes(x)
+ except:
+ x = str(x)
+ print(", ".join(map(lambda x: "%#04x"%orb(x), x)))
+
+def hexstr(x, onlyasc=0, onlyhex=0):
+ s = []
+ if not onlyasc:
+ s.append(" ".join(map(lambda x:"%02x"%orb(x), x)))
+ if not onlyhex:
+ s.append(sane(x))
+ return " ".join(s)
+
+
+@conf.commands.register
+def hexdiff(x,y):
+ """Show differences between 2 binary strings"""
+ x=any2b(x)[::-1]
+ y=any2b(y)[::-1]
+ SUBST=1
+ INSERT=1
+ d={}
+ d[-1,-1] = 0,(-1,-1)
+ for j in range(len(y)):
+ d[-1,j] = d[-1,j-1][0]+INSERT, (-1,j-1)
+ for i in range(len(x)):
+ d[i,-1] = d[i-1,-1][0]+INSERT, (i-1,-1)
+
+ for j in range(len(y)):
+ for i in range(len(x)):
+ d[i,j] = min( ( d[i-1,j-1][0]+SUBST*(x[i] != y[j]), (i-1,j-1) ),
+ ( d[i-1,j][0]+INSERT, (i-1,j) ),
+ ( d[i,j-1][0]+INSERT, (i,j-1) ) )
+
+
+ backtrackx = []
+ backtracky = []
+ i=len(x)-1
+ j=len(y)-1
+ while not (i == j == -1):
+ i2,j2 = d[i,j][1]
+ backtrackx.append(x[i2+1:i+1])
+ backtracky.append(y[j2+1:j+1])
+ i,j = i2,j2
+
+
+
+ x = y = i = 0
+ colorize = { 0: lambda x:x,
+ -1: conf.color_theme.left,
+ 1: conf.color_theme.right }
+
+ dox=1
+ doy=0
+ l = len(backtrackx)
+ while i < l:
+ separate=0
+ linex = backtrackx[i:i+16]
+ liney = backtracky[i:i+16]
+ xx = sum(len(k) for k in linex)
+ yy = sum(len(k) for k in liney)
+ if dox and not xx:
+ dox = 0
+ doy = 1
+ if dox and linex == liney:
+ doy=1
+
+ if dox:
+ xd = y
+ j = 0
+ while not linex[j]:
+ j += 1
+ xd -= 1
+ print(colorize[doy-dox]("%04x" % xd), end = " ")
+ x += xx
+ line=linex
+ else:
+ print(" ", end = " ")
+ if doy:
+ yd = y
+ j = 0
+ while not liney[j]:
+ j += 1
+ yd -= 1
+ print(colorize[doy-dox]("%04x" % yd), end = " ")
+ y += yy
+ line=liney
+ else:
+ print(" ", end = " ")
+
+ print(" ", end = " ")
+
+ cl = ""
+ for j in range(16):
+ if i+j < l:
+ if line[j]:
+ col = colorize[(linex[j]!=liney[j])*(doy-dox)]
+ print(col("%02X" % line[j][0]), end = " ")
+ if linex[j]==liney[j]:
+ cl += sane_color(line[j])
+ else:
+ cl += col(sane(line[j]))
+ else:
+ print(" ", end = " ")
+ cl += " "
+ else:
+ print(" ", end = " ")
+ if j == 7:
+ print("", end = " ")
+
+
+ print(" ",cl)
+
+ if doy or not yy:
+ doy=0
+ dox=1
+ i += 16
+ else:
+ if yy:
+ dox=0
+ doy=1
+ else:
+ i += 16
+
+
+crc32 = zlib.crc32
+
+if struct.pack("H",1) == b"\x00\x01": # big endian
+ def checksum(pkt):
+ if len(pkt) % 2 == 1:
+ pkt += b"\0"
+ s = sum(array.array("H", pkt))
+ s = (s >> 16) + (s & 0xffff)
+ s += s >> 16
+ s = ~s
+ return s & 0xffff
+else:
+ def checksum(pkt):
+ if len(pkt) % 2 == 1:
+ pkt += b"\0"
+ s = sum(array.array("H", pkt))
+ s = (s >> 16) + (s & 0xffff)
+ s += s >> 16
+ s = ~s
+ return (((s>>8)&0xff)|s<<8) & 0xffff
+
+def warning(x):
+ log_runtime.warning(x)
+
+def mac2str(mac):
+ #return "".join(map(lambda x: chr(int(x,16)), mac.split(":")))
+ if type(mac) != str:
+ mac = mac.decode('ascii')
+ return b''.join([ bytes([int(i, 16)]) for i in mac.split(":") ])
+
+def str2mac(s):
+ return ("%02x:"*6)[:-1] % tuple(s)
+
+def strxor(x,y):
+ #return "".join(map(lambda i,j:chr(ord(i)^ord(j)),x,y))
+ return bytes([ i[0] ^ i[1] for i in zip(x,y) ] )
+
+# Workarround bug 643005 : https://sourceforge.net/tracker/?func=detail&atid=105470&aid=643005&group_id=5470
+try:
+ socket.inet_aton("255.255.255.255")
+except socket.error:
+ def inet_aton(x):
+ if x == "255.255.255.255":
+ return b"\xff"*4
+ else:
+ return socket.inet_aton(x)
+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 *
+ log_loading.info("inet_ntop/pton functions not found. Python IPv6 support not present")
+
+
+def atol(x):
+ try:
+ ip = inet_aton(x)
+ except socket.error:
+ ip = inet_aton(socket.gethostbyname(x))
+ return struct.unpack("!I", ip)[0]
+def ltoa(x):
+ return inet_ntoa(struct.pack("!I", x&0xffffffff))
+
+def itom(x):
+ return (0xffffffff00000000>>x)&0xffffffff
+
+def do_graph(graph,prog=None,format='png',target=None,string=False,options=None, figsize = (12, 12), **kargs):
+ """do_graph(graph, prog=conf.prog.dot, format="png",
+ target=None, options=None, string=False):
+ if networkx library is available and graph is instance of Graph, use networkx.draw
+
+ string: if not False, simply return the graph string
+ graph: GraphViz graph description
+ format: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option. Ignored if target==None
+ target: filename. If None uses matplotlib to display
+ prog: which graphviz program to use
+ options: options to be passed to prog"""
+
+ from scapy.arch import NETWORKX
+ if NETWORKX:
+ import networkx as nx
+
+ if NETWORKX and isinstance(graph, nx.Graph):
+ nx.draw(graph, with_labels = True, edge_color = '0.75', **kargs)
+ else: # otherwise use dot as in scapy 2.x
+ if string:
+ return graph
+ if prog is None:
+ prog = conf.prog.dot
+
+ if not target or not format:
+ format = 'png'
+ format = "-T %s" % format
+
+ p = subprocess.Popen("%s %s %s" % (prog,options or "", format or ""), shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
+ w, r = p.stdin, p.stdout
+ w.write(graph.encode('utf-8'))
+ w.close()
+ if target:
+ with open(target, 'wb') as f:
+ f.write(r.read())
+ else:
+ try:
+ import matplotlib.image as mpimg
+ import matplotlib.pyplot as plt
+ plt.figure(figsize = figsize)
+ plt.axis('off')
+ return plt.imshow(mpimg.imread(r, format = format), **kargs)
+
+ except ImportError:
+ warning('matplotlib.image required for interactive graph viewing. Use target option to write to a file')
+
+_TEX_TR = {
+ "{":"{\\tt\\char123}",
+ "}":"{\\tt\\char125}",
+ "\\":"{\\tt\\char92}",
+ "^":"\\^{}",
+ "$":"\\$",
+ "#":"\\#",
+ "~":"\\~",
+ "_":"\\_",
+ "&":"\\&",
+ "%":"\\%",
+ "|":"{\\tt\\char124}",
+ "~":"{\\tt\\char126}",
+ "<":"{\\tt\\char60}",
+ ">":"{\\tt\\char62}",
+ }
+
+def tex_escape(x):
+ s = ""
+ for c in x:
+ s += _TEX_TR.get(c,c)
+ return s
+
+def colgen(*lstcol,**kargs):
+ """Returns a generator that mixes provided quantities forever
+ trans: a function to convert the three arguments into a color. lambda x,y,z:(x,y,z) by default"""
+ if len(lstcol) < 2:
+ lstcol *= 2
+ trans = kargs.get("trans", lambda x,y,z: (x,y,z))
+ while 1:
+ for i in range(len(lstcol)):
+ for j in range(len(lstcol)):
+ for k in range(len(lstcol)):
+ if i != j or j != k or k != i:
+ yield trans(lstcol[(i+j)%len(lstcol)],lstcol[(j+k)%len(lstcol)],lstcol[(k+i)%len(lstcol)])
+
+def incremental_label(label="tag%05i", start=0):
+ while True:
+ yield label % start
+ start += 1
+
+#########################
+#### Enum management ####
+#########################
+
+class EnumElement:
+ _value=None
+ def __init__(self, key, value):
+ self._key = key
+ self._value = value
+ def __repr__(self):
+ return "<%s %s[%r]>" % (self.__dict__.get("_name", self.__class__.__name__), self._key, self._value)
+ def __getattr__(self, attr):
+ return getattr(self._value, attr)
+ def __str__(self):
+ return self._key
+ def __eq__(self, other):
+ #return self._value == int(other)
+ return self._value == hash(other)
+ def __hash__(self):
+ return self._value
+
+
+class Enum_metaclass(type):
+ element_class = EnumElement
+ def __new__(cls, name, bases, dct):
+ rdict={}
+ for k,v in dct.items():
+ if type(v) is int:
+ v = cls.element_class(k,v)
+ dct[k] = v
+ rdict[v] = k
+ dct["__rdict__"] = rdict
+ return super(Enum_metaclass, cls).__new__(cls, name, bases, dct)
+ def __getitem__(self, attr):
+ return self.__rdict__[attr]
+ def __contains__(self, val):
+ return val in self.__rdict__
+ def get(self, attr, val=None):
+ return self._rdict__.get(attr, val)
+ def __repr__(self):
+ return "<%s>" % self.__dict__.get("name", self.__name__)
+
+
+
+###################
+## Object saving ##
+###################
+
+
+def export_object(obj):
+ import dill as pickle
+ import base64
+ return base64.b64encode(gzip.zlib.compress(pickle.dumps(obj,4),9)).decode('utf-8')
+
+
+def import_object(obj):
+ import dill as pickle
+ import base64
+# if obj is None:
+# obj = sys.stdin.read().strip().encode('utf-8')
+ if obj is str:
+ obj = obj.strip().encode('utf-8')
+ return pickle.loads(gzip.zlib.decompress(base64.b64decode(obj)))
+
+
+def save_object(fname, obj):
+ import dill as pickle
+ pickle.dump(obj,gzip.open(fname,"wb"))
+
+def load_object(fname):
+ import dill as pickle
+ return pickle.load(gzip.open(fname,"rb"))
+
+@conf.commands.register
+def corrupt_bytes(s, p=0.01, n=None):
+ """Corrupt a given percentage or number of bytes from bytes"""
+ s = str2bytes(s)
+ s = array.array("B",s)
+ l = len(s)
+ if n is None:
+ n = max(1,int(l*p))
+ for i in random.sample(range(l), n):
+ s[i] = (s[i]+random.randint(1,255))%256
+ return s.tobytes()
+
+@conf.commands.register
+def corrupt_bits(s, p=0.01, n=None):
+ """Flip a given percentage or number of bits from bytes"""
+ s = str2bytes(s)
+ s = array.array("B",s)
+ l = len(s)*8
+ if n is None:
+ n = max(1, int(l*p))
+ for i in random.sample(range(l), n):
+ s[i//8] ^= 1 << (i%8)
+ return s.tobytes()
+
+
+#############################
+## pcap capture file stuff ##
+#############################
+
+@conf.commands.register
+def wrpcap(filename, pkt, *args, **kargs):
+ """Write a list of packets to a pcap file
+gz: set to 1 to save a gzipped capture
+linktype: force linktype value
+endianness: "<" or ">", force endianness"""
+ with PcapWriter(filename, *args, **kargs) as pcap:
+ pcap.write(pkt)
+
+@conf.commands.register
+def rdpcap(filename, count=-1):
+ """Read a pcap file and return a packet list
+count: read only <count> packets"""
+ with PcapReader(filename) as pcap:
+ return pcap.read_all(count=count)
+
+class RawPcapReader:
+ """A stateful pcap reader. Each packet is returned as bytes"""
+ def __init__(self, filename):
+ self.filename = filename
+ try:
+ if not stat.S_ISREG(os.stat(filename).st_mode):
+ raise IOError("GZIP detection works only for regular files")
+ self.f = gzip.open(filename,"rb")
+ magic = self.f.read(4)
+ except IOError:
+ self.f = open(filename,"rb")
+ magic = self.f.read(4)
+ if magic == b"\xa1\xb2\xc3\xd4": #big endian
+ self.endian = ">"
+ self.reader = _RawPcapOldReader(self.f, self.endian)
+ elif magic == b"\xd4\xc3\xb2\xa1": #little endian
+ self.endian = "<"
+ self.reader = _RawPcapOldReader(self.f, self.endian)
+ elif magic == b"\x0a\x0d\x0d\x0a": #PcapNG
+ self.reader = _RawPcapNGReader(self.f)
+ else:
+ raise Scapy_Exception("Not a pcap capture file (bad magic)")
+
+ def __enter__(self):
+ return self.reader
+
+ def __exit__(self, exc_type, exc_value, tracback):
+ self.close()
+
+ def __iter__(self):
+ return self.reader.__iter__()
+
+ def dispatch(self, callback):
+ """call the specified callback routine for each packet read
+
+ This is just a convienience function for the main loop
+ that allows for easy launching of packet processing in a
+ thread.
+ """
+ for p in self:
+ callback(p)
+
+ def read_all(self,count=-1):
+ """return a list of all packets in the pcap file
+ """
+ res=[]
+ while count != 0:
+ count -= 1
+ p = self.read_packet()
+ if p is None:
+ break
+ res.append(p)
+ return res
+
+ def recv(self, size=MTU):
+ """ Emulate a socket
+ """
+ return self.read_packet(size)[0]
+
+ def fileno(self):
+ return self.f.fileno()
+
+ def close(self):
+ return self.f.close()
+
+ def read_packet(self, size = MTU):
+ return self.reader.read_packet(size)
+
+def align32(n):
+ return n + (4 - n % 4) % 4
+
+class _RawPcapNGReader:
+ def __init__(self, filep):
+ self.filep = filep
+ self.filep.seek(0, 0)
+ self.endian = '<'
+ self.tsresol = 6
+ self.linktype = None
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """implement the iterator protocol on a set of packets in a pcapng file"""
+ pkt = self.read_packet()
+ if pkt == None:
+ raise StopIteration
+ return pkt
+
+ def read_packet(self, size = MTU):
+ while True:
+ buf = self._read_bytes(4, check = False)
+ if len(buf) == 0:
+ return None
+ elif len(buf) != 4:
+ raise IOError("PacketNGReader: Premature end of file")
+ block_type, = struct.unpack(self.endian + 'i', buf)
+ if block_type == 168627466: #Section Header b'\x0a\x0d\x0d\x0a'
+ self.read_section_header()
+ elif block_type == 1:
+ self.read_interface_description()
+ elif block_type == 6:
+ return self.read_enhanced_packet(size)
+ else:
+ warning("PacketNGReader: Unparsed block type %d/#%x" % (block_type, block_type))
+ self.read_generic_block()
+
+ def _read_bytes(self, n, check = True):
+ buf = self.filep.read(n)
+ if check and len(buf) < n:
+ raise IOError("PacketNGReader: Premature end of file")
+ return buf
+
+ def read_generic_block(self):
+ block_length, = struct.unpack(self.endian + 'I', self._read_bytes(4))
+ self._read_bytes(block_length - 12)
+ self._check_length(block_length)
+
+ def read_section_header(self):
+ buf = self._read_bytes(16)
+ if buf[4:8] == b'\x1a\x2b\x3c\x4d':
+ self.endian = '>'
+ elif buf[4:8] == b'\x4d\x3c\x2b\x1a':
+ self.endian = '<'
+ else:
+ raise Scapy_Exception('Cannot read byte order value')
+ block_length, _, major_version, minor_version, section_length = struct.unpack(self.endian + 'IIHHi', buf)
+ options = self._read_bytes(block_length - 24)
+ if options:
+ opt = self.parse_options(options)
+ for i in opt.keys():
+ if not i & (0b1 << 15):
+ warning("PcapNGReader: Unparsed option %d/#%x in section header" % (i, i))
+ self._check_length(block_length)
+
+ def read_interface_description(self):
+ buf = self._read_bytes(12)
+ block_length, self.linktype, reserved, self.snaplen = struct.unpack(self.endian + 'IHHI', buf)
+ options = self._read_bytes(block_length - 20)
+ if options:
+ opt = self.parse_options(options)
+ for i in opt.keys():
+ if 9 in opt:
+ self.tsresol = opt[9][0]
+ elif not i & (0b1 << 15):
+ warning("PcapNGReader: Unparsed option %d/#%x in enhanced packet block" % (i, i))
+ try:
+ self.LLcls = conf.l2types[self.linktype]
+ except KeyError:
+ warning("RawPcapReader: unknown LL type [%i]/[%#x]. Using Raw packets" % (self.linktype,self.linktype))
+ self.LLcls = conf.raw_layer
+
+ self._check_length(block_length)
+
+ def read_enhanced_packet(self, size = MTU):
+ buf = self._read_bytes(24)
+ block_length, interface, ts_high, ts_low, caplen, wirelen = struct.unpack(self.endian + 'IIIIII', buf)
+ timestamp = (ts_high << 32) + ts_low
+
+ pkt = self._read_bytes(align32(caplen))[:caplen]
+ options = self._read_bytes(block_length - align32(caplen) - 32)
+ if options:
+ opt = self.parse_options(options)
+ for i in opt.keys():
+ if not i & (0b1 << 15):
+ warning("PcapNGReader: Unparsed option %d/#%x in enhanced packet block" % (i, i))
+ self._check_length(block_length)
+ return pkt[:MTU], (self.parse_sec(timestamp), self.parse_usec(timestamp), wirelen)
+
+ def parse_sec(self, t):
+ if self.tsresol & 0b10000000:
+ return t >> self.tsresol
+ else:
+ return t // pow(10, self.tsresol)
+
+ def parse_usec(self, t):
+ if self.tsresol & 0b10000000:
+ return t & (1 << self.tsresol) - 1
+ else:
+ return t % pow(10, self.tsresol)
+
+ def parse_options(self, opt):
+ buf = opt
+ options = {}
+ while buf:
+ opt_type, opt_len = struct.unpack(self.endian + 'HH', buf[:4])
+ if opt_type == 0:
+ return options
+ options[opt_type] = buf[4:4 + opt_len]
+ buf = buf[ 4 + align32(opt_len):]
+ return options
+
+ def _check_length(self, block_length):
+ check_length, = struct.unpack(self.endian + 'I', self._read_bytes(4))
+ if check_length != block_length:
+ raise Scapy_Exception('Block length values are not equal')
+
+class _RawPcapOldReader:
+ def __init__(self, filep, endianness):
+ self.endian = endianness
+ self.f = filep
+ hdr = self.f.read(20)
+ if len(hdr)<20:
+ raise Scapy_Exception("Invalid pcap file (too short)")
+ vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)
+
+ self.linktype = linktype
+ try:
+ self.LLcls = conf.l2types[self.linktype]
+ except KeyError:
+ warning("RawPcapReader: unknown LL type [%i]/[%#x]. Using Raw packets" % (self.linktype,self.linktype))
+ self.LLcls = conf.raw_layer
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """implement the iterator protocol on a set of packets in a pcap file"""
+ pkt = self.read_packet()
+ if pkt == None:
+ raise StopIteration
+ return pkt
+
+ def read_packet(self, size=MTU):
+ """return a single packet read from the file
+ bytes, (sec, #timestamp seconds
+ usec, #timestamp microseconds
+ wirelen) #actual length of packet
+ returns None when no more packets are available
+ """
+ hdr = self.f.read(16)
+ if len(hdr) < 16:
+ return None
+ sec,usec,caplen,wirelen = struct.unpack(self.endian+"IIII", hdr)
+ s = self.f.read(caplen)[:MTU]
+ return s,(sec,usec,wirelen) # caplen = len(s)
+
+
+class PcapReader(RawPcapReader):
+ def __init__(self, filename):
+ RawPcapReader.__init__(self, filename)
+ def __enter__(self):
+ return self
+ def __iter__(self):
+ return self
+ def __next__(self):
+ """implement the iterator protocol on a set of packets in a pcap file"""
+ pkt = self.read_packet()
+ if pkt == None:
+ raise StopIteration
+ return pkt
+ def read_packet(self, size=MTU):
+ rp = RawPcapReader.read_packet(self,size)
+ if rp is None:
+ return None
+ s,(sec,usec,wirelen) = rp
+
+
+ try:
+ p = self.reader.LLcls(s)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if conf.debug_dissector:
+ raise
+ p = conf.raw_layer(s)
+ p.time = sec+0.000001*usec
+ p.wirelen = wirelen
+ return p
+
+ def read_all(self,count=-1):
+ res = RawPcapReader.read_all(self, count)
+ import scapy.plist
+ return scapy.plist.PacketList(res,name = os.path.basename(self.filename))
+ def recv(self, size=MTU):
+ return self.read_packet(size)
+
+
+class RawPcapWriter:
+ """A stream PCAP writer with more control than wrpcap()"""
+ def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False):
+ """
+ linktype: force linktype to a given value. If None, linktype is taken
+ from the first writter packet
+ gz: compress the capture on the fly
+ endianness: force an endianness (little:"<", big:">"). Default is native
+ append: append packets to the capture file instead of truncating it
+ sync: do not bufferize writes to the capture file
+ """
+
+ self.linktype = linktype
+ self.header_present = 0
+ self.append=append
+ self.gz = gz
+ self.endian = endianness
+ self.filename=filename
+ self.sync=sync
+ bufsz=4096
+ if sync:
+ bufsz=0
+
+ self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz)
+
+ def fileno(self):
+ return self.f.fileno()
+
+ def _write_header(self, pkt):
+ self.header_present=1
+
+ if self.append:
+ # Even if prone to race conditions, this seems to be
+ # safest way to tell whether the header is already present
+ # because we have to handle compressed streams that
+ # are not as flexible as basic files
+ g = [open,gzip.open][self.gz](self.filename,"rb")
+ if g.read(16):
+ return
+
+ self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b2c3d4,
+ 2, 4, 0, 0, MTU, self.linktype))
+ self.f.flush()
+
+
+ def write(self, pkt):
+ """accepts a either a single packet or a list of packets
+ to be written to the dumpfile
+ """
+ if not self.header_present:
+ self._write_header(pkt)
+ if type(pkt) is bytes:
+ self._write_packet(pkt)
+ else:
+ for p in pkt:
+ self._write_packet(p)
+
+ def _write_packet(self, packet, sec=None, usec=None, caplen=None, wirelen=None):
+ """writes a single packet to the pcap file
+ """
+ if caplen is None:
+ caplen = len(packet)
+ if wirelen is None:
+ wirelen = caplen
+ if sec is None or usec is None:
+ t=time.time()
+ it = int(t)
+ if sec is None:
+ sec = it
+ if usec is None:
+ usec = int(round((t-it)*1000000))
+ self.f.write(struct.pack(self.endian+"IIII", sec, usec, caplen, wirelen))
+ self.f.write(packet)
+ if self.gz and self.sync:
+ self.f.flush()
+
+ def flush(self):
+ return self.f.flush()
+
+ def close(self):
+ return self.f.close()
+
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_value, tracback):
+ self.flush()
+ self.close()
+
+
+class PcapWriter(RawPcapWriter):
+ def _write_header(self, pkt):
+ if self.linktype == None:
+ if type(pkt) is list or type(pkt) is tuple or isinstance(pkt,BasePacketList):
+ pkt = pkt[0]
+ try:
+ self.linktype = conf.l2types[pkt.__class__]
+ except KeyError:
+ warning("PcapWriter: unknown LL type for %s. Using type 1 (Ethernet)" % pkt.__class__.__name__)
+ self.linktype = 1
+ RawPcapWriter._write_header(self, pkt)
+
+ def _write_packet(self, packet):
+ try:
+ sec = int(packet.time)
+ usec = int(round((packet.time-sec)*1000000))
+ s = bytes(packet)
+ caplen = len(s)
+ RawPcapWriter._write_packet(self, s, sec, usec, caplen, caplen)
+ except Exception as e:
+ log_interactive.error(e)
+ def write(self, pkt):
+ """accepts a either a single packet or a list of packets
+ to be written to the dumpfile
+ """
+ if not self.header_present:
+ self._write_header(pkt)
+ if isinstance(pkt, BasePacket):
+ self._write_packet(pkt)
+ else:
+ for p in pkt:
+ self._write_packet(p)
+
+
+re_extract_hexcap = re.compile("^((0x)?[0-9a-fA-F]{2,}[ :\t]{,3}|) *(([0-9a-fA-F]{2} {,2}){,16})")
+
+def import_hexcap():
+ p = ""
+ try:
+ while 1:
+ l = raw_input().strip()
+ try:
+ p += re_extract_hexcap.match(l).groups()[2]
+ except:
+ warning("Parsing error during hexcap")
+ continue
+ except EOFError:
+ pass
+
+ p = p.replace(" ","")
+ return p.decode("hex")
+
+
+
+@conf.commands.register
+def wireshark(pktlist, *args):
+ """Run wireshark on a list of packets"""
+ fname = get_temp_file()
+ wrpcap(fname, pktlist)
+ subprocess.Popen([conf.prog.wireshark, "-r", fname] + list(args))
+
+@conf.commands.register
+def tdecode(pkt, *args):
+ """Run tshark to decode and display the packet. If no args defined uses -V"""
+ if not args:
+ args = [ "-V" ]
+ fname = get_temp_file()
+ wrpcap(fname,[pkt])
+ subprocess.call(["tshark", "-r", fname] + list(args))
+
+@conf.commands.register
+def hexedit(x):
+ """Run external hex editor on a packet or bytes. Set editor in conf.prog.hexedit"""
+ x = bytes(x)
+ fname = get_temp_file()
+ with open(fname,"wb") as f:
+ f.write(x)
+ subprocess.call([conf.prog.hexedit, fname])
+ with open(fname, "rb") as f:
+ x = f.read()
+ return x
+
+def __make_table(yfmtfunc, fmtfunc, endline, items, fxyz, sortx=None, sorty=None, seplinefunc=None):
+ vx = {}
+ vy = {}
+ vz = {}
+ vxf = {}
+ vyf = {}
+ max_length = 0
+ for record in items:
+ xx,yy,zz = map(str, fxyz(record[0], record[1]))
+ max_length = max(len(yy),max_length)
+ vx[xx] = max(vx.get(xx,0), len(xx), len(zz))
+ vy[yy] = None
+ vz[(xx,yy)] = zz
+
+ vxk = list(vx.keys())
+ vyk = list(vy.keys())
+ if sortx:
+ vxk.sort(sortx)
+ else:
+ try:
+ vxk.sort(key = lambda x: atol(x))
+ except:
+ vxk.sort()
+ if sorty:
+ vyk.sort(sorty)
+ else:
+ try:
+ vyk.sort(key = lambda x: atol(x))
+ except:
+ vyk.sort()
+
+
+ if seplinefunc:
+ sepline = seplinefunc(max_length, [vx[x] for x in vxk])
+ print(sepline)
+
+ fmt = yfmtfunc(max_length)
+ print(fmt % "", end = " ")
+ for x in vxk:
+ vxf[x] = fmtfunc(vx[x])
+ print(vxf[x] % x, end = " ")
+ print(endline)
+ if seplinefunc:
+ print(sepline)
+ for y in vyk:
+ print(fmt % y, end = " ")
+ for x in vxk:
+ print(vxf[x] % vz.get((x,y), "-"), end = " ")
+ print(endline)
+ if seplinefunc:
+ print(sepline)
+
+def make_table(*args, **kargs):
+ __make_table(lambda l:"%%-%is" % l, lambda l:"%%-%is" % l, "", *args, **kargs)
+
+def make_lined_table(*args, **kargs):
+ __make_table(lambda l:"%%-%is |" % l, lambda l:"%%-%is |" % l, "",
+ seplinefunc=lambda max_length,x:"+".join([ "-"*(y+2) for y in [max_length-1]+x+[-2]]),
+ *args, **kargs)
+
+def make_tex_table(*args, **kargs):
+ __make_table(lambda l: "%s", lambda l: "& %s", "\\\\", seplinefunc=lambda a,x:"\\hline", *args, **kargs)
+
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py b/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
new file mode 100644
index 00000000..d9112aa5
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
@@ -0,0 +1,823 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp>
+## Arnaud Ebalard <arnaud.ebalard@eads.net>
+
+"""
+Utility functions for IPv6.
+"""
+
+import itertools
+from .config import conf
+from .data import *
+from .utils import *
+
+def cmp_to_key(mycmp):
+ 'Convert a cmp= function into a key= function'
+ class K(object):
+ def __init__(self, obj, *args):
+ self.obj = obj
+ def __lt__(self, other):
+ return mycmp(self.obj, other.obj) < 0
+ def __gt__(self, other):
+ return mycmp(self.obj, other.obj) > 0
+ def __eq__(self, other):
+ return mycmp(self.obj, other.obj) == 0
+ def __le__(self, other):
+ return mycmp(self.obj, other.obj) <= 0
+ def __ge__(self, other):
+ return mycmp(self.obj, other.obj) >= 0
+ def __ne__(self, other):
+ return mycmp(self.obj, other.obj) != 0
+ return K
+
+
+
+def construct_source_candidate_set(addr, plen, laddr, loname):
+ """
+ Given all addresses assigned to a specific interface ('laddr' parameter),
+ this function returns the "candidate set" associated with 'addr/plen'.
+
+ Basically, the function filters all interface addresses to keep only those
+ that have the same scope as provided prefix.
+
+ This is on this list of addresses that the source selection mechanism
+ will then be performed to select the best source address associated
+ with some specific destination that uses this prefix.
+ """
+ def cset_sort(x,y):
+ x_global = 0
+ if in6_isgladdr(x):
+ x_global = 1
+ y_global = 0
+ if in6_isgladdr(y):
+ y_global = 1
+ res = y_global - x_global
+ if res != 0 or y_global != 1:
+ return res
+ # two global addresses: if one is native, it wins.
+ if not in6_isaddr6to4(x):
+ return -1;
+ return -res
+
+ cset = []
+ if in6_isgladdr(addr) or in6_isuladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_GLOBAL ]
+ elif in6_islladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL ]
+ elif in6_issladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL ]
+ elif in6_ismaddr(addr):
+ if in6_ismnladdr(addr):
+ cset = [('::1', 16, loname)]
+ elif in6_ismgladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_GLOBAL ]
+ elif in6_ismlladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL ]
+ elif in6_ismsladdr(addr):
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL ]
+ elif addr == '::' and plen == 0:
+ cset = [ x for x in laddr if x[1] == IPV6_ADDR_GLOBAL ]
+ cset = [ x[0] for x in cset ]
+ cset.sort(key = cmp_to_key(cset_sort)) # Sort with global addresses first
+ return cset
+
+def get_source_addr_from_candidate_set(dst, candidate_set):
+ """
+ This function implement a limited version of source address selection
+ 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.
+ """
+
+ 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 not candidate_set:
+ # Should not happen
+ return None
+
+ candidate_set.sort(key=cmp_to_key(rfc3484_cmp), reverse=True)
+
+ return candidate_set[0]
+
+
+def find_ifaddr2(addr, plen, laddr):
+ dstAddrType = in6_getAddrType(addr)
+
+ if dstAddrType == IPV6_ADDR_UNSPECIFIED: # Shouldn't happen as dst addr
+ return None
+
+ if dstAddrType == IPV6_ADDR_LOOPBACK:
+ return None
+
+ #tmp = [[]] + map(lambda (x,y,z): (in6_getAddrType(x), x, y, z), laddr)
+ tmp = [[]] + map(lambda a: (in6_getAddrType(a[0]), a[0], a[1], a[2]), laddr)
+ #def filterSameScope(l, t):
+ # if (t[0] & dstAddrType & IPV6_ADDR_SCOPE_MASK) == 0:
+ # l.append(t)
+ # return l
+ #sameScope = reduce(filterSameScope, tmp)
+ sameScope = itertools.chain(*[ t for t in tmp if (t[0] & dstAddrType & IPV6_ADDR_SCOPE_MASK) == 0 ])
+
+ l = len(sameScope)
+ if l == 1: # Only one address for our scope
+ return sameScope[0][1]
+
+ elif l > 1: # Muliple addresses for our scope
+ #stfAddr = filter(lambda x: x[0] & IPV6_ADDR_6TO4, sameScope)
+ stfAddr = [ x for x in sameScope if x[0] & IPV6_ADDR_6TO4 ]
+ #nativeAddr = filter(lambda x: not (x[0] & IPV6_ADDR_6TO4), sameScope)
+ nativeAddr = [ x for x in sameScope if not (x[0] & IPV6_ADDR_6TO4) ]
+
+ if not (dstAddrType & IPV6_ADDR_6TO4): # destination is not 6to4
+ if len(nativeAddr) != 0:
+ return nativeAddr[0][1]
+ return stfAddr[0][1]
+
+ else: # Destination is 6to4, try to use source 6to4 addr if any
+ if len(stfAddr) != 0:
+ return stfAddr[0][1]
+ return nativeAddr[0][1]
+ else:
+ return None
+
+# Think before modify it : for instance, FE::1 does exist and is unicast
+# there are many others like that.
+# TODO : integrate Unique Local Addresses
+def in6_getAddrType(addr):
+ naddr = inet_pton(socket.AF_INET6, addr)
+ paddr = inet_ntop(socket.AF_INET6, naddr) # normalize
+ addrType = 0
+ # _Assignable_ Global Unicast Address space
+ # is defined in RFC 3513 as those in 2000::/3
+ #if ((struct.unpack("B", naddr[0])[0] & 0xE0) == 0x20):
+ if (((naddr[0]) & 0xE0) == 0x20):
+ addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL)
+ if naddr[:2] == b' \x02': # Mark 6to4 @
+ addrType |= IPV6_ADDR_6TO4
+ elif naddr[0] == 0xff: # multicast
+ addrScope = paddr[3]
+ if addrScope == '2':
+ addrType = (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)
+ elif addrScope == 'e':
+ addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
+ else:
+ addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
+ elif ((naddr[0] == 0xfe) and ((int(paddr[2], 16) & 0xC) == 0x8)):
+ addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)
+ elif paddr == "::1":
+ addrType = IPV6_ADDR_LOOPBACK
+ elif paddr == "::":
+ addrType = IPV6_ADDR_UNSPECIFIED
+ else:
+ # Everything else is global unicast (RFC 3513)
+ # Even old deprecated (RFC3879) Site-Local addresses
+ addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)
+
+ return addrType
+
+def in6_mactoifaceid(mac, ulbit=None):
+ """
+ Compute the interface ID in modified EUI-64 format associated
+ to the Ethernet address provided as input.
+ value taken by U/L bit in the interface identifier is basically
+ the reversed value of that in given MAC address it can be forced
+ to a specific value by using optional 'ulbit' parameter.
+ """
+ if len(mac) != 17: return None
+ m = "".join(mac.split(':'))
+ if len(m) != 12: return None
+ first = int(m[0:2], 16)
+ if ulbit is None or not (ulbit == 0 or ulbit == 1):
+ ulbit = [1,'-',0][first & 0x02]
+ ulbit *= 2
+ first = "%.02x" % ((first & 0xFD) | ulbit)
+ eui64 = first + m[2:4] + ":" + m[4:6] + "FF:FE" + m[6:8] + ":" + m[8:12]
+ return eui64.upper()
+
+def in6_ifaceidtomac(ifaceid): # TODO: finish commenting function behavior
+ """
+ Extract the mac address from provided iface ID. Iface ID is provided
+ in printable format ("XXXX:XXFF:FEXX:XXXX", eventually compressed). None
+ is returned on error.
+ """
+ try:
+ ifaceid = inet_pton(socket.AF_INET6, "::"+ifaceid)[8:16]
+ except:
+ return None
+ if ifaceid[3:5] != b'\xff\xfe':
+ return None
+ first = struct.unpack("B", ifaceid[:1])[0]
+ ulbit = 2*[1,'-',0][first & 0x02]
+ first = struct.pack("B", ((first & 0xFD) | ulbit))
+ oui = first + ifaceid[1:3]
+ end = ifaceid[5:]
+ #l = map(lambda x: "%.02x" % struct.unpack("B", x)[0], list(oui+end))
+ l = map(lambda x: "%.02x" % x, list(oui+end))
+ return ":".join(l)
+
+def in6_addrtomac(addr):
+ """
+ Extract the mac address from provided address. None is returned
+ on error.
+ """
+ mask = inet_pton(socket.AF_INET6, "::ffff:ffff:ffff:ffff")
+ x = in6_and(mask, inet_pton(socket.AF_INET6, addr))
+ ifaceid = inet_ntop(socket.AF_INET6, x)[2:]
+ return in6_ifaceidtomac(ifaceid)
+
+def in6_addrtovendor(addr):
+ """
+ Extract the MAC address from a modified EUI-64 constructed IPv6
+ address provided and use the IANA oui.txt file to get the vendor.
+ The database used for the conversion is the one loaded by Scapy,
+ based on Wireshark (/usr/share/wireshark/wireshark/manuf) None
+ is returned on error, "UNKNOWN" if the vendor is unknown.
+ """
+ mac = in6_addrtomac(addr)
+ if mac is None:
+ return None
+
+ res = conf.manufdb._get_manuf(mac)
+ if len(res) == 17 and res.count(b':') != 5: # Mac address, i.e. unknown
+ res = "UNKNOWN"
+
+ return res
+
+def in6_getLinkScopedMcastAddr(addr, grpid=None, scope=2):
+ """
+ Generate a Link-Scoped Multicast Address as described in RFC 4489.
+ Returned value is in printable notation.
+
+ 'addr' parameter specifies the link-local address to use for generating
+ Link-scoped multicast address IID.
+
+ By default, the function returns a ::/96 prefix (aka last 32 bits of
+ returned address are null). If a group id is provided through 'grpid'
+ parameter, last 32 bits of the address are set to that value (accepted
+ formats : '\x12\x34\x56\x78' or '12345678' or 0x12345678 or 305419896).
+
+ By default, generated address scope is Link-Local (2). That value can
+ be modified by passing a specific 'scope' value as an argument of the
+ function. RFC 4489 only authorizes scope values <= 2. Enforcement
+ is performed by the function (None will be returned).
+
+ If no link-local address can be used to generate the Link-Scoped IPv6
+ Multicast address, or if another error occurs, None is returned.
+ """
+ if not scope in [0, 1, 2]:
+ return None
+ try:
+ if not in6_islladdr(addr):
+ return None
+ addr = inet_pton(socket.AF_INET6, addr)
+ except:
+ warning("in6_getLinkScopedMcastPrefix(): Invalid address provided")
+ return None
+
+ iid = addr[8:]
+
+ if grpid is None:
+ grpid = b'\x00\x00\x00\x00'
+ else:
+ if type(grpid) is str:
+ grpid = grpid.encode('ascii')
+ if type(grpid) is bytes:
+ if len(grpid) == 8:
+ try:
+ grpid = int(grpid, 16) & 0xffffffff
+ except:
+ warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided")
+ return None
+ elif len(grpid) == 4:
+ try:
+ grpid = struct.unpack("!I", grpid)[0]
+ except:
+ warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided")
+ return None
+ grpid = struct.pack("!I", grpid)
+
+ flgscope = struct.pack("B", 0xff & ((0x3 << 4) | scope))
+ plen = b'\xff'
+ res = b'\x00'
+ a = b'\xff' + flgscope + res + plen + iid + grpid
+
+ return inet_ntop(socket.AF_INET6, a)
+
+def in6_get6to4Prefix(addr):
+ """
+ Returns the /48 6to4 prefix associated with provided IPv4 address
+ On error, None is returned. No check is performed on public/private
+ status of the address
+ """
+ try:
+ addr = inet_pton(socket.AF_INET, addr)
+ addr = inet_ntop(socket.AF_INET6, b'\x20\x02'+addr+b'\x00'*10)
+ except:
+ return None
+ return addr
+
+def in6_6to4ExtractAddr(addr):
+ """
+ Extract IPv4 address embbeded in 6to4 address. Passed address must be
+ a 6to4 addrees. None is returned on error.
+ """
+ try:
+ addr = inet_pton(socket.AF_INET6, addr)
+ except:
+ return None
+ if addr[:2] != b" \x02":
+ return None
+ return inet_ntop(socket.AF_INET, addr[2:6])
+
+
+def in6_getLocalUniquePrefix():
+ """
+ Returns a pseudo-randomly generated Local Unique prefix. Function
+ follows recommandation of Section 3.2.2 of RFC 4193 for prefix
+ generation.
+ """
+ # Extracted from RFC 1305 (NTP) :
+ # NTP timestamps are represented as a 64-bit unsigned fixed-point number,
+ # in seconds relative to 0h on 1 January 1900. The integer part is in the
+ # first 32 bits and the fraction part in the last 32 bits.
+
+ # epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0)
+ # x = time.time()
+ # from time import gmtime, strftime, gmtime, mktime
+ # delta = mktime(gmtime(0)) - mktime(self.epoch)
+ # x = x-delta
+
+ tod = time.time() # time of day. Will bother with epoch later
+ i = int(tod)
+ j = int((tod - i)*(2**32))
+ tod = struct.pack("!II", i,j)
+ # TODO: Add some check regarding system address gathering
+ rawmac = get_if_raw_hwaddr(conf.iface6)
+ mac = b":".join(map(lambda x: b"%.02x" % ord(x), list(rawmac)))
+ # construct modified EUI-64 ID
+ eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(mac))[8:]
+ import sha
+ globalid = sha.new(tod+eui64).digest()[:5]
+ return inet_ntop(socket.AF_INET6, b'\xfd' + globalid + b'\x00'*10)
+
+def in6_getRandomizedIfaceId(ifaceid, previous=None):
+ """
+ Implements the interface ID generation algorithm described in RFC 3041.
+ The function takes the Modified EUI-64 interface identifier generated
+ as described in RFC 4291 and an optional previous history value (the
+ first element of the output of this function). If no previous interface
+ identifier is provided, a random one is generated. The function returns
+ a tuple containing the randomized interface identifier and the history
+ value (for possible future use). Input and output values are provided in
+ a "printable" format as depicted below.
+
+ ex:
+
+ >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3')
+ ('4c61:76ff:f46a:a5f3', 'd006:d540:db11:b092')
+
+ >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3',
+ previous='d006:d540:db11:b092')
+ ('fe97:46fe:9871:bd38', 'eeed:d79c:2e3f:62e')
+ """
+
+ s = []
+ if previous is None:
+ #d = b"".join(map(chr, range(256)))
+ d = list(range(256))
+ for i in range(8):
+ s.append(random.choice(d))
+ s = bytes(s)
+ previous = s
+ s = inet_pton(socket.AF_INET6, "::"+ifaceid)[8:] + previous
+ import hashlib
+ s = hashlib.md5(s).digest()
+ s1,s2 = s[:8],s[8:]
+ s1 = bytes([(s1[0]) | 0x04]) + s1[1:]
+ s1 = inet_ntop(socket.AF_INET6, b"\xff"*8 + s1)[20:]
+ s2 = inet_ntop(socket.AF_INET6, b"\xff"*8 + s2)[20:]
+ return (s1, s2)
+
+
+_rfc1924map = [ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E',
+ 'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
+ 'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i',
+ 'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x',
+ 'y','z','!','#','$','%','&','(',')','*','+','-',';','<','=',
+ '>','?','@','^','_','`','{','|','}','~' ]
+
+def in6_ctop(addr):
+ """
+ Convert an IPv6 address in Compact Representation Notation
+ (RFC 1924) to printable representation ;-)
+ Returns None on error.
+ """
+ #if len(addr) != 20 or not reduce(lambda x,y: x and y, map(lambda x: x in _rfc1924map, addr)):
+ if len(addr) != 20 or not all(map(lambda x: x in _rfc1924map, addr)):
+ return None
+ i = 0
+ for c in addr:
+ j = _rfc1924map.index(c)
+ i = 85*i + j
+ res = []
+ for j in range(4):
+ res.append(struct.pack("!I", i%2**32))
+ i = i//(2**32)
+ res.reverse()
+ return inet_ntop(socket.AF_INET6, b"".join(res))
+
+def in6_ptoc(addr):
+ """
+ Converts an IPv6 address in printable representation to RFC
+ 1924 Compact Representation ;-)
+ Returns None on error.
+ """
+ try:
+ d=struct.unpack("!IIII", inet_pton(socket.AF_INET6, addr))
+ except:
+ return None
+ res = 0
+ m = [2**96, 2**64, 2**32, 1]
+ for i in range(4):
+ res += d[i]*m[i]
+ rem = res
+ res = []
+ while rem:
+ res.append(_rfc1924map[rem%85])
+ rem = rem//85
+ res.reverse()
+ return "".join(res)
+
+
+def in6_isaddr6to4(x):
+ """
+ Return True if provided address (in printable format) is a 6to4
+ address (being in 2002::/16).
+ """
+ x = inet_pton(socket.AF_INET6, x)
+ return x[:2] == ' \x02'
+
+conf.teredoPrefix = "2001::" # old one was 3ffe:831f (it is a /32)
+conf.teredoServerPort = 3544
+
+def in6_isaddrTeredo(x):
+ """
+ Return True if provided address is a Teredo, meaning it is under
+ the /32 conf.teredoPrefix prefix value (by default, 2001::).
+ Otherwise, False is returned. Address must be passed in printable
+ format.
+ """
+ our = inet_pton(socket.AF_INET6, x)[0:4]
+ teredoPrefix = inet_pton(socket.AF_INET6, conf.teredoPrefix)[0:4]
+ return teredoPrefix == our
+
+def teredoAddrExtractInfo(x):
+ """
+ Extract information from a Teredo address. Return value is
+ a 4-tuple made of IPv4 address of Teredo server, flag value (int),
+ mapped address (non obfuscated) and mapped port (non obfuscated).
+ No specific checks are performed on passed address.
+ """
+ addr = inet_pton(socket.AF_INET6, x)
+ server = inet_ntop(socket.AF_INET, addr[4:8])
+ flag = struct.unpack("!H",addr[8:10])[0]
+ mappedport = struct.unpack("!H",strxor(addr[10:12],b'\xff'*2))[0]
+ mappedaddr = inet_ntop(socket.AF_INET, strxor(addr[12:16],b'\xff'*4))
+ return server, flag, mappedaddr, mappedport
+
+def in6_iseui64(x):
+ """
+ Return True if provided address has an interface identifier part
+ created in modified EUI-64 format (meaning it matches *::*:*ff:fe*:*).
+ Otherwise, False is returned. Address must be passed in printable
+ format.
+ """
+ eui64 = inet_pton(socket.AF_INET6, '::ff:fe00:0')
+ x = in6_and(inet_pton(socket.AF_INET6, x), eui64)
+ return x == eui64
+
+def in6_isanycast(x): # RFC 2526
+ if in6_iseui64(x):
+ s = '::fdff:ffff:ffff:ff80'
+ packed_x = inet_pton(socket.AF_INET6, x)
+ packed_s = inet_pton(socket.AF_INET6, s)
+ x_and_s = in6_and(packed_x, packed_s)
+ return x_and_s == packed_s
+ else:
+ # not EUI-64
+ #| n bits | 121-n bits | 7 bits |
+ #+---------------------------------+------------------+------------+
+ #| subnet prefix | 1111111...111111 | anycast ID |
+ #+---------------------------------+------------------+------------+
+ # | interface identifier field |
+ warning('in6_isanycast(): TODO not EUI-64')
+ return 0
+
+def _in6_bitops(a1, a2, operator=0):
+ a1 = struct.unpack('4I', a1)
+ a2 = struct.unpack('4I', a2)
+ fop = [ lambda x,y: x | y,
+ lambda x,y: x & y,
+ lambda x,y: x ^ y
+ ]
+ ret = map(fop[operator%len(fop)], a1, a2)
+ t = b''.join(map(lambda x: struct.pack('I', x), ret))
+ return t
+
+def in6_or(a1, a2):
+ """
+ Provides a bit to bit OR of provided addresses. They must be
+ passed in network format. Return value is also an IPv6 address
+ in network format.
+ """
+ return _in6_bitops(a1, a2, 0)
+
+def in6_and(a1, a2):
+ """
+ Provides a bit to bit AND of provided addresses. They must be
+ passed in network format. Return value is also an IPv6 address
+ in network format.
+ """
+ return _in6_bitops(a1, a2, 1)
+
+def in6_xor(a1, a2):
+ """
+ Provides a bit to bit XOR of provided addresses. They must be
+ passed in network format. Return value is also an IPv6 address
+ in network format.
+ """
+ return _in6_bitops(a1, a2, 2)
+
+def in6_cidr2mask(m):
+ """
+ Return the mask (bitstring) associated with provided length
+ value. For instance if function is called on 48, return value is
+ '\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.
+
+ """
+ if m > 128 or m < 0:
+ raise Scapy_Exception("value provided to in6_cidr2mask outside [0, 128] domain (%d)" % m)
+
+ t = []
+ for i in range(0, 4):
+ t.append(max(0, 2**32 - 2**(32-min(32, m))))
+ m -= 32
+
+ return b"".join([ struct.pack('!I', i) for i in t ])
+
+def in6_getnsma(a):
+ """
+ Return link-local solicited-node multicast address for given
+ address. Passed address must be provided in network format.
+ Returned value is also in network format.
+ """
+
+ r = in6_and(a, inet_pton(socket.AF_INET6, '::ff:ffff'))
+ r = in6_or(inet_pton(socket.AF_INET6, 'ff02::1:ff00:0'), r)
+ return r
+
+def in6_getnsmac(a): # return multicast Ethernet address associated with multicast v6 destination
+ """
+ Return the multicast mac address associated with provided
+ IPv6 address. Passed address must be in network format.
+ """
+
+ a = struct.unpack('16B', a)[-4:]
+ mac = '33:33:'
+ mac += (':'.join(map(lambda x: '%.2x' %x, a)))
+ return mac
+
+def in6_getha(prefix):
+ """
+ Return the anycast address associated with all home agents on a given
+ subnet.
+ """
+ r = in6_and(inet_pton(socket.AF_INET6, prefix), in6_cidr2mask(64))
+ r = in6_or(r, inet_pton(socket.AF_INET6, '::fdff:ffff:ffff:fffe'))
+ return inet_ntop(socket.AF_INET6, r)
+
+def in6_ptop(s):
+ """
+ Normalizes IPv6 addresses provided in printable format, returning the
+ same address in printable format. (2001:0db8:0:0::1 -> 2001:db8::1)
+ """
+ return inet_ntop(socket.AF_INET6, inet_pton(socket.AF_INET6, s))
+
+def in6_isincluded(addr, prefix, plen):
+ """
+ Returns True when 'addr' belongs to prefix/plen. False otherwise.
+ """
+ temp = inet_pton(socket.AF_INET6, addr)
+ pref = in6_cidr2mask(plen)
+ zero = inet_pton(socket.AF_INET6, prefix)
+ return zero == in6_and(temp, pref)
+
+def in6_isdocaddr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ 2001:db8::/32 address space reserved for documentation (as defined
+ in RFC 3849).
+ """
+ return in6_isincluded(s, '2001:db8::', 32)
+
+def in6_islladdr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ _allocated_ link-local unicast address space (fe80::/10)
+ """
+ return in6_isincluded(s, 'fe80::', 10)
+
+def in6_issladdr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ _allocated_ site-local address space (fec0::/10). This prefix has
+ been deprecated, address being now reserved by IANA. Function
+ will remain for historic reasons.
+ """
+ return in6_isincluded(s, 'fec0::', 10)
+
+def in6_isuladdr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ Unique local address space (fc00::/7).
+ """
+ return in6_isincluded(s, 'fc00::', 7)
+
+# TODO : we should see the status of Unique Local addresses against
+# global address space.
+# Up-to-date information is available through RFC 3587.
+# We should review function behavior based on its content.
+def in6_isgladdr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ _allocated_ global address space (2000::/3). Please note that,
+ Unique Local addresses (FC00::/7) are not part of global address
+ space, and won't match.
+ """
+ return in6_isincluded(s, '2000::', 3)
+
+def in6_ismaddr(s):
+ """
+ Returns True if provided address in printable format belongs to
+ allocated Multicast address space (ff00::/8).
+ """
+ return in6_isincluded(s, 'ff00::', 8)
+
+def in6_ismnladdr(s):
+ """
+ Returns True if address belongs to node-local multicast address
+ space (ff01::/16) as defined in RFC
+ """
+ return in6_isincluded(s, 'ff01::', 16)
+
+def in6_ismgladdr(s):
+ """
+ Returns True if address belongs to global multicast address
+ space (ff0e::/16).
+ """
+ return in6_isincluded(s, 'ff0e::', 16)
+
+def in6_ismlladdr(s):
+ """
+ Returns True if address belongs to link-local multicast address
+ space (ff02::/16)
+ """
+ return in6_isincluded(s, 'ff02::', 16)
+
+def in6_ismsladdr(s):
+ """
+ Returns True if address belongs to site-local multicast address
+ space (ff05::/16). Site local address space has been deprecated.
+ Function remains for historic reasons.
+ """
+ return in6_isincluded(s, 'ff05::', 16)
+
+def in6_isaddrllallnodes(s):
+ """
+ Returns True if address is the link-local all-nodes multicast
+ address (ff02::1).
+ """
+ return (inet_pton(socket.AF_INET6, "ff02::1") ==
+ inet_pton(socket.AF_INET6, s))
+
+def in6_isaddrllallservers(s):
+ """
+ Returns True if address is the link-local all-servers multicast
+ address (ff02::2).
+ """
+ return (inet_pton(socket.AF_INET6, "ff02::2") ==
+ inet_pton(socket.AF_INET6, s))
+
+def in6_getscope(addr):
+ """
+ Returns the scope of the address.
+ """
+ if in6_isgladdr(addr) or in6_isuladdr(addr):
+ scope = IPV6_ADDR_GLOBAL
+ elif in6_islladdr(addr):
+ scope = IPV6_ADDR_LINKLOCAL
+ elif in6_issladdr(addr):
+ scope = IPV6_ADDR_SITELOCAL
+ elif in6_ismaddr(addr):
+ if in6_ismgladdr(addr):
+ scope = IPV6_ADDR_GLOBAL
+ elif in6_ismlladdr(addr):
+ scope = IPV6_ADDR_LINKLOCAL
+ elif in6_ismsladdr(addr):
+ scope = IPV6_ADDR_SITELOCAL
+ elif in6_ismnladdr(addr):
+ scope = IPV6_ADDR_LOOPBACK
+ else:
+ scope = -1
+ elif addr == '::1':
+ scope = IPV6_ADDR_LOOPBACK
+ else:
+ scope = -1
+ return scope
+
+def in6_get_common_plen(a, b):
+ """
+ Return common prefix length of IPv6 addresses a and b.
+ """
+ def matching_bits(byte1, byte2):
+ for i in range(8):
+ cur_mask = 0x80 >> i
+ if (byte1 & cur_mask) != (byte2 & cur_mask):
+ return i
+ return 8
+
+ tmpA = inet_pton(socket.AF_INET6, a)
+ tmpB = inet_pton(socket.AF_INET6, b)
+ for i in range(16):
+ #mbits = matching_bits(ord(tmpA[i]), ord(tmpB[i]))
+ mbits = matching_bits((tmpA[i]), (tmpB[i]))
+ if mbits != 8:
+ return 8*i + mbits
+ return 128
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/volatile.py b/scripts/external_libs/scapy-python3-0.18/scapy/volatile.py
new file mode 100644
index 00000000..ed5c26e4
--- /dev/null
+++ b/scripts/external_libs/scapy-python3-0.18/scapy/volatile.py
@@ -0,0 +1,685 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more informations
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+"""
+Fields that hold random numbers.
+"""
+
+import random,time,math
+from .base_classes import Net
+from .utils import corrupt_bits,corrupt_bytes
+
+####################
+## Random numbers ##
+####################
+
+
+class RandomEnumeration:
+ """iterate through a sequence in random order.
+ When all the values have been drawn, if forever=1, the drawing is done again.
+ If renewkeys=0, the draw will be in the same order, guaranteeing that the same
+ number will be drawn in not less than the number of integers of the sequence"""
+ def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0):
+ self.forever = forever
+ self.renewkeys = renewkeys
+ self.inf = inf
+ self.rnd = random.Random(seed)
+ self.sbox_size = 256
+
+ self.top = sup-inf+1
+
+ n=0
+ while (1<<n) < self.top:
+ n += 1
+ self.n =n
+
+ self.fs = min(3,(n+1)//2)
+ self.fsmask = 2**self.fs-1
+ self.rounds = max(self.n,3)
+ self.turns = 0
+ self.i = 0
+
+ def __iter__(self):
+ return self
+ def __next__(self):
+ while True:
+ if self.turns == 0 or (self.i == 0 and self.renewkeys):
+ self.cnt_key = self.rnd.randint(0,2**self.n-1)
+ self.sbox = [self.rnd.randint(0,self.fsmask) for k in range(self.sbox_size)]
+ self.turns += 1
+ while self.i < 2**self.n:
+ ct = self.i^self.cnt_key
+ self.i += 1
+ for k in range(self.rounds): # Unbalanced Feistel Network
+ lsb = ct & self.fsmask
+ ct >>= self.fs
+ lsb ^= self.sbox[ct%self.sbox_size]
+ ct |= lsb << (self.n-self.fs)
+
+ if ct < self.top:
+ return self.inf+ct
+ self.i = 0
+ if not self.forever:
+ raise StopIteration
+
+class _MetaVolatile(type):
+ def __init__(cls, name, bases, dct):
+ def special_gen(special_method):
+ def special_wrapper(self):
+ return getattr(getattr(self, "_fix")(), special_method)
+ return special_wrapper
+
+ #This is from scapy2 code. Usage places should be identified and fixed as there is no more __cmp__ in python3
+ # if attr == "__cmp__":
+ # x = self._fix()
+ # def cmp2(y,x=x):
+ # if type(x) != type(y):
+ # return -1
+ # return x.__cmp__(y)
+ # return cmp2
+
+ type.__init__(cls, name, bases, dct)
+ for i in ["__int__", "__repr__", "__str__", "__index__", "__add__", "__radd__", "__bytes__","__mul__","__rmul__"]:
+ setattr(cls, i, property(special_gen(i)))
+
+
+class VolatileValue(metaclass = _MetaVolatile):
+ def __repr__(self):
+ return "<%s>" % self.__class__.__name__
+ def __getattr__(self, attr):
+ if attr == "__setstate__":
+ raise AttributeError("__setstate__")
+ return getattr(self._fix(),attr)
+ def _fix(self):
+ return None
+
+
+class RandField(VolatileValue):
+ pass
+
+class RandNum(RandField):
+ """Instances evaluate to random integers in selected range"""
+ min = 0
+ max = 0
+ def __init__(self, min, max):
+ self.min = min
+ self.max = max
+ def _fix(self):
+ return random.randrange(self.min, self.max+1)
+
+class RandNumGamma(RandField):
+ def __init__(self, alpha, beta):
+ self.alpha = alpha
+ self.beta = beta
+ def _fix(self):
+ return int(round(random.gammavariate(self.alpha, self.beta)))
+
+class RandNumGauss(RandField):
+ def __init__(self, mu, sigma):
+ self.mu = mu
+ self.sigma = sigma
+ def _fix(self):
+ return int(round(random.gauss(self.mu, self.sigma)))
+
+class RandNumExpo(RandField):
+ def __init__(self, lambd, base=0):
+ self.lambd = lambd
+ self.base = base
+ def _fix(self):
+ return self.base+int(round(random.expovariate(self.lambd)))
+
+class RandEnum(RandNum):
+ """Instances evaluate to integer sampling without replacement from the given interval"""
+ def __init__(self, min, max):
+ self.seq = RandomEnumeration(min,max)
+ def _fix(self):
+ return next(self.seq)
+
+class RandByte(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, 0, 2**8-1)
+
+class RandSByte(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, -2**7, 2**7-1)
+
+class RandShort(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, 0, 2**16-1)
+
+class RandSShort(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, -2**15, 2**15-1)
+
+class RandInt(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, 0, 2**32-1)
+
+class RandSInt(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, -2**31, 2**31-1)
+
+class RandLong(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, 0, 2**64-1)
+
+class RandSLong(RandNum):
+ def __init__(self):
+ RandNum.__init__(self, -2**63, 2**63-1)
+
+class RandEnumByte(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, 0, 2**8-1)
+
+class RandEnumSByte(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, -2**7, 2**7-1)
+
+class RandEnumShort(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, 0, 2**16-1)
+
+class RandEnumSShort(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, -2**15, 2**15-1)
+
+class RandEnumInt(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, 0, 2**32-1)
+
+class RandEnumSInt(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, -2**31, 2**31-1)
+
+class RandEnumLong(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, 0, 2**64-1)
+
+class RandEnumSLong(RandEnum):
+ def __init__(self):
+ RandEnum.__init__(self, -2**63, 2**63-1)
+
+class RandChoice(RandField):
+ def __init__(self, *args):
+ if not args:
+ raise TypeError("RandChoice needs at least one choice")
+ self._choice = args
+ def _fix(self):
+ return random.choice(self._choice)
+
+class RandString(RandField):
+ def __init__(self, size=None, chars=b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"):
+ if size is None:
+ size = RandNumExpo(0.01)
+ self.size = size
+ self.chars = chars
+ def _fix(self):
+ s = []
+ for i in range(self.size):
+ s.append(random.choice(self.chars))
+ return bytes(s)
+
+class RandBin(RandString):
+ def __init__(self, size=None):
+ #RandString.__init__(self, size, b"".join(map(chr,range(256))))
+ RandString.__init__(self, size, b"".join([bytes([i]) for i in range(256)]))
+
+
+class RandTermString(RandString):
+ def __init__(self, size, term):
+ #RandString.__init__(self, size, b"".join(map(chr,range(1,256))))
+ RandString.__init__(self, size, bytes([i for i in range(1,256)]))
+ self.term = term
+ def _fix(self):
+ return RandString._fix(self)+self.term
+
+
+class RandIP(RandString):
+ def __init__(self, iptemplate="0.0.0.0/0"):
+ self.ip = Net(iptemplate)
+ def _fix(self):
+ return self.ip.choice()
+
+class RandMAC(RandString):
+ def __init__(self, template="*"):
+ template += ":*:*:*:*:*"
+ template = template.split(":")
+ self.mac = ()
+ for i in range(6):
+ if template[i] == "*":
+ v = RandByte()
+ elif "-" in template[i]:
+ x,y = template[i].split("-")
+ v = RandNum(int(x,16), int(y,16))
+ else:
+ v = int(template[i],16)
+ self.mac += (v,)
+ def _fix(self):
+ return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac
+
+class RandIP6(RandString):
+ def __init__(self, ip6template="**"):
+ self.tmpl = ip6template
+ self.sp = self.tmpl.split(":")
+ for i,v in enumerate(self.sp):
+ if not v or v == "**":
+ continue
+ if "-" in v:
+ a,b = v.split("-")
+ elif v == "*":
+ a=b=""
+ else:
+ a=b=v
+
+ if not a:
+ a = "0"
+ if not b:
+ b = "ffff"
+ if a==b:
+ self.sp[i] = int(a,16)
+ else:
+ self.sp[i] = RandNum(int(a,16), int(b,16))
+ self.variable = "" in self.sp
+ self.multi = self.sp.count("**")
+ def _fix(self):
+ done = 0
+ nbm = self.multi
+ ip = []
+ for i,n in enumerate(self.sp):
+ if n == "**":
+ nbm -= 1
+ remain = 8-(len(self.sp)-i-1)-len(ip)+nbm
+ if "" in self.sp:
+ remain += 1
+ if nbm or self.variable:
+ remain = random.randint(0,remain)
+ for j in range(remain):
+ ip.append("%04x" % random.randint(0,65535))
+ elif n == 0:
+ ip.append("0")
+ elif not n:
+ ip.append("")
+ else:
+ ip.append("%04x" % n)
+ if len(ip) == 9:
+ ip.remove("")
+ if ip[-1] == "":
+ ip[-1] = 0
+ return ":".join(ip)
+
+class RandOID(RandString):
+ def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)):
+ self.ori_fmt = fmt
+ if fmt is not None:
+ fmt = fmt.split(".")
+ for i in range(len(fmt)):
+ if "-" in fmt[i]:
+ fmt[i] = tuple(map(int, fmt[i].split("-")))
+ self.fmt = fmt
+ self.depth = depth
+ self.idnum = idnum
+ def __repr__(self):
+ if self.ori_fmt is None:
+ return "<%s>" % self.__class__.__name__
+ else:
+ return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt)
+ def _fix(self):
+ if self.fmt is None:
+ return ".".join(map(str, [self.idnum for i in range(1+self.depth)]))
+ else:
+ oid = []
+ for i in self.fmt:
+ if i == "*":
+ oid.append(str(self.idnum))
+ elif i == "**":
+ oid += map(str, [self.idnum for i in range(1+self.depth)])
+ elif type(i) is tuple:
+ oid.append(str(random.randrange(*i)))
+ else:
+ oid.append(i)
+ return ".".join(oid)
+
+
+class RandRegExp(RandField):
+ def __init__(self, regexp, lambda_=0.3,):
+ self._regexp = regexp
+ self._lambda = lambda_
+
+ @staticmethod
+ def choice_expand(s): #XXX does not support special sets like (ex ':alnum:')
+ m = ""
+ invert = s and s[0] == "^"
+ while True:
+ p = s.find("-")
+ if p < 0:
+ break
+ if p == 0 or p == len(s)-1:
+ m = "-"
+ if p:
+ s = s[:-1]
+ else:
+ s = s[1:]
+ else:
+ c1 = s[p-1]
+ c2 = s[p+1]
+ rng = "".join(map(chr, range(ord(c1),ord(c2)+1)))
+ s = s[:p-1]+rng+s[p+1:]
+ res = m+s
+ if invert:
+ res = "".join([chr(x) for x in range(256) if chr(x) not in res])
+ return res
+
+ @staticmethod
+ def stack_fix(lst, index):
+ r = ""
+ mul = 1
+ for e in lst:
+ if type(e) is list:
+ if mul != 1:
+ mul = mul-1
+ r += RandRegExp.stack_fix(e[1:]*mul, index)
+ # only the last iteration should be kept for back reference
+ f = RandRegExp.stack_fix(e[1:], index)
+ for i,idx in enumerate(index):
+ if e is idx:
+ index[i] = f
+ r += f
+ mul = 1
+ elif type(e) is tuple:
+ kind,val = e
+ if kind == "cite":
+ r += index[val-1]
+ elif kind == "repeat":
+ mul = val
+
+ elif kind == "choice":
+ if mul == 1:
+ c = random.choice(val)
+ r += RandRegExp.stack_fix(c[1:], index)
+ else:
+ r += RandRegExp.stack_fix([e]*mul, index)
+ mul = 1
+ else:
+ if mul != 1:
+ r += RandRegExp.stack_fix([e]*mul, index)
+ mul = 1
+ else:
+ r += str(e)
+ return r
+
+ def _fix(self):
+ stack = [None]
+ index = []
+ current = stack
+ i = 0
+ ln = len(self._regexp)
+ interp = True
+ while i < ln:
+ c = self._regexp[i]
+ i+=1
+
+ if c == '(':
+ current = [current]
+ current[0].append(current)
+ elif c == '|':
+ p = current[0]
+ ch = p[-1]
+ if type(ch) is not tuple:
+ ch = ("choice",[current])
+ p[-1] = ch
+ else:
+ ch[1].append(current)
+ current = [p]
+ elif c == ')':
+ ch = current[0][-1]
+ if type(ch) is tuple:
+ ch[1].append(current)
+ index.append(current)
+ current = current[0]
+ elif c == '[' or c == '{':
+ current = [current]
+ current[0].append(current)
+ interp = False
+ elif c == ']':
+ current = current[0]
+ choice = RandRegExp.choice_expand("".join(current.pop()[1:]))
+ current.append(RandChoice(*list(choice)))
+ interp = True
+ elif c == '}':
+ current = current[0]
+ num = "".join(current.pop()[1:])
+ e = current.pop()
+ if "," not in num:
+ n = int(num)
+ current.append([current]+[e]*n)
+ else:
+ num_min,num_max = num.split(",")
+ if not num_min:
+ num_min = "0"
+ if num_max:
+ n = RandNum(int(num_min),int(num_max))
+ else:
+ n = RandNumExpo(self._lambda,base=int(num_min))
+ current.append(("repeat",n))
+ current.append(e)
+ interp = True
+ elif c == '\\':
+ c = self._regexp[i]
+ if c == "s":
+ c = RandChoice(" ","\t")
+ elif c in "0123456789":
+ c = ("cite",ord(c)-0x30)
+ current.append(c)
+ i += 1
+ elif not interp:
+ current.append(c)
+ elif c == '+':
+ e = current.pop()
+ current.append([current]+[e]*(int(random.expovariate(self._lambda))+1))
+ elif c == '*':
+ e = current.pop()
+ current.append([current]+[e]*int(random.expovariate(self._lambda)))
+ elif c == '?':
+ if random.randint(0,1):
+ current.pop()
+ elif c == '.':
+ current.append(RandChoice(*[chr(x) for x in range(256)]))
+ elif c == '$' or c == '^':
+ pass
+ else:
+ current.append(c)
+
+ return RandRegExp.stack_fix(stack[1:], index)
+ def __repr__(self):
+ return "<%s [%r]>" % (self.__class__.__name__, self._regexp)
+
+class RandSingularity(RandChoice):
+ pass
+
+class RandSingNum(RandSingularity):
+ @staticmethod
+ def make_power_of_two(end):
+ sign = 1
+ if end == 0:
+ end = 1
+ if end < 0:
+ end = -end
+ sign = -1
+ end_n = int(math.log(end)/math.log(2))+1
+ return set([sign*2**i for i in range(end_n)])
+
+ def __init__(self, mn, mx):
+ sing = set([0, mn, mx, int((mn+mx)/2)])
+ sing |= self.make_power_of_two(mn)
+ sing |= self.make_power_of_two(mx)
+ for i in sing.copy():
+ sing.add(i+1)
+ sing.add(i-1)
+ for i in sing.copy():
+ if not mn <= i <= mx:
+ sing.remove(i)
+ self._choice = list(sing)
+
+
+class RandSingByte(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, 0, 2**8-1)
+
+class RandSingSByte(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, -2**7, 2**7-1)
+
+class RandSingShort(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, 0, 2**16-1)
+
+class RandSingSShort(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, -2**15, 2**15-1)
+
+class RandSingInt(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, 0, 2**32-1)
+
+class RandSingSInt(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, -2**31, 2**31-1)
+
+class RandSingLong(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, 0, 2**64-1)
+
+class RandSingSLong(RandSingNum):
+ def __init__(self):
+ RandSingNum.__init__(self, -2**63, 2**63-1)
+
+class RandSingString(RandSingularity): #TODO3
+ def __init__(self):
+ self._choice = [ b"",
+ b"%x",
+ b"%%",
+ b"%s",
+ b"%i",
+ b"%n",
+ b"%x%x%x%x%x%x%x%x%x",
+ b"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ b"%",
+ b"%%%",
+ b"A"*4096,
+ b"\x00"*4096,
+ b"\xff"*4096,
+ b"\x7f"*4096,
+ b"\x80"*4096,
+ b" "*4096,
+ b"\\"*4096,
+ b"("*4096,
+ b"../"*1024,
+ b"/"*1024,
+ b"${HOME}"*512,
+ b" or 1=1 --",
+ b"' or 1=1 --",
+ b'" or 1=1 --',
+ b" or 1=1; #",
+ b"' or 1=1; #",
+ b'" or 1=1; #',
+ b";reboot;",
+ b"$(reboot)",
+ b"`reboot`",
+ b"index.php%00",
+ b"\x00",
+ b"%00",
+ b"\\",
+ b"../../../../../../../../../../../../../../../../../etc/passwd",
+ b"%2e%2e%2f" * 20 + b"etc/passwd",
+ b"%252e%252e%252f" * 20 + b"boot.ini",
+ b"..%c0%af" * 20 + b"etc/passwd",
+ b"..%c0%af" * 20 + b"boot.ini",
+ b"//etc/passwd",
+ br"..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini",
+ b"AUX:",
+ b"CLOCK$",
+ b"COM:",
+ b"CON:",
+ b"LPT:",
+ b"LST:",
+ b"NUL:",
+ b"CON:",
+ br"C:\CON\CON",
+ br"C:\boot.ini",
+ br"\\myserver\share",
+ b"foo.exe:",
+ b"foo.exe\\", ]
+
+
+class RandPool(RandField):
+ def __init__(self, *args):
+ """Each parameter is a volatile object or a couple (volatile object, weight)"""
+ pool = []
+ for p in args:
+ w = 1
+ if type(p) is tuple:
+ p,w = p
+ pool += [p]*w
+ self._pool = pool
+ def _fix(self):
+ r = random.choice(self._pool)
+ return r._fix()
+
+# Automatic timestamp
+
+class AutoTime(VolatileValue):
+ def __init__(self, base=None):
+ if base == None:
+ self.diff = 0
+ else:
+ self.diff = time.time()-base
+ def _fix(self):
+ return time.time()-self.diff
+
+class IntAutoTime(AutoTime):
+ def _fix(self):
+ return int(time.time()-self.diff)
+
+
+class ZuluTime(AutoTime):
+ def __init__(self, diff=0):
+ self.diff=diff
+ def _fix(self):
+ return time.strftime("%y%m%d%H%M%SZ",time.gmtime(time.time()+self.diff))
+
+
+class DelayedEval(VolatileValue):
+ """ Example of usage: DelayedEval("time.time()") """
+ def __init__(self, expr):
+ self.expr = expr
+ def _fix(self):
+ return eval(self.expr)
+
+
+class IncrementalValue(VolatileValue):
+ def __init__(self, start=0, step=1, restart=-1):
+ self.start = self.val = start
+ self.step = step
+ self.restart = restart
+ def _fix(self):
+ v = self.val
+ if self.val == self.restart :
+ self.val = self.start
+ else:
+ self.val += self.step
+ return v
+
+class CorruptedBytes(VolatileValue):
+ def __init__(self, s, p=0.01, n=None):
+ self.s = s
+ self.p = p
+ self.n = n
+ def _fix(self):
+ return corrupt_bytes(self.s, p = self.p, n = self.n)
+
+class CorruptedBits(CorruptedBytes):
+ def _fix(self):
+ return corrupt_bits(self.s, p = self.p, n = self.n)
+
diff --git a/scripts/external_libs/scapy3-0.18-origin.rar b/scripts/external_libs/scapy3-0.18-origin.rar
new file mode 100644
index 00000000..0fda86fa
--- /dev/null
+++ b/scripts/external_libs/scapy3-0.18-origin.rar
Binary files differ